Skip to content

Commit

Permalink
Generate skybrush material
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
VReaperV committed Sep 13, 2024
1 parent e98fbad commit 256c8b6
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 8 deletions.
59 changes: 54 additions & 5 deletions src/engine/renderer/Material.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -792,7 +792,7 @@ void MaterialSystem::GenerateWorldMaterialsBuffer() {
uint32_t* materialsData = materialsSSBO.MapBufferRange( offset );
memset( materialsData, 0, offset * sizeof( uint32_t ) );

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

for ( drawSurf_t* drawSurf : material.drawSurfs ) {
Expand Down Expand Up @@ -960,7 +960,7 @@ void MaterialSystem::GenerateWorldCommandBuffer() {
}

shader = shader->remappedShader ? shader->remappedShader : shader;
if ( shader->isSky || shader->isPortal ) {
if ( shader->isPortal ) {
continue;
}

Expand Down Expand Up @@ -1332,6 +1332,9 @@ void MaterialSystem::ProcessStage( drawSurf_t* drawSurf, shaderStage_t* pStage,
} else {
materialPack = 2;
}
if ( shader->isSky ) {
materialPack = 3;
}
uint32_t id = packIDs[materialPack];

// In surfaces with multiple stages each consecutive stage must be drawn after the previous stage,
Expand Down Expand Up @@ -1433,8 +1436,7 @@ void MaterialSystem::GenerateWorldMaterials() {

drawSurf_t* drawSurf;
totalDrawSurfs = 0;

uint32_t packIDs[3] = { 0, 0, 0 };
uint32_t packIDs[4] = { 0, 0, 0, 0 };

for ( int i = 0; i < tr.refdef.numDrawSurfs; i++ ) {
drawSurf = &tr.refdef.drawSurfs[i];
Expand All @@ -1448,7 +1450,7 @@ void MaterialSystem::GenerateWorldMaterials() {
}

shader = shader->remappedShader ? shader->remappedShader : shader;
if ( shader->isSky || shader->isPortal ) {
if ( shader->isPortal ) {
continue;
}

Expand Down Expand Up @@ -1981,9 +1983,56 @@ void MaterialSystem::RenderMaterials( const shaderSort_t fromSort, const shaderS
continue;
}

// Use stencil buffer to avoid rendering stuff over the skybox that would normally be culled by the BSP
if ( backEnd.viewParms.portalLevel == 0 ) {
glEnable( GL_STENCIL_TEST );
glStencilMask( 0xff );
}

glStencilFunc( GL_EQUAL, backEnd.viewParms.portalLevel, 0xff );
glStencilOp( GL_KEEP, GL_KEEP, GL_INCR );

glState.glStateBitsMask = 0;

for ( Material& material : materialPacks[3].materials ) {
RenderMaterial( material, viewID );
renderedMaterials.emplace_back( &material );
}

glStencilFunc( GL_EQUAL, backEnd.viewParms.portalLevel + 1, 0xff );
glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );

GL_State( GLS_DEPTHMASK_TRUE | GLS_DEPTHFUNC_ALWAYS );
glState.glStateBitsMask = GLS_DEPTHMASK_TRUE | GLS_DEPTHFUNC_ALWAYS;
glDepthRange( 1.0, 1.0 );

for ( Material& material : materialPacks[3].materials ) {
RenderMaterial( material, viewID );
renderedMaterials.emplace_back( &material );
}

glState.glStateBitsMask = 0;
GL_State( GLS_DEFAULT );
glDepthRange( 0.0, 1.0 );

// Actually draw the skybox
tr.drawingSky = true;
Tess_Begin( Tess_StageIteratorSky, skyShader, nullptr, false, -1, 0, false );
Tess_End();

glStencilOp( GL_KEEP, GL_KEEP, GL_DECR );

for ( Material& material : materialPacks[3].materials ) {
RenderMaterial( material, viewID );
renderedMaterials.emplace_back( &material );
}

glStencilFunc( GL_EQUAL, backEnd.viewParms.portalLevel, 0xff );
glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );

if ( backEnd.viewParms.portalLevel == 0 ) {
glDisable( GL_STENCIL_TEST );
}
}
}
}
Expand Down
8 changes: 6 additions & 2 deletions src/engine/renderer/Material.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,12 +237,15 @@ class MaterialSystem {
}
};

MaterialPack materialPacks[3]{
MaterialPack materialPacks[4] {
{ shaderSort_t::SS_DEPTH, shaderSort_t::SS_DEPTH },
{ shaderSort_t::SS_ENVIRONMENT_FOG, shaderSort_t::SS_OPAQUE },
{ shaderSort_t::SS_ENVIRONMENT_NOFOG, shaderSort_t::SS_POST_PROCESS }
{ shaderSort_t::SS_ENVIRONMENT_NOFOG, shaderSort_t::SS_POST_PROCESS },
{ shaderSort_t::SS_BAD, shaderSort_t::SS_BAD }
};

Material skyBrushMaterial;

bool frameStart = false;

void AddTexture( Texture* texture );
Expand Down Expand Up @@ -304,6 +307,7 @@ class MaterialSystem {

bool AddPortalSurface( uint32_t viewID, PortalSurface* portalSurfs );

void RenderMaterialPack( MaterialPack& materialPack, const uint32_t viewID );
void RenderMaterial( Material& material, const uint32_t viewID );
void UpdateFrameData();
};
Expand Down
2 changes: 2 additions & 0 deletions src/engine/renderer/tr_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -1063,6 +1063,7 @@ enum class realtimeLightingRenderer_t { LEGACY, TILED };
ST_REFRACTIONMAP,
ST_DISPERSIONMAP,
ST_SKYBOXMAP,
ST_SKYBRUSHMAP,
ST_SCREENMAP, // 2d offscreen or portal rendering
ST_PORTALMAP,
ST_HEATHAZEMAP, // heatHaze post process effect
Expand Down Expand Up @@ -3446,6 +3447,7 @@ inline bool checkGLErrors()
void Render_lightMapping( shaderStage_t *pStage );
void Render_reflection_CB( shaderStage_t *pStage );
void Render_skybox( shaderStage_t *pStage );
void Render_materialPassThrough( shaderStage_t* pStage );
void Render_screen( shaderStage_t *pStage );
void Render_portal( shaderStage_t *pStage );
void Render_heatHaze( shaderStage_t *pStage );
Expand Down
2 changes: 1 addition & 1 deletion src/engine/renderer/tr_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1921,8 +1921,8 @@ void R_AddDrawSurf( surfaceType_t *surface, shader_t *shader, int lightmapNum, i
std::find( materialSystem.portalSurfacesTmp.begin(), materialSystem.portalSurfacesTmp.end(), drawSurf ),
materialSystem.portalSurfacesTmp.end() );
materialSystem.portalSurfacesTmp.emplace_back( drawSurf );
return;
}
return;
}

if ( shader->depthShader != nullptr ) {
Expand Down
12 changes: 12 additions & 0 deletions src/engine/renderer/tr_shade.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2071,6 +2071,18 @@ void Render_skybox( shaderStage_t *pStage )
GL_CheckErrors();
}

void Render_materialPassThrough( shaderStage_t* pStage ) {
GLimp_LogComment( "--- Render_materialPassThrough ---\n" );

// Pass-through for material system, not used normally
if ( materialSystem.generatingWorldCommandBuffer ) {
Tess_DrawElements();
return;
}

ASSERT_UNREACHABLE();
}

void Render_screen( shaderStage_t *pStage )
{
GLimp_LogComment( "--- Render_screen ---\n" );
Expand Down
23 changes: 23 additions & 0 deletions src/engine/renderer/tr_shader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5432,6 +5432,13 @@ static void SetStagesRenderers()
false, false,
};
break;
case stageType_t::ST_SKYBRUSHMAP:
stageRendererOptions = {
&Render_materialPassThrough,
&UpdateSurfaceDataGeneric3D, &BindShaderGeneric3D, &ProcessMaterialGeneric3D,
false, false,
};
break;
case stageType_t::ST_SCREENMAP:
stageRendererOptions = {
&Render_screen,
Expand Down Expand Up @@ -5806,6 +5813,22 @@ static shader_t *FinishShader()
numStages = MAX_SHADER_STAGES;
GroupActiveStages();

if ( glConfig2.materialSystemAvailable && shader.isSky ) {
shaderStage_t* pStage = &stages[numStages];

pStage->active = true;

pStage->type = stageType_t::ST_SKYBRUSHMAP;
pStage->deformIndex = 0;
pStage->stateBits = GLS_COLORMASK_BITS;
pStage->rgbGen = colorGen_t::CGEN_IDENTITY;
pStage->alphaGen = alphaGen_t::AGEN_IDENTITY;
pStage->bundle[TB_COLORMAP].image[0] = tr.whiteImage;
pStage->hasDepthFade = false;

numStages++;
}

// set appropriate stage information
for ( size_t stage = 0; stage < numStages; stage++ )
{
Expand Down

0 comments on commit 256c8b6

Please sign in to comment.