diff options
author | Graham Linden <graham@lindenlab.com> | 2013-07-12 13:01:31 -0700 |
---|---|---|
committer | Graham Linden <graham@lindenlab.com> | 2013-07-12 13:01:31 -0700 |
commit | 5efee00a835a30f09637b2459134d458a9efa6cd (patch) | |
tree | da53774d9b3b9256d5da00635b4e04505d0ff404 | |
parent | b588865f3f56a338fc068b55ab1a408f89307f2b (diff) |
NORSPEC-291 WIP added underwater deferred program and more reflection pass work
-rw-r--r-- | indra/newview/app_settings/shaders/class1/deferred/underWaterF.glsl | 120 | ||||
-rwxr-xr-x | indra/newview/lldrawpoolwater.cpp | 9 | ||||
-rwxr-xr-x | indra/newview/llviewershadermgr.cpp | 17 | ||||
-rwxr-xr-x | indra/newview/llviewershadermgr.h | 1 | ||||
-rwxr-xr-x | indra/newview/pipeline.cpp | 220 | ||||
-rwxr-xr-x | indra/newview/pipeline.h | 3 |
6 files changed, 315 insertions, 55 deletions
diff --git a/indra/newview/app_settings/shaders/class1/deferred/underWaterF.glsl b/indra/newview/app_settings/shaders/class1/deferred/underWaterF.glsl new file mode 100644 index 0000000000..c160b38cfe --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/underWaterF.glsl @@ -0,0 +1,120 @@ +/** + * @file underWaterF.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$ + */ + +#ifdef DEFINE_GL_FRAGCOLOR +out vec4 frag_data[3]; +#else +#define frag_data gl_FragData +#endif + +uniform sampler2D diffuseMap; +uniform sampler2D bumpMap; +uniform sampler2D screenTex; +uniform sampler2D refTex; +uniform sampler2D screenDepth; + +uniform vec4 fogCol; +uniform vec3 lightDir; +uniform vec3 specular; +uniform float lightExp; +uniform vec2 fbScale; +uniform float refScale; +uniform float znear; +uniform float zfar; +uniform float kd; +uniform vec4 waterPlane; +uniform vec3 eyeVec; +uniform vec4 waterFogColor; +uniform float waterFogDensity; +uniform float waterFogKS; +uniform vec2 screenRes; + +//bigWave is (refCoord.w, view.w); +VARYING vec4 refCoord; +VARYING vec4 littleWave; +VARYING vec4 view; + +vec2 encode_normal(vec3 n) +{ + float f = sqrt(8 * n.z + 8); + return n.xy / f + 0.5; +} + +vec4 applyWaterFog(vec4 color, vec3 viewVec) +{ + //normalize view vector + vec3 view = normalize(viewVec); + float es = -view.z; + + //find intersection point with water plane and eye vector + + //get eye depth + float e0 = max(-waterPlane.w, 0.0); + + //get object depth + float depth = length(viewVec); + + //get "thickness" of water + float l = max(depth, 0.1); + + float kd = waterFogDensity; + float ks = waterFogKS; + vec4 kc = waterFogColor; + + float F = 0.98; + + float t1 = -kd * pow(F, ks * e0); + float t2 = kd + ks * es; + float t3 = pow(F, t2*l) - 1.0; + + float L = min(t1/t2*t3, 1.0); + + float D = pow(0.98, l*kd); + //return vec4(1.0, 0.0, 1.0, 1.0); + return color * D + kc * L; + //depth /= 10.0; + //return vec4(depth,depth,depth,0.0); +} + +void main() +{ + vec4 color; + + //get detail normals + vec3 wave1 = texture2D(bumpMap, vec2(refCoord.w, view.w)).xyz*2.0-1.0; + vec3 wave2 = texture2D(bumpMap, littleWave.xy).xyz*2.0-1.0; + vec3 wave3 = texture2D(bumpMap, littleWave.zw).xyz*2.0-1.0; + vec3 wavef = normalize(wave1+wave2+wave3); + + //figure out distortion vector (ripply) + vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5; + distort = distort+wavef.xy*refScale; + + vec4 fb = texture2D(screenTex, distort); + + frag_data[0] = vec4(fb.rgb, 0.5); // diffuse + frag_data[1] = vec4(0.5,0.5,0.5, 0.95); // speccolor*spec, spec + frag_data[2] = vec4(encode_normal(wavef), 0.0, 0.0); // normalxyz, displace +} diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp index 5b0b173926..6774926f62 100755 --- a/indra/newview/lldrawpoolwater.cpp +++ b/indra/newview/lldrawpoolwater.cpp @@ -524,7 +524,14 @@ void LLDrawPoolWater::shade() if (eyedepth < 0.f && LLPipeline::sWaterReflections) { - shader = &gUnderWaterProgram; + if (deferred_render) + { + shader = &gDeferredUnderWaterProgram; + } + else + { + shader = &gUnderWaterProgram; + } } else if (deferred_render) { diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 3df8115402..e9c3990e9a 100755 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -168,6 +168,7 @@ LLGLSLShader gPostNightVisionProgram; // Deferred rendering shaders LLGLSLShader gDeferredImpostorProgram; LLGLSLShader gDeferredWaterProgram; +LLGLSLShader gDeferredUnderWaterProgram; LLGLSLShader gDeferredDiffuseProgram; LLGLSLShader gDeferredDiffuseAlphaMaskProgram; LLGLSLShader gDeferredNonIndexedDiffuseProgram; @@ -309,6 +310,7 @@ LLViewerShaderMgr::LLViewerShaderMgr() : mShaderList.push_back(&gDeferredEmissiveProgram); mShaderList.push_back(&gDeferredAvatarEyesProgram); mShaderList.push_back(&gDeferredWaterProgram); + mShaderList.push_back(&gDeferredUnderWaterProgram); mShaderList.push_back(&gDeferredAvatarAlphaProgram); mShaderList.push_back(&gDeferredWLSkyProgram); mShaderList.push_back(&gDeferredWLCloudProgram); @@ -1153,6 +1155,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredPostGammaCorrectProgram.unload(); gFXAAProgram.unload(); gDeferredWaterProgram.unload(); + gDeferredUnderWaterProgram.unload(); gDeferredWLSkyProgram.unload(); gDeferredWLCloudProgram.unload(); gDeferredStarProgram.unload(); @@ -1642,6 +1645,20 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { + // load water shader + gDeferredUnderWaterProgram.mName = "Deferred Under Water Shader"; + gDeferredUnderWaterProgram.mFeatures.calculatesAtmospherics = true; + gDeferredUnderWaterProgram.mFeatures.hasGamma = true; + gDeferredUnderWaterProgram.mFeatures.hasTransport = true; + gDeferredUnderWaterProgram.mShaderFiles.clear(); + gDeferredUnderWaterProgram.mShaderFiles.push_back(make_pair("deferred/waterV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredUnderWaterProgram.mShaderFiles.push_back(make_pair("deferred/underWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredUnderWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredUnderWaterProgram.createShader(NULL, &mWaterUniforms); + } + + if (success) + { gDeferredSoftenProgram.mName = "Deferred Soften Shader"; gDeferredSoftenProgram.mShaderFiles.clear(); gDeferredSoftenProgram.mShaderFiles.push_back(make_pair("deferred/softenLightV.glsl", GL_VERTEX_SHADER_ARB)); diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index 5310076013..f14180d957 100755 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -330,6 +330,7 @@ extern LLGLSLShader gPostNightVisionProgram; // Deferred rendering shaders extern LLGLSLShader gDeferredImpostorProgram; extern LLGLSLShader gDeferredWaterProgram; +extern LLGLSLShader gDeferredUnderWaterProgram; extern LLGLSLShader gDeferredDiffuseProgram; extern LLGLSLShader gDeferredDiffuseAlphaMaskProgram; extern LLGLSLShader gDeferredNonIndexedDiffuseAlphaMaskProgram; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index cac347b3a5..4e1eb4d8ad 100755 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -122,6 +122,10 @@ //#define DEBUG_INDICES #endif +// Expensive and currently broken... +// +#define MATERIALS_IN_REFLECTIONS 0 + bool gShiftFrame = false; //cached settings @@ -4647,6 +4651,103 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera) gGL.setColorMask(true, false); } +void LLPipeline::renderGeomDeferredToRT(LLCamera& camera) +{ + LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomDeferred"); + + LLFastTimer t(FTM_RENDER_GEOMETRY); + LLFastTimer t2(FTM_DEFERRED_POOLS); + + LLGLEnable cull(GL_CULL_FACE); + + LLGLEnable stencil(GL_STENCIL_TEST); + glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF); + stop_glerror(); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + stop_glerror(); + + for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) + { + LLDrawPool *poolp = *iter; + if (hasRenderType(poolp->getType())) + { + poolp->prerender(); + } + } + + LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0); + + LLVertexBuffer::unbind(); + + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); + + U32 cur_type = 0; + + gGL.setColorMask(true, true); + + pool_set_t::iterator iter1 = mPools.begin(); + + while ( iter1 != mPools.end() ) + { + LLDrawPool *poolp = *iter1; + + cur_type = poolp->getType(); + + pool_set_t::iterator iter2 = iter1; + if (hasRenderType(poolp->getType()) && poolp->getNumDeferredPasses() > 0) + { + LLFastTimer t(FTM_DEFERRED_POOLRENDER); + + gGLLastMatrix = NULL; + gGL.loadMatrix(gGLModelView); + + for( S32 i = 0; i < poolp->getNumDeferredPasses(); i++ ) + { + LLVertexBuffer::unbind(); + poolp->beginDeferredPass(i); + for (iter2 = iter1; iter2 != mPools.end(); iter2++) + { + LLDrawPool *p = *iter2; + if (p->getType() != cur_type) + { + break; + } + + if ( !p->getSkipRenderFlag() ) { p->renderDeferred(i); } + } + poolp->endDeferredPass(i); + LLVertexBuffer::unbind(); + + if (gDebugGL || gDebugPipeline) + { + LLGLState::checkStates(); + } + } + } + else + { + // Skip all pools of this type + for (iter2 = iter1; iter2 != mPools.end(); iter2++) + { + LLDrawPool *p = *iter2; + if (p->getType() != cur_type) + { + break; + } + } + } + iter1 = iter2; + stop_glerror(); + } + + gGLLastMatrix = NULL; + gGL.loadMatrix(gGLModelView); + + gGL.setColorMask(true, false); +} + void LLPipeline::renderGeomPostDeferred(LLCamera& camera, bool do_occlusion) { LLFastTimer t(FTM_POST_DEFERRED_POOLS); @@ -8047,10 +8148,12 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) static LLFastTimer::DeclareTimer FTM_BIND_DEFERRED("Bind Deferred"); -void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 noise_map) +void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, LLRenderTarget* alternative_target, U32 noise_map) { LLFastTimer t(FTM_BIND_DEFERRED); + LLRenderTarget* render_target = alternative_target ? alternative_target : &mScreen; + if (noise_map == 0xFFFFFFFF) { noise_map = mNoiseMap; @@ -8120,7 +8223,7 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n { if (light_index > 0) { - mScreen.bindTexture(0, channel); + render_target->bindTexture(0, channel); } else { @@ -8903,11 +9006,11 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target) LLViewerCamera* camera = LLViewerCamera::getInstance(); - /*{ + { LLGLDepthTest depth(GL_TRUE); mDeferredDepth.copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(), 0, 0, mDeferredDepth.getWidth(), mDeferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST); - }*/ + } LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0); @@ -8957,7 +9060,7 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target) mDeferredLight.bindTarget(); { //paint shadow/SSAO light map (direct lighting lightmap) LLFastTimer ftm(FTM_SUN_SHADOW); - bindDeferredShader(gDeferredSunProgram, 0); + bindDeferredShader(gDeferredSunProgram, 0, target); mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); glClearColor(1,1,1,1); mDeferredLight.clear(GL_COLOR_BUFFER_BIT); @@ -9006,17 +9109,16 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target) gGL.popMatrix(); stop_glerror(); - // Done by callers... - // - //target->bindTarget(); - // clear color buffer here - zeroing alpha (glow) is important or it will accumulate against sky - //glClearColor(0,0,0,0); + target->bindTarget(); + + //clear color buffer here - zeroing alpha (glow) is important or it will accumulate against sky + //glClearColor(0,1,0,0); //target->clear(GL_COLOR_BUFFER_BIT); if (RenderDeferredAtmospheric) { //apply sunlight contribution LLFastTimer ftm(FTM_ATMOSPHERICS); - bindDeferredShader(gDeferredSoftenProgram); + bindDeferredShader(gDeferredSoftenProgram,0,target); { LLGLDepthTest depth(GL_FALSE); LLGLDisable blend(GL_BLEND); @@ -9077,7 +9179,7 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target) LLVertexBuffer::unbind(); { - bindDeferredShader(gDeferredLightProgram); + bindDeferredShader(gDeferredLightProgram, 0, target); if (mCubeVB.isNull()) { @@ -9185,7 +9287,7 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target) if (!spot_lights.empty()) { LLGLDepthTest depth(GL_TRUE, GL_FALSE); - bindDeferredShader(gDeferredSpotLightProgram); + bindDeferredShader(gDeferredSpotLightProgram,0, target); mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX); @@ -9266,7 +9368,7 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target) if (count == max_count || fullscreen_lights.empty()) { U32 idx = count-1; - bindDeferredShader(gDeferredMultiLightProgram[idx]); + bindDeferredShader(gDeferredMultiLightProgram[idx],0, target); gDeferredMultiLightProgram[idx].uniform1i(LLShaderMgr::MULTI_LIGHT_COUNT, count); gDeferredMultiLightProgram[idx].uniform4fv(LLShaderMgr::MULTI_LIGHT, count, (GLfloat*) light); gDeferredMultiLightProgram[idx].uniform4fv(LLShaderMgr::MULTI_LIGHT_COL, count, (GLfloat*) col); @@ -9280,7 +9382,7 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target) unbindDeferredShader(gDeferredMultiLightProgram[0]); - bindDeferredShader(gDeferredMultiSpotLightProgram); + bindDeferredShader(gDeferredMultiSpotLightProgram, 0, target); gDeferredMultiSpotLightProgram.enableTexture(LLShaderMgr::DEFERRED_PROJECTION); @@ -9420,8 +9522,7 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target) popRenderTypeMask(); } - // Done by callers for flexibility - //target->flush(); + target->flush(); } void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep) @@ -9733,17 +9834,12 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) if (LLPipeline::sRenderDeferred) { gGL.setColorMask(true, true); - renderGeomDeferred(camera); - gPipeline.mDeferredScreen.flush(); - if(LLRenderTarget::sUseFBO) - { - LLRenderTarget::copyContentsToFramebuffer(gPipeline.mDeferredScreen, 0, 0, gPipeline.mDeferredScreen.getWidth(), - gPipeline.mDeferredScreen.getHeight(), 0, 0, - gPipeline.mDeferredScreen.getWidth(), - gPipeline.mDeferredScreen.getHeight(), - GL_DEPTH_BUFFER_BIT, GL_NEAREST); - } - renderDeferredLightingToRT(&mWaterRef); + gPipeline.mDeferredScreen.bindTarget(); + glClearColor(0,0,0,0); + gPipeline.mDeferredScreen.clear(); + + LLGLDepthTest d(GL_FALSE,GL_FALSE); + renderGeomDeferred(camera); } else #endif @@ -9754,6 +9850,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) gPipeline.popRenderTypeMask(); } + gGL.setColorMask(true, false); gPipeline.pushRenderTypeMask(); clearRenderTypeMask(LLPipeline::RENDER_TYPE_WATER, @@ -9795,26 +9892,30 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) #if MATERIALS_IN_REFLECTIONS if (LLPipeline::sRenderDeferred) { + LLGLDepthTest d(GL_FALSE,GL_FALSE); renderGeomDeferred(camera); - gPipeline.mDeferredScreen.flush(); - if(LLRenderTarget::sUseFBO) - { - LLRenderTarget::copyContentsToFramebuffer(gPipeline.mDeferredScreen, 0, 0, gPipeline.mDeferredScreen.getWidth(), - gPipeline.mDeferredScreen.getHeight(), 0, 0, - gPipeline.mDeferredScreen.getWidth(), - gPipeline.mDeferredScreen.getHeight(), - GL_DEPTH_BUFFER_BIT, GL_NEAREST); - } - renderDeferredLightingToRT(&mWaterRef); } else #endif { renderGeom(camera); - } + } } } +#if MATERIALS_IN_REFLECTIONS + if (LLPipeline::sRenderDeferred) + { + gPipeline.mDeferredScreen.flush(); + gPipeline.mWaterRef.copyContents(gPipeline.mDeferredScreen, + 0, 0, gPipeline.mDeferredScreen.getWidth(), gPipeline.mDeferredScreen.getHeight(), + 0, 0, gPipeline.mWaterRef.getWidth(), gPipeline.mWaterRef.getHeight(), + 0, GL_NEAREST); + mWaterRef.flush(); + renderDeferredLightingToRT(&mWaterRef); + } +#endif + gPipeline.popRenderTypeMask(); } glCullFace(GL_BACK); @@ -9849,10 +9950,12 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) LLViewerCamera::updateFrustumPlanes(camera); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + LLColor4& col = LLDrawPoolWater::sWaterFogColor; glClearColor(col.mV[0], col.mV[1], col.mV[2], 0.f); mWaterDis.bindTarget(); LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WATER1; + mWaterDis.getViewport(gGLViewport); if (!LLPipeline::sUnderWaterRender || LLDrawPoolWater::sNeedsReflectionUpdate) @@ -9868,33 +9971,44 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) gGL.setColorMask(true, true); mWaterDis.clear(); + gGL.setColorMask(true, false); #if MATERIALS_IN_REFLECTIONS if (LLPipeline::sRenderDeferred) - { + { + + gPipeline.mDeferredScreen.bindTarget(); + gGL.setColorMask(true, true); + glClearColor(1,0,1,0); + gPipeline.mDeferredScreen.clear(); + renderGeomDeferred(camera); + gPipeline.mDeferredScreen.flush(); - if(LLRenderTarget::sUseFBO) - { - LLRenderTarget::copyContentsToFramebuffer(gPipeline.mDeferredScreen, 0, 0, gPipeline.mDeferredScreen.getWidth(), - gPipeline.mDeferredScreen.getHeight(), 0, 0, - gPipeline.mDeferredScreen.getWidth(), - gPipeline.mDeferredScreen.getHeight(), - GL_DEPTH_BUFFER_BIT, GL_NEAREST); - } - renderDeferredLightingToRT(&mWaterDis); + + mWaterDis.copyContents(gPipeline.mDeferredScreen, + 0, 0, gPipeline.mDeferredScreen.getWidth(), gPipeline.mDeferredScreen.getHeight(), + 0, 0, gPipeline.mWaterDis.getWidth(), gPipeline.mWaterDis.getHeight(), + 0, GL_NEAREST); + mWaterDis.flush(); } else #endif { - gGL.setColorMask(true, false); - renderGeom(camera); + renderGeom(camera); } - + +#if MATERIALS_IN_REFLECTIONS + if (LLPipeline::sRenderDeferred) + { + renderDeferredLightingToRT(&mWaterDis); + } +#endif } - LLPipeline::sUnderWaterRender = FALSE; mWaterDis.flush(); + LLPipeline::sUnderWaterRender = FALSE; + } last_update = LLDrawPoolWater::sNeedsReflectionUpdate && LLDrawPoolWater::sNeedsDistortionUpdate; diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 36b293b998..8764616fba 100755 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -281,9 +281,10 @@ public: void renderGeom(LLCamera& camera, BOOL forceVBOUpdate = FALSE); void renderGeomDeferred(LLCamera& camera); + void renderGeomDeferredToRT(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 bindDeferredShader(LLGLSLShader& shader, U32 light_index = 0, LLRenderTarget* alternative_target = NULL, U32 noise_map = 0xFFFFFFFF); void setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep); void unbindDeferredShader(LLGLSLShader& shader); |