SH-2652 Faster depth of field

master
Dave Parks 2011-11-04 16:14:43 -05:00
parent fa5a0a90f4
commit e82c0561fa
7 changed files with 214 additions and 98 deletions

View File

@ -938,7 +938,7 @@ void LLVertexBuffer::releaseIndices()
{
sStreamIBOPool.release(mGLIndices, mMappedIndexData, mIndicesSize);
}
else if (mUsage == GL_DYNAMIC_DRAW_ARB)
else
{
sDynamicIBOPool.release(mGLIndices, mMappedIndexData, mIndicesSize);
}
@ -1122,6 +1122,8 @@ void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create)
}
}
static LLFastTimer::DeclareTimer FTM_SETUP_VERTEX_ARRAY("Setup VAO");
void LLVertexBuffer::setupVertexArray()
{
if (!mGLArray)
@ -1129,6 +1131,7 @@ void LLVertexBuffer::setupVertexArray()
return;
}
LLFastTimer t(FTM_SETUP_VERTEX_ARRAY);
#if GL_ARB_vertex_array_object
glBindVertexArray(mGLArray);
#endif
@ -1201,6 +1204,9 @@ void LLVertexBuffer::setupVertexArray()
}
}
//draw a dummy triangle to set index array pointer
//glDrawElements(GL_TRIANGLES, 0, GL_UNSIGNED_SHORT, NULL);
unbind();
}
@ -1843,14 +1849,18 @@ bool LLVertexBuffer::getClothWeightStrider(LLStrider<LLVector4>& strider, S32 in
//----------------------------------------------------------------------------
static LLFastTimer::DeclareTimer FTM_BIND_GL_ARRAY("Bind Array");
bool LLVertexBuffer::bindGLArray()
{
if (mGLArray && sGLRenderArray != mGLArray)
{
{
LLFastTimer t(FTM_BIND_GL_ARRAY);
#if GL_ARB_vertex_array_object
glBindVertexArray(mGLArray);
glBindVertexArray(mGLArray);
#endif
sGLRenderArray = mGLArray;
sGLRenderArray = mGLArray;
}
//really shouldn't be necessary, but some drivers don't properly restore the
//state of GL_ELEMENT_ARRAY_BUFFER_BINDING
@ -1862,6 +1872,8 @@ bool LLVertexBuffer::bindGLArray()
return false;
}
static LLFastTimer::DeclareTimer FTM_BIND_GL_BUFFER("Bind Buffer");
bool LLVertexBuffer::bindGLBuffer(bool force_bind)
{
bindGLArray();
@ -1870,6 +1882,7 @@ bool LLVertexBuffer::bindGLBuffer(bool force_bind)
if (useVBOs() && (force_bind || (mGLBuffer && (mGLBuffer != sGLRenderBuffer || !sVBOActive))))
{
LLFastTimer t(FTM_BIND_GL_BUFFER);
/*if (sMapped)
{
llerrs << "VBO bound while another VBO mapped!" << llendl;
@ -1891,6 +1904,8 @@ bool LLVertexBuffer::bindGLBuffer(bool force_bind)
return ret;
}
static LLFastTimer::DeclareTimer FTM_BIND_GL_INDICES("Bind Indices");
bool LLVertexBuffer::bindGLIndices(bool force_bind)
{
bindGLArray();
@ -1898,6 +1913,7 @@ bool LLVertexBuffer::bindGLIndices(bool force_bind)
bool ret = false;
if (useVBOs() && (force_bind || (mGLIndices && (mGLIndices != sGLRenderIndices || !sIBOActive))))
{
LLFastTimer t(FTM_BIND_GL_INDICES);
/*if (sMapped)
{
llerrs << "VBO bound while another VBO mapped!" << llendl;

View File

@ -9054,7 +9054,7 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
<integer>0</integer>
</map>
<key>RenderVBOMappingDisable</key>
<map>

View File

@ -0,0 +1,86 @@
/**
* @file cofF.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2007, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#extension GL_ARB_texture_rectangle : enable
#ifdef DEFINE_GL_FRAGCOLOR
out vec4 gl_FragColor;
#endif
uniform sampler2DRect diffuseRect;
uniform sampler2DRect depthMap;
uniform sampler2D bloomMap;
uniform float depth_cutoff;
uniform float norm_cutoff;
uniform float focal_distance;
uniform float blur_constant;
uniform float tan_pixel_angle;
uniform float magnification;
uniform mat4 inv_proj;
uniform vec2 screen_res;
VARYING vec2 vary_fragcoord;
float getDepth(vec2 pos_screen)
{
float z = texture2DRect(depthMap, pos_screen.xy).r;
z = z*2.0-1.0;
vec4 ndc = vec4(0.0, 0.0, z, 1.0);
vec4 p = inv_proj*ndc;
return p.z/p.w;
}
float calc_cof(float depth)
{
float sc = abs(depth-focal_distance)/-depth*blur_constant;
sc /= magnification;
// tan_pixel_angle = pixel_length/-depth;
float pixel_length = tan_pixel_angle*-focal_distance;
sc = sc/pixel_length;
sc *= 1.414;
return sc;
}
void main()
{
vec2 tc = vary_fragcoord.xy;
float depth = getDepth(tc);
vec4 diff = texture2DRect(diffuseRect, vary_fragcoord.xy);
float sc = calc_cof(depth);
sc = min(abs(sc), 10.0);
vec4 bloom = texture2D(bloomMap, vary_fragcoord.xy/screen_res);
gl_FragColor.rgb = diff.rgb + bloom.rgb;
gl_FragColor.a = sc/10.f;
}

View File

@ -30,13 +30,7 @@ out vec4 gl_FragColor;
#endif
uniform sampler2DRect diffuseRect;
uniform sampler2DRect edgeMap;
uniform sampler2DRect depthMap;
uniform sampler2DRect normalMap;
uniform sampler2D bloomMap;
uniform float depth_cutoff;
uniform float norm_cutoff;
uniform float focal_distance;
uniform float blur_constant;
uniform float tan_pixel_angle;
@ -47,59 +41,16 @@ uniform vec2 screen_res;
VARYING vec2 vary_fragcoord;
float getDepth(vec2 pos_screen)
void dofSample(inout vec4 diff, inout float w, float min_sc, vec2 tc)
{
float z = texture2DRect(depthMap, pos_screen.xy).r;
z = z*2.0-1.0;
vec4 ndc = vec4(0.0, 0.0, z, 1.0);
vec4 p = inv_proj*ndc;
return p.z/p.w;
}
float calc_cof(float depth)
{
float sc = abs(depth-focal_distance)/-depth*blur_constant;
sc /= magnification;
// tan_pixel_angle = pixel_length/-depth;
float pixel_length = tan_pixel_angle*-focal_distance;
sc = sc/pixel_length;
sc *= 1.414;
return sc;
}
void dofSampleNear(inout vec4 diff, inout float w, float cur_sc, vec2 tc)
{
float d = getDepth(tc);
float sc = calc_cof(d);
float wg = 0.25;
vec4 s = texture2DRect(diffuseRect, tc);
// de-weight dull areas to make highlights 'pop'
wg += s.r+s.g+s.b;
diff += wg*s;
w += wg;
}
void dofSample(inout vec4 diff, inout float w, float min_sc, float cur_depth, vec2 tc)
{
float d = getDepth(tc);
float sc = calc_cof(d);
if (sc > min_sc //sampled pixel is more "out of focus" than current sample radius
|| d < cur_depth) //sampled pixel is further away than current pixel
float sc = s.a*10.0;
if (sc > min_sc) //sampled pixel is more "out of focus" than current sample radius
{
float wg = 0.25;
vec4 s = texture2DRect(diffuseRect, tc);
// de-weight dull areas to make highlights 'pop'
wg += s.r+s.g+s.b;
@ -109,30 +60,20 @@ void dofSample(inout vec4 diff, inout float w, float min_sc, float cur_depth, ve
}
}
void main()
{
vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz;
norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
vec2 tc = vary_fragcoord.xy;
float depth = getDepth(tc);
vec4 diff = texture2DRect(diffuseRect, vary_fragcoord.xy);
{
float w = 1.0;
float sc = calc_cof(depth);
sc = min(abs(sc), 10.0);
float fd = depth*0.5f;
float sc = diff.a*10.0;
float PI = 3.14159265358979323846264;
// sample quite uniformly spaced points within a circle, for a circular 'bokeh'
//if (depth < focal_distance)
{
while (sc > 0.5)
{
@ -143,7 +84,7 @@ void main()
float samp_x = sc*sin(ang);
float samp_y = sc*cos(ang);
// you could test sample coords against an interesting non-circular aperture shape here, if desired.
dofSample(diff, w, sc, depth, vary_fragcoord.xy + vec2(samp_x,samp_y));
dofSample(diff, w, sc, vary_fragcoord.xy + vec2(samp_x,samp_y));
}
sc -= 1.0;
}
@ -152,6 +93,5 @@ void main()
diff /= w;
}
vec4 bloom = texture2D(bloomMap, vary_fragcoord.xy/screen_res);
gl_FragColor = diff + bloom;
gl_FragColor = diff;
}

View File

@ -186,6 +186,7 @@ LLGLSLShader gDeferredAvatarEyesProgram;
LLGLSLShader gDeferredFullbrightProgram;
LLGLSLShader gDeferredEmissiveProgram;
LLGLSLShader gDeferredPostProgram;
LLGLSLShader gDeferredCoFProgram;
LLGLSLShader gFXAAProgram;
LLGLSLShader gDeferredPostNoDoFProgram;
LLGLSLShader gDeferredWLSkyProgram;
@ -1013,6 +1014,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredEmissiveProgram.unload();
gDeferredAvatarEyesProgram.unload();
gDeferredPostProgram.unload();
gDeferredCoFProgram.unload();
gFXAAProgram.unload();
gDeferredWaterProgram.unload();
gDeferredWLSkyProgram.unload();
@ -1425,6 +1427,16 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
success = gDeferredPostProgram.createShader(NULL, NULL);
}
if (success)
{
gDeferredCoFProgram.mName = "Deferred CoF Shader";
gDeferredCoFProgram.mShaderFiles.clear();
gDeferredCoFProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredV.glsl", GL_VERTEX_SHADER_ARB));
gDeferredCoFProgram.mShaderFiles.push_back(make_pair("deferred/cofF.glsl", GL_FRAGMENT_SHADER_ARB));
gDeferredCoFProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
success = gDeferredCoFProgram.createShader(NULL, NULL);
}
if (success)
{
gDeferredPostNoDoFProgram.mName = "Deferred Post Shader";

View File

@ -330,6 +330,7 @@ extern LLGLSLShader gDeferredSoftenProgram;
extern LLGLSLShader gDeferredShadowProgram;
extern LLGLSLShader gDeferredShadowAlphaMaskProgram;
extern LLGLSLShader gDeferredPostProgram;
extern LLGLSLShader gDeferredCoFProgram;
extern LLGLSLShader gFXAAProgram;
extern LLGLSLShader gDeferredPostNoDoFProgram;
extern LLGLSLShader gDeferredAvatarShadowProgram;

View File

@ -443,7 +443,7 @@ void LLPipeline::init()
sRenderBump = gSavedSettings.getBOOL("RenderObjectBump");
sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips");
LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("RenderUseStreamVBO");
LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("RenderUseVAO");
LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO");
LLVertexBuffer::sPreferStreamDraw = gSavedSettings.getBOOL("RenderPreferStreamDraw");
sRenderAttachedLights = gSavedSettings.getBOOL("RenderAttachedLights");
sRenderAttachedParticles = gSavedSettings.getBOOL("RenderAttachedParticles");
@ -6136,7 +6136,7 @@ void LLPipeline::resetVertexBuffers()
sRenderBump = gSavedSettings.getBOOL("RenderObjectBump");
sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips");
LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("RenderUseStreamVBO");
LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("RenderUseVAO");
LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO");
LLVertexBuffer::sPreferStreamDraw = gSavedSettings.getBOOL("RenderPreferStreamDraw");
LLVertexBuffer::sEnableVBOs = gSavedSettings.getBOOL("RenderVBOEnable");
LLVertexBuffer::sDisableVBOMapping = LLVertexBuffer::sEnableVBOs && gSavedSettings.getBOOL("RenderVBOMappingDisable") ;
@ -6487,7 +6487,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
}
LLGLDisable blend(GL_BLEND);
bindDeferredShader(*shader);
if (dof_enabled)
{
@ -6595,41 +6595,102 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
blur_constant /= 1000.f; //convert to meters for shader
F32 magnification = focal_length/(subject_distance-focal_length);
mDeferredLight.bindTarget();
shader = &gDeferredCoFProgram;
bindDeferredShader(*shader);
S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
if (channel > -1)
{
mScreen.bindTexture(0, channel);
}
if (multisample)
{ //bloom has already been added, bind black
channel = shader->enableTexture(LLShaderMgr::DEFERRED_BLOOM);
if (channel > -1)
{
gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sBlackImagep);
}
}
shader->uniform1f(LLShaderMgr::DOF_FOCAL_DISTANCE, -subject_distance/1000.f);
shader->uniform1f(LLShaderMgr::DOF_BLUR_CONSTANT, blur_constant);
shader->uniform1f(LLShaderMgr::DOF_TAN_PIXEL_ANGLE, tanf(1.f/LLDrawable::sCurPixelAngle));
shader->uniform1f(LLShaderMgr::DOF_MAGNIFICATION, magnification);
}
S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
if (channel > -1)
{
mScreen.bindTexture(0, channel);
}
gGL.begin(LLRender::TRIANGLE_STRIP);
gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
gGL.vertex2f(-1,-1);
gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
gGL.vertex2f(-1,3);
gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
gGL.vertex2f(3,-1);
gGL.end();
if (multisample)
{ //bloom has already been added, bind black
channel = shader->enableTexture(LLShaderMgr::DEFERRED_BLOOM);
unbindDeferredShader(*shader);
mDeferredLight.flush();
shader = &gDeferredPostProgram;
bindDeferredShader(*shader);
channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage());
if (channel > -1)
{
gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sBlackImagep);
mDeferredLight.bindTexture(0, channel);
}
gGL.begin(LLRender::TRIANGLE_STRIP);
gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
gGL.vertex2f(-1,-1);
gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
gGL.vertex2f(-1,3);
gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
gGL.vertex2f(3,-1);
gGL.end();
unbindDeferredShader(*shader);
}
else
{
bindDeferredShader(*shader);
gGL.begin(LLRender::TRIANGLE_STRIP);
gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
gGL.vertex2f(-1,-1);
gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
gGL.vertex2f(-1,3);
gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
gGL.vertex2f(3,-1);
gGL.end();
S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
if (channel > -1)
{
mScreen.bindTexture(0, channel);
}
unbindDeferredShader(*shader);
if (multisample)
{ //bloom has already been added, bind black
channel = shader->enableTexture(LLShaderMgr::DEFERRED_BLOOM);
if (channel > -1)
{
gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sBlackImagep);
}
}
gGL.begin(LLRender::TRIANGLE_STRIP);
gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
gGL.vertex2f(-1,-1);
gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
gGL.vertex2f(-1,3);
gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
gGL.vertex2f(3,-1);
gGL.end();
unbindDeferredShader(*shader);
}
}
}
else