mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2025-03-02 23:41:51 +00:00
Improved shadow mapping performance using the shadow LOD and tweaked
polygon offsets to fight shadow acne
This commit is contained in:
parent
5153422d0d
commit
0eaaea4b96
10 changed files with 92 additions and 43 deletions
|
@ -185,13 +185,13 @@ void main( PS_IN fragment, out PS_OUT result )
|
||||||
shadowTexcoord.z = dot4( modelPosition, shadowMatrixZ );
|
shadowTexcoord.z = dot4( modelPosition, shadowMatrixZ );
|
||||||
shadowTexcoord.w = dot4( modelPosition, shadowMatrixW );
|
shadowTexcoord.w = dot4( modelPosition, shadowMatrixW );
|
||||||
|
|
||||||
//float bias = 0.001 * tan( acos( ldotN ) );
|
//float bias = 0.005 * tan( acos( ldotN ) );
|
||||||
//bias = clamp( bias, 0, 0.001 );
|
//bias = clamp( bias, 0, 0.01 );
|
||||||
float bias = 0.001;
|
float bias = 0.001;
|
||||||
|
|
||||||
shadowTexcoord.xyz /= shadowTexcoord.w;
|
shadowTexcoord.xyz /= shadowTexcoord.w;
|
||||||
shadowTexcoord.z = shadowTexcoord.z * 0.9991;
|
//shadowTexcoord.z = shadowTexcoord.z * 0.9991;
|
||||||
//shadowTexcoord.z = shadowTexcoord.z - bias;
|
shadowTexcoord.z = shadowTexcoord.z - bias;
|
||||||
shadowTexcoord.w = float(shadowIndex);
|
shadowTexcoord.w = float(shadowIndex);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|
|
@ -77,9 +77,14 @@ void Framebuffer::Init()
|
||||||
int width, height;
|
int width, height;
|
||||||
width = height = r_shadowMapImageSize.GetInteger();
|
width = height = r_shadowMapImageSize.GetInteger();
|
||||||
|
|
||||||
globalFramebuffers.shadowFBO = new Framebuffer( "_shadowMap" , width, height );
|
for( int i = 0; i < MAX_SHADOWMAP_RESOLUTIONS; i++ )
|
||||||
globalFramebuffers.shadowFBO->Bind();
|
{
|
||||||
glDrawBuffers( 0, NULL );
|
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->AddColorBuffer( GL_RGBA8, 0 );
|
||||||
// globalFramebuffers.shadowFBO->AddDepthBuffer( GL_DEPTH_COMPONENT24 );
|
// globalFramebuffers.shadowFBO->AddDepthBuffer( GL_DEPTH_COMPONENT24 );
|
||||||
// globalFramebuffers.shadowFBO->Check();
|
// globalFramebuffers.shadowFBO->Check();
|
||||||
|
|
|
@ -29,6 +29,13 @@ If you have questions concerning this license or the applicable additional terms
|
||||||
#ifndef __FRAMEBUFFER_H__
|
#ifndef __FRAMEBUFFER_H__
|
||||||
#define __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
|
class Framebuffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -82,7 +89,7 @@ private:
|
||||||
|
|
||||||
struct globalFramebuffers_t
|
struct globalFramebuffers_t
|
||||||
{
|
{
|
||||||
Framebuffer* shadowFBO;
|
Framebuffer* shadowFBO[MAX_SHADOWMAP_RESOLUTIONS];
|
||||||
};
|
};
|
||||||
extern globalFramebuffers_t globalFramebuffers;
|
extern globalFramebuffers_t globalFramebuffers;
|
||||||
|
|
||||||
|
|
|
@ -337,7 +337,7 @@ public:
|
||||||
idImage* fogImage; // increasing alpha is denser fog
|
idImage* fogImage; // increasing alpha is denser fog
|
||||||
idImage* fogEnterImage; // adjust fogImage alpha based on terminator plane
|
idImage* fogEnterImage; // adjust fogImage alpha based on terminator plane
|
||||||
// RB begin
|
// RB begin
|
||||||
idImage* shadowImage;
|
idImage* shadowImage[5];
|
||||||
idImage* jitterImage1; // shadow jitter
|
idImage* jitterImage1; // shadow jitter
|
||||||
idImage* jitterImage4;
|
idImage* jitterImage4;
|
||||||
idImage* jitterImage16;
|
idImage* jitterImage16;
|
||||||
|
|
|
@ -451,9 +451,33 @@ void R_QuadraticImage( idImage* image )
|
||||||
}
|
}
|
||||||
|
|
||||||
// RB begin
|
// 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 );
|
image->GenerateShadowArray( size, size, TF_LINEAR, TR_CLAMP_TO_ZERO_ALPHA, TD_SHADOW_ARRAY );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -562,7 +586,11 @@ void idImageManager::CreateIntrinsicImages()
|
||||||
ImageFromFunction( "_quadratic", R_QuadraticImage );
|
ImageFromFunction( "_quadratic", R_QuadraticImage );
|
||||||
|
|
||||||
// RB begin
|
// 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 );
|
jitterImage1 = globalImages->ImageFromFunction( "_jitter1", R_CreateJitterImage1 );
|
||||||
jitterImage4 = globalImages->ImageFromFunction( "_jitter4", R_CreateJitterImage4 );
|
jitterImage4 = globalImages->ImageFromFunction( "_jitter4", R_CreateJitterImage4 );
|
||||||
|
|
|
@ -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_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_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_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_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
|
// RB end
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1346,7 +1346,7 @@ static void RB_RenderInteractions( const drawSurf_t* surfList, const viewLight_t
|
||||||
{
|
{
|
||||||
// texture 5 will be the shadow maps array
|
// texture 5 will be the shadow maps array
|
||||||
GL_SelectTexture( INTERACTION_TEXUNIT_SHADOWMAPS );
|
GL_SelectTexture( INTERACTION_TEXUNIT_SHADOWMAPS );
|
||||||
globalImages->shadowImage->Bind();
|
globalImages->shadowImage[vLight->shadowLOD]->Bind();
|
||||||
|
|
||||||
// texture 6 will be the jitter texture for soft shadowing
|
// texture 6 will be the jitter texture for soft shadowing
|
||||||
GL_SelectTexture( INTERACTION_TEXUNIT_JITTER );
|
GL_SelectTexture( INTERACTION_TEXUNIT_JITTER );
|
||||||
|
@ -2237,18 +2237,28 @@ static void RB_ShadowMapPass( const drawSurf_t* drawSurfs, const viewLight_t* vL
|
||||||
|
|
||||||
uint64 glState = 0;
|
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
|
// 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
|
// disabled here, and that the value will get reset for the interactions without looking
|
||||||
// like a no-change-required
|
// like a no-change-required
|
||||||
//GL_State( glState | GLS_POLYGON_OFFSET );
|
GL_State( glState | GLS_POLYGON_OFFSET );
|
||||||
|
|
||||||
GL_State( GLS_DEFAULT );
|
switch( r_shadowMapOccluderFacing.GetInteger() )
|
||||||
|
{
|
||||||
// Two Sided Stencil reduces two draw calls to one for slightly faster shadows
|
case 0:
|
||||||
GL_Cull( CT_TWO_SIDED );
|
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 lightProjectionRenderMatrix;
|
||||||
idRenderMatrix lightViewRenderMatrix;
|
idRenderMatrix lightViewRenderMatrix;
|
||||||
|
@ -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 )
|
if( side < 0 )
|
||||||
{
|
{
|
||||||
globalFramebuffers.shadowFBO->AttachImageDepthLayer( globalImages->shadowImage, 0 );
|
globalFramebuffers.shadowFBO[vLight->shadowLOD]->AttachImageDepthLayer( globalImages->shadowImage[vLight->shadowLOD], 0 );
|
||||||
}
|
}
|
||||||
else
|
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 );
|
glClear( GL_DEPTH_BUFFER_BIT );
|
||||||
|
|
||||||
|
|
|
@ -1888,20 +1888,11 @@ static void RB_ShowShadowMapLODs()
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for( viewLight_t* vLight = backEnd.viewDef->viewLights; vLight != NULL; vLight = vLight->next )
|
for( viewLight_t* vLight = backEnd.viewDef->viewLights; vLight != NULL; vLight = vLight->next )
|
||||||
{
|
{
|
||||||
#if 0
|
if( !vLight->lightDef->LightCastsShadows() )
|
||||||
const idMaterial* lightShader = vLight->lightShader;
|
|
||||||
|
|
||||||
if( lightShader->IsFogLight() )
|
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( lightShader->IsBlendLight() )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
// depth buffered planes
|
// depth buffered planes
|
||||||
|
@ -2925,7 +2916,7 @@ void RB_ShowShadowMaps()
|
||||||
if( !r_showShadowMaps.GetBool() )
|
if( !r_showShadowMaps.GetBool() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
image = globalImages->shadowImage;
|
image = globalImages->shadowImage[0];
|
||||||
if( !image )
|
if( !image )
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -266,7 +266,7 @@ static void R_AddSingleLight( viewLight_t* vLight )
|
||||||
vLight->scissorRect.zmax = projected[1][2];
|
vLight->scissorRect.zmax = projected[1][2];
|
||||||
|
|
||||||
// RB: calculate shadow LOD similar to Q3A .md3 LOD code
|
// RB: calculate shadow LOD similar to Q3A .md3 LOD code
|
||||||
vLight->shadowLOD = -1;
|
vLight->shadowLOD = 0;
|
||||||
|
|
||||||
if( r_useShadowMapping.GetBool() && lightCastsShadows )
|
if( r_useShadowMapping.GetBool() && lightCastsShadows )
|
||||||
{
|
{
|
||||||
|
@ -275,7 +275,7 @@ static void R_AddSingleLight( viewLight_t* vLight )
|
||||||
int lod;
|
int lod;
|
||||||
int numLods;
|
int numLods;
|
||||||
|
|
||||||
numLods = 5;
|
numLods = MAX_SHADOWMAP_RESOLUTIONS;
|
||||||
|
|
||||||
// compute projected bounding sphere
|
// compute projected bounding sphere
|
||||||
// and use that as a criteria for selecting LOD
|
// and use that as a criteria for selecting LOD
|
||||||
|
@ -323,15 +323,17 @@ static void R_AddSingleLight( viewLight_t* vLight )
|
||||||
if( lod >= numLods )
|
if( lod >= numLods )
|
||||||
{
|
{
|
||||||
// don't draw any shadow
|
// don't draw any shadow
|
||||||
lod = -1;
|
//lod = -1;
|
||||||
|
|
||||||
//lod = numLods - 1;
|
lod = numLods - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// never give ultra quality for point lights
|
// never give ultra quality for point lights
|
||||||
if( lod == 0 && light->parms.pointLight )
|
if( lod == 0 && light->parms.pointLight )
|
||||||
|
{
|
||||||
lod = 1;
|
lod = 1;
|
||||||
|
}
|
||||||
|
|
||||||
vLight->shadowLOD = lod;
|
vLight->shadowLOD = lod;
|
||||||
}
|
}
|
||||||
// RB end
|
// RB end
|
||||||
|
|
|
@ -1065,6 +1065,9 @@ extern idCVar r_shadowMapSplits;
|
||||||
extern idCVar r_shadowMapSplitWeight;
|
extern idCVar r_shadowMapSplitWeight;
|
||||||
extern idCVar r_shadowMapLodScale;
|
extern idCVar r_shadowMapLodScale;
|
||||||
extern idCVar r_shadowMapLodBias;
|
extern idCVar r_shadowMapLodBias;
|
||||||
|
extern idCVar r_shadowMapPolygonFactor;
|
||||||
|
extern idCVar r_shadowMapPolygonOffset;
|
||||||
|
extern idCVar r_shadowMapOccluderFacing;
|
||||||
// RB end
|
// RB end
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in a new issue