Permalink
Browse files

Run depth-only pass before shading.

  • Loading branch information...
1 parent 4afee25 commit f1d1769dd102a5d1f32f86a2c0b0173fc1a19f73 @gimhael gimhael committed Feb 1, 2016
@@ -828,7 +828,8 @@ enum renderDrawSurfaces_e
DRAWSURFACES_ALL = DRAWSURFACES_WORLD | DRAWSURFACES_ALL_ENTITIES
};
-static void RB_RenderDrawSurfaces( bool opaque, renderDrawSurfaces_e drawSurfFilter )
+static void RB_RenderDrawSurfaces( shaderSort_t fromSort, shaderSort_t toSort,
+ renderDrawSurfaces_e drawSurfFilter )
{
trRefEntity_t *entity, *oldEntity;
shader_t *shader, *oldShader;
@@ -837,6 +838,7 @@ static void RB_RenderDrawSurfaces( bool opaque, renderDrawSurfaces_e drawSurfFil
bool depthRange, oldDepthRange;
int i;
drawSurf_t *drawSurf;
+ int lastSurf;
GLimp_LogComment( "--- RB_RenderDrawSurfaces ---\n" );
@@ -849,8 +851,11 @@ static void RB_RenderDrawSurfaces( bool opaque, renderDrawSurfaces_e drawSurfFil
depthRange = false;
backEnd.currentLight = nullptr;
- for ( i = 0, drawSurf = backEnd.viewParms.drawSurfs; i < backEnd.viewParms.numDrawSurfs; i++, drawSurf++ )
+ lastSurf = backEnd.viewParms.firstDrawSurf[ Util::ordinal(toSort) + 1 ];
+ for ( i = backEnd.viewParms.firstDrawSurf[ Util::ordinal(fromSort) ]; i < lastSurf; i++ )
{
+ drawSurf = &backEnd.viewParms.drawSurfs[ i ];
+
// update locals
entity = drawSurf->entity;
shader = tr.sortedShaders[ drawSurf->shaderNum() ];
@@ -868,23 +873,6 @@ static void RB_RenderDrawSurfaces( bool opaque, renderDrawSurfaces_e drawSurfFil
continue;
}
- if ( opaque )
- {
- // skip all translucent surfaces that don't matter for this pass
- if ( shader->sort > Util::ordinal(shaderSort_t::SS_OPAQUE) )
- {
- break;
- }
- }
- else
- {
- // skip all opaque surfaces that don't matter for this pass
- if ( shader->sort <= Util::ordinal(shaderSort_t::SS_OPAQUE) )
- {
- continue;
- }
- }
-
if ( entity == oldEntity && shader == oldShader && lightmapNum == oldLightmapNum && fogNum == oldFogNum )
{
// fast path, same as previous sort
@@ -4420,22 +4408,24 @@ static void RB_RenderView()
startTime = ri.Milliseconds();
}
+ RB_RenderDrawSurfaces( shaderSort_t::SS_DEPTH, shaderSort_t::SS_DEPTH, DRAWSURFACES_ALL );
+
if( tr.refdef.blurVec[0] != 0.0f ||
tr.refdef.blurVec[1] != 0.0f ||
tr.refdef.blurVec[2] != 0.0f )
{
// draw everything that is not the gun
- RB_RenderDrawSurfaces( true, DRAWSURFACES_ALL_FAR );
+ RB_RenderDrawSurfaces( shaderSort_t::SS_ENVIRONMENT_FOG, shaderSort_t::SS_OPAQUE, DRAWSURFACES_ALL_FAR );
RB_RenderMotionBlur();
// draw the gun and other "near" stuff
- RB_RenderDrawSurfaces( true, DRAWSURFACES_NEAR_ENTITIES );
+ RB_RenderDrawSurfaces( shaderSort_t::SS_ENVIRONMENT_FOG, shaderSort_t::SS_OPAQUE, DRAWSURFACES_NEAR_ENTITIES );
}
else
{
// draw everything that is opaque
- RB_RenderDrawSurfaces( true, DRAWSURFACES_ALL );
+ RB_RenderDrawSurfaces( shaderSort_t::SS_ENVIRONMENT_FOG, shaderSort_t::SS_OPAQUE, DRAWSURFACES_ALL );
}
if ( r_ssao->integer && GLEW_ARB_texture_gather ) {
@@ -4464,7 +4454,7 @@ static void RB_RenderView()
RB_RenderGlobalFog();
// draw everything that is translucent
- RB_RenderDrawSurfaces( false, DRAWSURFACES_ALL );
+ RB_RenderDrawSurfaces( shaderSort_t::SS_ENVIRONMENT_NOFOG, shaderSort_t::SS_POST_PROCESS, DRAWSURFACES_ALL );
GL_CheckErrors();
// render bloom post process effect
@@ -728,6 +728,8 @@ static inline void halfToFloat( const f16vec4_t in, vec4_t out )
SS_BAD,
SS_PORTAL, // mirrors, portals, viewscreens
+ SS_DEPTH, // depth pre-pass
+
SS_ENVIRONMENT_FOG, // sky
SS_OPAQUE, // opaque
@@ -758,7 +760,9 @@ static inline void halfToFloat( const f16vec4_t in, vec4_t out )
SS_ALMOST_NEAREST, // gun smoke puffs
SS_NEAREST, // blood blobs
- SS_POST_PROCESS
+ SS_POST_PROCESS,
+
+ SS_NUM_SORTS
};
struct shaderTable_t
@@ -1227,6 +1231,7 @@ static inline void halfToFloat( const f16vec4_t in, vec4_t out )
int index;
} altShader[ MAX_ALTSHADERS ]; // state-based remapping; note that index 0 is unused
+ struct shader_t *depthShader;
struct shader_t *next;
};
@@ -1479,6 +1484,7 @@ static inline void halfToFloat( const f16vec4_t in, vec4_t out )
int numDrawSurfs;
struct drawSurf_t *drawSurfs;
+ int firstDrawSurf[ Util::ordinal(shaderSort_t::SS_NUM_SORTS) + 1 ];
int numInteractions;
struct interaction_t *interactions;
@@ -1699,6 +1699,10 @@ void R_AddDrawSurf( surfaceType_t *surface, shader_t *shader, int lightmapNum, i
drawSurf->setSort( shader->sortedIndex, lightmapNum, entityNum, fogNum, index );
tr.refdef.numDrawSurfs++;
+
+ if ( shader->depthShader != nullptr ) {
+ R_AddDrawSurf( surface, shader->depthShader, 0, 0 );
+ }
}
/*
@@ -1708,9 +1712,9 @@ R_SortDrawSurfs
*/
static void R_SortDrawSurfs()
{
- drawSurf_t *drawSurf;
- shader_t *shader;
- int i;
+ drawSurf_t *drawSurf;
+ shader_t *shader;
+ int i, sort;
// it is possible for some views to not have any surfaces
if ( tr.viewParms.numDrawSurfs < 1 )
@@ -1747,23 +1751,35 @@ static void R_SortDrawSurfs()
return a.sort < b.sort;
} );
- // check for any pass through drawing, which
- // may cause another view to be rendered first
- for ( i = 0, drawSurf = tr.viewParms.drawSurfs; i < tr.viewParms.numDrawSurfs; i++, drawSurf++ )
+ // compute the offsets of the first surface of each SS_* type
+ sort = Util::ordinal( shaderSort_t::SS_BAD ) - 1;
+ for ( i = 0; i < tr.viewParms.numDrawSurfs; i++ )
{
+ drawSurf = &tr.viewParms.drawSurfs[ i ];
shader = tr.sortedShaders[ drawSurf->shaderNum() ];
- if ( shader->sort > Util::ordinal(shaderSort_t::SS_PORTAL) )
- {
- break;
- }
-
// no shader should ever have this sort type
if ( shader->sort == Util::ordinal(shaderSort_t::SS_BAD) )
{
ri.Error(errorParm_t::ERR_DROP, "Shader '%s'with sort == SS_BAD", shader->name );
}
+ while ( sort < Util::ordinal( shaderSort_t::SS_NUM_SORTS ) - 1 && shader->sort > sort ) {
+ tr.viewParms.firstDrawSurf[ ++sort ] = i;
+ }
+ }
+ while ( sort < Util::ordinal( shaderSort_t::SS_NUM_SORTS ) ) {
+ tr.viewParms.firstDrawSurf[ ++sort ] = tr.viewParms.numDrawSurfs;
+ }
+
+ // check for any pass through drawing, which
+ // may cause another view to be rendered first
+ for ( i = tr.viewParms.firstDrawSurf[ Util::ordinal(shaderSort_t::SS_PORTAL) ];
+ i < tr.viewParms.firstDrawSurf[ Util::ordinal(shaderSort_t::SS_PORTAL) + 1 ]; i++ )
+ {
+ drawSurf = &tr.viewParms.drawSurfs[ i ];
+ shader = tr.sortedShaders[ drawSurf->shaderNum() ];
+
// if the mirror was completely clipped away, we may need to check another surface
if ( R_MirrorViewBySurface( drawSurf ) )
{
@@ -4439,6 +4439,55 @@ static shader_t *FinishShader()
ret = GeneratePermanentShader();
+ // generate depth-only shader if necessary
+ if( !shader.isSky &&
+ shader.numStages > 0 &&
+ (stages[0].stateBits & GLS_DEPTHMASK_TRUE) &&
+ !(stages[0].stateBits & GLS_DEPTHFUNC_EQUAL) &&
+ !(shader.type == shaderType_t::SHADER_2D) &&
+ !shader.polygonOffset ) {
+ // keep only the first stage
+ stages[1].active = false;
+ shader.numStages = 1;
+ strcat(shader.name, "$depth");
+
+ if( stages[0].stateBits & GLS_ATEST_BITS ) {
+ // alpha test requires a custom depth shader
+ shader.sort = Util::ordinal( shaderSort_t::SS_DEPTH );
+ stages[0].stateBits &= ~GLS_SRCBLEND_BITS & ~GLS_DSTBLEND_BITS;
+ stages[0].stateBits |= GLS_COLORMASK_BITS;
+ stages[0].type = stageType_t::ST_COLORMAP;
+
+ ret->depthShader = GeneratePermanentShader();
+ } else if ( shader.cullType == 0 &&
+ shader.numDeforms == 0 &&
+ tr.defaultShader ) {
+ // can use the default depth shader
+ ret->depthShader = tr.defaultShader->depthShader;
+ } else {
+ // requires a custom depth shader, but can skip
+ // the texturing
+ shader.sort = Util::ordinal( shaderSort_t::SS_DEPTH );
+ stages[0].stateBits &= ~GLS_SRCBLEND_BITS & ~GLS_DSTBLEND_BITS;
+ stages[0].stateBits |= GLS_COLORMASK_BITS;
+ stages[0].type = stageType_t::ST_COLORMAP;
+
+ stages[0].bundle[0].image[0] = tr.whiteImage;
+ stages[0].bundle[0].numTexMods = 0;
+ stages[0].tcGen_Environment = false;
+ stages[0].tcGen_Lightmap = false;
+ stages[0].rgbGen = colorGen_t::CGEN_IDENTITY;
+ stages[0].alphaGen = alphaGen_t::AGEN_IDENTITY;
+
+ ret->depthShader = GeneratePermanentShader();
+ }
+ // disable depth writes in the main pass
+ ret->stages[0]->stateBits &= ~GLS_DEPTHMASK_TRUE;
+ } else {
+ ret->depthShader = NULL;
+ }
+
+ // load all altShaders recursively
for ( i = 1; i < MAX_ALTSHADERS; ++i )
{
if ( ret->altShader[ i ].name )
@@ -5090,6 +5139,10 @@ void R_ShaderList_f()
{
str += "SS_PORTAL ";
}
+ else if ( shader->sort == Util::ordinal(shaderSort_t::SS_DEPTH) )
+ {
+ str += "SS_DEPTH ";
+ }
else if ( shader->sort == Util::ordinal(shaderSort_t::SS_ENVIRONMENT_FOG) )
{
str += "SS_ENVIRONMENT_FOG ";

0 comments on commit f1d1769

Please sign in to comment.