From 9915d6ea5695929de3de94fe2e9a51c77bfc3632 Mon Sep 17 00:00:00 2001 From: James Canete Date: Tue, 1 May 2012 21:53:24 +0000 Subject: [PATCH] Add r_depthPrepass. --- reaction/Reaction-ChangeLog | 1 + reaction/code/renderergl2/tr_backend.c | 115 +++++++++++++++++++++++++ reaction/code/renderergl2/tr_init.c | 2 + reaction/code/renderergl2/tr_local.h | 2 + reaction/code/renderergl2/tr_shade.c | 57 +++++++++++- 5 files changed, 175 insertions(+), 2 deletions(-) diff --git a/reaction/Reaction-ChangeLog b/reaction/Reaction-ChangeLog index 3f34089e..88f272b9 100644 --- a/reaction/Reaction-ChangeLog +++ b/reaction/Reaction-ChangeLog @@ -1,3 +1,4 @@ +- Add r_depthPrepass. - Improve parallax mapping - Add AVG_MAP, BLACK_LEVEL, and WHITE_LEVEL defines to tonemap shader - Fix a bug in fragment shader tangent space calculations diff --git a/reaction/code/renderergl2/tr_backend.c b/reaction/code/renderergl2/tr_backend.c index 72439a47..f2eb6635 100644 --- a/reaction/code/renderergl2/tr_backend.c +++ b/reaction/code/renderergl2/tr_backend.c @@ -595,7 +595,122 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) { fbo = glState.currentFBO; + if (r_depthPrepass->integer) + { + qboolean skip = qfalse; + + // do a depth fill with just the static vbos + backEnd.depthFill = qtrue; + + oldEntityNum = -1; + backEnd.currentEntity = &tr.worldEntity; + oldShader = NULL; + oldFogNum = -1; + oldDepthRange = qfalse; + wasCrosshair = qfalse; + oldDlighted = qfalse; + oldPshadowed = qfalse; + oldSort = -1; + depthRange = qfalse; + + qglColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + + for (i = 0, drawSurf = drawSurfs ; i < numDrawSurfs ; i++, drawSurf++) { + if ( drawSurf->sort == oldSort ) { + // fast path, same as previous sort + if (!skip) + rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface ); + continue; + } + oldSort = drawSurf->sort; + R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlighted, &pshadowed ); + + skip = qfalse; + if (entityNum != ENTITYNUM_WORLD) + { + skip = qtrue; + continue; + } + + if (ShaderRequiresCPUDeforms(shader)) + { + skip = qtrue; + continue; + } + + if (shader->sort != SS_OPAQUE) + { + skip = qtrue; + continue; + } + + { + int stage; + shaderStage_t *pStage = NULL; + + for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ ) + { + if (shader->stages[stage]) + { + pStage = shader->stages[stage]; + break; + } + } + + if (pStage && (pStage->stateBits & GLS_ATEST_BITS) != 0) + { + skip = qtrue; + continue; + } + } + + // + // change the tess parameters if needed + // a "entityMergable" shader is a shader that can have surfaces from seperate + // entities merged into a single batch, like smoke and blood puff sprites + if (shader != oldShader || fogNum != oldFogNum || dlighted != oldDlighted || pshadowed != oldPshadowed + || ( entityNum != oldEntityNum && !shader->entityMergable ) ) { + if (oldShader != NULL) { + RB_EndSurface(); + } + RB_BeginSurface( shader, fogNum ); + backEnd.pc.c_surfBatches++; + oldShader = shader; + oldFogNum = fogNum; + oldDlighted = dlighted; + oldPshadowed = pshadowed; + } + + // + // change the modelview matrix if needed + // + if ( entityNum != oldEntityNum ) { + backEnd.currentEntity = &tr.worldEntity; + backEnd.refdef.floatTime = originalTime; + backEnd.or = backEnd.viewParms.world; + // we have to reset the shaderTime as well otherwise image animations on + // the world (like water) continue with the wrong frame + tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset; + + GL_SetModelviewMatrix( backEnd.or.modelMatrix ); + + oldEntityNum = entityNum; + } + + // add the triangles for this surface + rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface ); + } + + // draw the contents of the last shader batch + if (oldShader != NULL) { + RB_EndSurface(); + } + + qglColorMask(!backEnd.colorMask[0], !backEnd.colorMask[1], !backEnd.colorMask[2], !backEnd.colorMask[3]); + } + // draw everything + backEnd.depthFill = qfalse; oldEntityNum = -1; backEnd.currentEntity = &tr.worldEntity; oldShader = NULL; diff --git a/reaction/code/renderergl2/tr_init.c b/reaction/code/renderergl2/tr_init.c index 464bd067..286de910 100644 --- a/reaction/code/renderergl2/tr_init.c +++ b/reaction/code/renderergl2/tr_init.c @@ -113,6 +113,7 @@ cvar_t *r_toneMap; cvar_t *r_autoExposure; cvar_t *r_srgb; +cvar_t *r_depthPrepass; cvar_t *r_normalMapping; cvar_t *r_specularMapping; @@ -1135,6 +1136,7 @@ void R_Register( void ) r_cameraExposure = ri.Cvar_Get( "r_cameraExposure", "0", CVAR_CHEAT ); r_srgb = ri.Cvar_Get( "r_srgb", "0", CVAR_ARCHIVE | CVAR_LATCH ); + r_depthPrepass = ri.Cvar_Get( "r_depthPrepass", "1", CVAR_ARCHIVE | CVAR_LATCH ); r_normalMapping = ri.Cvar_Get( "r_normalMapping", "1", CVAR_ARCHIVE | CVAR_LATCH ); r_specularMapping = ri.Cvar_Get( "r_specularMapping", "1", CVAR_ARCHIVE | CVAR_LATCH ); diff --git a/reaction/code/renderergl2/tr_local.h b/reaction/code/renderergl2/tr_local.h index 84df8139..36ca7848 100644 --- a/reaction/code/renderergl2/tr_local.h +++ b/reaction/code/renderergl2/tr_local.h @@ -1697,6 +1697,7 @@ typedef struct { FBO_t *last2DFBO; qboolean colorMask[4]; qboolean framePostProcessed; + qboolean depthFill; } backEndState_t; /* @@ -2005,6 +2006,7 @@ extern cvar_t *r_autoExposure; extern cvar_t *r_cameraExposure; extern cvar_t *r_srgb; +extern cvar_t *r_depthPrepass; extern cvar_t *r_normalMapping; extern cvar_t *r_specularMapping; diff --git a/reaction/code/renderergl2/tr_shade.c b/reaction/code/renderergl2/tr_shade.c index ef989fb7..3b375daf 100644 --- a/reaction/code/renderergl2/tr_shade.c +++ b/reaction/code/renderergl2/tr_shade.c @@ -1036,7 +1036,37 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) break; } - if (pStage->glslShaderGroup) + if (backEnd.depthFill) + { + if (pStage->glslShaderGroup) + { + int index = 0; + + if (backEnd.currentEntity && backEnd.currentEntity != &tr.worldEntity) + { + index |= LIGHTDEF_ENTITY; + } + + sp = &pStage->glslShaderGroup[index]; + } + else + { + int shaderAttribs = 0; + + if (tess.shader->numDeforms && !ShaderRequiresCPUDeforms(tess.shader)) + { + shaderAttribs |= GENERICDEF_USE_DEFORM_VERTEXES; + } + + if (glState.vertexAttribsInterpolation > 0.0f && backEnd.currentEntity && backEnd.currentEntity != &tr.worldEntity) + { + shaderAttribs |= GENERICDEF_USE_VERTEX_ANIMATION; + } + + sp = &tr.genericShader[shaderAttribs]; + } + } + else if (pStage->glslShaderGroup) { int index = pStage->glslShaderIndex; @@ -1151,7 +1181,11 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) // // do multitexture // - if ( pStage->glslShaderGroup ) + if ( backEnd.depthFill ) + { + GL_BindToTMU( tr.whiteImage, 0 ); + } + else if ( pStage->glslShaderGroup ) { int i; @@ -1390,6 +1424,25 @@ void RB_StageIteratorGeneric( void ) return; } + // + // render depth if in depthfill mode + // + if (backEnd.depthFill) + { + RB_IterateStagesGeneric( input ); + + // + // reset polygon offset + // + if ( input->shader->polygonOffset ) + { + qglDisable( GL_POLYGON_OFFSET_FILL ); + } + + return; + } + + // // // call shader function //