Skip to content

Commit

Permalink
Improved shadow mapping performance using the shadow LOD and tweaked
Browse files Browse the repository at this point in the history
polygon offsets to fight shadow acne
  • Loading branch information
RobertBeckebans committed May 11, 2014
1 parent 5153422 commit 0eaaea4
Show file tree
Hide file tree
Showing 10 changed files with 92 additions and 43 deletions.
8 changes: 4 additions & 4 deletions base/renderprogs/interactionSM.pixel
Original file line number Diff line number Diff line change
Expand Up @@ -185,13 +185,13 @@ void main( PS_IN fragment, out PS_OUT result )
shadowTexcoord.z = dot4( modelPosition, shadowMatrixZ );
shadowTexcoord.w = dot4( modelPosition, shadowMatrixW );

//float bias = 0.001 * tan( acos( ldotN ) );
//bias = clamp( bias, 0, 0.001 );
//float bias = 0.005 * tan( acos( ldotN ) );
//bias = clamp( bias, 0, 0.01 );
float bias = 0.001;

shadowTexcoord.xyz /= shadowTexcoord.w;
shadowTexcoord.z = shadowTexcoord.z * 0.9991;
//shadowTexcoord.z = shadowTexcoord.z - bias;
//shadowTexcoord.z = shadowTexcoord.z * 0.9991;
shadowTexcoord.z = shadowTexcoord.z - bias;
shadowTexcoord.w = float(shadowIndex);

#if 0
Expand Down
11 changes: 8 additions & 3 deletions neo/renderer/Framebuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,14 @@ void Framebuffer::Init()
int width, height;
width = height = r_shadowMapImageSize.GetInteger();

globalFramebuffers.shadowFBO = new Framebuffer( "_shadowMap" , width, height );
globalFramebuffers.shadowFBO->Bind();
glDrawBuffers( 0, NULL );
for( int i = 0; i < MAX_SHADOWMAP_RESOLUTIONS; i++ )
{
width = height = shadowMapResolutions[i];

globalFramebuffers.shadowFBO[i] = new Framebuffer( "_shadowMap" , width, height );
globalFramebuffers.shadowFBO[i]->Bind();
glDrawBuffers( 0, NULL );
}
// globalFramebuffers.shadowFBO->AddColorBuffer( GL_RGBA8, 0 );
// globalFramebuffers.shadowFBO->AddDepthBuffer( GL_DEPTH_COMPONENT24 );
// globalFramebuffers.shadowFBO->Check();
Expand Down
9 changes: 8 additions & 1 deletion neo/renderer/Framebuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ If you have questions concerning this license or the applicable additional terms
#ifndef __FRAMEBUFFER_H__
#define __FRAMEBUFFER_H__

static const int MAX_SHADOWMAP_RESOLUTIONS = 5;
#if 1
static int shadowMapResolutions[MAX_SHADOWMAP_RESOLUTIONS] = { 2048, 1024, 512, 512, 256 };
#else
static int shadowMapResolutions[MAX_SHADOWMAP_RESOLUTIONS] = { 1024, 1024, 1024, 1024, 1024 };
#endif

class Framebuffer
{
public:
Expand Down Expand Up @@ -82,7 +89,7 @@ class Framebuffer

struct globalFramebuffers_t
{
Framebuffer* shadowFBO;
Framebuffer* shadowFBO[MAX_SHADOWMAP_RESOLUTIONS];
};
extern globalFramebuffers_t globalFramebuffers;

Expand Down
2 changes: 1 addition & 1 deletion neo/renderer/Image.h
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ class idImageManager
idImage* fogImage; // increasing alpha is denser fog
idImage* fogEnterImage; // adjust fogImage alpha based on terminator plane
// RB begin
idImage* shadowImage;
idImage* shadowImage[5];
idImage* jitterImage1; // shadow jitter
idImage* jitterImage4;
idImage* jitterImage16;
Expand Down
34 changes: 31 additions & 3 deletions neo/renderer/Image_intrinsic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -451,9 +451,33 @@ void R_QuadraticImage( idImage* image )
}

// RB begin
static void R_CreateShadowMapImage( idImage* image )
static void R_CreateShadowMapImage_Res0( idImage* image )
{
int size = r_shadowMapImageSize.GetInteger();
int size = shadowMapResolutions[0];
image->GenerateShadowArray( size, size, TF_LINEAR, TR_CLAMP_TO_ZERO_ALPHA, TD_SHADOW_ARRAY );
}

static void R_CreateShadowMapImage_Res1( idImage* image )
{
int size = shadowMapResolutions[1];
image->GenerateShadowArray( size, size, TF_LINEAR, TR_CLAMP_TO_ZERO_ALPHA, TD_SHADOW_ARRAY );
}

static void R_CreateShadowMapImage_Res2( idImage* image )
{
int size = shadowMapResolutions[2];
image->GenerateShadowArray( size, size, TF_LINEAR, TR_CLAMP_TO_ZERO_ALPHA, TD_SHADOW_ARRAY );
}

static void R_CreateShadowMapImage_Res3( idImage* image )
{
int size = shadowMapResolutions[3];
image->GenerateShadowArray( size, size, TF_LINEAR, TR_CLAMP_TO_ZERO_ALPHA, TD_SHADOW_ARRAY );
}

static void R_CreateShadowMapImage_Res4( idImage* image )
{
int size = shadowMapResolutions[4];
image->GenerateShadowArray( size, size, TF_LINEAR, TR_CLAMP_TO_ZERO_ALPHA, TD_SHADOW_ARRAY );
}

Expand Down Expand Up @@ -562,7 +586,11 @@ void idImageManager::CreateIntrinsicImages()
ImageFromFunction( "_quadratic", R_QuadraticImage );

// RB begin
shadowImage = ImageFromFunction( va( "_shadowMap%i_0", r_shadowMapImageSize.GetInteger() ), R_CreateShadowMapImage );
shadowImage[0] = ImageFromFunction( va( "_shadowMapArray%i", shadowMapResolutions[0] ), R_CreateShadowMapImage_Res0 );
shadowImage[1] = ImageFromFunction( va( "_shadowMapArray%i", shadowMapResolutions[1] ), R_CreateShadowMapImage_Res1 );
shadowImage[2] = ImageFromFunction( va( "_shadowMapArray%i", shadowMapResolutions[2] ), R_CreateShadowMapImage_Res2 );
shadowImage[3] = ImageFromFunction( va( "_shadowMapArray%i", shadowMapResolutions[3] ), R_CreateShadowMapImage_Res3 );
shadowImage[4] = ImageFromFunction( va( "_shadowMapArray%i", shadowMapResolutions[4] ), R_CreateShadowMapImage_Res4 );

jitterImage1 = globalImages->ImageFromFunction( "_jitter1", R_CreateJitterImage1 );
jitterImage4 = globalImages->ImageFromFunction( "_jitter4", R_CreateJitterImage4 );
Expand Down
5 changes: 4 additions & 1 deletion neo/renderer/RenderSystem_init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,11 @@ idCVar r_shadowMapBiasScale( "r_shadowMapBiasScale", "0.0001", CVAR_RENDERER | C
idCVar r_shadowMapSamples( "r_shadowMapSamples", "16", CVAR_RENDERER | CVAR_INTEGER, "0, 1, 4, or 16" );
idCVar r_shadowMapSplits( "r_shadowMapSplits", "3", CVAR_RENDERER | CVAR_INTEGER, "number of splits for cascaded shadow mapping with parallel lights", 0, 4 );
idCVar r_shadowMapSplitWeight( "r_shadowMapSplitWeight", "0.9", CVAR_RENDERER | CVAR_FLOAT, "" );
idCVar r_shadowMapLodScale( "r_shadowMapLodScale", "0.8", CVAR_RENDERER | CVAR_FLOAT, "" );
idCVar r_shadowMapLodScale( "r_shadowMapLodScale", "1.4", CVAR_RENDERER | CVAR_FLOAT, "" );
idCVar r_shadowMapLodBias( "r_shadowMapLodBias", "0", CVAR_RENDERER | CVAR_INTEGER, "" );
idCVar r_shadowMapPolygonFactor( "r_shadowMapPolygonFactor", "2", CVAR_RENDERER | CVAR_FLOAT, "polygonOffset factor for drawing shadow buffer" );
idCVar r_shadowMapPolygonOffset( "r_shadowMapPolygonOffset", "3000", CVAR_RENDERER | CVAR_FLOAT, "polygonOffset units for drawing shadow buffer" );
idCVar r_shadowMapOccluderFacing( "r_shadowMapOccluderFacing", "2", CVAR_RENDERER | CVAR_INTEGER, "0 = front faces, 1 = back faces, 2 = twosided" );
// RB end


Expand Down
38 changes: 24 additions & 14 deletions neo/renderer/tr_backend_draw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1346,7 +1346,7 @@ static void RB_RenderInteractions( const drawSurf_t* surfList, const viewLight_t
{
// texture 5 will be the shadow maps array
GL_SelectTexture( INTERACTION_TEXUNIT_SHADOWMAPS );
globalImages->shadowImage->Bind();
globalImages->shadowImage[vLight->shadowLOD]->Bind();

// texture 6 will be the jitter texture for soft shadowing
GL_SelectTexture( INTERACTION_TEXUNIT_JITTER );
Expand Down Expand Up @@ -2237,18 +2237,28 @@ static void RB_ShadowMapPass( const drawSurf_t* drawSurfs, const viewLight_t* vL

uint64 glState = 0;

//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( GLS_DEFAULT );
GL_State( glState | GLS_POLYGON_OFFSET );

// Two Sided Stencil reduces two draw calls to one for slightly faster shadows
GL_Cull( CT_TWO_SIDED );
switch( r_shadowMapOccluderFacing.GetInteger() )
{
case 0:
GL_Cull( CT_FRONT_SIDED );
GL_PolygonOffset( r_shadowMapPolygonFactor.GetFloat(), r_shadowMapPolygonOffset.GetFloat() );
break;

case 1:
GL_Cull( CT_BACK_SIDED );
GL_PolygonOffset( -r_shadowMapPolygonFactor.GetFloat(), -r_shadowMapPolygonOffset.GetFloat() );
break;

default:
GL_Cull( CT_TWO_SIDED );
GL_PolygonOffset( r_shadowMapPolygonFactor.GetFloat(), r_shadowMapPolygonOffset.GetFloat() );
break;
}

idRenderMatrix lightProjectionRenderMatrix;
idRenderMatrix lightViewRenderMatrix;
Expand Down Expand Up @@ -2546,20 +2556,20 @@ static void RB_ShadowMapPass( const drawSurf_t* drawSurfs, const viewLight_t* vL



globalFramebuffers.shadowFBO->Bind();
globalFramebuffers.shadowFBO[vLight->shadowLOD]->Bind();

if( side < 0 )
{
globalFramebuffers.shadowFBO->AttachImageDepthLayer( globalImages->shadowImage, 0 );
globalFramebuffers.shadowFBO[vLight->shadowLOD]->AttachImageDepthLayer( globalImages->shadowImage[vLight->shadowLOD], 0 );
}
else
{
globalFramebuffers.shadowFBO->AttachImageDepthLayer( globalImages->shadowImage, side );
globalFramebuffers.shadowFBO[vLight->shadowLOD]->AttachImageDepthLayer( globalImages->shadowImage[vLight->shadowLOD], side );
}

globalFramebuffers.shadowFBO->Check();
globalFramebuffers.shadowFBO[vLight->shadowLOD]->Check();

GL_ViewportAndScissor( 0, 0, r_shadowMapImageSize.GetInteger(), r_shadowMapImageSize.GetInteger() );
GL_ViewportAndScissor( 0, 0, shadowMapResolutions[vLight->shadowLOD], shadowMapResolutions[vLight->shadowLOD] );

glClear( GL_DEPTH_BUFFER_BIT );

Expand Down
13 changes: 2 additions & 11 deletions neo/renderer/tr_backend_rendertools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1888,20 +1888,11 @@ static void RB_ShowShadowMapLODs()
int count = 0;
for( viewLight_t* vLight = backEnd.viewDef->viewLights; vLight != NULL; vLight = vLight->next )
{
#if 0
const idMaterial* lightShader = vLight->lightShader;

if( lightShader->IsFogLight() )
if( !vLight->lightDef->LightCastsShadows() )
{
continue;
}

if( lightShader->IsBlendLight() )
{
continue;
}
#endif

count++;

// depth buffered planes
Expand Down Expand Up @@ -2925,7 +2916,7 @@ void RB_ShowShadowMaps()
if( !r_showShadowMaps.GetBool() )
return;

image = globalImages->shadowImage;
image = globalImages->shadowImage[0];
if( !image )
{
return;
Expand Down
12 changes: 7 additions & 5 deletions neo/renderer/tr_frontend_addlights.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ static void R_AddSingleLight( viewLight_t* vLight )
vLight->scissorRect.zmax = projected[1][2];

// RB: calculate shadow LOD similar to Q3A .md3 LOD code
vLight->shadowLOD = -1;
vLight->shadowLOD = 0;

if( r_useShadowMapping.GetBool() && lightCastsShadows )
{
Expand All @@ -275,7 +275,7 @@ static void R_AddSingleLight( viewLight_t* vLight )
int lod;
int numLods;

numLods = 5;
numLods = MAX_SHADOWMAP_RESOLUTIONS;

// compute projected bounding sphere
// and use that as a criteria for selecting LOD
Expand Down Expand Up @@ -323,15 +323,17 @@ static void R_AddSingleLight( viewLight_t* vLight )
if( lod >= numLods )
{
// don't draw any shadow
lod = -1;
//lod = -1;

//lod = numLods - 1;
lod = numLods - 1;
}

// never give ultra quality for point lights
if( lod == 0 && light->parms.pointLight )
{
lod = 1;

}

vLight->shadowLOD = lod;
}
// RB end
Expand Down
3 changes: 3 additions & 0 deletions neo/renderer/tr_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -1065,6 +1065,9 @@ extern idCVar r_shadowMapSplits;
extern idCVar r_shadowMapSplitWeight;
extern idCVar r_shadowMapLodScale;
extern idCVar r_shadowMapLodBias;
extern idCVar r_shadowMapPolygonFactor;
extern idCVar r_shadowMapPolygonOffset;
extern idCVar r_shadowMapOccluderFacing;
// RB end

/*
Expand Down

0 comments on commit 0eaaea4

Please sign in to comment.