Occlusion FBOs in deferred.

This commit is contained in:
Shyotl
2013-10-26 18:07:56 -05:00
parent 574022ed2c
commit 8e55d5499e
8 changed files with 346 additions and 12 deletions

View File

@@ -727,7 +727,8 @@ bool LLGLManager::initGL()
}
stop_glerror();
//Singu Note: Multisampled texture stuff in v3 is dead, however we DO use multisampled FBOs.
if (mHasFramebufferMultisample)
{
glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &mMaxIntegerSamples);

View File

@@ -0,0 +1,67 @@
/**
* @file debugF.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2011, 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$
*/
#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_color;
#else
#define frag_color gl_FragColor
#endif
uniform sampler2D depthMap;
uniform float delta;
VARYING vec2 tc0;
VARYING vec2 tc1;
VARYING vec2 tc2;
VARYING vec2 tc3;
VARYING vec2 tc4;
VARYING vec2 tc5;
VARYING vec2 tc6;
VARYING vec2 tc7;
VARYING vec2 tc8;
void main()
{
vec4 depth1 =
vec4(texture2D(depthMap, tc0).r,
texture2D(depthMap, tc1).r,
texture2D(depthMap, tc2).r,
texture2D(depthMap, tc3).r);
vec4 depth2 =
vec4(texture2D(depthMap, tc4).r,
texture2D(depthMap, tc5).r,
texture2D(depthMap, tc6).r,
texture2D(depthMap, tc7).r);
depth1 = min(depth1, depth2);
float depth = min(depth1.x, depth1.y);
depth = min(depth, depth1.z);
depth = min(depth, depth1.w);
depth = min(depth, texture2D(depthMap, tc8).r);
gl_FragDepth = depth;
}

View File

@@ -0,0 +1,69 @@
/**
* @file debugF.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2011, 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 frag_color;
#else
#define frag_color gl_FragColor
#endif
uniform sampler2DRect depthMap;
uniform float delta;
VARYING vec2 tc0;
VARYING vec2 tc1;
VARYING vec2 tc2;
VARYING vec2 tc3;
VARYING vec2 tc4;
VARYING vec2 tc5;
VARYING vec2 tc6;
VARYING vec2 tc7;
VARYING vec2 tc8;
void main()
{
vec4 depth1 =
vec4(texture2DRect(depthMap, tc0).r,
texture2DRect(depthMap, tc1).r,
texture2DRect(depthMap, tc2).r,
texture2DRect(depthMap, tc3).r);
vec4 depth2 =
vec4(texture2DRect(depthMap, tc4).r,
texture2DRect(depthMap, tc5).r,
texture2DRect(depthMap, tc6).r,
texture2DRect(depthMap, tc7).r);
depth1 = min(depth1, depth2);
float depth = min(depth1.x, depth1.y);
depth = min(depth, depth1.z);
depth = min(depth, depth1.w);
depth = min(depth, texture2DRect(depthMap, tc8).r);
gl_FragDepth = depth;
}

View File

@@ -0,0 +1,59 @@
/**
* @file debugV.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2011, 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$
*/
uniform mat4 modelview_projection_matrix;
ATTRIBUTE vec3 position;
uniform vec2 screen_res;
uniform vec2 delta;
VARYING vec2 tc0;
VARYING vec2 tc1;
VARYING vec2 tc2;
VARYING vec2 tc3;
VARYING vec2 tc4;
VARYING vec2 tc5;
VARYING vec2 tc6;
VARYING vec2 tc7;
VARYING vec2 tc8;
void main()
{
gl_Position = vec4(position, 1.0);
vec2 tc = (position.xy*0.5+0.5)*screen_res;
tc0 = tc+vec2(-delta.x,-delta.y);
tc1 = tc+vec2(0,-delta.y);
tc2 = tc+vec2(delta.x,-delta.y);
tc3 = tc+vec2(-delta.x,0);
tc4 = tc+vec2(0,0);
tc5 = tc+vec2(delta.x,0);
tc6 = tc+vec2(-delta.x,delta.y);
tc7 = tc+vec2(0,delta.y);
tc8 = tc+vec2(delta.x,delta.y);
}

View File

@@ -97,6 +97,8 @@ LLGLSLShader gTwoTextureAddProgram(LLViewerShaderMgr::SHADER_INTERFACE);
LLGLSLShader gOneTextureNoColorProgram(LLViewerShaderMgr::SHADER_INTERFACE);
LLGLSLShader gDebugProgram(LLViewerShaderMgr::SHADER_INTERFACE);
LLGLSLShader gClipProgram(LLViewerShaderMgr::SHADER_INTERFACE);
LLGLSLShader gDownsampleDepthProgram(LLViewerShaderMgr::SHADER_INTERFACE);
LLGLSLShader gDownsampleDepthRectProgram(LLViewerShaderMgr::SHADER_INTERFACE);
LLGLSLShader gAlphaMaskProgram(LLViewerShaderMgr::SHADER_INTERFACE);
LLGLSLShader gUIProgram(LLViewerShaderMgr::SHADER_INTERFACE);
@@ -2652,6 +2654,26 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
success = gClipProgram.createShader(NULL, NULL);
}
if (success)
{
gDownsampleDepthProgram.mName = "DownsampleDepth Shader";
gDownsampleDepthProgram.mShaderFiles.clear();
gDownsampleDepthProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthV.glsl", GL_VERTEX_SHADER_ARB));
gDownsampleDepthProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthF.glsl", GL_FRAGMENT_SHADER_ARB));
gDownsampleDepthProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
success = gDownsampleDepthProgram.createShader(NULL, NULL);
}
if (success)
{
gDownsampleDepthRectProgram.mName = "DownsampleDepthRect Shader";
gDownsampleDepthRectProgram.mShaderFiles.clear();
gDownsampleDepthRectProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthV.glsl", GL_VERTEX_SHADER_ARB));
gDownsampleDepthRectProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthRectF.glsl", GL_FRAGMENT_SHADER_ARB));
gDownsampleDepthRectProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
success = gDownsampleDepthRectProgram.createShader(NULL, NULL);
}
if (success)
{
gAlphaMaskProgram.mName = "Alpha Mask Shader";

View File

@@ -184,6 +184,7 @@ extern LLGLSLShader gTransformTexCoordProgram;
extern LLGLSLShader gTransformNormalProgram;
extern LLGLSLShader gTransformColorProgram;
extern LLGLSLShader gTransformTangentProgram;
//utility shaders
extern LLGLSLShader gOcclusionProgram;
extern LLGLSLShader gOcclusionCubeProgram;
@@ -193,6 +194,8 @@ extern LLGLSLShader gSplatTextureRectProgram;
extern LLGLSLShader gGlowCombineFXAAProgram;
extern LLGLSLShader gDebugProgram;
extern LLGLSLShader gClipProgram;
extern LLGLSLShader gDownsampleDepthProgram;
extern LLGLSLShader gDownsampleDepthRectProgram;
//output tex0[tc0] + tex1[tc1]
extern LLGLSLShader gTwoTextureAddProgram;

View File

@@ -774,10 +774,12 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
BOOL RenderDepthOfField = gSavedSettings.getBOOL("RenderDepthOfField");
static const LLCachedControl<F32> RenderShadowResolutionScale("RenderShadowResolutionScale",1.0f);
const U32 occlusion_divisor = 3;
//allocate deferred rendering color buffers
if (!mDeferredScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;
if (!mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;
if (!mOcclusionDepth.allocate(resX/occlusion_divisor, resY/occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;
if (!addDeferredAttachments(mDeferredScreen)) return false;
if (!mScreen.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;
@@ -807,6 +809,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
for (U32 i = 0; i < 4; i++)
{
if (!mShadow[i].allocate(sun_shadow_map_width,U32(resY*scale), 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE)) return false;
if (!mShadowOcclusion[i].allocate(mShadow[i].getWidth()/occlusion_divisor, mShadow[i].getHeight()/occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE)) return false;
}
}
else
@@ -814,6 +817,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
for (U32 i = 0; i < 4; i++)
{
mShadow[i].release();
mShadowOcclusion[i].release();
}
}
@@ -826,6 +830,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
for (U32 i = 4; i < 6; i++)
{
if (!mShadow[i].allocate(spot_shadow_map_width, height, 0, TRUE, FALSE)) return false;
if (!mShadowOcclusion[i].allocate(mShadow[i].getWidth()/occlusion_divisor, mShadow[i].getHeight()/occlusion_divisor, 0, TRUE, FALSE)) return false;
}
}
else
@@ -833,6 +838,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
for (U32 i = 4; i < 6; i++)
{
mShadow[i].release();
mShadowOcclusion[i].release();
}
}
@@ -849,13 +855,14 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
for (U32 i = 0; i < 6; i++)
{
mShadow[i].release();
mShadowOcclusion[i].release();
}
mFXAABuffer.release();
mScreen.release();
mDeferredScreen.release(); //make sure to release any render targets that share a depth buffer with mDeferredScreen first
mDeferredDepth.release();
mOcclusionDepth.release();
if (!mScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;
if(samples > 1 && mScreen.getFBO())
{
@@ -975,12 +982,14 @@ void LLPipeline::releaseScreenBuffers()
mDeferredScreen.release();
mDeferredDepth.release();
mDeferredLight.release();
mOcclusionDepth.release();
//mHighlight.release();
for (U32 i = 0; i < 6; i++)
{
mShadow[i].release();
mShadowOcclusion[i].release();
}
mSampleBuffer.release();
@@ -2167,7 +2176,14 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl
if (to_texture)
{
mScreen.bindTarget();
if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
{
mOcclusionDepth.bindTarget();
}
else
{
mScreen.bindTarget();
}
}
if (sUseOcclusion > 1)
@@ -2305,7 +2321,14 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl
if (to_texture)
{
mScreen.flush();
if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
{
mOcclusionDepth.flush();
}
else
{
mScreen.flush();
}
}
}
@@ -2373,6 +2396,79 @@ void LLPipeline::markOccluder(LLSpatialGroup* group)
}
}
void LLPipeline::downsampleDepthBuffer(LLRenderTarget& source, LLRenderTarget& dest, LLRenderTarget* scratch_space)
{
LLGLSLShader* last_shader = LLGLSLShader::sCurBoundShaderPtr;
LLGLSLShader* shader = NULL;
if (scratch_space)
{
scratch_space->copyContents(source,
0, 0, source.getWidth(), source.getHeight(),
0, 0, scratch_space->getWidth(), scratch_space->getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);
}
dest.bindTarget();
dest.clear(GL_DEPTH_BUFFER_BIT);
if(mDeferredVB.isNull())
{
mDeferredVB = new LLVertexBuffer(DEFERRED_VB_MASK, 0);
mDeferredVB->allocateBuffer(8, 0, true);
}
LLStrider<LLVector3> vert;
mDeferredVB->getVertexStrider(vert);
LLStrider<LLVector2> tc0;
vert[0].set(-1,1,0);
vert[1].set(-1,-3,0);
vert[2].set(3,1,0);
if (source.getUsage() == LLTexUnit::TT_RECT_TEXTURE)
{
shader = &gDownsampleDepthRectProgram;
shader->bind();
shader->uniform2f("delta", 1.f, 1.f);
shader->uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, source.getWidth(), source.getHeight());
}
else
{
shader = &gDownsampleDepthProgram;
shader->bind();
shader->uniform2f("delta", 1.f/source.getWidth(), 1.f/source.getHeight());
shader->uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, 1.f, 1.f);
}
gGL.getTexUnit(0)->bind(scratch_space ? scratch_space : &source, TRUE);
{
LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS);
mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
}
dest.flush();
if (last_shader)
{
last_shader->bind();
}
else
{
shader->unbind();
}
}
void LLPipeline::doOcclusion(LLCamera& camera, LLRenderTarget& source, LLRenderTarget& dest, LLRenderTarget* scratch_space)
{
downsampleDepthBuffer(source, dest, scratch_space);
dest.bindTarget();
doOcclusion(camera);
dest.flush();
}
void LLPipeline::doOcclusion(LLCamera& camera)
{
if (LLGLSLShader::sNoFixedFunction && LLPipeline::sUseOcclusion > 1 && sCull->hasOcclusionGroups())
@@ -4188,7 +4284,7 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera)
gGL.setColorMask(true, false);
}
void LLPipeline::renderGeomPostDeferred(LLCamera& camera)
void LLPipeline::renderGeomPostDeferred(LLCamera& camera, bool do_occlusion)
{
LLFastTimer t(FTM_POST_DEFERRED_POOLS);
U32 cur_type = 0;
@@ -4204,7 +4300,7 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera)
gGL.setColorMask(true, false);
pool_set_t::iterator iter1 = mPools.begin();
BOOL occlude = LLPipeline::sUseOcclusion > 1;
BOOL occlude = LLPipeline::sUseOcclusion > 1 && do_occlusion;
while ( iter1 != mPools.end() )
{
@@ -4218,7 +4314,7 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera)
gGLLastMatrix = NULL;
gGL.loadMatrix(gGLModelView);
LLGLSLShader::bindNoShader();
doOcclusion(camera);
doOcclusion(camera, mScreen, mOcclusionDepth, &mDeferredDepth);
gGL.setColorMask(true, false);
}
@@ -5310,7 +5406,7 @@ void LLPipeline::calcNearbyLights(LLCamera& camera)
// crazy cast so that we can overwrite the fade value
// even though gcc enforces sets as const
// (fade value doesn't affect sort so this is safe)
Light* farthest_light = ((Light*) (&(*(mNearbyLights.rbegin()))));
Light* farthest_light = (const_cast<Light*>(&(*(mNearbyLights.rbegin()))));
if (light->dist < farthest_light->dist)
{
if (farthest_light->fade >= 0.f)
@@ -7755,7 +7851,7 @@ void LLPipeline::renderDeferredLighting()
LLPipeline::END_RENDER_TYPES);
renderGeomPostDeferred(*LLViewerCamera::getInstance());
renderGeomPostDeferred(*LLViewerCamera::getInstance(), false);
gPipeline.popRenderTypeMask();
}
@@ -8604,9 +8700,15 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
gDeferredShadowCubeProgram.bind();
}
LLRenderTarget& occlusion_target = mShadowOcclusion[LLViewerCamera::sCurCameraID-1];
occlusion_target.bindTarget();
updateCull(shadow_cam, result);
occlusion_target.flush();
stateSort(shadow_cam, result);
//generate shadow map
gGL.matrixMode(LLRender::MM_PROJECTION);
gGL.pushMatrix();
@@ -8685,7 +8787,10 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
gDeferredShadowCubeProgram.bind();
gGLLastMatrix = NULL;
gGL.loadMatrix(gGLModelView);
doOcclusion(shadow_cam);
LLRenderTarget& occlusion_source = mShadow[LLViewerCamera::sCurCameraID-1];
doOcclusion(shadow_cam, occlusion_source, occlusion_target);
if (use_shader)
{

View File

@@ -177,6 +177,12 @@ public:
// Object related methods
void markVisible(LLDrawable *drawablep, LLCamera& camera);
void markOccluder(LLSpatialGroup* group);
//downsample source to dest, taking the maximum depth value per pixel in source and writing to dest
// if source's depth buffer cannot be bound for reading, a scratch space depth buffer must be provided
void downsampleDepthBuffer(LLRenderTarget& source, LLRenderTarget& dest, LLRenderTarget* scratch_space = NULL);
void doOcclusion(LLCamera& camera, LLRenderTarget& source, LLRenderTarget& dest, LLRenderTarget* scratch_space = NULL);
void doOcclusion(LLCamera& camera);
void markNotCulled(LLSpatialGroup* group, LLCamera &camera);
void markMoved(LLDrawable *drawablep, BOOL damped_motion = FALSE);
@@ -274,7 +280,7 @@ public:
void renderGeom(LLCamera& camera, BOOL forceVBOUpdate = FALSE);
void renderGeomDeferred(LLCamera& camera);
void renderGeomPostDeferred(LLCamera& camera);
void renderGeomPostDeferred(LLCamera& camera, bool do_occlusion=true);
void renderGeomShadow(LLCamera& camera);
void bindDeferredShader(LLGLSLShader& shader, U32 light_index = 0, U32 noise_map = 0xFFFFFFFF);
void setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep);
@@ -573,6 +579,7 @@ public:
LLRenderTarget mFXAABuffer;
LLRenderTarget mEdgeMap;
LLRenderTarget mDeferredDepth;
LLRenderTarget mOcclusionDepth;
LLRenderTarget mDeferredLight;
LLMultisampleBuffer mSampleBuffer;
LLRenderTarget mPhysicsDisplay;
@@ -585,6 +592,7 @@ public:
//sun shadow map
LLRenderTarget mShadow[6];
LLRenderTarget mShadowOcclusion[6];
std::vector<LLVector3> mShadowFrustPoints[4];
LLVector4 mShadowError;
LLVector4 mShadowFOV;