From 2307a94d53815508c29df0a189178659c155dbb7 Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Sun, 11 May 2014 14:36:51 +0200 Subject: [PATCH] Added r_forceShadowMapsOnAlphaTestedSurfaces 1 --- neo/renderer/tr_backend_draw.cpp | 134 +++++++++++++++++++++++-- neo/renderer/tr_frontend_addmodels.cpp | 10 +- 2 files changed, 133 insertions(+), 11 deletions(-) diff --git a/neo/renderer/tr_backend_draw.cpp b/neo/renderer/tr_backend_draw.cpp index 09b0b895..08d1316e 100644 --- a/neo/renderer/tr_backend_draw.cpp +++ b/neo/renderer/tr_backend_draw.cpp @@ -2237,13 +2237,15 @@ static void RB_ShadowMapPass( const drawSurf_t* drawSurfs, const viewLight_t* vL uint64 glState = 0; - GL_PolygonOffset( r_shadowPolygonFactor.GetFloat(), -r_shadowPolygonOffset.GetFloat() ); + //GL_PolygonOffset( r_shadowPolygonFactor.GetFloat(), -r_shadowPolygonOffset.GetFloat() ); // the actual stencil func will be set in the draw code, but we need to make sure it isn't // disabled here, and that the value will get reset for the interactions without looking // like a no-change-required - GL_State( glState | GLS_POLYGON_OFFSET ); + //GL_State( glState | GLS_POLYGON_OFFSET ); + + GL_State( GLS_DEFAULT ); // Two Sided Stencil reduces two draw calls to one for slightly faster shadows GL_Cull( CT_TWO_SIDED ); @@ -2591,7 +2593,6 @@ static void RB_ShadowMapPass( const drawSurf_t* drawSurfs, const viewLight_t* vL if( drawSurf->space != backEnd.currentSpace ) { - idRenderMatrix modelRenderMatrix; idRenderMatrix::Transpose( *( idRenderMatrix* )drawSurf->space->modelMatrix, modelRenderMatrix ); @@ -2631,23 +2632,136 @@ static void RB_ShadowMapPass( const drawSurf_t* drawSurfs, const viewLight_t* vL backEnd.currentSpace = drawSurf->space; } - if( drawSurf->jointCache ) + bool didDraw = false; + + const idMaterial* shader = drawSurf->material; + + // get the expressions for conditionals / color / texcoords + const float* regs = drawSurf->shaderRegisters; + idVec4 color( 0, 0, 0, 1 ); + + uint64 surfGLState = 0; + + // set polygon offset if necessary + if( shader->TestMaterialFlag( MF_POLYGONOFFSET ) ) { - renderProgManager.BindShader_DepthSkinned(); - } - else - { - renderProgManager.BindShader_Depth(); + surfGLState |= GLS_POLYGON_OFFSET; + GL_PolygonOffset( r_offsetFactor.GetFloat(), r_offsetUnits.GetFloat() * shader->GetPolygonOffset() ); } - RB_DrawElementsWithCounters( drawSurf ); +#if 1 + if( shader->Coverage() == MC_PERFORATED ) + { + // perforated surfaces may have multiple alpha tested stages + for( int stage = 0; stage < shader->GetNumStages(); stage++ ) + { + const shaderStage_t* pStage = shader->GetStage( stage ); + + if( !pStage->hasAlphaTest ) + { + continue; + } + + // check the stage enable condition + if( regs[ pStage->conditionRegister ] == 0 ) + { + continue; + } + + // if we at least tried to draw an alpha tested stage, + // we won't draw the opaque surface + didDraw = true; + + // set the alpha modulate + color[3] = regs[ pStage->color.registers[3] ]; + + // skip the entire stage if alpha would be black + if( color[3] <= 0.0f ) + { + continue; + } + + uint64 stageGLState = surfGLState; + + // set privatePolygonOffset if necessary + if( pStage->privatePolygonOffset ) + { + GL_PolygonOffset( r_offsetFactor.GetFloat(), r_offsetUnits.GetFloat() * pStage->privatePolygonOffset ); + stageGLState |= GLS_POLYGON_OFFSET; + } + + GL_Color( color ); + +#ifdef USE_CORE_PROFILE + GL_State( stageGLState ); + idVec4 alphaTestValue( regs[ pStage->alphaTestRegister ] ); + SetFragmentParm( RENDERPARM_ALPHA_TEST, alphaTestValue.ToFloatPtr() ); +#else + GL_State( stageGLState | GLS_ALPHATEST_FUNC_GREATER | GLS_ALPHATEST_MAKE_REF( idMath::Ftob( 255.0f * regs[ pStage->alphaTestRegister ] ) ) ); +#endif + + if( drawSurf->jointCache ) + { + renderProgManager.BindShader_TextureVertexColorSkinned(); + } + else + { + renderProgManager.BindShader_TextureVertexColor(); + } + + RB_SetVertexColorParms( SVC_IGNORE ); + + // bind the texture + GL_SelectTexture( 0 ); + pStage->texture.image->Bind(); + + // set texture matrix and texGens + RB_PrepareStageTexturing( pStage, drawSurf ); + + // must render with less-equal for Z-Cull to work properly + assert( ( GL_GetCurrentState() & GLS_DEPTHFUNC_BITS ) == GLS_DEPTHFUNC_LESS ); + + // draw it + RB_DrawElementsWithCounters( drawSurf ); + + // clean up + RB_FinishStageTexturing( pStage, drawSurf ); + + // unset privatePolygonOffset if necessary + if( pStage->privatePolygonOffset ) + { + GL_PolygonOffset( r_offsetFactor.GetFloat(), r_offsetUnits.GetFloat() * shader->GetPolygonOffset() ); + } + } + } +#endif + + if( !didDraw ) + { + if( drawSurf->jointCache ) + { + renderProgManager.BindShader_DepthSkinned(); + } + else + { + renderProgManager.BindShader_Depth(); + } + + RB_DrawElementsWithCounters( drawSurf ); + } } // cleanup the shadow specific rendering state Framebuffer::BindNull(); + renderProgManager.Unbind(); + GL_State( GLS_DEFAULT ); GL_Cull( CT_FRONT_SIDED ); + +#ifdef USE_CORE_PROFILE + SetFragmentParm( RENDERPARM_ALPHA_TEST, vec4_zero.ToFloatPtr() ); +#endif } /* diff --git a/neo/renderer/tr_frontend_addmodels.cpp b/neo/renderer/tr_frontend_addmodels.cpp index 6c339c49..55c45a7d 100644 --- a/neo/renderer/tr_frontend_addmodels.cpp +++ b/neo/renderer/tr_frontend_addmodels.cpp @@ -41,6 +41,9 @@ idCVar r_useShadowPreciseInsideTest( "r_useShadowPreciseInsideTest", "1", CVAR_R idCVar r_cullDynamicShadowTriangles( "r_cullDynamicShadowTriangles", "1", CVAR_RENDERER | CVAR_BOOL, "cull occluder triangles that are outside the light frustum so they do not contribute to the dynamic shadow volume" ); idCVar r_cullDynamicLightTriangles( "r_cullDynamicLightTriangles", "1", CVAR_RENDERER | CVAR_BOOL, "cull surface triangles that are outside the light frustum so they do not get rendered for interactions" ); idCVar r_forceShadowCaps( "r_forceShadowCaps", "0", CVAR_RENDERER | CVAR_BOOL, "0 = skip rendering shadow caps if view is outside shadow volume, 1 = always render shadow caps" ); +// RB begin +idCVar r_forceShadowMapsOnAlphaTestedSurfaces( "r_forceShadowMapsOnAlphaTestedSurfaces", "1", CVAR_RENDERER | CVAR_BOOL, "0 = same shadowing as with stencil shadows, 1 = ignore noshadows for alpha tested materials" ); +// RB end static const float CHECK_BOUNDS_EPSILON = 1.0f; @@ -912,7 +915,7 @@ void R_AddSingleModel( viewEntity_t* vEntity ) // surface shadows //-------------------------- - if( !shader->SurfaceCastsShadow() ) + if( !shader->SurfaceCastsShadow() && !( r_useShadowMapping.GetBool() && r_forceShadowMapsOnAlphaTestedSurfaces.GetBool() && shader->Coverage() == MC_PERFORATED ) ) { continue; } @@ -1000,6 +1003,11 @@ void R_AddSingleModel( viewEntity_t* vEntity ) shadowDrawSurf->renderZFail = 0; //shadowDrawSurf->shaderRegisters = baseDrawSurf->shaderRegisters; + if( shader->Coverage() == MC_PERFORATED ) + { + R_SetupDrawSurfShader( shadowDrawSurf, shader, renderEntity ); + } + R_SetupDrawSurfJoints( shadowDrawSurf, tri, shader ); // determine which linked list to add the shadow surface to