mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2025-03-15 07:00:58 +00:00
Merged some SS2 shadow mapping performance improvements
This commit is contained in:
parent
081c848f87
commit
3e1d21ef34
3 changed files with 367 additions and 205 deletions
|
@ -3,6 +3,8 @@
|
|||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
Copyright (C) 2014-2016 Robert Beckebans
|
||||
Copyright (C) 2014-2016 Kot in Action Creative Artel
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
|
@ -1205,6 +1207,11 @@ void idMaterial::ParseFragmentMap( idLexer& src, newShaderStage_t* newStage )
|
|||
{
|
||||
src.ReadTokenOnLine( &token );
|
||||
|
||||
if( !token.Icmp( "normalMap" ) )
|
||||
{
|
||||
td = TD_BUMP;
|
||||
continue;
|
||||
}
|
||||
if( !token.Icmp( "cubeMap" ) )
|
||||
{
|
||||
cubeMap = CF_NATIVE;
|
||||
|
@ -2337,7 +2344,8 @@ void idMaterial::ParseMaterial( idLexer& src )
|
|||
// volume would be coplanar with the surface, giving depth fighting
|
||||
// we could make this no-self-shadows, but it may be more important
|
||||
// to receive shadows from no-self-shadow monsters
|
||||
SetMaterialFlag( MF_NOSHADOWS );
|
||||
if( !r_useShadowMapping.GetBool() ) // motorsep 11-08-2014; when shadow mapping is on, we allow two-sided surfaces to cast shadows
|
||||
SetMaterialFlag( MF_NOSHADOWS );
|
||||
}
|
||||
// backSided
|
||||
else if( !token.Icmp( "backSided" ) )
|
||||
|
@ -2507,6 +2515,33 @@ void idMaterial::ParseMaterial( idLexer& src )
|
|||
SetMaterialFlag( MF_NOSHADOWS );
|
||||
continue;
|
||||
}
|
||||
|
||||
// motorsep 11-23-2014; material LOD keys that define what LOD iteration the surface falls into
|
||||
else if( !token.Icmp( "lod1" ) )
|
||||
{
|
||||
SetMaterialFlag( MF_LOD1 );
|
||||
continue;
|
||||
}
|
||||
else if( !token.Icmp( "lod2" ) )
|
||||
{
|
||||
SetMaterialFlag( MF_LOD2 );
|
||||
continue;
|
||||
}
|
||||
else if( !token.Icmp( "lod3" ) )
|
||||
{
|
||||
SetMaterialFlag( MF_LOD3 );
|
||||
continue;
|
||||
}
|
||||
else if( !token.Icmp( "lod4" ) )
|
||||
{
|
||||
SetMaterialFlag( MF_LOD4 );
|
||||
continue;
|
||||
}
|
||||
else if( !token.Icmp( "persistentLOD" ) )
|
||||
{
|
||||
SetMaterialFlag( MF_LOD_PERSISTENT );
|
||||
continue;
|
||||
}
|
||||
else if( token == "{" )
|
||||
{
|
||||
// create the new stage
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
Copyright (C) 2014-2016 Robert Beckebans
|
||||
Copyright (C) 2014-2016 Kot in Action Creative Artel
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
|
@ -280,8 +282,15 @@ typedef enum
|
|||
MF_NOSHADOWS = BIT( 2 ),
|
||||
MF_FORCESHADOWS = BIT( 3 ),
|
||||
MF_NOSELFSHADOW = BIT( 4 ),
|
||||
MF_NOPORTALFOG = BIT( 5 ), // this fog volume won't ever consider a portal fogged out
|
||||
MF_EDITOR_VISIBLE = BIT( 6 ) // in use (visible) per editor
|
||||
MF_NOPORTALFOG = BIT( 5 ), // this fog volume won't ever consider a portal fogged out
|
||||
MF_EDITOR_VISIBLE = BIT( 6 ), // in use (visible) per editor
|
||||
// motorsep 11-23-2014; material LOD keys that define what LOD iteration the surface falls into
|
||||
MF_LOD1_SHIFT = 7,
|
||||
MF_LOD1 = BIT( 7 ), // motorsep 11-24-2014; material flag for LOD1 iteration
|
||||
MF_LOD2 = BIT( 8 ), // motorsep 11-24-2014; material flag for LOD2 iteration
|
||||
MF_LOD3 = BIT( 9 ), // motorsep 11-24-2014; material flag for LOD3 iteration
|
||||
MF_LOD4 = BIT( 10 ), // motorsep 11-24-2014; material flag for LOD4 iteration
|
||||
MF_LOD_PERSISTENT = BIT( 11 ) // motorsep 11-24-2014; material flag for persistent LOD iteration
|
||||
} materialFlags_t;
|
||||
|
||||
// contents flags, NOTE: make sure to keep the defines in doom_defs.script up to date with these!
|
||||
|
@ -789,6 +798,24 @@ public:
|
|||
};
|
||||
void AddReference();
|
||||
|
||||
// motorsep 11-23-2014; material LOD keys that define what LOD iteration the surface falls into
|
||||
// lod1 - lod4 defines several levels of LOD
|
||||
// persistentLOD specifies the LOD iteration that still being rendered, even after the camera is beyond the distance at which LOD iteration should not be rendered
|
||||
|
||||
bool IsLOD() const
|
||||
{
|
||||
return ( materialFlags & ( MF_LOD1 | MF_LOD2 | MF_LOD3 | MF_LOD4 ) ) != 0;
|
||||
}
|
||||
// foresthale 2014-11-24: added IsLODVisibleForDistance method
|
||||
bool IsLODVisibleForDistance( float distance, float lodBase ) const
|
||||
{
|
||||
int bit = ( materialFlags & ( MF_LOD1 | MF_LOD2 | MF_LOD3 | MF_LOD4 ) ) >> MF_LOD1_SHIFT;
|
||||
float m1 = lodBase * ( bit >> 1 );
|
||||
float m2 = lodBase * bit;
|
||||
return distance >= m1 && ( distance < m2 || ( materialFlags & ( MF_LOD_PERSISTENT ) ) );
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
// parse the entire material
|
||||
void CommonInit();
|
||||
|
@ -825,7 +852,7 @@ private:
|
|||
idStr desc; // description
|
||||
idStr renderBump; // renderbump command options, without the "renderbump" at the start
|
||||
|
||||
idImage* lightFalloffImage; // only for light shaders
|
||||
idImage* lightFalloffImage; // only for light shaders
|
||||
|
||||
idImage* fastPathBumpImage; // if any of these are set, they all will be
|
||||
idImage* fastPathDiffuseImage;
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
Copyright (C) 2013-2014 Robert Beckebans
|
||||
Copyright (C) 2014-2016 Robert Beckebans
|
||||
Copyright (C) 2014-2016 Kot in Action Creative Artel
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
|
@ -26,7 +27,6 @@ If you have questions concerning this license or the applicable additional terms
|
|||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#pragma hdrstop
|
||||
#include "precompiled.h"
|
||||
|
||||
|
@ -44,6 +44,8 @@ idCVar r_forceShadowCaps( "r_forceShadowCaps", "0", CVAR_RENDERER | CVAR_BOOL, "
|
|||
// RB begin
|
||||
idCVar r_forceShadowMapsOnAlphaTestedSurfaces( "r_forceShadowMapsOnAlphaTestedSurfaces", "1", CVAR_RENDERER | CVAR_BOOL, "0 = same shadowing as with stencil shadows, 1 = ignore noshadows for alpha tested materials" );
|
||||
// RB end
|
||||
// foresthale 2014-11-24: cvar to control the material lod flags - this is the distance at which a mesh switches from lod1 to lod2, where lod3 will appear at this distance *2, lod4 at *4, and persistentLOD keyword will disable the max distance check (thus extending this LOD to all further distances, rather than disappearing)
|
||||
idCVar r_lodMaterialDistance( "r_lodMaterialDistance", "500", CVAR_RENDERER | CVAR_FLOAT, "surfaces further than this distance will use lower quality versions (if their material uses the lod1-4 keywords, persistentLOD disables the max distance checks)" );
|
||||
|
||||
static const float CHECK_BOUNDS_EPSILON = 1.0f;
|
||||
|
||||
|
@ -315,7 +317,7 @@ void R_SetupDrawSurfShader( drawSurf_t* drawSurf, const idMaterial* shader, cons
|
|||
shaderParms = generatedShaderParms;
|
||||
}
|
||||
|
||||
// allocte frame memory for the shader register values
|
||||
// allocate frame memory for the shader register values
|
||||
float* regs = ( float* )R_FrameAlloc( shader->GetNumRegisters() * sizeof( float ), FRAME_ALLOC_SHADER_REGISTER );
|
||||
drawSurf->shaderRegisters = regs;
|
||||
|
||||
|
@ -602,7 +604,36 @@ void R_AddSingleModel( viewEntity_t* vEntity )
|
|||
{
|
||||
continue;
|
||||
}
|
||||
if( !shader->IsDrawn() )
|
||||
|
||||
// motorsep 11-24-2014; checking for LOD surface for LOD1 iteration
|
||||
if( shader->IsLOD() )
|
||||
{
|
||||
// foresthale 2014-11-24: calculate the bounds and get the distance from camera to bounds
|
||||
idBounds& localBounds = tri->bounds;
|
||||
if( tri->staticModelWithJoints )
|
||||
{
|
||||
// skeletal models have difficult to compute bounds for surfaces, so use the whole entity
|
||||
localBounds = vEntity->entityDef->localReferenceBounds;
|
||||
}
|
||||
const float* bounds = localBounds.ToFloatPtr();
|
||||
idVec3 nearestPointOnBounds = localViewOrigin;
|
||||
nearestPointOnBounds.x = Max( nearestPointOnBounds.x, bounds[0] );
|
||||
nearestPointOnBounds.x = Min( nearestPointOnBounds.x, bounds[3] );
|
||||
nearestPointOnBounds.y = Max( nearestPointOnBounds.y, bounds[1] );
|
||||
nearestPointOnBounds.y = Min( nearestPointOnBounds.y, bounds[4] );
|
||||
nearestPointOnBounds.z = Max( nearestPointOnBounds.z, bounds[2] );
|
||||
nearestPointOnBounds.z = Min( nearestPointOnBounds.z, bounds[5] );
|
||||
idVec3 delta = nearestPointOnBounds - localViewOrigin;
|
||||
float distance = delta.LengthFast();
|
||||
|
||||
if( !shader->IsLODVisibleForDistance( distance, r_lodMaterialDistance.GetFloat() ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// foresthale 2014-09-01: don't skip surfaces that use the "forceShadows" flag
|
||||
if( !shader->IsDrawn() && !shader->SurfaceCastsShadow() )
|
||||
{
|
||||
continue; // collision hulls, etc
|
||||
}
|
||||
|
@ -625,7 +656,8 @@ void R_AddSingleModel( viewEntity_t* vEntity )
|
|||
{
|
||||
continue;
|
||||
}
|
||||
if( !shader->IsDrawn() )
|
||||
// foresthale 2014-09-01: don't skip surfaces that use the "forceShadows" flag
|
||||
if( !shader->IsDrawn() && !shader->SurfaceCastsShadow() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -680,84 +712,90 @@ void R_AddSingleModel( viewEntity_t* vEntity )
|
|||
//--------------------------
|
||||
// base drawing surface
|
||||
//--------------------------
|
||||
drawSurf_t* baseDrawSurf = NULL;
|
||||
if( surfaceDirectlyVisible )
|
||||
const float* shaderRegisters = NULL;
|
||||
if( shader->IsDrawn() )
|
||||
{
|
||||
// make sure we have an ambient cache and all necessary normals / tangents
|
||||
if( !vertexCache.CacheIsCurrent( tri->indexCache ) )
|
||||
drawSurf_t* baseDrawSurf = NULL;
|
||||
if( surfaceDirectlyVisible )
|
||||
{
|
||||
tri->indexCache = vertexCache.AllocIndex( tri->indexes, ALIGN( tri->numIndexes * sizeof( triIndex_t ), INDEX_CACHE_ALIGN ) );
|
||||
}
|
||||
|
||||
if( !vertexCache.CacheIsCurrent( tri->ambientCache ) )
|
||||
{
|
||||
// we are going to use it for drawing, so make sure we have the tangents and normals
|
||||
if( shader->ReceivesLighting() && !tri->tangentsCalculated )
|
||||
{
|
||||
assert( tri->staticModelWithJoints == NULL );
|
||||
R_DeriveTangents( tri );
|
||||
|
||||
// RB: this was hit by parametric particle models ..
|
||||
//assert( false ); // this should no longer be hit
|
||||
// RB end
|
||||
}
|
||||
tri->ambientCache = vertexCache.AllocVertex( tri->verts, ALIGN( tri->numVerts * sizeof( idDrawVert ), VERTEX_CACHE_ALIGN ) );
|
||||
}
|
||||
|
||||
// add the surface for drawing
|
||||
// we can re-use some of the values for light interaction surfaces
|
||||
baseDrawSurf = ( drawSurf_t* )R_FrameAlloc( sizeof( *baseDrawSurf ), FRAME_ALLOC_DRAW_SURFACE );
|
||||
baseDrawSurf->frontEndGeo = tri;
|
||||
baseDrawSurf->space = vEntity;
|
||||
baseDrawSurf->scissorRect = vEntity->scissorRect;
|
||||
baseDrawSurf->extraGLState = 0;
|
||||
baseDrawSurf->renderZFail = 0;
|
||||
|
||||
R_SetupDrawSurfShader( baseDrawSurf, shader, renderEntity );
|
||||
|
||||
// Check for deformations (eyeballs, flares, etc)
|
||||
const deform_t shaderDeform = shader->Deform();
|
||||
if( shaderDeform != DFRM_NONE )
|
||||
{
|
||||
drawSurf_t* deformDrawSurf = R_DeformDrawSurf( baseDrawSurf );
|
||||
if( deformDrawSurf != NULL )
|
||||
{
|
||||
// any deforms may have created multiple draw surfaces
|
||||
for( drawSurf_t* surf = deformDrawSurf, * next = NULL; surf != NULL; surf = next )
|
||||
{
|
||||
next = surf->nextOnLight;
|
||||
|
||||
surf->linkChain = NULL;
|
||||
surf->nextOnLight = vEntity->drawSurfs;
|
||||
vEntity->drawSurfs = surf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Most deform source surfaces do not need to be rendered.
|
||||
// However, particles are rendered in conjunction with the source surface.
|
||||
if( shaderDeform == DFRM_NONE || shaderDeform == DFRM_PARTICLE || shaderDeform == DFRM_PARTICLE2 )
|
||||
{
|
||||
// copy verts and indexes to this frame's hardware memory if they aren't already there
|
||||
if( !vertexCache.CacheIsCurrent( tri->ambientCache ) )
|
||||
{
|
||||
tri->ambientCache = vertexCache.AllocVertex( tri->verts, ALIGN( tri->numVerts * sizeof( tri->verts[0] ), VERTEX_CACHE_ALIGN ) );
|
||||
}
|
||||
// make sure we have an ambient cache and all necessary normals / tangents
|
||||
if( !vertexCache.CacheIsCurrent( tri->indexCache ) )
|
||||
{
|
||||
tri->indexCache = vertexCache.AllocIndex( tri->indexes, ALIGN( tri->numIndexes * sizeof( tri->indexes[0] ), INDEX_CACHE_ALIGN ) );
|
||||
tri->indexCache = vertexCache.AllocIndex( tri->indexes, ALIGN( tri->numIndexes * sizeof( triIndex_t ), INDEX_CACHE_ALIGN ) );
|
||||
}
|
||||
|
||||
R_SetupDrawSurfJoints( baseDrawSurf, tri, shader );
|
||||
if( !vertexCache.CacheIsCurrent( tri->ambientCache ) )
|
||||
{
|
||||
// we are going to use it for drawing, so make sure we have the tangents and normals
|
||||
if( shader->ReceivesLighting() && !tri->tangentsCalculated )
|
||||
{
|
||||
assert( tri->staticModelWithJoints == NULL );
|
||||
R_DeriveTangents( tri );
|
||||
|
||||
// RB: this was hit by parametric particle models ..
|
||||
//assert( false ); // this should no longer be hit
|
||||
// RB end
|
||||
}
|
||||
tri->ambientCache = vertexCache.AllocVertex( tri->verts, ALIGN( tri->numVerts * sizeof( idDrawVert ), VERTEX_CACHE_ALIGN ) );
|
||||
}
|
||||
|
||||
baseDrawSurf->numIndexes = tri->numIndexes;
|
||||
baseDrawSurf->ambientCache = tri->ambientCache;
|
||||
baseDrawSurf->indexCache = tri->indexCache;
|
||||
baseDrawSurf->shadowCache = 0;
|
||||
// add the surface for drawing
|
||||
// we can re-use some of the values for light interaction surfaces
|
||||
baseDrawSurf = ( drawSurf_t* )R_FrameAlloc( sizeof( *baseDrawSurf ), FRAME_ALLOC_DRAW_SURFACE );
|
||||
baseDrawSurf->frontEndGeo = tri;
|
||||
baseDrawSurf->space = vEntity;
|
||||
baseDrawSurf->scissorRect = vEntity->scissorRect;
|
||||
baseDrawSurf->extraGLState = 0;
|
||||
baseDrawSurf->renderZFail = 0;
|
||||
|
||||
baseDrawSurf->linkChain = NULL; // link to the view
|
||||
baseDrawSurf->nextOnLight = vEntity->drawSurfs;
|
||||
vEntity->drawSurfs = baseDrawSurf;
|
||||
R_SetupDrawSurfShader( baseDrawSurf, shader, renderEntity );
|
||||
|
||||
shaderRegisters = baseDrawSurf->shaderRegisters;
|
||||
|
||||
// Check for deformations (eyeballs, flares, etc)
|
||||
const deform_t shaderDeform = shader->Deform();
|
||||
if( shaderDeform != DFRM_NONE )
|
||||
{
|
||||
drawSurf_t* deformDrawSurf = R_DeformDrawSurf( baseDrawSurf );
|
||||
if( deformDrawSurf != NULL )
|
||||
{
|
||||
// any deforms may have created multiple draw surfaces
|
||||
for( drawSurf_t* surf = deformDrawSurf, * next = NULL; surf != NULL; surf = next )
|
||||
{
|
||||
next = surf->nextOnLight;
|
||||
|
||||
surf->linkChain = NULL;
|
||||
surf->nextOnLight = vEntity->drawSurfs;
|
||||
vEntity->drawSurfs = surf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Most deform source surfaces do not need to be rendered.
|
||||
// However, particles are rendered in conjunction with the source surface.
|
||||
if( shaderDeform == DFRM_NONE || shaderDeform == DFRM_PARTICLE || shaderDeform == DFRM_PARTICLE2 )
|
||||
{
|
||||
// copy verts and indexes to this frame's hardware memory if they aren't already there
|
||||
if( !vertexCache.CacheIsCurrent( tri->ambientCache ) )
|
||||
{
|
||||
tri->ambientCache = vertexCache.AllocVertex( tri->verts, ALIGN( tri->numVerts * sizeof( tri->verts[0] ), VERTEX_CACHE_ALIGN ) );
|
||||
}
|
||||
if( !vertexCache.CacheIsCurrent( tri->indexCache ) )
|
||||
{
|
||||
tri->indexCache = vertexCache.AllocIndex( tri->indexes, ALIGN( tri->numIndexes * sizeof( tri->indexes[0] ), INDEX_CACHE_ALIGN ) );
|
||||
}
|
||||
|
||||
R_SetupDrawSurfJoints( baseDrawSurf, tri, shader );
|
||||
|
||||
baseDrawSurf->numIndexes = tri->numIndexes;
|
||||
baseDrawSurf->ambientCache = tri->ambientCache;
|
||||
baseDrawSurf->indexCache = tri->indexCache;
|
||||
baseDrawSurf->shadowCache = 0;
|
||||
|
||||
baseDrawSurf->linkChain = NULL; // link to the view
|
||||
baseDrawSurf->nextOnLight = vEntity->drawSurfs;
|
||||
vEntity->drawSurfs = baseDrawSurf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -810,104 +848,117 @@ void R_AddSingleModel( viewEntity_t* vEntity )
|
|||
// contact the light, even when the total model does
|
||||
if( surfInter == NULL || surfInter->lightTrisIndexCache > 0 )
|
||||
{
|
||||
// create a drawSurf for this interaction
|
||||
drawSurf_t* lightDrawSurf = ( drawSurf_t* )R_FrameAlloc( sizeof( *lightDrawSurf ), FRAME_ALLOC_DRAW_SURFACE );
|
||||
|
||||
if( surfInter != NULL )
|
||||
// make sure we have a valid shader register even if we didn't generate a drawn mesh above
|
||||
if( shaderRegisters == NULL )
|
||||
{
|
||||
// optimized static interaction
|
||||
lightDrawSurf->numIndexes = surfInter->numLightTrisIndexes;
|
||||
lightDrawSurf->indexCache = surfInter->lightTrisIndexCache;
|
||||
drawSurf_t scratchSurf;
|
||||
R_SetupDrawSurfShader( &scratchSurf, shader, renderEntity );
|
||||
shaderRegisters = scratchSurf.shaderRegisters;
|
||||
}
|
||||
else
|
||||
|
||||
if( shaderRegisters != NULL )
|
||||
{
|
||||
// throw the entire source surface at it without any per-triangle culling
|
||||
lightDrawSurf->numIndexes = tri->numIndexes;
|
||||
lightDrawSurf->indexCache = tri->indexCache;
|
||||
// create a drawSurf for this interaction
|
||||
drawSurf_t* lightDrawSurf = ( drawSurf_t* )R_FrameAlloc( sizeof( *lightDrawSurf ), FRAME_ALLOC_DRAW_SURFACE );
|
||||
|
||||
// optionally cull the triangles to the light volume
|
||||
if( r_cullDynamicLightTriangles.GetBool() )
|
||||
if( surfInter != NULL )
|
||||
{
|
||||
|
||||
vertCacheHandle_t lightIndexCache = vertexCache.AllocIndex( NULL, ALIGN( lightDrawSurf->numIndexes * sizeof( triIndex_t ), INDEX_CACHE_ALIGN ) );
|
||||
if( vertexCache.CacheIsCurrent( lightIndexCache ) )
|
||||
// optimized static interaction
|
||||
lightDrawSurf->numIndexes = surfInter->numLightTrisIndexes;
|
||||
lightDrawSurf->indexCache = surfInter->lightTrisIndexCache;
|
||||
}
|
||||
else
|
||||
{
|
||||
// throw the entire source surface at it without any per-triangle culling
|
||||
lightDrawSurf->numIndexes = tri->numIndexes;
|
||||
lightDrawSurf->indexCache = tri->indexCache;
|
||||
|
||||
// optionally cull the triangles to the light volume
|
||||
// motorsep 11-09-2014; added && shader->SurfaceCastsShadow() per Lordhavoc's recommendation; should skip shadows calculation for surfaces with noShadows material flag
|
||||
// when using shadow volumes
|
||||
if( r_cullDynamicLightTriangles.GetBool() && !r_skipDynamicShadows.GetBool() && !r_useShadowMapping.GetBool() && shader->SurfaceCastsShadow() )
|
||||
{
|
||||
lightDrawSurf->indexCache = lightIndexCache;
|
||||
|
||||
dynamicShadowParms = ( dynamicShadowVolumeParms_t* )R_FrameAlloc( sizeof( dynamicShadowParms[0] ), FRAME_ALLOC_SHADOW_VOLUME_PARMS );
|
||||
|
||||
dynamicShadowParms->verts = tri->verts;
|
||||
dynamicShadowParms->numVerts = tri->numVerts;
|
||||
dynamicShadowParms->indexes = tri->indexes;
|
||||
dynamicShadowParms->numIndexes = tri->numIndexes;
|
||||
dynamicShadowParms->silEdges = tri->silEdges;
|
||||
dynamicShadowParms->numSilEdges = tri->numSilEdges;
|
||||
dynamicShadowParms->joints = gpuSkinned ? tri->staticModelWithJoints->jointsInverted : NULL;
|
||||
dynamicShadowParms->numJoints = gpuSkinned ? tri->staticModelWithJoints->numInvertedJoints : 0;
|
||||
dynamicShadowParms->triangleBounds = tri->bounds;
|
||||
dynamicShadowParms->triangleMVP = vEntity->mvp;
|
||||
dynamicShadowParms->localLightOrigin = localLightOrigin;
|
||||
dynamicShadowParms->localViewOrigin = localViewOrigin;
|
||||
idRenderMatrix::Multiply( vLight->lightDef->baseLightProject, entityDef->modelRenderMatrix, dynamicShadowParms->localLightProject );
|
||||
dynamicShadowParms->zNear = znear;
|
||||
dynamicShadowParms->lightZMin = vLight->scissorRect.zmin;
|
||||
dynamicShadowParms->lightZMax = vLight->scissorRect.zmax;
|
||||
dynamicShadowParms->cullShadowTrianglesToLight = false;
|
||||
dynamicShadowParms->forceShadowCaps = false;
|
||||
dynamicShadowParms->useShadowPreciseInsideTest = false;
|
||||
dynamicShadowParms->useShadowDepthBounds = false;
|
||||
dynamicShadowParms->tempFacing = NULL;
|
||||
dynamicShadowParms->tempCulled = NULL;
|
||||
dynamicShadowParms->tempVerts = NULL;
|
||||
dynamicShadowParms->indexBuffer = NULL;
|
||||
dynamicShadowParms->shadowIndices = NULL;
|
||||
dynamicShadowParms->maxShadowIndices = 0;
|
||||
dynamicShadowParms->numShadowIndices = NULL;
|
||||
dynamicShadowParms->lightIndices = ( triIndex_t* )vertexCache.MappedIndexBuffer( lightIndexCache );
|
||||
dynamicShadowParms->maxLightIndices = lightDrawSurf->numIndexes;
|
||||
dynamicShadowParms->numLightIndices = &lightDrawSurf->numIndexes;
|
||||
dynamicShadowParms->renderZFail = NULL;
|
||||
dynamicShadowParms->shadowZMin = NULL;
|
||||
dynamicShadowParms->shadowZMax = NULL;
|
||||
dynamicShadowParms->shadowVolumeState = & lightDrawSurf->shadowVolumeState;
|
||||
|
||||
lightDrawSurf->shadowVolumeState = SHADOWVOLUME_UNFINISHED;
|
||||
|
||||
dynamicShadowParms->next = vEntity->dynamicShadowVolumes;
|
||||
vEntity->dynamicShadowVolumes = dynamicShadowParms;
|
||||
vertCacheHandle_t lightIndexCache = vertexCache.AllocIndex( NULL, ALIGN( lightDrawSurf->numIndexes * sizeof( triIndex_t ), INDEX_CACHE_ALIGN ) );
|
||||
if( vertexCache.CacheIsCurrent( lightIndexCache ) )
|
||||
{
|
||||
lightDrawSurf->indexCache = lightIndexCache;
|
||||
|
||||
dynamicShadowParms = ( dynamicShadowVolumeParms_t* )R_FrameAlloc( sizeof( dynamicShadowParms[0] ), FRAME_ALLOC_SHADOW_VOLUME_PARMS );
|
||||
|
||||
dynamicShadowParms->verts = tri->verts;
|
||||
dynamicShadowParms->numVerts = tri->numVerts;
|
||||
dynamicShadowParms->indexes = tri->indexes;
|
||||
dynamicShadowParms->numIndexes = tri->numIndexes;
|
||||
dynamicShadowParms->silEdges = tri->silEdges;
|
||||
dynamicShadowParms->numSilEdges = tri->numSilEdges;
|
||||
dynamicShadowParms->joints = gpuSkinned ? tri->staticModelWithJoints->jointsInverted : NULL;
|
||||
dynamicShadowParms->numJoints = gpuSkinned ? tri->staticModelWithJoints->numInvertedJoints : 0;
|
||||
dynamicShadowParms->triangleBounds = tri->bounds;
|
||||
dynamicShadowParms->triangleMVP = vEntity->mvp;
|
||||
dynamicShadowParms->localLightOrigin = localLightOrigin;
|
||||
dynamicShadowParms->localViewOrigin = localViewOrigin;
|
||||
idRenderMatrix::Multiply( vLight->lightDef->baseLightProject, entityDef->modelRenderMatrix, dynamicShadowParms->localLightProject );
|
||||
dynamicShadowParms->zNear = znear;
|
||||
dynamicShadowParms->lightZMin = vLight->scissorRect.zmin;
|
||||
dynamicShadowParms->lightZMax = vLight->scissorRect.zmax;
|
||||
dynamicShadowParms->cullShadowTrianglesToLight = false;
|
||||
dynamicShadowParms->forceShadowCaps = false;
|
||||
dynamicShadowParms->useShadowPreciseInsideTest = false;
|
||||
dynamicShadowParms->useShadowDepthBounds = false;
|
||||
dynamicShadowParms->tempFacing = NULL;
|
||||
dynamicShadowParms->tempCulled = NULL;
|
||||
dynamicShadowParms->tempVerts = NULL;
|
||||
dynamicShadowParms->indexBuffer = NULL;
|
||||
dynamicShadowParms->shadowIndices = NULL;
|
||||
dynamicShadowParms->maxShadowIndices = 0;
|
||||
dynamicShadowParms->numShadowIndices = NULL;
|
||||
dynamicShadowParms->lightIndices = ( triIndex_t* )vertexCache.MappedIndexBuffer( lightIndexCache );
|
||||
dynamicShadowParms->maxLightIndices = lightDrawSurf->numIndexes;
|
||||
dynamicShadowParms->numLightIndices = &lightDrawSurf->numIndexes;
|
||||
dynamicShadowParms->renderZFail = NULL;
|
||||
dynamicShadowParms->shadowZMin = NULL;
|
||||
dynamicShadowParms->shadowZMax = NULL;
|
||||
dynamicShadowParms->shadowVolumeState = & lightDrawSurf->shadowVolumeState;
|
||||
|
||||
lightDrawSurf->shadowVolumeState = SHADOWVOLUME_UNFINISHED;
|
||||
|
||||
dynamicShadowParms->next = vEntity->dynamicShadowVolumes;
|
||||
vEntity->dynamicShadowVolumes = dynamicShadowParms;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lightDrawSurf->ambientCache = tri->ambientCache;
|
||||
lightDrawSurf->shadowCache = 0;
|
||||
lightDrawSurf->frontEndGeo = tri;
|
||||
lightDrawSurf->space = vEntity;
|
||||
lightDrawSurf->material = shader;
|
||||
lightDrawSurf->extraGLState = 0;
|
||||
lightDrawSurf->scissorRect = vLight->scissorRect; // interactionScissor;
|
||||
lightDrawSurf->sort = 0.0f;
|
||||
lightDrawSurf->renderZFail = 0;
|
||||
lightDrawSurf->shaderRegisters = shaderRegisters;
|
||||
|
||||
R_SetupDrawSurfJoints( lightDrawSurf, tri, shader );
|
||||
|
||||
// Determine which linked list to add the light surface to.
|
||||
// There will only be localSurfaces if the light casts shadows and
|
||||
// there are surfaces with NOSELFSHADOW.
|
||||
if( shader->Coverage() == MC_TRANSLUCENT )
|
||||
{
|
||||
lightDrawSurf->linkChain = &vLight->translucentInteractions;
|
||||
}
|
||||
else if( !lightDef->parms.noShadows && shader->TestMaterialFlag( MF_NOSELFSHADOW ) )
|
||||
{
|
||||
lightDrawSurf->linkChain = &vLight->localInteractions;
|
||||
}
|
||||
else
|
||||
{
|
||||
lightDrawSurf->linkChain = &vLight->globalInteractions;
|
||||
}
|
||||
lightDrawSurf->nextOnLight = vEntity->drawSurfs;
|
||||
vEntity->drawSurfs = lightDrawSurf;
|
||||
}
|
||||
lightDrawSurf->ambientCache = tri->ambientCache;
|
||||
lightDrawSurf->shadowCache = 0;
|
||||
lightDrawSurf->frontEndGeo = tri;
|
||||
lightDrawSurf->space = vEntity;
|
||||
lightDrawSurf->material = shader;
|
||||
lightDrawSurf->extraGLState = 0;
|
||||
lightDrawSurf->scissorRect = vLight->scissorRect; // interactionScissor;
|
||||
lightDrawSurf->sort = 0.0f;
|
||||
lightDrawSurf->renderZFail = 0;
|
||||
lightDrawSurf->shaderRegisters = baseDrawSurf->shaderRegisters;
|
||||
|
||||
R_SetupDrawSurfJoints( lightDrawSurf, tri, shader );
|
||||
|
||||
// Determine which linked list to add the light surface to.
|
||||
// There will only be localSurfaces if the light casts shadows and
|
||||
// there are surfaces with NOSELFSHADOW.
|
||||
if( shader->Coverage() == MC_TRANSLUCENT )
|
||||
{
|
||||
lightDrawSurf->linkChain = &vLight->translucentInteractions;
|
||||
}
|
||||
else if( !lightDef->parms.noShadows && shader->TestMaterialFlag( MF_NOSELFSHADOW ) )
|
||||
{
|
||||
lightDrawSurf->linkChain = &vLight->localInteractions;
|
||||
}
|
||||
else
|
||||
{
|
||||
lightDrawSurf->linkChain = &vLight->globalInteractions;
|
||||
}
|
||||
lightDrawSurf->nextOnLight = vEntity->drawSurfs;
|
||||
vEntity->drawSurfs = lightDrawSurf;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -915,10 +966,51 @@ void R_AddSingleModel( viewEntity_t* vEntity )
|
|||
// surface shadows
|
||||
//--------------------------
|
||||
|
||||
#if 1
|
||||
if( !shader->SurfaceCastsShadow() && !( r_useShadowMapping.GetBool() && r_forceShadowMapsOnAlphaTestedSurfaces.GetBool() && shader->Coverage() == MC_PERFORATED ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
#else
|
||||
// Steel Storm 2 behaviour - this destroys many alpha tested shadows in vanilla BFG
|
||||
|
||||
// motorsep 11-08-2014; if r_forceShadowMapsOnAlphaTestedSurfaces is 0 when shadow mapping is on,
|
||||
// don't render shadows from all alphaTest surfaces.
|
||||
// Useful as global performance booster for old GPUs to disable shadows from grass/foliage/etc.
|
||||
if( r_useShadowMapping.GetBool() )
|
||||
{
|
||||
if( shader->Coverage() == MC_PERFORATED )
|
||||
{
|
||||
if( !r_forceShadowMapsOnAlphaTestedSurfaces.GetBool() )
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// if material has "noShadows" global key
|
||||
if( !shader->SurfaceCastsShadow() )
|
||||
{
|
||||
// motorsep 11-08-2014; if r_forceShadowMapsOnAlphaTestedSurfaces is 1 when shadow mapping is on,
|
||||
// check if a surface IS NOT alphaTested and has "noShadows" global key;
|
||||
// or if a surface IS alphaTested and has "noShadows" global key;
|
||||
// if either is true, don't make surfaces cast shadow maps.
|
||||
if( r_useShadowMapping.GetBool() )
|
||||
{
|
||||
if( shader->Coverage() != MC_PERFORATED && shader->TestMaterialFlag( MF_NOSHADOWS ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if( shader->Coverage() == MC_PERFORATED && shader->TestMaterialFlag( MF_NOSHADOWS ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if( !lightDef->LightCastsShadows() )
|
||||
{
|
||||
continue;
|
||||
|
@ -929,9 +1021,10 @@ void R_AddSingleModel( viewEntity_t* vEntity )
|
|||
}
|
||||
|
||||
// if the static shadow does not have any shadows
|
||||
if( surfInter != NULL && surfInter->numShadowIndexes == 0 && !r_useShadowMapping.GetBool() )
|
||||
if( surfInter != NULL && surfInter->numShadowIndexes == 0 )
|
||||
{
|
||||
continue;
|
||||
if( !r_useShadowMapping.GetBool() )
|
||||
continue;
|
||||
}
|
||||
|
||||
// some entities, like view weapons, don't cast any shadows
|
||||
|
@ -946,6 +1039,7 @@ void R_AddSingleModel( viewEntity_t* vEntity )
|
|||
continue;
|
||||
}
|
||||
|
||||
|
||||
// RB begin
|
||||
if( r_useShadowMapping.GetBool() )
|
||||
{
|
||||
|
@ -1050,7 +1144,7 @@ void R_AddSingleModel( viewEntity_t* vEntity )
|
|||
shadowDrawSurf->scissorRect = vLight->scissorRect; // default to the light scissor and light depth bounds
|
||||
shadowDrawSurf->shadowVolumeState = SHADOWVOLUME_DONE; // assume the shadow volume is done in case r_skipStaticShadows is set
|
||||
|
||||
if( !r_skipStaticShadows.GetBool() )
|
||||
if( !r_skipStaticShadows.GetBool() && !r_useShadowMapping.GetBool() )
|
||||
{
|
||||
staticShadowVolumeParms_t* staticShadowParms = ( staticShadowVolumeParms_t* )R_FrameAlloc( sizeof( staticShadowParms[0] ), FRAME_ALLOC_SHADOW_VOLUME_PARMS );
|
||||
|
||||
|
@ -1107,9 +1201,8 @@ void R_AddSingleModel( viewEntity_t* vEntity )
|
|||
shadowDrawSurf->shadowVolumeState = SHADOWVOLUME_DONE; // assume the shadow volume is done in case the index cache allocation failed
|
||||
|
||||
// if the index cache was successfully allocated then setup the parms to create a shadow volume in parallel
|
||||
if( vertexCache.CacheIsCurrent( shadowDrawSurf->indexCache ) && !r_skipDynamicShadows.GetBool() )
|
||||
if( vertexCache.CacheIsCurrent( shadowDrawSurf->indexCache ) && !r_skipDynamicShadows.GetBool() && !r_useShadowMapping.GetBool() )
|
||||
{
|
||||
|
||||
// if the parms were not already allocated for culling interaction triangles to the light frustum
|
||||
if( dynamicShadowParms == NULL )
|
||||
{
|
||||
|
@ -1265,48 +1358,55 @@ void R_AddModels()
|
|||
//-------------------------------------------------
|
||||
// Kick off jobs to setup static and dynamic shadow volumes.
|
||||
//-------------------------------------------------
|
||||
|
||||
if( r_useParallelAddShadows.GetInteger() == 1 )
|
||||
if( ( r_skipStaticShadows.GetBool() && r_skipDynamicShadows.GetBool() ) || r_useShadowMapping.GetBool() )
|
||||
{
|
||||
for( viewEntity_t* vEntity = tr.viewDef->viewEntitys; vEntity != NULL; vEntity = vEntity->next )
|
||||
{
|
||||
for( staticShadowVolumeParms_t* shadowParms = vEntity->staticShadowVolumes; shadowParms != NULL; shadowParms = shadowParms->next )
|
||||
{
|
||||
tr.frontEndJobList->AddJob( ( jobRun_t )StaticShadowVolumeJob, shadowParms );
|
||||
}
|
||||
for( dynamicShadowVolumeParms_t* shadowParms = vEntity->dynamicShadowVolumes; shadowParms != NULL; shadowParms = shadowParms->next )
|
||||
{
|
||||
tr.frontEndJobList->AddJob( ( jobRun_t )DynamicShadowVolumeJob, shadowParms );
|
||||
}
|
||||
vEntity->staticShadowVolumes = NULL;
|
||||
vEntity->dynamicShadowVolumes = NULL;
|
||||
}
|
||||
tr.frontEndJobList->Submit();
|
||||
// wait here otherwise the shadow volume index buffer may be unmapped before all shadow volumes have been constructed
|
||||
tr.frontEndJobList->Wait();
|
||||
// no shadow volumes were chained to any entity, all are in DONE state, we don't need to Submit() or Wait()
|
||||
}
|
||||
else
|
||||
{
|
||||
int start = Sys_Microseconds();
|
||||
|
||||
for( viewEntity_t* vEntity = tr.viewDef->viewEntitys; vEntity != NULL; vEntity = vEntity->next )
|
||||
if( r_useParallelAddShadows.GetInteger() == 1 )
|
||||
{
|
||||
for( staticShadowVolumeParms_t* shadowParms = vEntity->staticShadowVolumes; shadowParms != NULL; shadowParms = shadowParms->next )
|
||||
for( viewEntity_t* vEntity = tr.viewDef->viewEntitys; vEntity != NULL; vEntity = vEntity->next )
|
||||
{
|
||||
StaticShadowVolumeJob( shadowParms );
|
||||
for( staticShadowVolumeParms_t* shadowParms = vEntity->staticShadowVolumes; shadowParms != NULL; shadowParms = shadowParms->next )
|
||||
{
|
||||
tr.frontEndJobList->AddJob( ( jobRun_t )StaticShadowVolumeJob, shadowParms );
|
||||
}
|
||||
for( dynamicShadowVolumeParms_t* shadowParms = vEntity->dynamicShadowVolumes; shadowParms != NULL; shadowParms = shadowParms->next )
|
||||
{
|
||||
tr.frontEndJobList->AddJob( ( jobRun_t )DynamicShadowVolumeJob, shadowParms );
|
||||
}
|
||||
vEntity->staticShadowVolumes = NULL;
|
||||
vEntity->dynamicShadowVolumes = NULL;
|
||||
}
|
||||
for( dynamicShadowVolumeParms_t* shadowParms = vEntity->dynamicShadowVolumes; shadowParms != NULL; shadowParms = shadowParms->next )
|
||||
{
|
||||
DynamicShadowVolumeJob( shadowParms );
|
||||
}
|
||||
vEntity->staticShadowVolumes = NULL;
|
||||
vEntity->dynamicShadowVolumes = NULL;
|
||||
tr.frontEndJobList->Submit();
|
||||
// wait here otherwise the shadow volume index buffer may be unmapped before all shadow volumes have been constructed
|
||||
tr.frontEndJobList->Wait();
|
||||
}
|
||||
else
|
||||
{
|
||||
int start = Sys_Microseconds();
|
||||
|
||||
for( viewEntity_t* vEntity = tr.viewDef->viewEntitys; vEntity != NULL; vEntity = vEntity->next )
|
||||
{
|
||||
for( staticShadowVolumeParms_t* shadowParms = vEntity->staticShadowVolumes; shadowParms != NULL; shadowParms = shadowParms->next )
|
||||
{
|
||||
StaticShadowVolumeJob( shadowParms );
|
||||
}
|
||||
for( dynamicShadowVolumeParms_t* shadowParms = vEntity->dynamicShadowVolumes; shadowParms != NULL; shadowParms = shadowParms->next )
|
||||
{
|
||||
DynamicShadowVolumeJob( shadowParms );
|
||||
}
|
||||
vEntity->staticShadowVolumes = NULL;
|
||||
vEntity->dynamicShadowVolumes = NULL;
|
||||
}
|
||||
|
||||
int end = Sys_Microseconds();
|
||||
backEnd.pc.shadowMicroSec += end - start;
|
||||
}
|
||||
|
||||
int end = Sys_Microseconds();
|
||||
backEnd.pc.shadowMicroSec += end - start;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// Move the draw surfs to the view.
|
||||
//-------------------------------------------------
|
||||
|
|
Loading…
Reference in a new issue