NORSPEC-291 WIP added underwater deferred program and more reflection pass work

master
Graham Linden 2013-07-12 13:01:31 -07:00
parent b588865f3f
commit 5efee00a83
6 changed files with 315 additions and 55 deletions

View File

@ -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
}

View File

@ -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)
{

View File

@ -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();
@ -1640,6 +1643,20 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
success = gDeferredWaterProgram.createShader(NULL, &mWaterUniforms);
}
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";

View File

@ -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;

View File

@ -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;

View File

@ -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);