mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2025-03-01 23:20:44 +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.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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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:
|
||||
|
@ -82,7 +89,7 @@ private:
|
|||
|
||||
struct globalFramebuffers_t
|
||||
{
|
||||
Framebuffer* shadowFBO;
|
||||
Framebuffer* shadowFBO[MAX_SHADOWMAP_RESOLUTIONS];
|
||||
};
|
||||
extern globalFramebuffers_t globalFramebuffers;
|
||||
|
||||
|
|
|
@ -337,7 +337,7 @@ public:
|
|||
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;
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
@ -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 );
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
@ -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( glState | GLS_POLYGON_OFFSET );
|
||||
|
||||
GL_State( GLS_DEFAULT );
|
||||
|
||||
// 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;
|
||||
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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
|
||||
|
@ -2925,7 +2916,7 @@ void RB_ShowShadowMaps()
|
|||
if( !r_showShadowMaps.GetBool() )
|
||||
return;
|
||||
|
||||
image = globalImages->shadowImage;
|
||||
image = globalImages->shadowImage[0];
|
||||
if( !image )
|
||||
{
|
||||
return;
|
||||
|
|
|
@ -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 )
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue