Skip to content

Commit 4fa3b84

Browse files
committed
Generate skybrush material
Generate a material for skybrushes and use it with the stencil buffer to prevent material system from rendering stuff over the skybox which would be normally culled by the BSP.
1 parent e98fbad commit 4fa3b84

File tree

6 files changed

+129
-28
lines changed

6 files changed

+129
-28
lines changed

src/engine/renderer/Material.cpp

Lines changed: 73 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -792,7 +792,7 @@ void MaterialSystem::GenerateWorldMaterialsBuffer() {
792792
uint32_t* materialsData = materialsSSBO.MapBufferRange( offset );
793793
memset( materialsData, 0, offset * sizeof( uint32_t ) );
794794

795-
for ( uint32_t materialPackID = 0; materialPackID < 3; materialPackID++ ) {
795+
for ( uint32_t materialPackID = 0; materialPackID < 4; materialPackID++ ) {
796796
for ( Material& material : materialPacks[materialPackID].materials ) {
797797

798798
for ( drawSurf_t* drawSurf : material.drawSurfs ) {
@@ -960,7 +960,7 @@ void MaterialSystem::GenerateWorldCommandBuffer() {
960960
}
961961

962962
shader = shader->remappedShader ? shader->remappedShader : shader;
963-
if ( shader->isSky || shader->isPortal ) {
963+
if ( shader->isPortal ) {
964964
continue;
965965
}
966966

@@ -1332,6 +1332,9 @@ void MaterialSystem::ProcessStage( drawSurf_t* drawSurf, shaderStage_t* pStage,
13321332
} else {
13331333
materialPack = 2;
13341334
}
1335+
if ( shader->isSky ) {
1336+
materialPack = 3;
1337+
}
13351338
uint32_t id = packIDs[materialPack];
13361339

13371340
// In surfaces with multiple stages each consecutive stage must be drawn after the previous stage,
@@ -1358,6 +1361,14 @@ void MaterialSystem::ProcessStage( drawSurf_t* drawSurf, shaderStage_t* pStage,
13581361
drawSurf->texturesDynamic[stage] = true;
13591362
}
13601363

1364+
if ( shader->isSky ) {
1365+
if ( std::find( skyShaders.begin(), skyShaders.end(), shader ) == skyShaders.end() ) {
1366+
skyShaders.emplace_back( shader );
1367+
}
1368+
1369+
material.skyShader = shader;
1370+
}
1371+
13611372
pStage->materialProcessor( &material, pStage, drawSurf );
13621373

13631374
std::vector<Material>& materials = materialPacks[materialPack].materials;
@@ -1433,8 +1444,7 @@ void MaterialSystem::GenerateWorldMaterials() {
14331444

14341445
drawSurf_t* drawSurf;
14351446
totalDrawSurfs = 0;
1436-
1437-
uint32_t packIDs[3] = { 0, 0, 0 };
1447+
uint32_t packIDs[4] = { 0, 0, 0, 0 };
14381448

14391449
for ( int i = 0; i < tr.refdef.numDrawSurfs; i++ ) {
14401450
drawSurf = &tr.refdef.drawSurfs[i];
@@ -1448,7 +1458,7 @@ void MaterialSystem::GenerateWorldMaterials() {
14481458
}
14491459

14501460
shader = shader->remappedShader ? shader->remappedShader : shader;
1451-
if ( shader->isSky || shader->isPortal ) {
1461+
if ( shader->isPortal ) {
14521462
continue;
14531463
}
14541464

@@ -1981,9 +1991,67 @@ void MaterialSystem::RenderMaterials( const shaderSort_t fromSort, const shaderS
19811991
continue;
19821992
}
19831993

1994+
// Use stencil buffer to avoid rendering stuff over the skybox that would normally be culled by the BSP
1995+
if ( backEnd.viewParms.portalLevel == 0 ) {
1996+
glEnable( GL_STENCIL_TEST );
1997+
glStencilMask( 0xff );
1998+
}
1999+
2000+
glStencilFunc( GL_EQUAL, backEnd.viewParms.portalLevel, 0xff );
2001+
glStencilOp( GL_KEEP, GL_KEEP, GL_INCR );
2002+
2003+
glState.glStateBitsMask = 0;
2004+
2005+
for ( Material& material : materialPacks[3].materials ) {
2006+
if ( material.skyShader == skyShader ) {
2007+
RenderMaterial( material, viewID );
2008+
renderedMaterials.emplace_back( &material );
2009+
}
2010+
}
2011+
2012+
glStencilFunc( GL_EQUAL, backEnd.viewParms.portalLevel + 1, 0xff );
2013+
glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
2014+
2015+
GL_State( GLS_DEPTHMASK_TRUE | GLS_DEPTHFUNC_ALWAYS );
2016+
glState.glStateBitsMask = GLS_COLORMASK_BITS | GLS_DEPTHMASK_TRUE | GLS_DEPTHFUNC_ALWAYS;
2017+
glDepthRange( 1.0, 1.0 );
2018+
2019+
for ( Material& material : materialPacks[3].materials ) {
2020+
if ( material.skyShader == skyShader ) {
2021+
RenderMaterial( material, viewID );
2022+
renderedMaterials.emplace_back( &material );
2023+
}
2024+
}
2025+
2026+
// Actually draw the skybox
19842027
tr.drawingSky = true;
19852028
Tess_Begin( Tess_StageIteratorSky, skyShader, nullptr, false, -1, 0, false );
19862029
Tess_End();
2030+
2031+
glStencilOp( GL_KEEP, GL_KEEP, GL_DECR );
2032+
2033+
glState.glStateBitsMask = 0;
2034+
GL_State( GLS_COLORMASK_BITS | GLS_DEPTHMASK_TRUE | GLS_DEPTHFUNC_ALWAYS );
2035+
glState.glStateBitsMask = GLS_COLORMASK_BITS | GLS_DEPTHMASK_TRUE | GLS_DEPTHFUNC_ALWAYS;
2036+
glDepthRange( 1.0, 1.0 );
2037+
2038+
for ( Material& material : materialPacks[3].materials ) {
2039+
if ( material.skyShader == skyShader ) {
2040+
RenderMaterial( material, viewID );
2041+
renderedMaterials.emplace_back( &material );
2042+
}
2043+
}
2044+
2045+
glStencilFunc( GL_EQUAL, backEnd.viewParms.portalLevel, 0xff );
2046+
glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
2047+
2048+
glState.glStateBitsMask = 0;
2049+
GL_State( GLS_DEFAULT );
2050+
glDepthRange( 0.0, 1.0 );
2051+
2052+
if ( backEnd.viewParms.portalLevel == 0 ) {
2053+
glDisable( GL_STENCIL_TEST );
2054+
}
19872055
}
19882056
}
19892057
}

src/engine/renderer/Material.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ struct Material {
110110
bool enableNormalMapping;
111111
bool enablePhysicalMapping;
112112

113+
shader_t* skyShader = nullptr;
114+
113115
cullType_t cullType;
114116

115117
bool usePolygonOffset = false;
@@ -124,7 +126,8 @@ struct Material {
124126

125127
bool operator==( const Material& other ) {
126128
return program == other.program && stateBits == other.stateBits && vbo == other.vbo && ibo == other.ibo
127-
&& cullType == other.cullType && usePolygonOffset == other.usePolygonOffset;
129+
&& cullType == other.cullType && usePolygonOffset == other.usePolygonOffset
130+
&& ( skyShader == nullptr || other.skyShader == nullptr || skyShader == other.skyShader );
128131
}
129132

130133
void AddTexture( Texture* texture ) {
@@ -237,12 +240,15 @@ class MaterialSystem {
237240
}
238241
};
239242

240-
MaterialPack materialPacks[3]{
243+
MaterialPack materialPacks[4] {
241244
{ shaderSort_t::SS_DEPTH, shaderSort_t::SS_DEPTH },
242245
{ shaderSort_t::SS_ENVIRONMENT_FOG, shaderSort_t::SS_OPAQUE },
243-
{ shaderSort_t::SS_ENVIRONMENT_NOFOG, shaderSort_t::SS_POST_PROCESS }
246+
{ shaderSort_t::SS_ENVIRONMENT_NOFOG, shaderSort_t::SS_POST_PROCESS },
247+
{ shaderSort_t::SS_BAD, shaderSort_t::SS_BAD }
244248
};
245249

250+
Material skyBrushMaterial;
251+
246252
bool frameStart = false;
247253

248254
void AddTexture( Texture* texture );
@@ -304,6 +310,7 @@ class MaterialSystem {
304310

305311
bool AddPortalSurface( uint32_t viewID, PortalSurface* portalSurfs );
306312

313+
void RenderMaterialPack( MaterialPack& materialPack, const uint32_t viewID );
307314
void RenderMaterial( Material& material, const uint32_t viewID );
308315
void UpdateFrameData();
309316
};

src/engine/renderer/tr_local.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,6 +1063,7 @@ enum class realtimeLightingRenderer_t { LEGACY, TILED };
10631063
ST_REFRACTIONMAP,
10641064
ST_DISPERSIONMAP,
10651065
ST_SKYBOXMAP,
1066+
ST_SKYBRUSHMAP,
10661067
ST_SCREENMAP, // 2d offscreen or portal rendering
10671068
ST_PORTALMAP,
10681069
ST_HEATHAZEMAP, // heatHaze post process effect
@@ -3446,6 +3447,7 @@ inline bool checkGLErrors()
34463447
void Render_lightMapping( shaderStage_t *pStage );
34473448
void Render_reflection_CB( shaderStage_t *pStage );
34483449
void Render_skybox( shaderStage_t *pStage );
3450+
void Render_materialPassThrough( shaderStage_t* pStage );
34493451
void Render_screen( shaderStage_t *pStage );
34503452
void Render_portal( shaderStage_t *pStage );
34513453
void Render_heatHaze( shaderStage_t *pStage );

src/engine/renderer/tr_main.cpp

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1873,14 +1873,11 @@ R_AddDrawSurf
18731873
*/
18741874
void R_AddDrawSurf( surfaceType_t *surface, shader_t *shader, int lightmapNum, int fogNum, bool bspSurface )
18751875
{
1876-
int index;
1877-
drawSurf_t *drawSurf;
1878-
18791876
// instead of checking for overflow, we just mask the index
18801877
// so it wraps around
1881-
index = tr.refdef.numDrawSurfs & DRAWSURF_MASK;
1878+
int index = tr.refdef.numDrawSurfs & DRAWSURF_MASK;
18821879

1883-
drawSurf = &tr.refdef.drawSurfs[ index ];
1880+
drawSurf_t* drawSurf = &tr.refdef.drawSurfs[ index ];
18841881

18851882
drawSurf->entity = tr.currentEntity;
18861883
drawSurf->surface = surface;
@@ -1907,21 +1904,13 @@ void R_AddDrawSurf( surfaceType_t *surface, shader_t *shader, int lightmapNum, i
19071904

19081905
tr.refdef.numDrawSurfs++;
19091906

1910-
// Portal and sky surfaces are not handled by the material system at all
1911-
if ( materialSystem.generatingWorldCommandBuffer && ( shader->isPortal || shader->isSky ) ) {
1912-
if ( shader->isSky && std::find( materialSystem.skyShaders.begin(), materialSystem.skyShaders.end(), shader )
1913-
== materialSystem.skyShaders.end() ) {
1914-
materialSystem.skyShaders.emplace_back( shader );
1915-
}
1916-
1917-
if ( shader->isPortal )
1918-
{
1919-
// R_AddWorldSurfaces guarantees not to add surfaces more than once
1920-
ASSERT_EQ(
1921-
std::find( materialSystem.portalSurfacesTmp.begin(), materialSystem.portalSurfacesTmp.end(), drawSurf ),
1922-
materialSystem.portalSurfacesTmp.end() );
1923-
materialSystem.portalSurfacesTmp.emplace_back( drawSurf );
1924-
}
1907+
// Portal surfaces are not handled by the material system at all
1908+
if ( materialSystem.generatingWorldCommandBuffer && shader->isPortal ) {
1909+
// R_AddWorldSurfaces guarantees not to add surfaces more than once
1910+
ASSERT_EQ(
1911+
std::find( materialSystem.portalSurfacesTmp.begin(), materialSystem.portalSurfacesTmp.end(), drawSurf ),
1912+
materialSystem.portalSurfacesTmp.end() );
1913+
materialSystem.portalSurfacesTmp.emplace_back( drawSurf );
19251914
return;
19261915
}
19271916

src/engine/renderer/tr_shade.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2071,6 +2071,18 @@ void Render_skybox( shaderStage_t *pStage )
20712071
GL_CheckErrors();
20722072
}
20732073

2074+
void Render_materialPassThrough( shaderStage_t* ) {
2075+
GLimp_LogComment( "--- Render_materialPassThrough ---\n" );
2076+
2077+
// Pass-through for material system, not used normally
2078+
if ( materialSystem.generatingWorldCommandBuffer ) {
2079+
Tess_DrawElements();
2080+
return;
2081+
}
2082+
2083+
ASSERT_UNREACHABLE();
2084+
}
2085+
20742086
void Render_screen( shaderStage_t *pStage )
20752087
{
20762088
GLimp_LogComment( "--- Render_screen ---\n" );

src/engine/renderer/tr_shader.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5432,6 +5432,13 @@ static void SetStagesRenderers()
54325432
false, false,
54335433
};
54345434
break;
5435+
case stageType_t::ST_SKYBRUSHMAP:
5436+
stageRendererOptions = {
5437+
&Render_materialPassThrough,
5438+
&UpdateSurfaceDataGeneric3D, &BindShaderGeneric3D, &ProcessMaterialGeneric3D,
5439+
false, false,
5440+
};
5441+
break;
54355442
case stageType_t::ST_SCREENMAP:
54365443
stageRendererOptions = {
54375444
&Render_screen,
@@ -5806,6 +5813,22 @@ static shader_t *FinishShader()
58065813
numStages = MAX_SHADER_STAGES;
58075814
GroupActiveStages();
58085815

5816+
if ( glConfig2.materialSystemAvailable && shader.isSky ) {
5817+
shaderStage_t* pStage = &stages[numStages];
5818+
5819+
pStage->active = true;
5820+
5821+
pStage->type = stageType_t::ST_SKYBRUSHMAP;
5822+
pStage->deformIndex = 0;
5823+
pStage->stateBits = GLS_COLORMASK_BITS;
5824+
pStage->rgbGen = colorGen_t::CGEN_IDENTITY;
5825+
pStage->alphaGen = alphaGen_t::AGEN_IDENTITY;
5826+
pStage->bundle[TB_COLORMAP].image[0] = tr.whiteImage;
5827+
pStage->hasDepthFade = false;
5828+
5829+
numStages++;
5830+
}
5831+
58095832
// set appropriate stage information
58105833
for ( size_t stage = 0; stage < numStages; stage++ )
58115834
{

0 commit comments

Comments
 (0)