From 33c85ad3c3bcb69eed9c24cc9a753a1530595eff Mon Sep 17 00:00:00 2001 From: VReaperV Date: Sun, 18 May 2025 18:22:49 +0300 Subject: [PATCH 01/41] Update azure pipelines image 20.04 is no longer supported by azure. --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index d5b61aba9..fea411540 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -64,7 +64,7 @@ jobs: - job: Linux pool: - vmImage: 'ubuntu-20.04' + vmImage: 'ubuntu-22.04' strategy: matrix: GCC: From e101fedf7e06c872f54f8f15b50d053c3521c013 Mon Sep 17 00:00:00 2001 From: VReaperV Date: Mon, 19 May 2025 11:05:59 +0300 Subject: [PATCH 02/41] NUKE RDF_SKYBOXPORTAL usages This is half of a feature from Wolf:ET, but we don't have the sgame/cgame counterpart, and none of the maps made for Unvanquished/Tremulous appear to use it. --- src/engine/renderer/tr_bsp.cpp | 4 ---- src/engine/renderer/tr_local.h | 6 ----- src/engine/renderer/tr_scene.cpp | 2 +- src/engine/renderer/tr_world.cpp | 40 +++++--------------------------- 4 files changed, 7 insertions(+), 45 deletions(-) diff --git a/src/engine/renderer/tr_bsp.cpp b/src/engine/renderer/tr_bsp.cpp index b327378de..45ed91ed5 100644 --- a/src/engine/renderer/tr_bsp.cpp +++ b/src/engine/renderer/tr_bsp.cpp @@ -2980,10 +2980,6 @@ static void R_LoadNodesAndLeafs( lump_t *nodeLump, lump_t *leafLump ) s_worldData.numnodes = numNodes + numLeafs; s_worldData.numDecisionNodes = numNodes; - // ydnar: skybox optimization - s_worldData.numSkyNodes = 0; - s_worldData.skyNodes = (bspNode_t**) ri.Hunk_Alloc( WORLD_MAX_SKY_NODES * sizeof( *s_worldData.skyNodes ), ha_pref::h_low ); - // load nodes for ( i = 0; i < numNodes; i++, in++, out++ ) { diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index 283b80d06..4107c049c 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -1890,9 +1890,6 @@ enum class ssaoMode { vec3_t maxs; }; -// ydnar: optimization -#define WORLD_MAX_SKY_NODES 32 - struct world_t { char name[ MAX_QPATH ]; // ie: maps/tim_dm2.bsp @@ -1913,9 +1910,6 @@ enum class ssaoMode { int numDecisionNodes; bspNode_t *nodes; - int numSkyNodes; - bspNode_t **skyNodes; // ydnar: don't walk the entire bsp when rendering sky - int numPortals; AABB *portals; diff --git a/src/engine/renderer/tr_scene.cpp b/src/engine/renderer/tr_scene.cpp index 4626d9dae..97bde5c87 100644 --- a/src/engine/renderer/tr_scene.cpp +++ b/src/engine/renderer/tr_scene.cpp @@ -541,7 +541,7 @@ void RE_RenderScene( const refdef_t *fd ) // will force a reset of the visible leafs even if the view hasn't moved tr.refdef.areamaskModified = false; - if ( !( tr.refdef.rdflags & RDF_NOWORLDMODEL ) && !( ( tr.refdef.rdflags & RDF_SKYBOXPORTAL ) && tr.world->numSkyNodes > 0 ) ) + if ( !( tr.refdef.rdflags & RDF_NOWORLDMODEL ) ) { int areaDiff; int i; diff --git a/src/engine/renderer/tr_world.cpp b/src/engine/renderer/tr_world.cpp index 43b746845..335e67f99 100644 --- a/src/engine/renderer/tr_world.cpp +++ b/src/engine/renderer/tr_world.cpp @@ -794,20 +794,6 @@ static void R_MarkLeaves() continue; } - // ydnar: don't want to walk the entire bsp to add skybox surfaces - if ( tr.refdef.rdflags & RDF_SKYBOXPORTAL ) - { - // this only happens once, as game/cgame know the origin of the skybox - // this also means the skybox portal cannot move, as this list is calculated once and never again - if ( tr.world->numSkyNodes < WORLD_MAX_SKY_NODES ) - { - tr.world->skyNodes[ tr.world->numSkyNodes++ ] = leaf; - } - - R_AddLeafSurfaces( leaf, FRUSTUM_CLIPALL ); - continue; - } - parent = leaf; do @@ -846,28 +832,14 @@ void R_AddWorldSurfaces() // clear out the visible min/max ClearBounds( tr.viewParms.visBounds[ 0 ], tr.viewParms.visBounds[ 1 ] ); - // render sky or world? - if ( tr.refdef.rdflags & RDF_SKYBOXPORTAL && tr.world->numSkyNodes > 0 ) - { - int i; - bspNode_t **node; + // determine which leaves are in the PVS / areamask + R_MarkLeaves(); - for ( i = 0, node = tr.world->skyNodes; i < tr.world->numSkyNodes; i++, node++ ) - { - R_AddLeafSurfaces( *node, FRUSTUM_CLIPALL ); - } - } - else - { - // determine which leaves are in the PVS / areamask - R_MarkLeaves(); - - // clear traversal list - backEndData[ tr.smpFrame ]->traversalLength = 0; + // clear traversal list + backEndData[ tr.smpFrame ]->traversalLength = 0; - // update visbounds and add surfaces that weren't cached with VBOs - R_RecursiveWorldNode( tr.world->nodes, FRUSTUM_CLIPALL ); - } + // update visbounds and add surfaces that weren't cached with VBOs + R_RecursiveWorldNode( tr.world->nodes, FRUSTUM_CLIPALL ); } /* From 801f058d9cbddf67846f0d70554701dca84ee035 Mon Sep 17 00:00:00 2001 From: VReaperV Date: Wed, 7 May 2025 02:02:12 +0300 Subject: [PATCH 03/41] Set totalDrawSurfs correctly --- src/engine/renderer/Material.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/engine/renderer/Material.cpp b/src/engine/renderer/Material.cpp index eb8488f4f..1ec60c78f 100644 --- a/src/engine/renderer/Material.cpp +++ b/src/engine/renderer/Material.cpp @@ -521,6 +521,8 @@ void MaterialSystem::GenerateWorldCommandBuffer( std::vector& s Log::Debug( "Total batch count: %u", totalBatchCount ); + totalDrawSurfs = surfaces.size(); + surfaceDescriptorsCount = totalDrawSurfs; descriptorSize = BOUNDING_SPHERE_SIZE + maxStages; surfaceDescriptorsSSBO.BufferData( surfaceDescriptorsCount * descriptorSize, nullptr, GL_STATIC_DRAW ); @@ -685,7 +687,7 @@ void MaterialSystem::GenerateWorldCommandBuffer( std::vector& s for ( MaterialPack& pack : materialPacks ) { totalCount += pack.materials.size(); } - Log::Notice( "Generated %u BSP materials from %u BSP surfaces", totalCount, surfaces.size() ); + Log::Notice( "Generated %u BSP materials from %u BSP surfaces", totalCount, totalDrawSurfs ); Log::Notice( "Materials UBO: total: %.2f kb, dynamic: %.2f kb, texData: %.2f kb", totalStageSize * 4 / 1024.0f, dynamicStagesSize * 4 / 1024.0f, ( texData.size() + dynamicTexData.size() ) * TEX_BUNDLE_SIZE * 4 / 1024.0f ); @@ -1326,8 +1328,6 @@ void MaterialSystem::ProcessStage( MaterialSurface* surface, shaderStage_t* pSta A material represents a distinct global OpenGL state (e. g. blend function, depth test, depth write etc.) Materials can have a dependency on other materials to make sure that consecutive stages are rendered in the proper order */ void MaterialSystem::GenerateMaterial( MaterialSurface* surface ) { - totalDrawSurfs++; - uint32_t stage = 0; uint32_t previousMaterialID = 0; From 3885575160e4279ab7b2c87bbb7c5f7501e90ce5 Mon Sep 17 00:00:00 2001 From: VReaperV Date: Tue, 6 May 2025 16:06:12 +0300 Subject: [PATCH 04/41] Merge material system surfaces Impoves VS lane usage. The triangles are assigned to a grid with cell size dependent on map bounds. This allows fast merging without running out of memory. --- src/engine/renderer/GeometryOptimiser.cpp | 231 +++++++++++++++++++--- src/engine/renderer/GeometryOptimiser.h | 31 +-- src/engine/renderer/Material.cpp | 19 +- src/engine/renderer/Material.h | 5 +- src/engine/renderer/tr_bsp.cpp | 15 +- src/engine/renderer/tr_local.h | 8 + 6 files changed, 251 insertions(+), 58 deletions(-) diff --git a/src/engine/renderer/GeometryOptimiser.cpp b/src/engine/renderer/GeometryOptimiser.cpp index 1ab9791a0..b33912944 100644 --- a/src/engine/renderer/GeometryOptimiser.cpp +++ b/src/engine/renderer/GeometryOptimiser.cpp @@ -27,6 +27,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "GeometryOptimiser.h" +#include "ShadeCommon.h" +#include "GeometryCache.h" + static int LeafSurfaceCompare( const void* a, const void* b ) { bspSurface_t* aa, * bb; @@ -420,35 +423,39 @@ void MergeDuplicateVertices( bspSurface_t** rendererSurfaces, int numSurfaces, s Log::Notice( "Merged %i vertices into %i in %i ms", numVerticesIn, numVerticesOut, Sys::Milliseconds() - start ); } -/* static void ProcessMaterialSurface( MaterialSurface& surface, std::vector& materialSurfaces, - std::vector& processedMaterialSurfaces, - srfVert_t* verts, glIndex_t* indices ) { - if ( surface.count == MAX_MATERIAL_SURFACE_TRIS ) { - materialSurfaces.emplace_back( surface ); +static void ProcessMaterialSurface( MaterialSurface* surface, SurfaceIndexes* surfaceIdxs, + std::vector& processedSurfaces, + const srfVert_t* vertexes, glIndex_t* idxs, uint32_t* numIndices ) { + vec3_t mins; + vec3_t maxs; + ClearBounds( mins, maxs ); + + for ( uint32_t i = 0; i < surface->count; i++ ) { + AddPointToBounds( vertexes[surfaceIdxs->idxs[i]].xyz, mins, maxs ); } - while ( surface.count > MAX_MATERIAL_SURFACE_TRIS ) { - MaterialSurface srf = surface; + const uint32_t oldFirstIndex = surface->firstIndex; + surface->firstIndex = *numIndices; - srf.count = MAX_MATERIAL_SURFACE_TRIS; - surface.count -= MAX_MATERIAL_SURFACE_TRIS; - surface.firstIndex += MAX_MATERIAL_SURFACE_TRIS; + memcpy( idxs + ( *numIndices ), surfaceIdxs->idxs, surface->count * sizeof( glIndex_t ) ); - processedMaterialSurfaces.push_back( srf ); - } -} */ + *numIndices += surface->count; -std::vector OptimiseMapGeometryMaterial(bspSurface_t** rendererSurfaces, int numSurfaces ) { - std::vector materialSurfaces; - materialSurfaces.reserve( numSurfaces ); + SphereFromBounds( mins, maxs, surface->origin, &surface->radius ); - std::vector processedMaterialSurfaces; - processedMaterialSurfaces.reserve( numSurfaces ); + processedSurfaces.emplace_back( *surface ); - // std::unordered_map triEdges; + surface->firstIndex = oldFirstIndex; +} + +std::vector OptimiseMapGeometryMaterial( world_t* world, bspSurface_t** rendererSurfaces, int numSurfaces, + const srfVert_t* vertices, const int numVerticesIn, const glIndex_t* indices, const int numIndicesIn ) { + std::vector materialSurfaces; + materialSurfaces.reserve( numSurfaces ); - vec3_t worldBounds[2] = {}; materialSystem.buildOneShader = false; + vec3_t worldBounds[2] = {}; + ClearBounds( worldBounds[0], worldBounds[1] ); for ( int i = 0; i < numSurfaces; i++ ) { bspSurface_t* surface = rendererSurfaces[i]; @@ -483,13 +490,191 @@ std::vector OptimiseMapGeometryMaterial(bspSurface_t** renderer materialSurfaces.emplace_back( srf ); } - + materialSystem.SetWorldBounds( worldBounds ); materialSystem.buildOneShader = true; + /* GenerateWorldMaterialsBuffer() must be called before the surface merging loop, because it will compare the UBO offsets, + which are set by this call */ materialSystem.GenerateWorldMaterialsBuffer(); + + std::vector processedMaterialSurfaces; + processedMaterialSurfaces.reserve( numSurfaces ); + + std::function + materialSurfaceSort = []( const MaterialSurface& lhs, const MaterialSurface& rhs ) { + if ( lhs.stages < rhs.stages ) { + return true; + } else if ( lhs.stages > rhs.stages ) { + return false; + } + + for ( uint8_t stage = 0; stage < lhs.stages; stage++ ) { + if ( lhs.materialPackIDs[stage] < rhs.materialPackIDs[stage] ) { + return true; + } else if ( lhs.materialPackIDs[stage] > rhs.materialPackIDs[stage] ) { + return false; + } + + if ( lhs.materialIDs[stage] < rhs.materialIDs[stage] ) { + return true; + } else if ( lhs.materialIDs[stage] > rhs.materialIDs[stage] ) { + return false; + } + + shaderStage_t* pStage = lhs.shaderStages[stage]; + pStage = pStage->materialRemappedStage ? pStage->materialRemappedStage : pStage; + + const uint32_t surfaceMaterialID = + pStage->materialOffset + pStage->variantOffsets[lhs.shaderVariant[stage]]; + + pStage = rhs.shaderStages[stage]; + pStage = pStage->materialRemappedStage ? pStage->materialRemappedStage : pStage; + + const uint32_t surfaceMaterialID2 = + pStage->materialOffset + pStage->variantOffsets[rhs.shaderVariant[stage]]; + + if ( surfaceMaterialID < surfaceMaterialID2 ) { + return true; + } else if ( surfaceMaterialID > surfaceMaterialID2 ) { + return false; + } + + uint32_t texData = lhs.texDataDynamic[stage] + ? ( lhs.texDataIDs[stage] + materialSystem.GetTexDataSize() ) << TEX_BUNDLE_BITS + : lhs.texDataIDs[stage] << TEX_BUNDLE_BITS; + texData |= ( HasLightMap( &lhs ) ? GetLightMapNum( &lhs ) : 255 ) << LIGHTMAP_BITS; + + uint32_t texData2 = rhs.texDataDynamic[stage] + ? ( rhs.texDataIDs[stage] + materialSystem.GetTexDataSize() ) << TEX_BUNDLE_BITS + : rhs.texDataIDs[stage] << TEX_BUNDLE_BITS; + texData2 |= ( HasLightMap( &rhs ) ? GetLightMapNum( &rhs ) : 255 ) << LIGHTMAP_BITS; + + if ( texData < texData2 ) { + return true; + } else if ( texData > texData2 ) { + return false; + } + } + + return lhs.firstIndex < rhs.firstIndex; + }; + + std::sort( materialSurfaces.begin(), materialSurfaces.end(), materialSurfaceSort ); + + Grid surfaceGrid( true ); + uint32_t gridSize[3] {}; + uint32_t cellSize[3]; + vec3_t worldSize; + VectorSubtract( worldBounds[1], worldBounds[0], worldSize ); + for ( int i = 0; i < 3; i++ ) { + if ( worldSize[i] < 32768 ) { + cellSize[i] = 1024; + } else if ( worldSize[i] < 64000 ) { + cellSize[i] = 2048; + } else if ( worldSize[i] < 240000 ) { + cellSize[i] = 8192; + } else { + cellSize[i] = 65536; + } + + gridSize[i] = ( worldSize[i] + cellSize[i] - 1 ) / cellSize[i]; + } + + glIndex_t* idxs = ( glIndex_t* ) ri.Hunk_AllocateTempMemory( numIndicesIn * sizeof( glIndex_t ) ); + uint32_t numIndices = 0; + surfaceGrid.SetSize( gridSize[0], gridSize[1], gridSize[2] ); + surfaceGrid.Clear(); + + Grid surfaceIdxsGrid( true ); + surfaceIdxsGrid.SetSize( gridSize[0], gridSize[1], gridSize[2] ); + + { + uint32_t surfaceIndex = 0; + MaterialSurface* surface = &materialSurfaces[0]; + while ( true ) { + MaterialSurface* surface2 = &materialSurfaces[surfaceIndex]; + if ( surface2->skyBrush ) { + surfaceIndex++; + + if ( surfaceIndex == materialSurfaces.size() ) { + break; + } + + continue; + } + + bool newGrid = materialSurfaceSort( *surface, *surface2 ); + + if ( surfaceIndex == materialSurfaces.size() - 1 ) { + newGrid = true; + } + + if ( newGrid ) { + for ( Grid::Iterator it = surfaceGrid.begin(); it != surfaceGrid.end(); it++ ) { + if ( *it ) { + SurfaceIndexes* srfIdxs = &surfaceIdxsGrid( it - surfaceGrid.begin() ); + surface->count = *it; + ProcessMaterialSurface( surface, srfIdxs, processedMaterialSurfaces, vertices, idxs, &numIndices ); + } + } + + surfaceGrid.Clear(); + + surface = surface2; + } + + for ( uint32_t i = 0; i < surface2->count; i += 3 ) { + glIndex_t tri[3] = { indices[i + surface2->firstIndex], indices[i + 1 + surface2->firstIndex], + indices[i + 2 + surface2->firstIndex] }; + + srfVert_t triVerts[3] = { vertices[tri[0]], vertices[tri[1]], vertices[tri[2]] }; + + vec3_t origin; + VectorAdd( triVerts[0].xyz, triVerts[1].xyz, origin ); + VectorAdd( origin, triVerts[2].xyz, origin ); + + VectorScale( origin, 1.0f / 3.0f, origin ); + VectorSubtract( origin, world->nodes[0].mins, origin ); + + uint32_t gridOrigin[3] { uint32_t( origin[0] / cellSize[0] ), uint32_t( origin[1] / cellSize[1] ), + uint32_t( origin[2] / cellSize[2] ) }; + + uint32_t* count = &surfaceGrid( gridOrigin[0], gridOrigin[1], gridOrigin[2] ); + SurfaceIndexes* srfIdxs = &surfaceIdxsGrid( gridOrigin[0], gridOrigin[1], gridOrigin[2] ); + + memcpy( srfIdxs->idxs + ( *count ), tri, 3 * sizeof( glIndex_t ) ); + + *count += 3; + + if ( *count + 3 >= MAX_MATERIAL_SURFACE_INDEXES ) { + const uint32_t oldCount = surface2->count; + surface2->count = *count; + ProcessMaterialSurface( surface2, srfIdxs, processedMaterialSurfaces, vertices, idxs, &numIndices ); + surface2->count = oldCount; + *count = 0; + } + } + + surfaceIndex++; + if ( surfaceIndex == materialSurfaces.size() ) { + break; + } + } + } + materialSystem.GeneratePortalBoundingSpheres(); - materialSystem.SetWorldBounds( worldBounds ); - materialSystem.GenerateWorldCommandBuffer( materialSurfaces ); + materialSystem.GenerateWorldCommandBuffer( processedMaterialSurfaces ); + + vertexAttributeSpec_t attrs[] { + { ATTR_INDEX_POSITION, GL_FLOAT, GL_FLOAT, &vertices[0].xyz, 3, sizeof( *vertices ), 0 }, + { ATTR_INDEX_COLOR, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE, &vertices[0].lightColor, 4, sizeof( *vertices ), ATTR_OPTION_NORMALIZE }, + { ATTR_INDEX_QTANGENT, GL_SHORT, GL_SHORT, &vertices[0].qtangent, 4, sizeof( *vertices ), ATTR_OPTION_NORMALIZE }, + { ATTR_INDEX_TEXCOORD, GL_FLOAT, GL_HALF_FLOAT, &vertices[0].st, 4, sizeof( *vertices ), 0 }, + }; + + geometryCache.AddMapGeometry( numVerticesIn, numIndices, std::begin( attrs ), std::end( attrs ), idxs ); + + ri.Hunk_FreeTempMemory( idxs ); return materialSurfaces; } diff --git a/src/engine/renderer/GeometryOptimiser.h b/src/engine/renderer/GeometryOptimiser.h index 263d70af7..3a24a972d 100644 --- a/src/engine/renderer/GeometryOptimiser.h +++ b/src/engine/renderer/GeometryOptimiser.h @@ -41,30 +41,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. static const uint32_t MAX_MATERIAL_SURFACE_TRIS = 64; static const uint32_t MAX_MATERIAL_SURFACE_INDEXES = 3 * MAX_MATERIAL_SURFACE_TRIS; -static const uint32_t MAX_MATERIAL_SURFACE_DISTANCE = 256; - -struct TriEdge { - enum State : uint32_t { - MERGEABLE_TRUE = BIT( 27 ), - MERGEABLE_FALSE = BIT( 28 ), - MERGEABLE_NOT_PROCESSED = BIT( 29 ), - NONE = BIT( 30 ) - }; - - uint32_t index1; - uint32_t index2; -}; - -struct TriEdgeHasher { - size_t operator()( const TriEdge& triEdge ) { - return std::hash{} ( triEdge.index1 ) ^ ( std::hash{} ( triEdge.index2 ) << 16 ); - } -}; - -struct TriIndex { - int tri1 = -1; - int tri2 = -1; -}; struct MapVertHasher { size_t operator()( const srfVert_t& vert ) const { @@ -97,6 +73,10 @@ struct MapVertEqual { } }; +struct SurfaceIndexes { + glIndex_t idxs[MAX_MATERIAL_SURFACE_INDEXES]; +}; + void MarkShaderBuildNONE( const shaderStage_t* ); void MarkShaderBuildNOP( const shaderStage_t* ); void MarkShaderBuildGeneric3D( const shaderStage_t* pStage ); @@ -120,6 +100,7 @@ void OptimiseMapGeometryCore( world_t* world, bspSurface_t** rendererSurfaces, i void MergeLeafSurfacesCore( world_t* world, bspSurface_t** rendererSurfaces, int numSurfaces ); void MergeDuplicateVertices( bspSurface_t** rendererSurfaces, int numSurfaces, srfVert_t* vertices, int numVerticesIn, glIndex_t* indices, int numIndicesIn, int& numVerticesOut, int& numIndicesOut ); -std::vector OptimiseMapGeometryMaterial( bspSurface_t** rendererSurfaces, int numSurfaces ); +std::vector OptimiseMapGeometryMaterial( world_t* world, bspSurface_t** rendererSurfaces, int numSurfaces, + const srfVert_t* vertices, const int numVerticesIn, const glIndex_t* indices, const int numIndicesIn ); #endif // GEOMETRY_OPTIMISER_H diff --git a/src/engine/renderer/Material.cpp b/src/engine/renderer/Material.cpp index 1ec60c78f..92a29a456 100644 --- a/src/engine/renderer/Material.cpp +++ b/src/engine/renderer/Material.cpp @@ -498,6 +498,17 @@ void MaterialSystem::GenerateWorldCommandBuffer( std::vector& s totalBatchCount = 0; + for ( MaterialSurface& surface : surfaces ) { + if ( surface.skyBrush ) { + continue; + } + + for ( uint8_t stage = 0; stage < surface.stages; stage++ ) { + Material* material = &materialPacks[surface.materialPackIDs[stage]].materials[surface.materialIDs[stage]]; + material->drawCommandCount++; + } + } + uint32_t batchOffset = 0; uint32_t globalID = 0; for ( MaterialPack& pack : materialPacks ) { @@ -514,6 +525,8 @@ void MaterialSystem::GenerateWorldCommandBuffer( std::vector& s batchOffset += batchCount; material.globalID = globalID; + material.drawCommandCount = 0; + totalBatchCount += batchCount; globalID++; } @@ -652,7 +665,7 @@ void MaterialSystem::GenerateWorldCommandBuffer( std::vector& s for ( uint8_t stage = 0; stage < surface.stages; stage++ ) { Material* material = &materialPacks[surface.materialPackIDs[stage]].materials[surface.materialIDs[stage]]; - uint32_t cmdID = material->surfaceCommandBatchOffset * SURFACE_COMMANDS_PER_BATCH + material->drawCommandCount2; + uint32_t cmdID = material->surfaceCommandBatchOffset * SURFACE_COMMANDS_PER_BATCH + material->drawCommandCount; // Add 1 because cmd 0 == no-command surfaceDescriptor.surfaceCommandIDs[stage] = cmdID + 1; @@ -672,7 +685,7 @@ void MaterialSystem::GenerateWorldCommandBuffer( std::vector& s surfaceCommand.drawCommand.baseInstance |= ( HasLightMap( &surface ) ? GetLightMapNum( &surface ) : 255 ) << LIGHTMAP_BITS; surfaceCommands[cmdID] = surfaceCommand; - material->drawCommandCount2++; + material->drawCommandCount++; } memcpy( surfaceDescriptors, &surfaceDescriptor, descriptorSize * sizeof( uint32_t ) ); @@ -1319,8 +1332,6 @@ void MaterialSystem::ProcessStage( MaterialSurface* surface, shaderStage_t* pSta packIDs[materialPack] = id; - materials[previousMaterialID].drawCommandCount++; - stage++; } diff --git a/src/engine/renderer/Material.h b/src/engine/renderer/Material.h index 2fd085ada..d11b3abb5 100644 --- a/src/engine/renderer/Material.h +++ b/src/engine/renderer/Material.h @@ -150,7 +150,6 @@ struct Material { int fog = 0; uint32_t drawCommandCount = 0; - uint32_t drawCommandCount2 = 0; bool texturesResident = false; std::vector textures; @@ -382,6 +381,10 @@ class MaterialSystem { void InitGLBuffers(); void FreeGLBuffers(); + uint32_t GetTexDataSize() const { + return texData.size(); + } + void AddStageTextures( MaterialSurface* surface, shader_t* shader, shaderStage_t* pStage, const uint32_t stage, Material* material ); void AddStage( MaterialSurface* surface, shaderStage_t* pStage, uint32_t stage, const bool mayUseVertexOverbright, const bool vertexLit, const bool fullbright ); diff --git a/src/engine/renderer/tr_bsp.cpp b/src/engine/renderer/tr_bsp.cpp index 45ed91ed5..7b2d25b83 100644 --- a/src/engine/renderer/tr_bsp.cpp +++ b/src/engine/renderer/tr_bsp.cpp @@ -2699,14 +2699,23 @@ static void R_CreateWorldVBO() { bspSurface_t** rendererSurfaces = ( bspSurface_t** ) ri.Hunk_AllocateTempMemory( sizeof( bspSurface_t* ) * numSurfaces ); numSurfaces = 0; + vec3_t worldBounds[2] = {}; + ClearBounds( worldBounds[0], worldBounds[1] ); for ( int i = 0; i < s_worldData.numSurfaces; i++ ) { bspSurface_t* surface = &s_worldData.surfaces[i]; if ( surface->renderable ) { rendererSurfaces[numSurfaces++] = surface; + + BoundsAdd( worldBounds[0], worldBounds[1], + ( ( srfGeneric_t* ) surface->data )->bounds[0], ( ( srfGeneric_t* ) surface->data )->bounds[1] ); } } + if ( glConfig2.usingMaterialSystem ) { + materialSystem.SetWorldBounds( worldBounds ); + } + OptimiseMapGeometryCore( &s_worldData, rendererSurfaces, numSurfaces ); Log::Debug( "...calculating world VBO ( %i verts %i tris )", numVertsInitial, numTriangles ); @@ -2721,7 +2730,7 @@ static void R_CreateWorldVBO() { MergeDuplicateVertices( rendererSurfaces, numSurfaces, vboVerts, numVertsInitial, vboIdxs, 3 * numTriangles, numVerts, numIndices ); if ( glConfig2.usingMaterialSystem ) { - OptimiseMapGeometryMaterial( rendererSurfaces, numSurfaces ); + OptimiseMapGeometryMaterial( &s_worldData, rendererSurfaces, numSurfaces, vboVerts, numVerts, vboIdxs, numIndices ); } vertexAttributeSpec_t attrs[]{ @@ -2731,10 +2740,6 @@ static void R_CreateWorldVBO() { { ATTR_INDEX_TEXCOORD, GL_FLOAT, GL_HALF_FLOAT, &vboVerts[0].st, 4, sizeof( *vboVerts ), 0 }, }; - if ( glConfig2.usingGeometryCache ) { - geometryCache.AddMapGeometry( numVerts, numIndices, std::begin( attrs ), std::end( attrs ), vboIdxs ); - } - s_worldData.vbo = R_CreateStaticVBO( "staticWorld_VBO", std::begin( attrs ), std::end( attrs ), numVerts ); s_worldData.ibo = R_CreateStaticIBO2( "staticWorld_IBO", numTriangles, vboIdxs ); diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index 4107c049c..31a1ce292 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -2530,6 +2530,10 @@ enum class ssaoMode { grid = ( T* ) ri.Hunk_Alloc( size * sizeof( T ), ha_pref::h_low ); } + void Clear() { + memset( grid, 0, size * sizeof( T ) ); + } + struct Iterator { T* ptr; @@ -2545,6 +2549,10 @@ enum class ssaoMode { return ptr; } + ptrdiff_t operator-( const Iterator& other ) const { + return ptr - other.ptr; + } + Iterator& operator++() { ptr++; return *this; From 47afcb3540be9b5d65451c57f7376a8041dd8b73 Mon Sep 17 00:00:00 2001 From: VReaperV Date: Sun, 18 May 2025 18:13:53 +0300 Subject: [PATCH 05/41] Merge distant material surfaces separately Use a larger grid size for surfaces outside of the normal 64k range (background, skybrushes), to keep useable sizes for normal surfaces for culling. --- src/engine/renderer/GeometryOptimiser.cpp | 226 ++++++++++++++-------- src/engine/renderer/tr_bsp.cpp | 9 - 2 files changed, 141 insertions(+), 94 deletions(-) diff --git a/src/engine/renderer/GeometryOptimiser.cpp b/src/engine/renderer/GeometryOptimiser.cpp index b33912944..b790f4dfb 100644 --- a/src/engine/renderer/GeometryOptimiser.cpp +++ b/src/engine/renderer/GeometryOptimiser.cpp @@ -448,14 +448,107 @@ static void ProcessMaterialSurface( MaterialSurface* surface, SurfaceIndexes* su surface->firstIndex = oldFirstIndex; } +static void OptimiseMaterialSurfaces( std::vector& materialSurfaces, + const uint32_t gridSize[3], const uint32_t cellSize[3], const vec3_t worldMins, + std::function materialSurfaceSort, + const srfVert_t* vertices, const glIndex_t* indices, + glIndex_t* idxs, + std::vector& processedMaterialSurfaces, uint32_t& numIndices ) { + + Grid surfaceGrid( true ); + surfaceGrid.SetSize( gridSize[0], gridSize[1], gridSize[2] ); + surfaceGrid.Clear(); + + Grid surfaceIdxsGrid( true ); + surfaceIdxsGrid.SetSize( gridSize[0], gridSize[1], gridSize[2] ); + + uint32_t surfaceIndex = 0; + MaterialSurface* surface = &materialSurfaces[0]; + while ( true ) { + MaterialSurface* surface2 = &materialSurfaces[surfaceIndex]; + if ( surface2->skyBrush ) { + surfaceIndex++; + + if ( surfaceIndex == materialSurfaces.size() ) { + break; + } + + continue; + } + + bool newGrid = materialSurfaceSort( *surface, *surface2 ); + + if ( surfaceIndex == materialSurfaces.size() - 1 ) { + newGrid = true; + } + + if ( newGrid ) { + for ( Grid::Iterator it = surfaceGrid.begin(); it != surfaceGrid.end(); it++ ) { + if ( *it ) { + SurfaceIndexes* srfIdxs = &surfaceIdxsGrid( it - surfaceGrid.begin() ); + surface->count = *it; + ProcessMaterialSurface( surface, srfIdxs, processedMaterialSurfaces, vertices, idxs, &numIndices ); + } + } + + surfaceGrid.Clear(); + + surface = surface2; + } + + for ( uint32_t i = 0; i < surface2->count; i += 3 ) { + glIndex_t tri[3] = { indices[i + surface2->firstIndex], indices[i + 1 + surface2->firstIndex], + indices[i + 2 + surface2->firstIndex] }; + + srfVert_t triVerts[3] = { vertices[tri[0]], vertices[tri[1]], vertices[tri[2]] }; + + vec3_t origin; + VectorAdd( triVerts[0].xyz, triVerts[1].xyz, origin ); + VectorAdd( origin, triVerts[2].xyz, origin ); + + VectorScale( origin, 1.0f / 3.0f, origin ); + VectorSubtract( origin, worldMins, origin ); + + uint32_t gridOrigin[3]{ uint32_t( origin[0] / cellSize[0] ), uint32_t( origin[1] / cellSize[1] ), + uint32_t( origin[2] / cellSize[2] ) }; + + uint32_t* count = &surfaceGrid( gridOrigin[0], gridOrigin[1], gridOrigin[2] ); + SurfaceIndexes* srfIdxs = &surfaceIdxsGrid( gridOrigin[0], gridOrigin[1], gridOrigin[2] ); + + memcpy( srfIdxs->idxs + ( *count ), tri, 3 * sizeof( glIndex_t ) ); + + *count += 3; + + if ( *count + 3 >= MAX_MATERIAL_SURFACE_INDEXES ) { + const uint32_t oldCount = surface2->count; + surface2->count = *count; + + ProcessMaterialSurface( surface2, srfIdxs, processedMaterialSurfaces, vertices, idxs, &numIndices ); + + surface2->count = oldCount; + *count = 0; + } + } + + surfaceIndex++; + if ( surfaceIndex == materialSurfaces.size() ) { + break; + } + } +} + std::vector OptimiseMapGeometryMaterial( world_t* world, bspSurface_t** rendererSurfaces, int numSurfaces, const srfVert_t* vertices, const int numVerticesIn, const glIndex_t* indices, const int numIndicesIn ) { std::vector materialSurfaces; + std::vector materialSurfacesExtended; materialSurfaces.reserve( numSurfaces ); + materialSurfacesExtended.reserve( numSurfaces ); materialSystem.buildOneShader = false; vec3_t worldBounds[2] = {}; + vec3_t worldBoundsExtended[2] = {}; ClearBounds( worldBounds[0], worldBounds[1] ); + ClearBounds( worldBoundsExtended[0], worldBoundsExtended[1] ); for ( int i = 0; i < numSurfaces; i++ ) { bspSurface_t* surface = rendererSurfaces[i]; @@ -483,14 +576,30 @@ std::vector OptimiseMapGeometryMaterial( world_t* world, bspSur VectorCopy( ( ( srfGeneric_t* ) surface->data )->origin, srf.origin ); srf.radius = ( ( srfGeneric_t* ) surface->data )->radius; - BoundsAdd( worldBounds[0], worldBounds[1], - ( ( srfGeneric_t* ) surface->data )->bounds[0], ( ( srfGeneric_t* ) surface->data )->bounds[1] ); - materialSystem.GenerateMaterial( &srf ); - materialSurfaces.emplace_back( srf ); + static const float MAX_NORMAL_SURFACE_DISTANCE = 65536.0f * sqrtf( 2.0f ); + if ( VectorLength( ( ( srfGeneric_t* ) surface->data )->bounds[0] ) > MAX_NORMAL_SURFACE_DISTANCE + || VectorLength( ( ( srfGeneric_t* ) surface->data )->bounds[1] ) > MAX_NORMAL_SURFACE_DISTANCE ) { + BoundsAdd( worldBoundsExtended[0], worldBoundsExtended[1], + ( ( srfGeneric_t* ) surface->data )->bounds[0], ( ( srfGeneric_t* ) surface->data )->bounds[1] ); + + materialSurfacesExtended.emplace_back( srf ); + } else { + BoundsAdd( worldBounds[0], worldBounds[1], + ( ( srfGeneric_t* ) surface->data )->bounds[0], ( ( srfGeneric_t* ) surface->data )->bounds[1] ); + + materialSurfaces.emplace_back( srf ); + } } - materialSystem.SetWorldBounds( worldBounds ); + + vec3_t fullWorldBounds[2]; + VectorCopy( worldBounds[0], fullWorldBounds[0] ); + VectorCopy( worldBounds[1], fullWorldBounds[1] ); + BoundsAdd( fullWorldBounds[0], fullWorldBounds[1], worldBoundsExtended[0], worldBoundsExtended[1] ); + + materialSystem.SetWorldBounds( fullWorldBounds ); + materialSystem.buildOneShader = true; /* GenerateWorldMaterialsBuffer() must be called before the surface merging loop, because it will compare the UBO offsets, @@ -559,9 +668,9 @@ std::vector OptimiseMapGeometryMaterial( world_t* world, bspSur return lhs.firstIndex < rhs.firstIndex; }; - std::sort( materialSurfaces.begin(), materialSurfaces.end(), materialSurfaceSort ); + glIndex_t* idxs = ( glIndex_t* ) ri.Hunk_AllocateTempMemory( numIndicesIn * sizeof( glIndex_t ) ); + uint32_t numIndices = 0; - Grid surfaceGrid( true ); uint32_t gridSize[3] {}; uint32_t cellSize[3]; vec3_t worldSize; @@ -569,97 +678,44 @@ std::vector OptimiseMapGeometryMaterial( world_t* world, bspSur for ( int i = 0; i < 3; i++ ) { if ( worldSize[i] < 32768 ) { cellSize[i] = 1024; - } else if ( worldSize[i] < 64000 ) { - cellSize[i] = 2048; - } else if ( worldSize[i] < 240000 ) { - cellSize[i] = 8192; } else { - cellSize[i] = 65536; + cellSize[i] = 2048; } gridSize[i] = ( worldSize[i] + cellSize[i] - 1 ) / cellSize[i]; } - glIndex_t* idxs = ( glIndex_t* ) ri.Hunk_AllocateTempMemory( numIndicesIn * sizeof( glIndex_t ) ); - uint32_t numIndices = 0; - surfaceGrid.SetSize( gridSize[0], gridSize[1], gridSize[2] ); - surfaceGrid.Clear(); + Log::Debug( "BSP material surface grid cell size: %u %u %u", cellSize[0], cellSize[1], cellSize[2] ); - Grid surfaceIdxsGrid( true ); - surfaceIdxsGrid.SetSize( gridSize[0], gridSize[1], gridSize[2] ); - - { - uint32_t surfaceIndex = 0; - MaterialSurface* surface = &materialSurfaces[0]; - while ( true ) { - MaterialSurface* surface2 = &materialSurfaces[surfaceIndex]; - if ( surface2->skyBrush ) { - surfaceIndex++; - - if ( surfaceIndex == materialSurfaces.size() ) { - break; - } - - continue; - } - - bool newGrid = materialSurfaceSort( *surface, *surface2 ); - - if ( surfaceIndex == materialSurfaces.size() - 1 ) { - newGrid = true; - } - - if ( newGrid ) { - for ( Grid::Iterator it = surfaceGrid.begin(); it != surfaceGrid.end(); it++ ) { - if ( *it ) { - SurfaceIndexes* srfIdxs = &surfaceIdxsGrid( it - surfaceGrid.begin() ); - surface->count = *it; - ProcessMaterialSurface( surface, srfIdxs, processedMaterialSurfaces, vertices, idxs, &numIndices ); - } - } - - surfaceGrid.Clear(); + std::sort( materialSurfaces.begin(), materialSurfaces.end(), materialSurfaceSort ); - surface = surface2; + OptimiseMaterialSurfaces( materialSurfaces, gridSize, cellSize, world->nodes[0].mins, + materialSurfaceSort, + vertices, indices, idxs, processedMaterialSurfaces, numIndices ); + + /* On some maps surfaces go outside the 64k range, used for background and sky brushes. + We process them separately so we can use a larger cell size there, otherwise we'll run out of memory. + The regular surfaces can continue using samller grid sizes this way, + resulting in actually useable bounding spheres */ + if( materialSurfacesExtended.size() ) { + VectorSubtract( worldBoundsExtended[1], worldBoundsExtended[0], worldSize ); + for ( int i = 0; i < 3; i++ ) { + if ( worldSize[i] < 240000 ) { + cellSize[i] = 8192; + } else { + cellSize[i] = 65536; } - for ( uint32_t i = 0; i < surface2->count; i += 3 ) { - glIndex_t tri[3] = { indices[i + surface2->firstIndex], indices[i + 1 + surface2->firstIndex], - indices[i + 2 + surface2->firstIndex] }; - - srfVert_t triVerts[3] = { vertices[tri[0]], vertices[tri[1]], vertices[tri[2]] }; - - vec3_t origin; - VectorAdd( triVerts[0].xyz, triVerts[1].xyz, origin ); - VectorAdd( origin, triVerts[2].xyz, origin ); - - VectorScale( origin, 1.0f / 3.0f, origin ); - VectorSubtract( origin, world->nodes[0].mins, origin ); - - uint32_t gridOrigin[3] { uint32_t( origin[0] / cellSize[0] ), uint32_t( origin[1] / cellSize[1] ), - uint32_t( origin[2] / cellSize[2] ) }; - - uint32_t* count = &surfaceGrid( gridOrigin[0], gridOrigin[1], gridOrigin[2] ); - SurfaceIndexes* srfIdxs = &surfaceIdxsGrid( gridOrigin[0], gridOrigin[1], gridOrigin[2] ); - - memcpy( srfIdxs->idxs + ( *count ), tri, 3 * sizeof( glIndex_t ) ); + gridSize[i] = ( worldSize[i] + cellSize[i] - 1 ) / cellSize[i]; + } - *count += 3; + Log::Debug( "BSP material surface extended grid cell size: %u %u %u", cellSize[0], cellSize[1], cellSize[2] ); - if ( *count + 3 >= MAX_MATERIAL_SURFACE_INDEXES ) { - const uint32_t oldCount = surface2->count; - surface2->count = *count; - ProcessMaterialSurface( surface2, srfIdxs, processedMaterialSurfaces, vertices, idxs, &numIndices ); - surface2->count = oldCount; - *count = 0; - } - } + std::sort( materialSurfacesExtended.begin(), materialSurfacesExtended.end(), materialSurfaceSort ); - surfaceIndex++; - if ( surfaceIndex == materialSurfaces.size() ) { - break; - } - } + OptimiseMaterialSurfaces( materialSurfacesExtended, gridSize, cellSize, world->nodes[0].mins, + materialSurfaceSort, + vertices, indices, idxs, processedMaterialSurfaces, numIndices ); } materialSystem.GeneratePortalBoundingSpheres(); diff --git a/src/engine/renderer/tr_bsp.cpp b/src/engine/renderer/tr_bsp.cpp index 7b2d25b83..36f98d2c4 100644 --- a/src/engine/renderer/tr_bsp.cpp +++ b/src/engine/renderer/tr_bsp.cpp @@ -2699,23 +2699,14 @@ static void R_CreateWorldVBO() { bspSurface_t** rendererSurfaces = ( bspSurface_t** ) ri.Hunk_AllocateTempMemory( sizeof( bspSurface_t* ) * numSurfaces ); numSurfaces = 0; - vec3_t worldBounds[2] = {}; - ClearBounds( worldBounds[0], worldBounds[1] ); for ( int i = 0; i < s_worldData.numSurfaces; i++ ) { bspSurface_t* surface = &s_worldData.surfaces[i]; if ( surface->renderable ) { rendererSurfaces[numSurfaces++] = surface; - - BoundsAdd( worldBounds[0], worldBounds[1], - ( ( srfGeneric_t* ) surface->data )->bounds[0], ( ( srfGeneric_t* ) surface->data )->bounds[1] ); } } - if ( glConfig2.usingMaterialSystem ) { - materialSystem.SetWorldBounds( worldBounds ); - } - OptimiseMapGeometryCore( &s_worldData, rendererSurfaces, numSurfaces ); Log::Debug( "...calculating world VBO ( %i verts %i tris )", numVertsInitial, numTriangles ); From 6aa0f9da7d8d634cc314c08c682a34c868b78e56 Mon Sep 17 00:00:00 2001 From: VReaperV Date: Mon, 19 May 2025 11:56:52 +0300 Subject: [PATCH 06/41] Ensure grid size never gets too large --- src/engine/renderer/GeometryOptimiser.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/engine/renderer/GeometryOptimiser.cpp b/src/engine/renderer/GeometryOptimiser.cpp index b790f4dfb..7012cc003 100644 --- a/src/engine/renderer/GeometryOptimiser.cpp +++ b/src/engine/renderer/GeometryOptimiser.cpp @@ -700,11 +700,7 @@ std::vector OptimiseMapGeometryMaterial( world_t* world, bspSur if( materialSurfacesExtended.size() ) { VectorSubtract( worldBoundsExtended[1], worldBoundsExtended[0], worldSize ); for ( int i = 0; i < 3; i++ ) { - if ( worldSize[i] < 240000 ) { - cellSize[i] = 8192; - } else { - cellSize[i] = 65536; - } + cellSize[i] = std::max( 2048.0f, worldSize[i] / 32.0f ); gridSize[i] = ( worldSize[i] + cellSize[i] - 1 ) / cellSize[i]; } From 4a1e33121d5a6c8f71b37f693b734c39cba82759 Mon Sep 17 00:00:00 2001 From: VReaperV Date: Wed, 21 May 2025 09:33:40 +0300 Subject: [PATCH 07/41] Make sure surfaceGrid is always processed at the end of the loop --- src/engine/renderer/GeometryOptimiser.cpp | 57 +++++++++++------------ 1 file changed, 28 insertions(+), 29 deletions(-) diff --git a/src/engine/renderer/GeometryOptimiser.cpp b/src/engine/renderer/GeometryOptimiser.cpp index 7012cc003..aa1b9237d 100644 --- a/src/engine/renderer/GeometryOptimiser.cpp +++ b/src/engine/renderer/GeometryOptimiser.cpp @@ -462,38 +462,38 @@ static void OptimiseMaterialSurfaces( std::vector& materialSurf Grid surfaceIdxsGrid( true ); surfaceIdxsGrid.SetSize( gridSize[0], gridSize[1], gridSize[2] ); - uint32_t surfaceIndex = 0; MaterialSurface* surface = &materialSurfaces[0]; - while ( true ) { - MaterialSurface* surface2 = &materialSurfaces[surfaceIndex]; - if ( surface2->skyBrush ) { - surfaceIndex++; + MaterialSurface* surface2; + bool addedSurfaces = false; - if ( surfaceIndex == materialSurfaces.size() ) { - break; - } - - continue; + std::function processGrid = [&]() { + if ( !addedSurfaces ) { + surface = surface2; + return; } - bool newGrid = materialSurfaceSort( *surface, *surface2 ); - - if ( surfaceIndex == materialSurfaces.size() - 1 ) { - newGrid = true; + for ( Grid::Iterator it = surfaceGrid.begin(); it != surfaceGrid.end(); it++ ) { + if ( *it ) { + SurfaceIndexes* srfIdxs = &surfaceIdxsGrid( it - surfaceGrid.begin() ); + surface->count = *it; + ProcessMaterialSurface( surface, srfIdxs, processedMaterialSurfaces, vertices, idxs, &numIndices ); + } } - if ( newGrid ) { - for ( Grid::Iterator it = surfaceGrid.begin(); it != surfaceGrid.end(); it++ ) { - if ( *it ) { - SurfaceIndexes* srfIdxs = &surfaceIdxsGrid( it - surfaceGrid.begin() ); - surface->count = *it; - ProcessMaterialSurface( surface, srfIdxs, processedMaterialSurfaces, vertices, idxs, &numIndices ); - } - } + surfaceGrid.Clear(); - surfaceGrid.Clear(); + surface = surface2; + addedSurfaces = false; + }; - surface = surface2; + for ( uint32_t surfaceIndex = 0; surfaceIndex < materialSurfaces.size(); surfaceIndex++ ) { + surface2 = &materialSurfaces[surfaceIndex]; + if ( surface2->skyBrush ) { + continue; + } + + if ( materialSurfaceSort( *surface, *surface2 ) ) { + processGrid(); } for ( uint32_t i = 0; i < surface2->count; i += 3 ) { @@ -527,14 +527,13 @@ static void OptimiseMaterialSurfaces( std::vector& materialSurf surface2->count = oldCount; *count = 0; + } else { + addedSurfaces = true; } } - - surfaceIndex++; - if ( surfaceIndex == materialSurfaces.size() ) { - break; - } } + + processGrid(); } std::vector OptimiseMapGeometryMaterial( world_t* world, bspSurface_t** rendererSurfaces, int numSurfaces, From 880bc3292b400a3335f7d146c26c6162a7c6b8c2 Mon Sep 17 00:00:00 2001 From: VReaperV Date: Mon, 19 May 2025 12:12:50 +0300 Subject: [PATCH 08/41] NUKE some unused stuff --- src/engine/renderer/tr_local.h | 22 ---------------------- src/engine/renderer/tr_skin.cpp | 18 ------------------ 2 files changed, 40 deletions(-) diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index 31a1ce292..9732bcdea 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -165,7 +165,6 @@ static inline void halfToFloat( const f16vec4_t in, vec4_t out ) #define SMP_FRAMES 2 #define MAX_SHADERS ( 1 << 12 ) -#define SHADERS_MASK ( MAX_SHADERS - 1 ) #define MAX_SHADER_TABLES 1024 #define MAX_SHADER_STAGES 16 @@ -353,7 +352,6 @@ enum class ssaoMode { }; #define REF_CUBEMAP_SIZE 32 -#define REF_CUBEMAP_STORE_SIZE 1024 #define REF_COLORGRADE_SLOTS 4 #define REF_COLORGRADEMAP_SIZE 16 @@ -967,8 +965,6 @@ enum class ssaoMode { }; #define MAX_SHADER_DEFORMS 3 -#define MAX_SHADER_DEFORM_STEPS 4 -#define MAX_SHADER_DEFORM_PARMS ( MAX_SHADER_DEFORMS * MAX_SHADER_DEFORM_STEPS ) struct deformStage_t { deform_t deformation; // vertex coordinate modification type @@ -1469,23 +1465,12 @@ enum class ssaoMode { shader_t *shader; }; -//----(SA) modified -#define MAX_PART_MODELS 5 - - struct skinModel_t - { - char type[ MAX_QPATH ]; // md3_lower, md3_lbelt, md3_rbelt, etc. - char model[ MAX_QPATH ]; // lower.md3, belt1.md3, etc. - int hash; - }; - struct skin_t { char name[ MAX_QPATH ]; // game path, including extension int numSurfaces; int numModels; skinSurface_t *surfaces[ MD3_MAX_SURFACES ]; - skinModel_t *models[ MAX_PART_MODELS ]; }; //----(SA) end @@ -3170,10 +3155,8 @@ inline bool checkGLErrors() ==================================================================== */ void GL_Bind( image_t *image ); - void GL_BindNearestCubeMap( int unit, const vec3_t xyz ); void GL_Unbind( image_t *image ); GLuint64 BindAnimatedImage( int unit, const textureBundle_t *bundle ); - void GL_TextureFilter( image_t *image, filterType_t filterType ); void GL_BindProgram( ShaderProgramDescriptor* program ); GLuint64 GL_BindToTMU( int unit, image_t *image ); void GL_BindNullProgram(); @@ -3238,9 +3221,6 @@ inline bool checkGLErrors() bool R_GetModeInfo( int *width, int *height, int mode ); -// https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=516 - const void *RB_TakeScreenshotCmd( const void *data ); - void R_InitSkins(); skin_t *R_GetSkinByHandle( qhandle_t hSkin ); @@ -3670,7 +3650,6 @@ void GLimp_LogComment_( std::string comment ); void RE_ClearScene(); void RE_AddRefEntityToScene( const refEntity_t *ent ); - void RE_AddPolyToSceneQ3A( qhandle_t hShader, int numVerts, const polyVert_t *verts, int num ); void RE_AddPolyToSceneET( qhandle_t hShader, int numVerts, const polyVert_t *verts ); void RE_AddPolysToScene( qhandle_t hShader, int numVerts, const polyVert_t *verts, int numPolys ); @@ -4003,7 +3982,6 @@ void GLimp_LogComment_( std::string comment ); // video stuff - const void *RB_TakeVideoFrameCmd( const void *data ); void RE_TakeVideoFrame( int width, int height, byte *captureBuffer, byte *encodeBuffer, bool motionJpeg ); // cubemap reflections stuff diff --git a/src/engine/renderer/tr_skin.cpp b/src/engine/renderer/tr_skin.cpp index 2f3afbf11..171bc38ee 100644 --- a/src/engine/renderer/tr_skin.cpp +++ b/src/engine/renderer/tr_skin.cpp @@ -165,7 +165,6 @@ qhandle_t RE_RegisterSkin( const char *name ) qhandle_t hSkin; skin_t *skin; skinSurface_t *surf; - skinModel_t *model; //----(SA) added const char *text_p; const char *token; char surfName[ MAX_QPATH ]; @@ -226,7 +225,6 @@ qhandle_t RE_RegisterSkin( const char *name ) tr.skins[ hSkin ] = skin; Q_strncpyz( skin->name, name, sizeof( skin->name ) ); skin->numSurfaces = 0; - skin->numModels = 0; //----(SA) added //----(SA) end @@ -256,22 +254,6 @@ qhandle_t RE_RegisterSkin( const char *name ) continue; } - if ( !Q_strnicmp( token, "md3_", 4 ) ) - { - // this is specifying a model - model = skin->models[ skin->numModels ] = (skinModel_t*) ri.Hunk_Alloc( sizeof( *skin->models[ 0 ] ), ha_pref::h_low ); - Q_strncpyz( model->type, token, sizeof( model->type ) ); - model->hash = Com_HashKey( model->type, sizeof( model->type ) ); - - // get the model name - token = CommaParse( &text_p ); - - Q_strncpyz( model->model, token, sizeof( model->model ) ); - - skin->numModels++; - continue; - } - // parse the shader name token = CommaParse( &text_p ); From 243d2d9189c11b84cfeb1630ce2aa2fb9c8f9818 Mon Sep 17 00:00:00 2001 From: VReaperV Date: Mon, 19 May 2025 12:18:27 +0300 Subject: [PATCH 09/41] Adjust some comments on srfGeneric_t --- src/engine/renderer/tr_local.h | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index 9732bcdea..b6fc9d44b 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -1725,17 +1725,16 @@ enum class ssaoMode { // BSP VBO offset int firstIndex; + + int numVerts; + + int numTriangles; + srfTriangle_t* triangles; // ^ Valid in: SF_FACE, SF_GRID, SF_TRIANGLES, SF_VBO_MESH cplane_t plane; // Valid in: SF_FACE, SF_TRIANGLES - int numVerts; // Valid in: SF_FACE, SF_GRID, SF_TRIANGLES, SF_VBO_MESH srfVert_t* verts; // Valid in: SF_FACE, SF_GRID, SF_TRIANGLES - - // v Valid in: SF_FACE, SF_GRID, SF_TRIANGLES - int numTriangles; - srfTriangle_t* triangles; - // ^ Valid in: SF_FACE, SF_GRID, SF_TRIANGLES }; struct srfGridMesh_t : srfGeneric_t { From adabe8c05fe52f690e0941f6f37c4176e2311ed1 Mon Sep 17 00:00:00 2001 From: VReaperV Date: Thu, 22 May 2025 18:35:13 +0300 Subject: [PATCH 10/41] Use MD5_IDENTSTRING --- src/engine/renderer/tr_animation.cpp | 2 +- src/engine/renderer/tr_model.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/engine/renderer/tr_animation.cpp b/src/engine/renderer/tr_animation.cpp index bc2be2de6..3f5e21e9d 100644 --- a/src/engine/renderer/tr_animation.cpp +++ b/src/engine/renderer/tr_animation.cpp @@ -540,7 +540,7 @@ qhandle_t RE_RegisterAnimation( const char *name ) return 0; } - if ( Str::IsPrefix( "MD5Version", buffer ) ) + if ( Str::IsPrefix( MD5_IDENTSTRING, buffer ) ) { loaded = R_LoadMD5Anim( anim, buffer.c_str(), name ); } diff --git a/src/engine/renderer/tr_model.cpp b/src/engine/renderer/tr_model.cpp index 4bf9c67e3..2f80a8e48 100644 --- a/src/engine/renderer/tr_model.cpp +++ b/src/engine/renderer/tr_model.cpp @@ -147,7 +147,7 @@ qhandle_t RE_RegisterModel( const char *name ) if ( !err ) { - if ( Str::IsIPrefix( "MD5Version", buffer ) ) + if ( Str::IsIPrefix( MD5_IDENTSTRING, buffer ) ) { loaded = R_LoadMD5( mod, buffer.c_str(), name ); } From ef316ed8406c92a08cb4e0aab0d8e1b25cbd720a Mon Sep 17 00:00:00 2001 From: slipher Date: Tue, 20 May 2025 08:15:02 -0500 Subject: [PATCH 11/41] Remove unused uniform u_ViewUp --- src/engine/renderer/Material.cpp | 1 - src/engine/renderer/gl_shader.cpp | 4 +--- src/engine/renderer/gl_shader.h | 17 ----------------- src/engine/renderer/tr_shade.cpp | 1 - 4 files changed, 1 insertion(+), 22 deletions(-) diff --git a/src/engine/renderer/Material.cpp b/src/engine/renderer/Material.cpp index 92a29a456..0e20486a2 100644 --- a/src/engine/renderer/Material.cpp +++ b/src/engine/renderer/Material.cpp @@ -755,7 +755,6 @@ void BindShaderGeneric3D( Material* material ) { // Set shader uniforms. if ( material->tcGenEnvironment ) { gl_genericShaderMaterial->SetUniform_ViewOrigin( backEnd.orientation.viewOrigin ); - gl_genericShaderMaterial->SetUniform_ViewUp( backEnd.orientation.axis[2] ); } gl_genericShaderMaterial->SetUniform_ModelMatrix( backEnd.orientation.transformMatrix ); diff --git a/src/engine/renderer/gl_shader.cpp b/src/engine/renderer/gl_shader.cpp index 2227ca6d7..490ec8beb 100644 --- a/src/engine/renderer/gl_shader.cpp +++ b/src/engine/renderer/gl_shader.cpp @@ -1726,7 +1726,7 @@ std::string GLShaderManager::ShaderPostProcess( GLShader *shader, const std::str /* Remove local uniform declarations, but avoid removing uniform / storage blocks; * their values will be sourced from a buffer instead - * Global uniforms (like u_ViewUp and u_ViewOrigin) will still be set as regular uniforms */ + * Global uniforms (like u_ViewOrigin) will still be set as regular uniforms */ while( std::getline( shaderTextStream, line, '\n' ) ) { bool skip = false; if ( line.find( "uniform" ) < line.find( "//" ) && line.find( ";" ) != std::string::npos ) { @@ -2460,7 +2460,6 @@ GLShader_generic::GLShader_generic() : u_DepthMap( this ), u_TextureMatrix( this ), u_ViewOrigin( this ), - u_ViewUp( this ), u_AlphaThreshold( this ), u_ModelMatrix( this ), u_ModelViewProjectionMatrix( this ), @@ -2495,7 +2494,6 @@ GLShader_genericMaterial::GLShader_genericMaterial() : u_DepthMap( this ), u_TextureMatrix( this ), u_ViewOrigin( this ), - u_ViewUp( this ), u_AlphaThreshold( this ), u_ModelMatrix( this ), u_ModelViewProjectionMatrix( this ), diff --git a/src/engine/renderer/gl_shader.h b/src/engine/renderer/gl_shader.h index eb500c0a5..79b04e2f8 100644 --- a/src/engine/renderer/gl_shader.h +++ b/src/engine/renderer/gl_shader.h @@ -2712,21 +2712,6 @@ class u_ViewOrigin : } }; -class u_ViewUp : - GLUniform3f -{ -public: - u_ViewUp( GLShader *shader ) : - GLUniform3f( shader, "u_ViewUp", true ) - { - } - - void SetUniform_ViewUp( const vec3_t v ) - { - this->SetValue( v ); - } -}; - class u_LightDir : GLUniform3f { @@ -4066,7 +4051,6 @@ class GLShader_generic : public u_DepthMap, public u_TextureMatrix, public u_ViewOrigin, - public u_ViewUp, public u_AlphaThreshold, public u_ModelMatrix, public u_ModelViewProjectionMatrix, @@ -4097,7 +4081,6 @@ class GLShader_genericMaterial : public u_DepthMap, public u_TextureMatrix, public u_ViewOrigin, - public u_ViewUp, public u_AlphaThreshold, public u_ModelMatrix, public u_ModelViewProjectionMatrix, diff --git a/src/engine/renderer/tr_shade.cpp b/src/engine/renderer/tr_shade.cpp index 223303a1d..03fa949d5 100644 --- a/src/engine/renderer/tr_shade.cpp +++ b/src/engine/renderer/tr_shade.cpp @@ -931,7 +931,6 @@ void Render_generic3D( shaderStage_t *pStage ) { // calculate the environment texcoords in object space gl_genericShader->SetUniform_ViewOrigin( backEnd.orientation.viewOrigin ); - gl_genericShader->SetUniform_ViewUp( backEnd.orientation.axis[ 2 ] ); } // u_AlphaThreshold From 47b7a81fd2366ac9ebed56425b24aeb2304e8cd0 Mon Sep 17 00:00:00 2001 From: slipher Date: Tue, 20 May 2025 10:11:35 -0500 Subject: [PATCH 12/41] Move refLight_t out of the IPC types header refLightType_t and refLight_t are not used in IPC so they should not be in tr_types.h. --- src/engine/renderer/tr_local.h | 39 ++++++++++++++++++++++++++++ src/engine/renderer/tr_types.h | 46 ---------------------------------- 2 files changed, 39 insertions(+), 46 deletions(-) diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index b6fc9d44b..262e42892 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -398,6 +398,45 @@ enum class ssaoMode { CUBESIDE_CLIPALL = 1 | 2 | 4 | 8 | 16 | 32 }; + enum class refLightType_t + { + RL_OMNI, // point light + RL_PROJ, // spot light + RL_DIRECTIONAL, // sun light + + RL_MAX_REF_LIGHT_TYPE + }; + + struct refLight_t + { + refLightType_t rlType; + + qhandle_t attenuationShader; + + vec3_t origin; + quat_t rotation; + vec3_t center; + vec3_t color; // range from 0.0 to 1.0, should be color normalized + + float scale; // r_lightScale if not set + + // omni-directional light specific + float radius; + + // projective light specific + vec3_t projTarget; + vec3_t projRight; + vec3_t projUp; + vec3_t projStart; + vec3_t projEnd; + + bool noShadows; + short noShadowID; // don't cast shadows of all entities with this id + + bool inverseShadows; // don't cast light and draw shadows by darken the scene + // this is useful for drawing player shadows with shadow mapping + }; + // a trRefLight_t has all the information passed in by // the client game, as well as some locally derived info struct trRefLight_t diff --git a/src/engine/renderer/tr_types.h b/src/engine/renderer/tr_types.h index e00a2cd01..16e414fdd 100644 --- a/src/engine/renderer/tr_types.h +++ b/src/engine/renderer/tr_types.h @@ -220,52 +220,6 @@ struct refEntity_t // ================================================================================================ -// XreaL BEGIN - -enum class refLightType_t -{ - RL_OMNI, // point light - RL_PROJ, // spot light - RL_DIRECTIONAL, // sun light - - RL_MAX_REF_LIGHT_TYPE -}; - -struct refLight_t -{ - refLightType_t rlType; -// int lightfx; - - qhandle_t attenuationShader; - - vec3_t origin; - quat_t rotation; - vec3_t center; - vec3_t color; // range from 0.0 to 1.0, should be color normalized - - float scale; // r_lightScale if not set - - // omni-directional light specific - float radius; - - // projective light specific - vec3_t projTarget; - vec3_t projRight; - vec3_t projUp; - vec3_t projStart; - vec3_t projEnd; - - bool8_t noShadows; - short noShadowID; // don't cast shadows of all entities with this id - - bool8_t inverseShadows; // don't cast light and draw shadows by darken the scene - // this is useful for drawing player shadows with shadow mapping -}; - -// XreaL END - -// ================================================================================================ - struct refdef_t { int x, y, width, height; From fdcb49d012194e21deab3409f3addcc72708fd64 Mon Sep 17 00:00:00 2001 From: slipher Date: Tue, 20 May 2025 04:55:38 -0500 Subject: [PATCH 13/41] Remove "INTERACTLIGHT" from /listshaders Some forward lighting junk. --- src/engine/renderer/tr_shader.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/engine/renderer/tr_shader.cpp b/src/engine/renderer/tr_shader.cpp index e20f707d5..507639839 100644 --- a/src/engine/renderer/tr_shader.cpp +++ b/src/engine/renderer/tr_shader.cpp @@ -6576,7 +6576,6 @@ class ListShadersCmd : public Cmd::StaticCmd std::string shaderType = "shaderType"; std::string shaderSort = "shaderSort"; std::string stageType = "stageType"; - std::string interactLight = "interactLight"; std::string stageNumber = "stageNumber"; std::string shaderName = "shaderName"; @@ -6588,7 +6587,6 @@ class ListShadersCmd : public Cmd::StaticCmd size_t shaderTypeLen = shaderType.length(); size_t shaderSortLen = shaderSort.length(); size_t stageTypeLen = stageType.length(); - size_t interactLightLen = interactLight.length(); // Value size for ( const auto& kv : shaderTypeName ) @@ -6615,7 +6613,6 @@ class ListShadersCmd : public Cmd::StaticCmd lineStream << std::setw(shaderTypeLen) << shaderType << separator; lineStream << std::setw(shaderSortLen) << shaderSort << separator; lineStream << std::setw(stageTypeLen) << stageType << separator; - lineStream << std::setw(interactLightLen) << interactLight << separator; lineStream << stageNumber << ":" << shaderName; std::string lineSeparator( lineStream.str().length(), '-' ); @@ -6657,7 +6654,6 @@ class ListShadersCmd : public Cmd::StaticCmd shaderSort = shaderSortName.at( (shaderSort_t) shader->sort ); } - interactLight = shader->interactLight ? "INTERACTLIGHT" : ""; shaderName = shader->name; shaderName += shader->defaultShader ? " (DEFAULTED)" : ""; @@ -6671,7 +6667,6 @@ class ListShadersCmd : public Cmd::StaticCmd lineStream << std::setw(shaderTypeLen) << shaderType << separator; lineStream << std::setw(shaderSortLen) << shaderSort << separator; lineStream << std::setw(stageTypeLen) << stageType << separator; - lineStream << std::setw(interactLightLen) << interactLight << separator; lineStream << "-:" << shaderName; Print( lineStream.str() ); @@ -6704,7 +6699,6 @@ class ListShadersCmd : public Cmd::StaticCmd lineStream << std::setw(shaderTypeLen) << shaderType << separator; lineStream << std::setw(shaderSortLen) << shaderSort << separator; lineStream << std::setw(stageTypeLen) << stageType << separator; - lineStream << std::setw(interactLightLen) << interactLight << separator; lineStream << j << ":" << shaderName; Print( lineStream.str() ); From 9827184f45dda3e0ee5a4b65ec3540831c3d13ce Mon Sep 17 00:00:00 2001 From: slipher Date: Tue, 20 May 2025 07:51:31 -0500 Subject: [PATCH 14/41] NUKE broken shadow mapping code The shadow code no longer produced any effect for a player shadow with 2 <= cg_shadows <= 6, regardless of r_realtimeLightingRenderer. The code was mostly designed for forward lighting anyway, which is being removed. --- src.cmake | 4 - src/engine/renderer/gl_shader.cpp | 183 +- src/engine/renderer/gl_shader.h | 349 +--- .../glsl_source/debugShadowMap_fp.glsl | 72 - .../glsl_source/debugShadowMap_vp.glsl | 38 - .../glsl_source/forwardLighting_fp.glsl | 831 -------- .../renderer/glsl_source/shadowFill_fp.glsl | 125 -- .../renderer/glsl_source/shadowFill_vp.glsl | 78 - src/engine/renderer/shaders.cpp | 8 - src/engine/renderer/tr_animation.cpp | 46 +- src/engine/renderer/tr_backend.cpp | 1686 ++--------------- src/engine/renderer/tr_cmds.cpp | 5 - src/engine/renderer/tr_fbo.cpp | 49 - src/engine/renderer/tr_image.cpp | 152 -- src/engine/renderer/tr_init.cpp | 100 +- src/engine/renderer/tr_light.cpp | 250 +-- src/engine/renderer/tr_local.h | 78 +- src/engine/renderer/tr_main.cpp | 211 +-- src/engine/renderer/tr_mesh.cpp | 24 +- src/engine/renderer/tr_public.h | 2 - src/engine/renderer/tr_scene.cpp | 15 +- src/engine/renderer/tr_shade.cpp | 322 +--- src/engine/renderer/tr_shader.cpp | 48 +- src/engine/renderer/tr_types.h | 12 +- src/engine/renderer/tr_world.cpp | 14 +- 25 files changed, 192 insertions(+), 4510 deletions(-) delete mode 100644 src/engine/renderer/glsl_source/debugShadowMap_fp.glsl delete mode 100644 src/engine/renderer/glsl_source/debugShadowMap_vp.glsl delete mode 100644 src/engine/renderer/glsl_source/shadowFill_fp.glsl delete mode 100644 src/engine/renderer/glsl_source/shadowFill_vp.glsl diff --git a/src.cmake b/src.cmake index 1af07da64..8cdef74b8 100644 --- a/src.cmake +++ b/src.cmake @@ -183,8 +183,6 @@ set(GLSLSOURCELIST ${ENGINE_DIR}/renderer/glsl_source/vertexSkinning_vp.glsl # Regular shaders - ${ENGINE_DIR}/renderer/glsl_source/debugShadowMap_vp.glsl - ${ENGINE_DIR}/renderer/glsl_source/debugShadowMap_fp.glsl ${ENGINE_DIR}/renderer/glsl_source/fogQuake3_vp.glsl ${ENGINE_DIR}/renderer/glsl_source/fogQuake3_fp.glsl ${ENGINE_DIR}/renderer/glsl_source/forwardLighting_vp.glsl @@ -203,8 +201,6 @@ set(GLSLSOURCELIST ${ENGINE_DIR}/renderer/glsl_source/reflection_CB_fp.glsl ${ENGINE_DIR}/renderer/glsl_source/screen_vp.glsl ${ENGINE_DIR}/renderer/glsl_source/screen_fp.glsl - ${ENGINE_DIR}/renderer/glsl_source/shadowFill_vp.glsl - ${ENGINE_DIR}/renderer/glsl_source/shadowFill_fp.glsl ${ENGINE_DIR}/renderer/glsl_source/skybox_vp.glsl ${ENGINE_DIR}/renderer/glsl_source/skybox_fp.glsl ) diff --git a/src/engine/renderer/gl_shader.cpp b/src/engine/renderer/gl_shader.cpp index 490ec8beb..9f812bf2c 100644 --- a/src/engine/renderer/gl_shader.cpp +++ b/src/engine/renderer/gl_shader.cpp @@ -78,10 +78,8 @@ GLShader_reflection *gl_reflectionShader = nullptr; GLShader_reflectionMaterial *gl_reflectionShaderMaterial = nullptr; GLShader_screen *gl_screenShader = nullptr; GLShader_screenMaterial *gl_screenShaderMaterial = nullptr; -GLShader_shadowFill *gl_shadowFillShader = nullptr; GLShader_skybox *gl_skyboxShader = nullptr; GLShader_skyboxMaterial *gl_skyboxShaderMaterial = nullptr; -GLShader_debugShadowMap *gl_debugShadowMapShader = nullptr; GLShaderManager gl_shaderManager; namespace // Implementation details @@ -320,11 +318,6 @@ static inline void AddDefine( std::string& defines, const std::string& define, f defines += Str::Format("#ifndef %s\n#define %s vec2(%.8e, %.8e)\n#endif\n", define, define, v1, v2); } -static inline void AddDefine( std::string& defines, const std::string& define ) -{ - defines += Str::Format("#ifndef %s\n#define %s\n#endif\n", define, define); -} - // Has to match enum genFunc_t in tr_local.h static const char *const genFuncNames[] = { "DSTEP_NONE", @@ -494,10 +487,12 @@ static void AddConst( std::string& str, const std::string& name, float value ) str += Str::Format("const float %s = %.8e;\n", name, value); } +#if 0 static void AddConst( std::string& str, const std::string& name, float v1, float v2 ) { str += Str::Format("const vec2 %s = vec2(%.8e, %.8e);\n", name, v1, v2); } +#endif static std::string GenVersionDeclaration( const std::vector &addedExtensions ) { // Declare version. @@ -680,7 +675,6 @@ static std::string GenEngineConstants() { AddDefine( str, "r_zNear", r_znear->value ); AddDefine( str, "M_PI", static_cast< float >( M_PI ) ); - AddDefine( str, "MAX_SHADOWMAPS", MAX_SHADOWMAPS ); AddDefine( str, "MAX_REF_LIGHTS", MAX_REF_LIGHTS ); AddDefine( str, "NUM_LIGHT_LAYERS", glConfig2.realtimeLightLayers ); AddDefine( str, "TILE_SIZE", TILE_SIZE ); @@ -689,94 +683,6 @@ static std::string GenEngineConstants() { AddDefine( str, "r_tileStep", glState.tileStep[0], glState.tileStep[1] ); - if ( glConfig2.shadowMapping ) - { - switch( glConfig2.shadowingMode ) - { - case shadowingMode_t::SHADOWING_ESM16: - case shadowingMode_t::SHADOWING_ESM32: - AddDefine( str, "ESM", 1 ); - break; - case shadowingMode_t::SHADOWING_VSM16: - case shadowingMode_t::SHADOWING_VSM32: - AddDefine( str, "VSM", 1 ); - - if ( glConfig.hardwareType == glHardwareType_t::GLHW_R300 ) - { - AddDefine( str, "VSM_CLAMP", 1 ); - } - break; - case shadowingMode_t::SHADOWING_EVSM32: - AddDefine( str, "EVSM", 1 ); - - // The exponents for the EVSM techniques should be less than ln(FLT_MAX/FILTER_SIZE)/2 {ln(FLT_MAX/1)/2 ~44.3} - // 42.9 is the maximum possible value for FILTER_SIZE=15 - // 42.0 is the truncated value that we pass into the sample - AddConst( str, "r_EVSMExponents", 42.0f, 42.0f ); - - if ( r_evsmPostProcess->integer ) - { - AddDefine( str, "r_EVSMPostProcess", 1 ); - } - break; - default: - DAEMON_ASSERT( false ); - break; - } - - switch( glConfig2.shadowingMode ) - { - case shadowingMode_t::SHADOWING_ESM16: - case shadowingMode_t::SHADOWING_ESM32: - break; - case shadowingMode_t::SHADOWING_VSM16: - AddConst( str, "VSM_EPSILON", 0.0001f ); - break; - case shadowingMode_t::SHADOWING_VSM32: - // GLHW_R300 should not be GLDRV_OPENGL3 anyway. - if ( glConfig.driverType != glDriverType_t::GLDRV_OPENGL3 - || glConfig.hardwareType == glHardwareType_t::GLHW_R300 ) - { - AddConst( str, "VSM_EPSILON", 0.0001f ); - } - else - { - AddConst( str, "VSM_EPSILON", 0.000001f ); - } - break; - case shadowingMode_t::SHADOWING_EVSM32: - // This may be wrong, but the code did that before it was rewritten. - AddConst( str, "VSM_EPSILON", 0.0001f ); - break; - default: - DAEMON_ASSERT( false ); - break; - } - - if ( r_lightBleedReduction->value ) - AddConst( str, "r_lightBleedReduction", r_lightBleedReduction->value ); - - if ( r_overDarkeningFactor->value ) - AddConst( str, "r_overDarkeningFactor", r_overDarkeningFactor->value ); - - if ( r_shadowMapDepthScale->value ) - AddConst( str, "r_shadowMapDepthScale", r_shadowMapDepthScale->value ); - - if ( r_debugShadowMaps->integer ) - AddDefine( str, "r_debugShadowMaps", r_debugShadowMaps->integer ); - - if ( r_softShadows->integer == 6 ) - AddDefine( str, "PCSS", 1 ); - else if ( r_softShadows->integer ) - AddConst( str, "r_PCFSamples", r_softShadows->value + 1.0f ); - - if ( r_parallelShadowSplits->integer ) - AddDefine( str, Str::Format( "r_parallelShadowSplits_%d", r_parallelShadowSplits->integer ) ); - - if ( r_showParallelShadowSplits->integer ) - AddDefine( str, "r_showParallelShadowSplits", 1 ); - } - if ( glConfig2.realtimeLighting ) { AddDefine( str, "r_realtimeLighting", 1 ); @@ -2655,8 +2561,6 @@ GLShader_forwardLighting_omniXYZ::GLShader_forwardLighting_omniXYZ(): u_MaterialMap( this ), u_AttenuationMapXY( this ), u_AttenuationMapZ( this ), - u_ShadowMap( this ), - u_ShadowClipMap( this ), u_RandomMap( this ), u_HeightMap( this ), u_TextureMatrix( this ), @@ -2672,8 +2576,6 @@ GLShader_forwardLighting_omniXYZ::GLShader_forwardLighting_omniXYZ(): u_LightRadius( this ), u_LightScale( this ), u_LightAttenuationMatrix( this ), - u_ShadowTexelSize( this ), - u_ShadowBlur( this ), u_ModelMatrix( this ), u_ModelViewProjectionMatrix( this ), u_Bones( this ), @@ -2685,8 +2587,7 @@ GLShader_forwardLighting_omniXYZ::GLShader_forwardLighting_omniXYZ(): GLCompileMacro_USE_VERTEX_SKINNING( this ), GLCompileMacro_USE_VERTEX_ANIMATION( this ), GLCompileMacro_USE_HEIGHTMAP_IN_NORMALMAP( this ), - GLCompileMacro_USE_RELIEF_MAPPING( this ), - GLCompileMacro_USE_SHADOWING( this ) + GLCompileMacro_USE_RELIEF_MAPPING( this ) { } @@ -2697,9 +2598,7 @@ void GLShader_forwardLighting_omniXYZ::SetShaderProgramUniforms( ShaderProgramDe glUniform1i( glGetUniformLocation( shaderProgram->id, "u_MaterialMap" ), 2 ); glUniform1i( glGetUniformLocation( shaderProgram->id, "u_AttenuationMapXY" ), 3 ); glUniform1i( glGetUniformLocation( shaderProgram->id, "u_AttenuationMapZ" ), 4 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowMap" ), 5 ); glUniform1i( glGetUniformLocation( shaderProgram->id, "u_RandomMap" ), 6 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowClipMap" ), 7 ); glUniform1i( glGetUniformLocation( shaderProgram->id, "u_HeightMap" ), 15 ); } @@ -2711,8 +2610,6 @@ GLShader_forwardLighting_projXYZ::GLShader_forwardLighting_projXYZ(): u_MaterialMap( this ), u_AttenuationMapXY( this ), u_AttenuationMapZ( this ), - u_ShadowMap0( this ), - u_ShadowClipMap0( this ), u_RandomMap( this ), u_HeightMap( this ), u_TextureMatrix( this ), @@ -2728,9 +2625,6 @@ GLShader_forwardLighting_projXYZ::GLShader_forwardLighting_projXYZ(): u_LightRadius( this ), u_LightScale( this ), u_LightAttenuationMatrix( this ), - u_ShadowTexelSize( this ), - u_ShadowBlur( this ), - u_ShadowMatrix( this ), u_ModelMatrix( this ), u_ModelViewProjectionMatrix( this ), u_Bones( this ), @@ -2742,8 +2636,7 @@ GLShader_forwardLighting_projXYZ::GLShader_forwardLighting_projXYZ(): GLCompileMacro_USE_VERTEX_SKINNING( this ), GLCompileMacro_USE_VERTEX_ANIMATION( this ), GLCompileMacro_USE_HEIGHTMAP_IN_NORMALMAP( this ), - GLCompileMacro_USE_RELIEF_MAPPING( this ), - GLCompileMacro_USE_SHADOWING( this ) + GLCompileMacro_USE_RELIEF_MAPPING( this ) { } @@ -2759,9 +2652,7 @@ void GLShader_forwardLighting_projXYZ::SetShaderProgramUniforms( ShaderProgramDe glUniform1i( glGetUniformLocation( shaderProgram->id, "u_MaterialMap" ), 2 ); glUniform1i( glGetUniformLocation( shaderProgram->id, "u_AttenuationMapXY" ), 3 ); glUniform1i( glGetUniformLocation( shaderProgram->id, "u_AttenuationMapZ" ), 4 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowMap0" ), 5 ); glUniform1i( glGetUniformLocation( shaderProgram->id, "u_RandomMap" ), 6 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowClipMap0" ), 7 ); glUniform1i( glGetUniformLocation( shaderProgram->id, "u_HeightMap" ), 15 ); } @@ -2771,16 +2662,6 @@ GLShader_forwardLighting_directionalSun::GLShader_forwardLighting_directionalSun u_DiffuseMap( this ), u_NormalMap( this ), u_MaterialMap( this ), - u_ShadowMap0( this ), - u_ShadowMap1( this ), - u_ShadowMap2( this ), - u_ShadowMap3( this ), - u_ShadowMap4( this ), - u_ShadowClipMap0( this ), - u_ShadowClipMap1( this ), - u_ShadowClipMap2( this ), - u_ShadowClipMap3( this ), - u_ShadowClipMap4( this ), u_HeightMap( this ), u_TextureMatrix( this ), u_SpecularExponent( this ), @@ -2795,10 +2676,6 @@ GLShader_forwardLighting_directionalSun::GLShader_forwardLighting_directionalSun u_LightRadius( this ), u_LightScale( this ), u_LightAttenuationMatrix( this ), - u_ShadowTexelSize( this ), - u_ShadowBlur( this ), - u_ShadowMatrix( this ), - u_ShadowParallelSplitDistances( this ), u_ModelMatrix( this ), u_ViewMatrix( this ), u_ModelViewProjectionMatrix( this ), @@ -2811,8 +2688,7 @@ GLShader_forwardLighting_directionalSun::GLShader_forwardLighting_directionalSun GLCompileMacro_USE_VERTEX_SKINNING( this ), GLCompileMacro_USE_VERTEX_ANIMATION( this ), GLCompileMacro_USE_HEIGHTMAP_IN_NORMALMAP( this ), - GLCompileMacro_USE_RELIEF_MAPPING( this ), - GLCompileMacro_USE_SHADOWING( this ) + GLCompileMacro_USE_RELIEF_MAPPING( this ) { } @@ -2828,45 +2704,9 @@ void GLShader_forwardLighting_directionalSun::SetShaderProgramUniforms( ShaderPr glUniform1i( glGetUniformLocation( shaderProgram->id, "u_MaterialMap" ), 2 ); //glUniform1i(glGetUniformLocation( shaderProgram->id, "u_AttenuationMapXY" ), 3); //glUniform1i(glGetUniformLocation( shaderProgram->id, "u_AttenuationMapZ" ), 4); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowMap0" ), 5 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowMap1" ), 6 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowMap2" ), 7 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowMap3" ), 8 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowMap4" ), 9 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowClipMap0" ), 10 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowClipMap1" ), 11 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowClipMap2" ), 12 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowClipMap3" ), 13 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowClipMap4" ), 14 ); glUniform1i( glGetUniformLocation( shaderProgram->id, "u_HeightMap" ), 15 ); } -GLShader_shadowFill::GLShader_shadowFill() : - GLShader( "shadowFill", ATTR_POSITION | ATTR_TEXCOORD | ATTR_QTANGENT, - false, "shadowFill", "shadowFill" ), - u_ColorMap( this ), - u_TextureMatrix( this ), - u_AlphaThreshold( this ), - u_LightOrigin( this ), - u_LightRadius( this ), - u_ModelMatrix( this ), - u_ModelViewProjectionMatrix( this ), - u_Color_Float( this ), - u_Color_Uint( this ), - u_Bones( this ), - u_VertexInterpolation( this ), - GLDeformStage( this ), - GLCompileMacro_USE_VERTEX_SKINNING( this ), - GLCompileMacro_USE_VERTEX_ANIMATION( this ), - GLCompileMacro_LIGHT_DIRECTIONAL( this ) -{ -} - -void GLShader_shadowFill::SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) -{ - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ColorMap" ), 0 ); -} - GLShader_reflection::GLShader_reflection(): GLShader( "reflection", ATTR_POSITION | ATTR_TEXCOORD | ATTR_QTANGENT, false, "reflection_CB", "reflection_CB" ), @@ -3153,19 +2993,6 @@ void GLShader_blur::SetShaderProgramUniforms( ShaderProgramDescriptor *shaderPro glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ColorMap" ), 0 ); } -GLShader_debugShadowMap::GLShader_debugShadowMap() : - GLShader( "debugShadowMap", ATTR_POSITION, - false, "debugShadowMap", "debugShadowMap" ), - u_CurrentMap( this ), - u_ModelViewProjectionMatrix( this ) -{ -} - -void GLShader_debugShadowMap::SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) -{ - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_CurrentMap" ), 0 ); -} - GLShader_liquid::GLShader_liquid() : GLShader( "liquid", ATTR_POSITION | ATTR_TEXCOORD | ATTR_QTANGENT, false, "liquid", "liquid" ), diff --git a/src/engine/renderer/gl_shader.h b/src/engine/renderer/gl_shader.h index 79b04e2f8..fc0aa7d94 100644 --- a/src/engine/renderer/gl_shader.h +++ b/src/engine/renderer/gl_shader.h @@ -1535,7 +1535,6 @@ class GLCompileMacro USE_HEIGHTMAP_IN_NORMALMAP, USE_RELIEF_MAPPING, USE_REFLECTIVE_SPECULAR, - USE_SHADOWING, LIGHT_DIRECTIONAL, USE_DEPTH_FADE, USE_PHYSICAL_MAPPING, @@ -1967,35 +1966,6 @@ class GLCompileMacro_LIGHT_DIRECTIONAL : } }; -class GLCompileMacro_USE_SHADOWING : - GLCompileMacro -{ -public: - GLCompileMacro_USE_SHADOWING( GLShader *shader ) : - GLCompileMacro( shader ) - { - } - - const char *GetName() const override - { - return "USE_SHADOWING"; - } - - EGLCompileMacro GetType() const override - { - return EGLCompileMacro::USE_SHADOWING; - } - - int GetShaderTypes() const override { - return ShaderType::FRAGMENT; - } - - void SetShadowing( bool enable ) - { - SetMacro( enable ); - } -}; - class GLCompileMacro_USE_DEPTH_FADE : GLCompileMacro { @@ -2423,198 +2393,6 @@ class u_AttenuationMapZ : } }; -class u_ShadowMap : - GLUniformSampler2D { - public: - u_ShadowMap( GLShader* shader ) : - GLUniformSampler2D( shader, "u_ShadowMap" ) { - } - - void SetUniform_ShadowMapBindless( GLuint64 bindlessHandle ) { - this->SetValueBindless( bindlessHandle ); - } - - GLint GetUniformLocation_ShadowMap() { - return this->GetLocation(); - } -}; - -class u_ShadowMap0 : - GLUniformSampler2D { - public: - u_ShadowMap0( GLShader* shader ) : - GLUniformSampler2D( shader, "u_ShadowMap0" ) { - } - - void SetUniform_ShadowMap0Bindless( GLuint64 bindlessHandle ) { - this->SetValueBindless( bindlessHandle ); - } - - GLint GetUniformLocation_ShadowMap0() { - return this->GetLocation(); - } -}; - -class u_ShadowMap1 : - GLUniformSampler2D { - public: - u_ShadowMap1( GLShader* shader ) : - GLUniformSampler2D( shader, "u_ShadowMap1" ) { - } - - void SetUniform_ShadowMap1Bindless( GLuint64 bindlessHandle ) { - this->SetValueBindless( bindlessHandle ); - } - - GLint GetUniformLocation_ShadowMap1() { - return this->GetLocation(); - } -}; - -class u_ShadowMap2 : - GLUniformSampler2D { - public: - u_ShadowMap2( GLShader* shader ) : - GLUniformSampler2D( shader, "u_ShadowMap2" ) { - } - - void SetUniform_ShadowMap2Bindless( GLuint64 bindlessHandle ) { - this->SetValueBindless( bindlessHandle ); - } - - GLint GetUniformLocation_ShadowMap2() { - return this->GetLocation(); - } -}; - -class u_ShadowMap3 : - GLUniformSampler2D { - public: - u_ShadowMap3( GLShader* shader ) : - GLUniformSampler2D( shader, "u_ShadowMap3" ) { - } - - void SetUniform_ShadowMap3Bindless( GLuint64 bindlessHandle ) { - this->SetValueBindless( bindlessHandle ); - } - - GLint GetUniformLocation_ShadowMap3() { - return this->GetLocation(); - } -}; - -class u_ShadowMap4 : - GLUniformSampler2D { - public: - u_ShadowMap4( GLShader* shader ) : - GLUniformSampler2D( shader, "u_ShadowMap4" ) { - } - - void SetUniform_ShadowMap4Bindless( GLuint64 bindlessHandle ) { - this->SetValueBindless( bindlessHandle ); - } - - GLint GetUniformLocation_ShadowMap4() { - return this->GetLocation(); - } -}; - -class u_ShadowClipMap : - GLUniformSampler2D { - public: - u_ShadowClipMap( GLShader* shader ) : - GLUniformSampler2D( shader, "u_ShadowClipMap" ) { - } - - void SetUniform_ShadowClipMapBindless( GLuint64 bindlessHandle ) { - this->SetValueBindless( bindlessHandle ); - } - - GLint GetUniformLocation_ShadowClipMap() { - return this->GetLocation(); - } -}; - -class u_ShadowClipMap0 : - GLUniformSampler2D { - public: - u_ShadowClipMap0( GLShader* shader ) : - GLUniformSampler2D( shader, "u_ShadowClipMap0" ) { - } - - void SetUniform_ShadowClipMap0Bindless( GLuint64 bindlessHandle ) { - this->SetValueBindless( bindlessHandle ); - } - - GLint GetUniformLocation_ShadowClipMap0() { - return this->GetLocation(); - } -}; - -class u_ShadowClipMap1 : - GLUniformSampler2D { - public: - u_ShadowClipMap1( GLShader* shader ) : - GLUniformSampler2D( shader, "u_ShadowClipMap1" ) { - } - - void SetUniform_ShadowClipMap1Bindless( GLuint64 bindlessHandle ) { - this->SetValueBindless( bindlessHandle ); - } - - GLint GetUniformLocation_ShadowClipMap1() { - return this->GetLocation(); - } -}; - -class u_ShadowClipMap2 : - GLUniformSampler2D { - public: - u_ShadowClipMap2( GLShader* shader ) : - GLUniformSampler2D( shader, "u_ShadowClipMap2" ) { - } - - void SetUniform_ShadowClipMap2Bindless( GLuint64 bindlessHandle ) { - this->SetValueBindless( bindlessHandle ); - } - - GLint GetUniformLocation_ShadowClipMap2() { - return this->GetLocation(); - } -}; - -class u_ShadowClipMap3 : - GLUniformSampler2D { - public: - u_ShadowClipMap3( GLShader* shader ) : - GLUniformSampler2D( shader, "u_ShadowClipMap3" ) { - } - - void SetUniform_ShadowClipMap3Bindless( GLuint64 bindlessHandle ) { - this->SetValueBindless( bindlessHandle ); - } - - GLint GetUniformLocation_ShadowClipMap3() { - return this->GetLocation(); - } -}; - -class u_ShadowClipMap4 : - GLUniformSampler2D { - public: - u_ShadowClipMap4( GLShader* shader ) : - GLUniformSampler2D( shader, "u_ShadowClipMap4" ) { - } - - void SetUniform_ShadowClipMap4Bindless( GLuint64 bindlessHandle ) { - this->SetValueBindless( bindlessHandle ); - } - - GLint GetUniformLocation_ShadowClipMap4() { - return this->GetLocation(); - } -}; - class u_TextureMatrix : GLUniformMatrix32f { @@ -2817,66 +2595,6 @@ class u_LightFrustum : } }; -class u_ShadowTexelSize : - GLUniform1f -{ -public: - u_ShadowTexelSize( GLShader *shader ) : - GLUniform1f( shader, "u_ShadowTexelSize" ) - { - } - - void SetUniform_ShadowTexelSize( float value ) - { - this->SetValue( value ); - } -}; - -class u_ShadowBlur : - GLUniform1f -{ -public: - u_ShadowBlur( GLShader *shader ) : - GLUniform1f( shader, "u_ShadowBlur" ) - { - } - - void SetUniform_ShadowBlur( float value ) - { - this->SetValue( value ); - } -}; - -class u_ShadowMatrix : - GLUniformMatrix4fv -{ -public: - u_ShadowMatrix( GLShader *shader ) : - GLUniformMatrix4fv( shader, "u_ShadowMatrix", MAX_SHADOWMAPS ) - { - } - - void SetUniform_ShadowMatrix( matrix_t m[ MAX_SHADOWMAPS ] ) - { - this->SetValue( MAX_SHADOWMAPS, GL_FALSE, m ); - } -}; - -class u_ShadowParallelSplitDistances : - GLUniform4f -{ -public: - u_ShadowParallelSplitDistances( GLShader *shader ) : - GLUniform4f( shader, "u_ShadowParallelSplitDistances" ) - { - } - - void SetUniform_ShadowParallelSplitDistances( const vec4_t v ) - { - this->SetValue( v ); - } -}; - class u_RefractionIndex : GLUniform1f { @@ -4208,8 +3926,6 @@ class GLShader_forwardLighting_omniXYZ : public u_MaterialMap, public u_AttenuationMapXY, public u_AttenuationMapZ, - public u_ShadowMap, - public u_ShadowClipMap, public u_RandomMap, public u_HeightMap, public u_TextureMatrix, @@ -4225,8 +3941,6 @@ class GLShader_forwardLighting_omniXYZ : public u_LightRadius, public u_LightScale, public u_LightAttenuationMatrix, - public u_ShadowTexelSize, - public u_ShadowBlur, public u_ModelMatrix, public u_ModelViewProjectionMatrix, public u_Bones, @@ -4238,8 +3952,7 @@ class GLShader_forwardLighting_omniXYZ : public GLCompileMacro_USE_VERTEX_SKINNING, public GLCompileMacro_USE_VERTEX_ANIMATION, public GLCompileMacro_USE_HEIGHTMAP_IN_NORMALMAP, - public GLCompileMacro_USE_RELIEF_MAPPING, - public GLCompileMacro_USE_SHADOWING //, + public GLCompileMacro_USE_RELIEF_MAPPING { public: GLShader_forwardLighting_omniXYZ(); @@ -4253,8 +3966,6 @@ class GLShader_forwardLighting_projXYZ : public u_MaterialMap, public u_AttenuationMapXY, public u_AttenuationMapZ, - public u_ShadowMap0, - public u_ShadowClipMap0, public u_RandomMap, public u_HeightMap, public u_TextureMatrix, @@ -4270,9 +3981,6 @@ class GLShader_forwardLighting_projXYZ : public u_LightRadius, public u_LightScale, public u_LightAttenuationMatrix, - public u_ShadowTexelSize, - public u_ShadowBlur, - public u_ShadowMatrix, public u_ModelMatrix, public u_ModelViewProjectionMatrix, public u_Bones, @@ -4284,8 +3992,7 @@ class GLShader_forwardLighting_projXYZ : public GLCompileMacro_USE_VERTEX_SKINNING, public GLCompileMacro_USE_VERTEX_ANIMATION, public GLCompileMacro_USE_HEIGHTMAP_IN_NORMALMAP, - public GLCompileMacro_USE_RELIEF_MAPPING, - public GLCompileMacro_USE_SHADOWING //, + public GLCompileMacro_USE_RELIEF_MAPPING { public: GLShader_forwardLighting_projXYZ(); @@ -4298,16 +4005,6 @@ class GLShader_forwardLighting_directionalSun : public u_DiffuseMap, public u_NormalMap, public u_MaterialMap, - public u_ShadowMap0, - public u_ShadowMap1, - public u_ShadowMap2, - public u_ShadowMap3, - public u_ShadowMap4, - public u_ShadowClipMap0, - public u_ShadowClipMap1, - public u_ShadowClipMap2, - public u_ShadowClipMap3, - public u_ShadowClipMap4, public u_HeightMap, public u_TextureMatrix, public u_SpecularExponent, @@ -4322,10 +4019,6 @@ class GLShader_forwardLighting_directionalSun : public u_LightRadius, public u_LightScale, public u_LightAttenuationMatrix, - public u_ShadowTexelSize, - public u_ShadowBlur, - public u_ShadowMatrix, - public u_ShadowParallelSplitDistances, public u_ModelMatrix, public u_ViewMatrix, public u_ModelViewProjectionMatrix, @@ -4338,8 +4031,7 @@ class GLShader_forwardLighting_directionalSun : public GLCompileMacro_USE_VERTEX_SKINNING, public GLCompileMacro_USE_VERTEX_ANIMATION, public GLCompileMacro_USE_HEIGHTMAP_IN_NORMALMAP, - public GLCompileMacro_USE_RELIEF_MAPPING, - public GLCompileMacro_USE_SHADOWING //, + public GLCompileMacro_USE_RELIEF_MAPPING { public: GLShader_forwardLighting_directionalSun(); @@ -4347,29 +4039,6 @@ class GLShader_forwardLighting_directionalSun : void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; }; -class GLShader_shadowFill : - public GLShader, - public u_ColorMap, - public u_TextureMatrix, - public u_AlphaThreshold, - public u_LightOrigin, - public u_LightRadius, - public u_ModelMatrix, - public u_ModelViewProjectionMatrix, - public u_Color_Float, - public u_Color_Uint, - public u_Bones, - public u_VertexInterpolation, - public GLDeformStage, - public GLCompileMacro_USE_VERTEX_SKINNING, - public GLCompileMacro_USE_VERTEX_ANIMATION, - public GLCompileMacro_LIGHT_DIRECTIONAL -{ -public: - GLShader_shadowFill(); - void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; -}; - class GLShader_reflection : public GLShader, public u_ColorMapCube, @@ -4604,16 +4273,6 @@ class GLShader_blur : void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; }; -class GLShader_debugShadowMap : - public GLShader, - public u_CurrentMap, - public u_ModelViewProjectionMatrix -{ -public: - GLShader_debugShadowMap(); - void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; -}; - class GLShader_liquid : public GLShader, public u_CurrentMap, @@ -4836,10 +4495,8 @@ extern GLShader_reflection *gl_reflectionShader; extern GLShader_reflectionMaterial *gl_reflectionShaderMaterial; extern GLShader_screen *gl_screenShader; extern GLShader_screenMaterial *gl_screenShaderMaterial; -extern GLShader_shadowFill *gl_shadowFillShader; extern GLShader_skybox *gl_skyboxShader; extern GLShader_skyboxMaterial *gl_skyboxShaderMaterial; -extern GLShader_debugShadowMap *gl_debugShadowMapShader; extern GLShaderManager gl_shaderManager; #endif // GL_SHADER_H diff --git a/src/engine/renderer/glsl_source/debugShadowMap_fp.glsl b/src/engine/renderer/glsl_source/debugShadowMap_fp.glsl deleted file mode 100644 index 9f29c1005..000000000 --- a/src/engine/renderer/glsl_source/debugShadowMap_fp.glsl +++ /dev/null @@ -1,72 +0,0 @@ -/* -=========================================================================== -Copyright (C) 2009 Robert Beckebans - -This file is part of XreaL source code. - -XreaL source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -XreaL source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with XreaL source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -/* debugShadowMap_fp.glsl */ - -/* swizzle one- and two-component textures to RG */ -#if defined(HAVE_ARB_texture_rg) -# define SWIZ1 r -# define SWIZ2 rg -#else -# define SWIZ1 a -# define SWIZ2 ar -#endif - -uniform sampler2D u_ShadowMap; - -IN(smooth) vec2 var_TexCoord; - -DECLARE_OUTPUT(vec4) - -void main() -{ -#if defined(ESM) - - float shadowMoments = texture2D(u_ShadowMap, var_TexCoord).SWIZ1; - - float shadowDistance = shadowMoments; - - outputColor = vec4(shadowDistance, 0.0, 0.0, 1.0); - -#elif defined(VSM) - vec2 shadowMoments = texture2D(u_ShadowMap, var_TexCoord).SWIZ2; - - float shadowDistance = shadowMoments.r; - float shadowDistanceSquared = shadowMoments.g; - - outputColor = vec4(shadowDistance, 0.0, 0.0, 1.0); - -#elif defined(EVSM) - - vec4 shadowMoments = texture2D(u_ShadowMap, var_TexCoord); - -#if defined(r_EVSMPostProcess) - float shadowDistance = shadowMoments.r; -#else - float shadowDistance = log(shadowMoments.b); -#endif - - outputColor = vec4(shadowDistance, 0.0, 0.0, 1.0); -#else - discard; -#endif -} diff --git a/src/engine/renderer/glsl_source/debugShadowMap_vp.glsl b/src/engine/renderer/glsl_source/debugShadowMap_vp.glsl deleted file mode 100644 index 211ac3bc5..000000000 --- a/src/engine/renderer/glsl_source/debugShadowMap_vp.glsl +++ /dev/null @@ -1,38 +0,0 @@ -/* -=========================================================================== -Copyright (C) 2009 Robert Beckebans - -This file is part of XreaL source code. - -XreaL source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -XreaL source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with XreaL source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -/* debugShadowMap_vp.glsl */ - -IN vec3 attr_Position; -IN vec2 attr_TexCoord0; - -uniform mat4 u_ModelViewProjectionMatrix; - -OUT(smooth) vec2 var_TexCoord; - -void main() -{ - // transform vertex position into homogenous clip-space - gl_Position = u_ModelViewProjectionMatrix * vec4(attr_Position, 1.0); - - var_TexCoord = attr_TexCoord0.st; -} diff --git a/src/engine/renderer/glsl_source/forwardLighting_fp.glsl b/src/engine/renderer/glsl_source/forwardLighting_fp.glsl index 1021815f2..21f0a19cf 100644 --- a/src/engine/renderer/glsl_source/forwardLighting_fp.glsl +++ b/src/engine/renderer/glsl_source/forwardLighting_fp.glsl @@ -41,25 +41,6 @@ uniform sampler2D u_MaterialMap; uniform sampler2D u_AttenuationMapXY; uniform sampler2D u_AttenuationMapZ; -#if defined(LIGHT_DIRECTIONAL) -uniform sampler2D u_ShadowMap0; -uniform sampler2D u_ShadowMap1; -uniform sampler2D u_ShadowMap2; -uniform sampler2D u_ShadowMap3; -uniform sampler2D u_ShadowMap4; -uniform sampler2D u_ShadowClipMap0; -uniform sampler2D u_ShadowClipMap1; -uniform sampler2D u_ShadowClipMap2; -uniform sampler2D u_ShadowClipMap3; -uniform sampler2D u_ShadowClipMap4; -#elif defined(LIGHT_PROJ) -uniform sampler2D u_ShadowMap0; -uniform sampler2D u_ShadowClipMap0; -#else -uniform samplerCube u_ShadowMap; -uniform samplerCube u_ShadowClipMap; -#endif - uniform sampler2D u_RandomMap; // random normals uniform vec3 u_ViewOrigin; @@ -74,11 +55,6 @@ uniform float u_LightRadius; uniform float u_LightScale; uniform float u_AlphaThreshold; -uniform mat4 u_ShadowMatrix[MAX_SHADOWMAPS]; -uniform vec4 u_ShadowParallelSplitDistances; -uniform float u_ShadowTexelSize; -uniform float u_ShadowBlur; - uniform mat4 u_ViewMatrix; IN(smooth) vec3 var_Position; @@ -91,38 +67,11 @@ IN(smooth) vec4 var_Color; DECLARE_OUTPUT(vec4) -/* -================ -MakeNormalVectors - -Given a normalized forward vector, create two -other perpendicular vectors -================ -*/ -void MakeNormalVectors(const vec3 forward, inout vec3 right, inout vec3 up) -{ - // this rotate and negate guarantees a vector - // not colinear with the original - right.y = -forward.x; - right.z = forward.y; - right.x = forward.z; - - float d = dot(right, forward); - right += forward * -d; - normalize(right); - up = cross(right, forward); // GLSL cross product is the same as in Q3A -} - float Rand(vec2 co) { return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); } -float Noise(vec2 co) -{ - return Rand(floor(co * 128.0)); -} - vec3 RandomVec3(vec2 uv) { vec3 dir; @@ -140,609 +89,6 @@ vec3 RandomVec3(vec2 uv) return dir; } - -/* -source: http://en.wikipedia.org/wiki/Chebyshev%27s_inequality - -X = distribution -mu = mean -sigma = standard deviation - -=> then for any real number k > 0: - -Pr(X -mu >= k * sigma) <= 1 / ( 1 + k^2) -*/ - -#if defined(VSM) || defined(EVSM) -float linstep(float low, float high, float v) -{ - return clamp((v - low)/(high - low), 0.0, 1.0); -} - -float ChebyshevUpperBound(vec2 shadowMoments, float vertexDistance, float minVariance) -{ - float shadowDistance = shadowMoments.x; - float shadowDistanceSquared = shadowMoments.y; - - // compute variance - float E_x2 = shadowDistanceSquared; - float Ex_2 = shadowDistance * shadowDistance; - - float variance = max(E_x2 - Ex_2, max(minVariance, VSM_EPSILON)); - // float variance = smoothstep(minVariance, 1.0, max(E_x2 - Ex_2, 0.0)); - - // compute probabilistic upper bound - float d = vertexDistance - shadowDistance; - float pMax = variance / (variance + (d * d)); - -#if defined(r_lightBleedReduction) - pMax = linstep(r_lightBleedReduction, 1.0, pMax); -#endif - - // one-tailed Chebyshev with k > 0 - return (vertexDistance <= shadowDistance ? 1.0 : pMax); -} -#endif - - -#if defined(EVSM) -vec2 WarpDepth(float depth) -{ - // rescale depth into [-1, 1] - depth = 2.0 * depth - 1.0; - float pos = exp( r_EVSMExponents.x * depth); - float neg = -exp(-r_EVSMExponents.y * depth); - - return vec2(pos, neg); -} - -vec4 ShadowDepthToEVSM(float depth) -{ - vec2 warpedDepth = WarpDepth(depth); - return vec4(warpedDepth.x, warpedDepth.x * warpedDepth.x, warpedDepth.y, warpedDepth.y * warpedDepth.y); -} -#endif // #if defined(EVSM) - -vec4 FixShadowMoments( vec4 moments ) -{ -#if !defined(EVSM) || defined(r_EVSMPostProcess) - return vec4( moments.SWIZ2, moments.SWIZ2 ); -#else - return moments; -#endif -} - -#if defined(LIGHT_DIRECTIONAL) - -void FetchShadowMoments(vec3 Pworld, out vec4 shadowVert, - out vec4 shadowMoments, out vec4 shadowClipMoments) -{ - // transform to camera space - vec4 Pcam = u_ViewMatrix * vec4(Pworld.xyz, 1.0); - float vertexDistanceToCamera = -Pcam.z; - -#if defined(r_parallelShadowSplits_1) - if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.x) - { - shadowVert = u_ShadowMatrix[0] * vec4(Pworld.xyz, 1.0); - shadowMoments = texture2DProj(u_ShadowMap0, shadowVert.xyw); - shadowClipMoments = texture2DProj(u_ShadowClipMap0, shadowVert.xyw); - } - else - { - shadowVert = u_ShadowMatrix[1] * vec4(Pworld.xyz, 1.0); - shadowMoments = texture2DProj(u_ShadowMap1, shadowVert.xyw); - shadowClipMoments = texture2DProj(u_ShadowClipMap1, shadowVert.xyw); - } -#elif defined(r_parallelShadowSplits_2) - if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.x) - { - shadowVert = u_ShadowMatrix[0] * vec4(Pworld.xyz, 1.0); - shadowMoments = texture2DProj(u_ShadowMap0, shadowVert.xyw); - shadowClipMoments = texture2DProj(u_ShadowClipMap0, shadowVert.xyw); - } - else if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.y) - { - shadowVert = u_ShadowMatrix[1] * vec4(Pworld.xyz, 1.0); - shadowMoments = texture2DProj(u_ShadowMap1, shadowVert.xyw); - shadowClipMoments = texture2DProj(u_ShadowClipMap1, shadowVert.xyw); - } - else - { - shadowVert = u_ShadowMatrix[2] * vec4(Pworld.xyz, 1.0); - shadowMoments = texture2DProj(u_ShadowMap2, shadowVert.xyw); - shadowClipMoments = texture2DProj(u_ShadowClipMap2, shadowVert.xyw); - } -#elif defined(r_parallelShadowSplits_3) - if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.x) - { - shadowVert = u_ShadowMatrix[0] * vec4(Pworld.xyz, 1.0); - shadowMoments = texture2DProj(u_ShadowMap0, shadowVert.xyw); - shadowClipMoments = texture2DProj(u_ShadowClipMap0, shadowVert.xyw); - } - else if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.y) - { - shadowVert = u_ShadowMatrix[1] * vec4(Pworld.xyz, 1.0); - shadowMoments = texture2DProj(u_ShadowMap1, shadowVert.xyw); - shadowClipMoments = texture2DProj(u_ShadowClipMap1, shadowVert.xyw); - } - else if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.z) - { - shadowVert = u_ShadowMatrix[2] * vec4(Pworld.xyz, 1.0); - shadowMoments = texture2DProj(u_ShadowMap2, shadowVert.xyw); - shadowClipMoments = texture2DProj(u_ShadowClipMap2, shadowVert.xyw); - } - else - { - shadowVert = u_ShadowMatrix[3] * vec4(Pworld.xyz, 1.0); - shadowMoments = texture2DProj(u_ShadowMap3, shadowVert.xyw); - shadowClipMoments = texture2DProj(u_ShadowClipMap3, shadowVert.xyw); - } -#elif defined(r_parallelShadowSplits_4) - if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.x) - { - shadowVert = u_ShadowMatrix[0] * vec4(Pworld.xyz, 1.0); - shadowMoments = texture2DProj(u_ShadowMap0, shadowVert.xyw); - shadowClipMoments = texture2DProj(u_ShadowClipMap0, shadowVert.xyw); - } - else if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.y) - { - shadowVert = u_ShadowMatrix[1] * vec4(Pworld.xyz, 1.0); - shadowMoments = texture2DProj(u_ShadowMap1, shadowVert.xyw); - shadowClipMoments = texture2DProj(u_ShadowClipMap1, shadowVert.xyw); - } - else if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.z) - { - shadowVert = u_ShadowMatrix[2] * vec4(Pworld.xyz, 1.0); - shadowMoments = texture2DProj(u_ShadowMap2, shadowVert.xyw); - shadowClipMoments = texture2DProj(u_ShadowClipMap2, shadowVert.xyw); - } - else if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.w) - { - shadowVert = u_ShadowMatrix[3] * vec4(Pworld.xyz, 1.0); - shadowMoments = texture2DProj(u_ShadowMap3, shadowVert.xyw); - shadowClipMoments = texture2DProj(u_ShadowClipMap3, shadowVert.xyw); - } - else - { - shadowVert = u_ShadowMatrix[4] * vec4(Pworld.xyz, 1.0); - shadowMoments = texture2DProj(u_ShadowMap4, shadowVert.xyw); - shadowClipMoments = texture2DProj(u_ShadowClipMap4, shadowVert.xyw); - } -#else - { - shadowVert = u_ShadowMatrix[0] * vec4(Pworld.xyz, 1.0); - shadowMoments = texture2DProj(u_ShadowMap0, shadowVert.xyw); - shadowClipMoments = texture2DProj(u_ShadowClipMap0, shadowVert.xyw); - } -#endif - - shadowMoments = FixShadowMoments(shadowMoments); - shadowClipMoments = FixShadowMoments(shadowClipMoments); - -#if defined(EVSM) && defined(r_EVSMPostProcess) - shadowMoments = ShadowDepthToEVSM(shadowMoments.x); - shadowClipMoments = ShadowDepthToEVSM(shadowClipMoments.x); -#endif -} - -#if defined(r_PCFSamples) -vec4 PCF(vec3 Pworld, float filterWidth, float samples, out vec4 clipMoments) -{ - vec3 forward, right, up; - - // filterWidth *= u_LightRadius; - - forward = normalize(-u_LightDir); - MakeNormalVectors(forward, right, up); - - vec4 moments = vec4(0.0, 0.0, 0.0, 0.0); - clipMoments = vec4(0.0, 0.0, 0.0, 0.0); - -#if 0 - // compute step size for iterating through the kernel - float stepSize = 2.0 * filterWidth / samples; - - for(float i = -filterWidth; i < filterWidth; i += stepSize) - { - for(float j = -filterWidth; j < filterWidth; j += stepSize) - { - vec4 shadowVert; - vec4 shadowMoments; - vec4 shadowClipMoments; - - FetchShadowMoments(Pworld + right * i + up * j, shadowVert, shadowMoments, shadowClipMoments); - moments += shadowMoments; - clipMoments += shadowClipMoments; - } - } -#else - for(int i = 0; i < samples; i++) - { - for(int j = 0; j < samples; j++) - { - vec3 rand = RandomVec3(gl_FragCoord.st / r_FBufSize + vec2(i, j)) * filterWidth; - // rand.z = 0; - // rand = normalize(rand) * filterWidth; - - vec4 shadowVert; - vec4 shadowMoments; - vec4 shadowClipMoments; - - FetchShadowMoments(Pworld + right * rand.x + up * rand.y, shadowVert, shadowMoments, shadowClipMoments); - moments += shadowMoments; - clipMoments += shadowClipMoments; - } - } -#endif - - // return average of the samples - float factor = (1.0 / (samples * samples)); - moments *= factor; - clipMoments *= factor; - return moments; -} -#endif // #if defined(r_PCFSamples) - - - -#elif defined(LIGHT_PROJ) - -void FetchShadowMoments(vec2 st, out vec4 shadowMoments, out vec4 shadowClipMoments) -{ -#if defined(EVSM) && defined(r_EVSMPostProcess) - shadowMoments = ShadowDepthToEVSM(texture2D(u_ShadowMap0, st).SWIZ1); - shadowClipMoments = ShadowDepthToEVSM(texture2D(u_ShadowClipMap0, st).SWIZ1); -#else - shadowMoments = FixShadowMoments(texture2D(u_ShadowMap0, st)); - shadowClipMoments = FixShadowMoments(texture2D(u_ShadowClipMap0, st)); -#endif -} - -#if defined(r_PCFSamples) -vec4 PCF(vec4 shadowVert, float filterWidth, float samples, out vec4 clipMoments) -{ - vec4 moments = vec4(0.0, 0.0, 0.0, 0.0); - clipMoments = moments; - -#if 0 - // compute step size for iterating through the kernel - float stepSize = 2.0 * filterWidth / samples; - - for(float i = -filterWidth; i < filterWidth; i += stepSize) - { - for(float j = -filterWidth; j < filterWidth; j += stepSize) - { - vec4 sm, scm; - FetchShadowMoments(shadowVert.xy / shadowVert.w + vec2(i, j), sm, scm); - moments += sm; - clipMoments += scm; - } - } -#else - for(int i = 0; i < samples; i++) - { - for(int j = 0; j < samples; j++) - { - vec3 rand = RandomVec3(gl_FragCoord.st / r_FBufSize + vec2(i, j)) * filterWidth; - // rand = vec3(0.0, 0.0, 1.0); - // rand.z = 0; - // rand = normalize(rand);// * filterWidth; - - vec4 sm, scm; - FetchShadowMoments(shadowVert.xy / shadowVert.w + rand.xy, sm, scm); - moments += sm; - clipMoments += scm; - } - } -#endif - - // return average of the samples - float factor = (1.0 / (samples * samples)); - moments *= factor; - clipMoments *= factor; - return moments; -} -#endif // #if defined(r_PCFSamples) - -#else - -void FetchShadowMoments(vec3 incidentRay, out vec4 shadowMoments, out vec4 shadowClipMoments) -{ -#if defined(EVSM) && defined(r_EVSMPostProcess) - shadowMoments = ShadowDepthToEVSM(textureCube(u_ShadowMap, incidentRay).SWIZ1); - shadowClipMoments = ShadowDepthToEVSM(textureCube(u_ShadowClipMap, incidentRay).SWIZ1); -#else - shadowMoments = FixShadowMoments(textureCube(u_ShadowMap, incidentRay)); - shadowClipMoments = FixShadowMoments(textureCube(u_ShadowClipMap, incidentRay)); -#endif -} - -#if defined(r_PCFSamples) -vec4 PCF(vec4 incidentRay, float filterWidth, float samples, out vec4 clipMoments) -{ - vec3 forward, right, up; - - forward = normalize(incidentRay.xyz); - MakeNormalVectors(forward, right, up); - - vec4 moments = vec4(0.0, 0.0, 0.0, 0.0); - clipMoments = moments; - -#if 0 - // compute step size for iterating through the kernel - float stepSize = 2.0 * filterWidth / samples; - - for(float i = -filterWidth; i < filterWidth; i += stepSize) - { - for(float j = -filterWidth; j < filterWidth; j += stepSize) - { - vec4 sm, scm; - FetchShadowMoments(incidentRay.xyz + right * i + up * j, sm, scm); - moments += sm; - clipMoments += scm; - } - } -#else - for(int i = 0; i < samples; i++) - { - for(int j = 0; j < samples; j++) - { - vec3 rand = RandomVec3(gl_FragCoord.st / r_FBufSize + vec2(i, j)) * filterWidth; - // rand.z = 0; - // rand = normalize(rand) * filterWidth; - - vec4 sm, scm; - FetchShadowMoments(incidentRay.xyz + right * rand.x + up * rand.y, sm, scm); - moments += sm; - clipMoments += scm; - } - } -#endif - - // return average of the samples - float factor = (1.0 / (samples * samples)); - moments *= factor; - clipMoments *= factor; - return moments; -} -#endif // #if defined(r_PCFSamples) - -#endif - - -#if 0//defined(PCSS) - - -#if defined(LIGHT_DIRECTIONAL) -// TODO SumBlocker for sun shadowing - -#elif defined(LIGHT_PROJ) -float SumBlocker(vec4 shadowVert, float vertexDistance, float filterWidth, float samples) -{ - float stepSize = 2.0 * filterWidth / samples; - - float blockerCount = 0.0; - float blockerSum = 0.0; - - for(float i = -filterWidth; i < filterWidth; i += stepSize) - { - for(float j = -filterWidth; j < filterWidth; j += stepSize) - { - float shadowDistance = texture2DProj(u_ShadowMap0, vec3(shadowVert.xy + vec2(i, j), shadowVert.w)).SWIZ1; - // float shadowDistance = texture2D(u_ShadowMap, shadowVert.xy / shadowVert.w + vec2(i, j)).x; - - // FIXME VSM_CLAMP - - if(vertexDistance > shadowDistance) - { - blockerCount += 1.0; - blockerSum += shadowDistance; - } - } - } - - float result; - if(blockerCount > 0.0) - result = blockerSum / blockerCount; - else - result = 0.0; - - return result; -} -#else -// case LIGHT_OMNI -float SumBlocker(vec4 incidentRay, float vertexDistance, float filterWidth, float samples) -{ - vec3 forward, right, up; - - forward = normalize(incidentRay.xyz); - MakeNormalVectors(forward, right, up); - - float stepSize = 2.0 * filterWidth / samples; - - float blockerCount = 0.0; - float blockerSum = 0.0; - - for(float i = -filterWidth; i < filterWidth; i += stepSize) - { - for(float j = -filterWidth; j < filterWidth; j += stepSize) - { - float shadowDistance = textureCube(u_ShadowMap, incidentRay.xyz + right * i + up * j).SWIZ1; - - if(vertexDistance > shadowDistance) - { - blockerCount += 1.0; - blockerSum += shadowDistance; - } - } - } - - float result; - if(blockerCount > 0.0) - result = blockerSum / blockerCount; - else - result = -1.0; - - return result; -} -#endif - -float EstimatePenumbra(float vertexDistance, float blocker) -{ - float penumbra; - - if(blocker == 0.0) - penumbra = 0.0; - else - penumbra = ((vertexDistance - blocker) * u_LightRadius) / blocker; - - return penumbra; -} - -vec4 PCSS( vec4 incidentRay, float vertexDistance, float PCFSamples ) -{ - // step 1: find blocker estimate - const float blockerSamples = 6.0; - float blockerSearchWidth = u_ShadowTexelSize * u_LightRadius / vertexDistance; - float blocker = SumBlocker(incidentRay, vertexDistance, blockerSearchWidth, blockerSamples); - - // step 2: estimate penumbra using parallel planes approximation - float penumbra = EstimatePenumbra(vertexDistance, blocker); - - // step 3: compute percentage-closer filter - vec4 shadowMoments; - - if(penumbra > 0.0 && blocker > -1.0) - { - // float maxpen = PCFsamples * (1.0 / u_ShadowTexelSize); - // if(penumbra > maxpen) - // penumbra = maxpen; - // - - // shadowMoments = PCF(incidentRay, penumbra, PCFsamples); - vec4 clipMoments; - shadowMoments = PCF(incidentRay, u_ShadowTexelSize * u_ShadowBlur * penumbra, PCFsamples, clipMoments); - } - else - { - shadowMoments = FetchShadowMoments(incidentRay); - } -} -#endif - -float ShadowTest( float vertexDistance, vec4 shadowMoments, vec4 shadowClipMoments ) -{ - float shadow = 1.0; -#if defined( ESM ) - float shadowDistance = shadowMoments.x; - - // standard shadow mapping - if( vertexDistance <= 1.0 ) - shadow = step( vertexDistance, shadowDistance ); - if( u_LightScale < 0.0 ) { - shadow = 1.0 - shadow; - shadow *= step( vertexDistance, shadowClipMoments.x ); - } - - //shadow = vertexDistance <= shadowDistance ? 1.0 : 0.0; - // exponential shadow mapping - // shadow = clamp(exp(r_overDarkeningFactor * (shadowDistance - log(vertexDistance))), 0.0, 1.0); - // shadow = clamp(exp(r_overDarkeningFactor * shadowDistance) * exp(-r_overDarkeningFactor * vertexDistance), 0.0, 1.0); - // shadow = smoothstep(0.0, 1.0, shadow); - -#if defined(r_debugShadowMaps) && defined( HAVE_EXT_gpu_shader4 ) - outputColor.r = (r_debugShadowMaps & 1) != 0 ? shadowDistance : 0.0; - outputColor.g = (r_debugShadowMaps & 2) != 0 ? -(shadowDistance - vertexDistance) : 0.0; - outputColor.b = (r_debugShadowMaps & 4) != 0 ? shadow : 0.0; - outputColor.a = 1.0; -#endif - -#elif defined( VSM ) -#if defined(VSM_CLAMP) - // convert to [-1, 1] vector space - shadowMoments = 2.0 * (shadowMoments - 0.5); -#endif - - shadow = ChebyshevUpperBound(shadowMoments.xy, vertexDistance, VSM_EPSILON); - if( u_LightScale < 0.0 ) { - shadow = 1.0 - shadow; - shadow *= ChebyshevUpperBound(shadowClipMoments.xy, vertexDistance, VSM_EPSILON); - } -#elif defined( EVSM ) - vec2 warpedVertexDistances = WarpDepth(vertexDistance); - - // derivative of warping at depth - vec2 depthScale = VSM_EPSILON * r_EVSMExponents * warpedVertexDistances; - vec2 minVariance = depthScale * depthScale; - - float posContrib = ChebyshevUpperBound(shadowMoments.xy, warpedVertexDistances.x, minVariance.x); - float negContrib = ChebyshevUpperBound(shadowMoments.zw, warpedVertexDistances.y, minVariance.y); - - shadow = min(posContrib, negContrib); - -#if defined(r_debugShadowMaps) && defined( HAVE_EXT_gpu_shader4 ) - outputColor.r = (r_debugShadowMaps & 1) != 0 ? posContrib : 0.0; - outputColor.g = (r_debugShadowMaps & 2) != 0 ? negContrib : 0.0; - outputColor.b = (r_debugShadowMaps & 4) != 0 ? shadow : 0.0; - outputColor.a = 1.0; -#endif - - if( u_LightScale < 0.0 ) { - shadow = 1.0 - shadow; - posContrib = ChebyshevUpperBound(shadowClipMoments.xy, warpedVertexDistances.x, minVariance.x); - negContrib = ChebyshevUpperBound(shadowClipMoments.zw, warpedVertexDistances.y, minVariance.y); - - shadow *= 1.0 - min(posContrib, negContrib); - } -#endif - return shadow; -} - -/* -Some explanations by Marco Salvi about exponential shadow mapping: - -Now you are filtering exponential values which rapidly go out of range, -to avoid this issue you can filter the logarithm of these values (and the go back to exp space) - -For example if you averaging two exponential value such as exp(A) and exp(B) you have: - -a*exp(A) + b*exp(B) (a and b are some filter weights) - -but you can rewrite the same expression as: - -exp(A) * (a + b*exp(B-A)) , - -exp(A) * exp( log (a + b*exp(B-A)))), - -and: - -exp(A + log(a + b*exp(B-A)) - -Now your sum of exponential is written as a single exponential, if you take the logarithm of it you can then just work on its argument: - -A + log(a + b*exp(B-A)) - -Basically you end up filtering the argument of your exponential functions, which are just linear depth values, -so you enjoy the same range you have with less exotic techniques. -Just don't forget to go back to exp space when you use the final filtered value. - - -Though hardware texture filtering is not mathematically correct in log space it just causes a some overdarkening, nothing major. - -If you have your shadow map filtered in log space occlusion is just computed like this (let assume we use bilinear filtering): - -float occluder = tex2D( esm_sampler, esm_uv ); -float occlusion = exp( occluder - receiver ); - -while with filtering in exp space you have: - -float exp_occluder = tex2D( esm_sampler, esm_uv ); -float occlusion = exp_occluder / exp( receiver ); - -EDIT: if more complex filters are used (trilinear, aniso, with mip maps) you need to generate mip maps using log filteirng as well. -*/ - /* float log_conv(float x0, float X, float y0, float Y) { @@ -760,182 +106,6 @@ void main() return; #endif - - float shadow = 1.0; -#if defined(USE_SHADOWING) - const float SHADOW_BIAS = 0.010; -#if defined(LIGHT_DIRECTIONAL) - - - vec4 shadowVert; - vec4 shadowMoments, shadowClipMoments; - FetchShadowMoments(var_Position.xyz, shadowVert, shadowMoments, shadowClipMoments); - - float vertexDistance = shadowVert.z - SHADOW_BIAS; - // FIXME -#if 0 // defined(r_PCFSamples) - shadowMoments = PCF(var_Position.xyz, u_ShadowTexelSize * u_ShadowBlur, r_PCFSamples); -#endif - -#if 0 - outputColor = vec4(u_ShadowTexelSize * u_ShadowBlur * u_LightRadius, 0.0, 0.0, 1.0); - return; -#endif - -#if defined(r_showParallelShadowSplits) - // transform to camera space - vec4 Pcam = u_ViewMatrix * vec4(var_Position.xyz, 1.0); - float vertexDistanceToCamera = -Pcam.z; - -#if defined(r_parallelShadowSplits_1) - if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.x) - { - outputColor = vec4(1.0, 0.0, 0.0, 1.0); - return; - } - else - { - outputColor = vec4(1.0, 0.0, 1.0, 1.0); - return; - } -#elif defined(r_parallelShadowSplits_2) - if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.x) - { - outputColor = vec4(1.0, 0.0, 0.0, 1.0); - return; - } - else if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.y) - { - outputColor = vec4(0.0, 1.0, 0.0, 1.0); - return; - } - else - { - outputColor = vec4(1.0, 0.0, 1.0, 1.0); - return; - } -#elif defined(r_parallelShadowSplits_3) - if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.x) - { - outputColor = vec4(1.0, 0.0, 0.0, 1.0); - return; - } - else if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.y) - { - outputColor = vec4(0.0, 1.0, 0.0, 1.0); - return; - } - else if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.z) - { - outputColor = vec4(0.0, 0.0, 1.0, 1.0); - return; - } - else - { - outputColor = vec4(1.0, 0.0, 1.0, 1.0); - return; - } -#elif defined(r_parallelShadowSplits_4) - if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.x) - { - outputColor = vec4(1.0, 0.0, 0.0, 1.0); - return; - } - else if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.y) - { - outputColor = vec4(0.0, 1.0, 0.0, 1.0); - return; - } - else if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.z) - { - outputColor = vec4(0.0, 0.0, 1.0, 1.0); - return; - } - else if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.w) - { - outputColor = vec4(1.0, 1.0, 0.0, 1.0); - return; - } - else - { - outputColor = vec4(1.0, 0.0, 1.0, 1.0); - return; - } -#else - { - outputColor = vec4(1.0, 0.0, 1.0, 1.0); - return; - } -#endif -#endif // #if defined(r_showParallelShadowSplits) - -#elif defined(LIGHT_PROJ) - - vec4 shadowVert = u_ShadowMatrix[0] * vec4(var_Position.xyz, 1.0); - - // compute incident ray - vec3 incidentRay = var_Position.xyz - u_LightOrigin; - - float vertexDistance = length(incidentRay) / u_LightRadius - SHADOW_BIAS; - if( vertexDistance >= 1.0f ) { - discard; - return; - } - -#if defined(r_PCFSamples) -#if 0//defined( PCSS ) - vec4 shadowMoments = PCSS(vertexDistance, r_PCFSamples); -#else - vec4 shadowClipMoments; - vec4 shadowMoments = PCF(shadowVert, u_ShadowTexelSize * u_ShadowBlur, r_PCFSamples, shadowClipMoments); -#endif -#else - - // no filter - vec4 shadowMoments, shadowClipMoments; - - FetchShadowMoments(shadowVert.xy / shadowVert.w, shadowMoments, shadowClipMoments); - -#endif - -#else - // compute incident ray - vec3 incidentRay = var_Position.xyz - u_LightOrigin; - float incidentRayLen = length(incidentRay); - float vertexDistance = incidentRayLen / u_LightRadius - SHADOW_BIAS; - -#if 0 - outputColor = vec4(u_ShadowTexelSize * u_ShadowBlur * incidentRayLen, 0.0, 0.0, 1.0); - return; -#endif - -#if defined(r_PCFSamples) -#if 0//defined(PCSS) - vec4 shadowMoments = PCSS(vec4(incidentRay, 0.0), r_PCFSamples); -#else - vec4 shadowClipMoments; - vec4 shadowMoments = PCF(vec4(incidentRay, 0.0), u_ShadowTexelSize * u_ShadowBlur * incidentRayLen, r_PCFSamples, shadowClipMoments); -#endif -#else - // no extra filtering, single tap - vec4 shadowMoments, shadowClipMoments; - FetchShadowMoments(incidentRay, shadowMoments, shadowClipMoments); -#endif -#endif - shadow = ShadowTest(vertexDistance, shadowMoments, shadowClipMoments); - -#if defined(r_debugShadowMaps) - return; -#endif - - if(shadow <= 0.0) - { - discard; - return; - } - -#endif // USE_SHADOWING - // compute light direction in world space #if defined(LIGHT_DIRECTIONAL) vec3 lightDir = u_LightDir; @@ -1016,7 +186,6 @@ void main() color.rgb *= attenuationZ; #endif color.rgb *= abs(u_LightScale); - color.rgb *= shadow; color.rgb *= var_Color.rgb; diff --git a/src/engine/renderer/glsl_source/shadowFill_fp.glsl b/src/engine/renderer/glsl_source/shadowFill_fp.glsl deleted file mode 100644 index 2b4160f2f..000000000 --- a/src/engine/renderer/glsl_source/shadowFill_fp.glsl +++ /dev/null @@ -1,125 +0,0 @@ -/* -=========================================================================== -Copyright (C) 2006-2011 Robert Beckebans - -This file is part of XreaL source code. - -XreaL source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -XreaL source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with XreaL source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -/* shadowFill_fp.glsl */ - -uniform sampler2D u_ColorMap; -uniform float u_AlphaThreshold; -uniform vec3 u_LightOrigin; -uniform float u_LightRadius; - -IN(smooth) vec3 var_Position; -IN(smooth) vec2 var_TexCoords; -IN(smooth) vec4 var_Color; - -DECLARE_OUTPUT(vec4) - -#if defined(HAVE_ARB_texture_rg) -# define SWIZ1 r -# define SWIZ2 rg -#else -# define SWIZ1 a -# define SWIZ2 ar -#endif - -#if defined(EVSM) - -vec2 WarpDepth(float depth) -{ - // rescale depth into [-1, 1] - depth = 2.0 * depth - 1.0; - float pos = exp( r_EVSMExponents.x * depth); - float neg = -exp(-r_EVSMExponents.y * depth); - - return vec2(pos, neg); -} - -vec4 ShadowDepthToEVSM(float depth) -{ - vec2 warpedDepth = WarpDepth(depth); - return vec4(warpedDepth.x, warpedDepth.x * warpedDepth.x, warpedDepth.y, warpedDepth.y * warpedDepth.y); -} - -#endif // #if defined(EVSM) - -void main() -{ - vec4 color = texture2D(u_ColorMap, var_TexCoords); - - if( abs(color.a + u_AlphaThreshold) <= 1.0 ) - { - discard; - return; - } - - -#if defined(VSM) - - float distance; - -#if defined(LIGHT_DIRECTIONAL) - distance = gl_FragCoord.z; -#else - distance = length(var_Position - u_LightOrigin) / u_LightRadius; -#endif - - float distanceSquared = distance * distance; - - // shadowmap can be float RGBA or luminance alpha so store distanceSquared into alpha - -#if defined(VSM_CLAMP) - // convert to [0,1] color space - outputColor.SWIZ2 = vec2(distance, distanceSquared) * 0.5 + 0.5; -#else - outputColor.SWIZ2 = vec2(distance, distanceSquared); -#endif - -#elif defined(EVSM) || defined(ESM) - - float distance; -#if defined(LIGHT_DIRECTIONAL) - { - distance = gl_FragCoord.z;// * r_shadowMapDepthScale; - //distance /= gl_FragCoord.w; - //distance = var_Position.z / var_Position.w; - //distance = var_Position.z; - } -#else - { - distance = (length(var_Position - u_LightOrigin) / u_LightRadius); // * r_shadowMapDepthScale; - } -#endif - -#if defined(EVSM) -#if !defined(r_EVSMPostProcess) - outputColor = ShadowDepthToEVSM(distance); -#else - outputColor.SWIZ1 = distance; -#endif -#else - outputColor.SWIZ1 = distance; -#endif // defined(EVSM) - -#else - outputColor = vec4(0.0, 0.0, 0.0, 0.0); -#endif -} diff --git a/src/engine/renderer/glsl_source/shadowFill_vp.glsl b/src/engine/renderer/glsl_source/shadowFill_vp.glsl deleted file mode 100644 index 9c082423d..000000000 --- a/src/engine/renderer/glsl_source/shadowFill_vp.glsl +++ /dev/null @@ -1,78 +0,0 @@ -/* -=========================================================================== -Copyright (C) 2006-2011 Robert Beckebans - -This file is part of XreaL source code. - -XreaL source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -XreaL source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with XreaL source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -/* shadowFill_vp.glsl */ - -#insert common -#insert vertexSimple_vp -#insert vertexSkinning_vp -#insert vertexAnimation_vp - -uniform colorPack u_Color; - -uniform mat3x2 u_TextureMatrix; -uniform mat4 u_ModelMatrix; -uniform mat4 u_ModelViewProjectionMatrix; - -uniform float u_Time; - -OUT(smooth) vec3 var_Position; -OUT(smooth) vec2 var_TexCoords; -OUT(smooth) vec4 var_Color; - -void DeformVertex( inout vec4 pos, - inout vec3 normal, - inout vec2 st, - inout vec4 color, - in float time); - -void main() -{ - vec4 position; - localBasis LB; - vec2 texCoord, lmCoord; - vec4 color; - - VertexFetch( position, LB, color, texCoord, lmCoord ); - - DeformVertex( position, - LB.normal, - texCoord, - color, - u_Time); - - // transform vertex position into homogenous clip-space - gl_Position = u_ModelViewProjectionMatrix * position; - // transform position into world space -#if defined(LIGHT_DIRECTIONAL) - var_Position = gl_Position.xyz / gl_Position.w; -#else - // transform position into world space - var_Position = (u_ModelMatrix * position).xyz; -#endif - - // transform texcoords - var_TexCoords = (u_TextureMatrix * vec3(texCoord, 1.0)).st; - - // assign color - var_Color = UnpackColor( u_Color ); -} diff --git a/src/engine/renderer/shaders.cpp b/src/engine/renderer/shaders.cpp index 40f14d107..eab116bcd 100644 --- a/src/engine/renderer/shaders.cpp +++ b/src/engine/renderer/shaders.cpp @@ -37,8 +37,6 @@ #include "vertexSimple_vp.glsl.h" #include "vertexSkinning_vp.glsl.h" -#include "debugShadowMap_vp.glsl.h" -#include "debugShadowMap_fp.glsl.h" #include "fogQuake3_vp.glsl.h" #include "fogQuake3_fp.glsl.h" #include "forwardLighting_vp.glsl.h" @@ -57,8 +55,6 @@ #include "reflection_CB_fp.glsl.h" #include "screen_vp.glsl.h" #include "screen_fp.glsl.h" -#include "shadowFill_vp.glsl.h" -#include "shadowFill_fp.glsl.h" #include "skybox_vp.glsl.h" #include "skybox_fp.glsl.h" @@ -105,8 +101,6 @@ std::unordered_map shadermap({ { "vertexSkinning_vp.glsl", std::string( reinterpret_cast< const char* >( vertexSkinning_vp_glsl ), sizeof( vertexSkinning_vp_glsl ) ) }, // Regular shaders - { "debugShadowMap_vp.glsl", std::string( reinterpret_cast< const char* >( debugShadowMap_vp_glsl ), sizeof( debugShadowMap_vp_glsl ) ) }, - { "debugShadowMap_fp.glsl", std::string( reinterpret_cast< const char* >( debugShadowMap_fp_glsl ), sizeof( debugShadowMap_fp_glsl ) ) }, { "fogQuake3_vp.glsl", std::string( reinterpret_cast< const char* >( fogQuake3_vp_glsl ), sizeof( fogQuake3_vp_glsl ) ) }, { "fogQuake3_fp.glsl", std::string( reinterpret_cast< const char* >( fogQuake3_fp_glsl ), sizeof( fogQuake3_fp_glsl ) ) }, { "forwardLighting_vp.glsl", std::string( reinterpret_cast< const char* >( forwardLighting_vp_glsl ), sizeof( forwardLighting_vp_glsl ) ) }, @@ -125,8 +119,6 @@ std::unordered_map shadermap({ { "reflection_CB_fp.glsl", std::string( reinterpret_cast< const char* >( reflection_CB_fp_glsl ), sizeof( reflection_CB_fp_glsl ) ) }, { "screen_vp.glsl", std::string( reinterpret_cast< const char* >( screen_vp_glsl ), sizeof( screen_vp_glsl ) ) }, { "screen_fp.glsl", std::string( reinterpret_cast< const char* >( screen_fp_glsl ), sizeof( screen_fp_glsl ) ) }, - { "shadowFill_vp.glsl", std::string( reinterpret_cast< const char* >( shadowFill_vp_glsl ), sizeof( shadowFill_vp_glsl ) ) }, - { "shadowFill_fp.glsl", std::string( reinterpret_cast< const char* >( shadowFill_fp_glsl ), sizeof( shadowFill_fp_glsl ) ) }, { "skybox_vp.glsl", std::string( reinterpret_cast< const char* >( skybox_vp_glsl ), sizeof( skybox_vp_glsl ) ) }, { "skybox_fp.glsl", std::string( reinterpret_cast< const char* >( skybox_fp_glsl ), sizeof( skybox_fp_glsl ) ) }, }); diff --git a/src/engine/renderer/tr_animation.cpp b/src/engine/renderer/tr_animation.cpp index 3f5e21e9d..b77469b72 100644 --- a/src/engine/renderer/tr_animation.cpp +++ b/src/engine/renderer/tr_animation.cpp @@ -817,26 +817,6 @@ void R_AddIQMInteractions( trRefEntity_t *ent, trRefLight_t *light, interactionT } } - // avoid drawing of certain objects -#if defined( USE_REFENTITY_NOSHADOWID ) - - if ( light->l.inverseShadows ) - { - if ( (iaType & IA_SHADOW) && ( light->l.noShadowID && ( light->l.noShadowID != ent->e.noShadowID ) ) ) - { - return; - } - } - else - { - if ( (iaType & IA_SHADOW) && ( light->l.noShadowID && ( light->l.noShadowID == ent->e.noShadowID ) ) ) - { - return; - } - } - -#endif - // don't add third_person objects if not in a portal personalModel = ( ent->e.renderfx & RF_THIRD_PERSON ) && tr.viewParms.portalLevel == 0; @@ -899,7 +879,7 @@ void R_AddIQMInteractions( trRefEntity_t *ent, trRefLight_t *light, interactionT } // skip all surfaces that don't matter for lighting only pass - if ( shader->isSky || ( !shader->interactLight && shader->noShadows ) ) + if ( shader->isSky || !shader->interactLight ) { continue; } @@ -939,26 +919,6 @@ void R_AddMD5Interactions( trRefEntity_t *ent, trRefLight_t *light, interactionT return; } - // avoid drawing of certain objects -#if defined( USE_REFENTITY_NOSHADOWID ) - - if ( light->l.inverseShadows ) - { - if ( (iaType & IA_SHADOW) && ( light->l.noShadowID && ( light->l.noShadowID != ent->e.noShadowID ) ) ) - { - return; - } - } - else - { - if ( (iaType & IA_SHADOW) && ( light->l.noShadowID && ( light->l.noShadowID == ent->e.noShadowID ) ) ) - { - return; - } - } - -#endif - // don't add third_person objects if not in a portal personalModel = ( ent->e.renderfx & RF_THIRD_PERSON ) && tr.viewParms.portalLevel == 0; @@ -1027,7 +987,7 @@ void R_AddMD5Interactions( trRefEntity_t *ent, trRefLight_t *light, interactionT } // skip all surfaces that don't matter for lighting only pass - if ( shader->isSky || ( !shader->interactLight && shader->noShadows ) ) + if ( shader->isSky || !shader->interactLight ) { continue; } @@ -1086,7 +1046,7 @@ void R_AddMD5Interactions( trRefEntity_t *ent, trRefLight_t *light, interactionT } // skip all surfaces that don't matter for lighting only pass - if ( shader->isSky || ( !shader->interactLight && shader->noShadows ) ) + if ( shader->isSky || !shader->interactLight ) { continue; } diff --git a/src/engine/renderer/tr_backend.cpp b/src/engine/renderer/tr_backend.cpp index f67c2117b..10be006b8 100644 --- a/src/engine/renderer/tr_backend.cpp +++ b/src/engine/renderer/tr_backend.cpp @@ -967,1516 +967,165 @@ static void RB_RenderDrawSurfaces( shaderSort_t fromSort, shaderSort_t toSort, GL_CheckErrors(); } -/* - * helper function for parallel split shadow mapping - */ -static int MergeInteractionBounds( const matrix_t lightViewProjectionMatrix, interaction_t *ia, int iaCount, vec3_t bounds[ 2 ], bool shadowCasters ) -{ - int i; - int j; - surfaceType_t *surface; - vec4_t point; - vec4_t transf; - vec3_t worldBounds[ 2 ]; - int numCasters; - - frustum_t frustum; - cplane_t *clipPlane; - int r; - - numCasters = 0; - ClearBounds( bounds[ 0 ], bounds[ 1 ] ); - - // calculate frustum planes using the modelview projection matrix - R_SetupFrustum2( frustum, lightViewProjectionMatrix ); - - while ( iaCount < backEnd.viewParms.numInteractions ) - { - surface = ia->surface; - - if ( shadowCasters ) - { - if ( !(ia->type & IA_SHADOW) ) - { - goto skipInteraction; - } - } - else - { - // we only merge shadow receivers - if ( !(ia->type & IA_LIGHT) ) - { - goto skipInteraction; - } - } - - if ( *surface == surfaceType_t::SF_FACE || *surface == surfaceType_t::SF_GRID || *surface == surfaceType_t::SF_TRIANGLES - || *surface == surfaceType_t::SF_VBO_MESH ) - { - srfGeneric_t *gen = ( srfGeneric_t * ) surface; - - VectorCopy( gen->bounds[ 0 ], worldBounds[ 0 ] ); - VectorCopy( gen->bounds[ 1 ], worldBounds[ 1 ] ); - } - else if ( *surface == surfaceType_t::SF_MDV ) - { - goto skipInteraction; - } - else - { - goto skipInteraction; - } - - // use the frustum planes to cut off shadow casters beyond the split frustum - for ( i = 0; i < 6; i++ ) - { - clipPlane = &frustum[ i ]; - - // we can have shadow casters outside the initial computed light view frustum - if ( i == Util::ordinal(frustumBits_t::FRUSTUM_NEAR) && shadowCasters ) - { - continue; - } - - r = BoxOnPlaneSide( worldBounds[ 0 ], worldBounds[ 1 ], clipPlane ); - - if ( r == 2 ) - { - goto skipInteraction; - } - } - - if ( shadowCasters && (ia->type & IA_SHADOW) ) - { - numCasters++; - } - - for ( j = 0; j < 8; j++ ) - { - point[ 0 ] = worldBounds[ j & 1 ][ 0 ]; - point[ 1 ] = worldBounds[( j >> 1 ) & 1 ][ 1 ]; - point[ 2 ] = worldBounds[( j >> 2 ) & 1 ][ 2 ]; - point[ 3 ] = 1; - - MatrixTransform4( lightViewProjectionMatrix, point, transf ); - transf[ 0 ] /= transf[ 3 ]; - transf[ 1 ] /= transf[ 3 ]; - transf[ 2 ] /= transf[ 3 ]; - - AddPointToBounds( transf, bounds[ 0 ], bounds[ 1 ] ); - } - -skipInteraction: - - if ( !ia->next ) - { - // this is the last interaction of the current light - break; - } - else - { - // just continue - ia = ia->next; - iaCount++; - } - } - - return numCasters; -} - -static interaction_t *IterateLights( const interaction_t *prev ) -{ - if ( !prev && backEnd.viewParms.numInteractions > 0 ) - { - return backEnd.viewParms.interactions; - } - - if ( backEnd.viewParms.numInteractions <= 0 ) - { - return nullptr; - } - - const interaction_t *next = prev; - const interaction_t *last = &backEnd.viewParms.interactions[ backEnd.viewParms.numInteractions - 1 ]; - - while ( next <= last && next->light == prev->light ) - { - next++; - } - - if ( next > last ) - { - next = nullptr; - } - - return ( interaction_t * ) next; -} - -static void RB_SetupLightAttenuationForEntity( trRefLight_t *light, const trRefEntity_t *entity ) -{ - matrix_t modelToLight; - - // transform light origin into model space for u_LightOrigin parameter - if ( entity != &tr.worldEntity ) - { - vec3_t tmp; - VectorSubtract( light->origin, backEnd.orientation.origin, tmp ); - light->transformed[ 0 ] = DotProduct( tmp, backEnd.orientation.axis[ 0 ] ); - light->transformed[ 1 ] = DotProduct( tmp, backEnd.orientation.axis[ 1 ] ); - light->transformed[ 2 ] = DotProduct( tmp, backEnd.orientation.axis[ 2 ] ); - } - else - { - VectorCopy( light->origin, light->transformed ); - } - - MatrixMultiply( light->viewMatrix, backEnd.orientation.transformMatrix, modelToLight ); - - // build the attenuation matrix using the entity transform - switch ( light->l.rlType ) - { - case refLightType_t::RL_OMNI: - { - MatrixSetupTranslation( light->attenuationMatrix, 0.5, 0.5, 0.5 ); // bias - MatrixMultiplyScale( light->attenuationMatrix, 0.5, 0.5, 0.5 ); // scale - MatrixMultiply2( light->attenuationMatrix, light->projectionMatrix ); - MatrixMultiply2( light->attenuationMatrix, modelToLight ); - - MatrixCopy( light->attenuationMatrix, light->shadowMatrices[ 0 ] ); - break; - } - - case refLightType_t::RL_PROJ: - { - MatrixSetupTranslation( light->attenuationMatrix, 0.5, 0.5, 0.0 ); // bias - MatrixMultiplyScale( light->attenuationMatrix, 0.5f, 0.5f, 1.0f / std::min( light->falloffLength, 1.0f ) ); // scale - MatrixMultiply2( light->attenuationMatrix, light->projectionMatrix ); - MatrixMultiply2( light->attenuationMatrix, modelToLight ); - - MatrixCopy( light->attenuationMatrix, light->shadowMatrices[ 0 ] ); - break; - } - - case refLightType_t::RL_DIRECTIONAL: - { - MatrixSetupTranslation( light->attenuationMatrix, 0.5, 0.5, 0.5 ); // bias - MatrixMultiplyScale( light->attenuationMatrix, 0.5, 0.5, 0.5 ); // scale - MatrixMultiply2( light->attenuationMatrix, light->projectionMatrix ); - MatrixMultiply2( light->attenuationMatrix, modelToLight ); - break; - } - - case refLightType_t::RL_MAX_REF_LIGHT_TYPE: - { - //Nothing for right now... - break; - } - } -} - -/* -================= -RB_RenderInteractions -================= -*/ -static void RB_RenderInteractions() -{ - shader_t *shader, *oldShader; - trRefEntity_t *entity, *oldEntity; - trRefLight_t *light; - const interaction_t *ia; - const interaction_t *iaFirst; - bool depthRange, oldDepthRange; - surfaceType_t *surface; - int startTime = 0, endTime = 0; - - GLIMP_LOGCOMMENT( "--- RB_RenderInteractions ---" ); - - if ( r_speeds->integer == Util::ordinal(renderSpeeds_t::RSPEEDS_SHADING_TIMES)) - { - glFinish(); - startTime = ri.Milliseconds(); - } - - // draw everything - oldEntity = nullptr; - oldShader = nullptr; - oldDepthRange = false; - depthRange = false; - iaFirst = nullptr; - - // render interactions - while ( ( iaFirst = IterateLights( iaFirst ) ) ) - { - backEnd.currentLight = light = iaFirst->light; - - // set light scissor to reduce fillrate - GL_Scissor( iaFirst->scissorX, iaFirst->scissorY, iaFirst->scissorWidth, iaFirst->scissorHeight ); - - for ( ia = iaFirst; ia; ia = ia->next ) - { - backEnd.currentEntity = entity = ia->entity; - surface = ia->surface; - shader = ia->shader; - - if ( !shader || !shader->interactLight ) - { - // skip this interaction because the surface shader has no ability to interact with light - // this will save texcoords and matrix calculations - continue; - } - - if ( !(ia->type & IA_LIGHT) ) - { - // skip this interaction because the interaction is meant for shadowing only - continue; - } - - GLIMP_LOGCOMMENT( "----- Rendering new light -----" ); - - // Tr3B: this should never happen in the first iteration - if ( entity == oldEntity && shader == oldShader ) - { - // fast path, same as previous - rb_surfaceTable[Util::ordinal(*surface)](surface ); - continue; - } - - // draw the contents of the last shader batch - Tess_End(); - - // begin a new batch - Tess_Begin( Tess_StageIteratorLighting, shader, light->shader, false, -1, 0 ); - - // change the modelview matrix if needed - if ( entity != oldEntity ) - { - depthRange = false; - - if ( entity != &tr.worldEntity ) - { - // set up the transformation matrix - R_RotateEntityForViewParms( backEnd.currentEntity, &backEnd.viewParms, &backEnd.orientation ); - - if ( backEnd.currentEntity->e.renderfx & RF_DEPTHHACK ) - { - // hack the depth range to prevent view model from poking into walls - depthRange = true; - } - } - else - { - backEnd.orientation = backEnd.viewParms.world; - } - - GL_LoadModelViewMatrix( backEnd.orientation.modelViewMatrix ); - - // change depthrange if needed - if ( oldDepthRange != depthRange ) - { - if ( depthRange ) - { - glDepthRange( 0, 0.3 ); - } - else - { - glDepthRange( 0, 1 ); - } - - oldDepthRange = depthRange; - } - - RB_SetupLightAttenuationForEntity( light, entity ); - } - - // add the triangles for this surface - rb_surfaceTable[Util::ordinal(*surface)](surface ); - oldEntity = entity; - oldShader = shader; - } - - // draw the contents of the last shader batch - Tess_End(); - - // force updates - oldEntity = nullptr; - oldShader = nullptr; - } - - Tess_End(); - - // go back to the world modelview matrix - GL_LoadModelViewMatrix( backEnd.viewParms.world.modelViewMatrix ); - - if ( depthRange ) - { - glDepthRange( 0, 1 ); - } - - // reset scissor - GL_Scissor( backEnd.viewParms.scissorX, backEnd.viewParms.scissorY, - backEnd.viewParms.scissorWidth, backEnd.viewParms.scissorHeight ); - - GL_CheckErrors(); - - if ( r_speeds->integer == Util::ordinal(renderSpeeds_t::RSPEEDS_SHADING_TIMES) ) - { - glFinish(); - endTime = ri.Milliseconds(); - backEnd.pc.c_forwardLightingTime += endTime - startTime; - } -} - -static void RB_SetupLightForShadowing( trRefLight_t *light, int index, - bool shadowClip ) -{ - // HACK: bring OpenGL into a safe state or strange FBO update problems will occur - GL_BindNullProgram(); - GL_State( GLS_DEFAULT ); - - GL_Bind( tr.whiteImage ); - int cubeSide = index; - int splitFrustumIndex = index; - interaction_t *ia = light->firstInteraction; - int iaCount = ia - backEnd.viewParms.interactions; - - switch ( light->l.rlType ) - { - case refLightType_t::RL_OMNI: - { - float zNear, zFar; - float fovX, fovY; - bool flipX, flipY; - vec3_t angles; - matrix_t rotationMatrix, transformMatrix, viewMatrix; - - GLIMP_LOGCOMMENT( "----- Rendering shadowCube side: %i -----", cubeSide ); - - R_BindFBO( tr.shadowMapFBO[ light->shadowLOD ] ); - if( shadowClip ) - { - R_AttachFBOTexture2D( GL_TEXTURE_CUBE_MAP_POSITIVE_X + cubeSide, - tr.shadowClipCubeFBOImage[ light->shadowLOD ]->texnum, 0 ); - } - else - { - R_AttachFBOTexture2D( GL_TEXTURE_CUBE_MAP_POSITIVE_X + cubeSide, - tr.shadowCubeFBOImage[ light->shadowLOD ]->texnum, 0 ); - } - - if ( checkGLErrors() ) - { - R_CheckFBO( tr.shadowMapFBO[ light->shadowLOD ] ); - } - - // set the window clipping - GL_Viewport( 0, 0, shadowMapResolutions[ light->shadowLOD ], shadowMapResolutions[ light->shadowLOD ] ); - GL_Scissor( 0, 0, shadowMapResolutions[ light->shadowLOD ], shadowMapResolutions[ light->shadowLOD ] ); - - glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); - - switch ( cubeSide ) - { - case 0: - { - // view parameters - VectorSet( angles, 0, 0, 90 ); - - // projection parameters - flipX = false; - flipY = false; - break; - } - - case 1: - { - VectorSet( angles, 0, 180, 90 ); - flipX = true; - flipY = true; - break; - } - - case 2: - { - VectorSet( angles, 0, 90, 0 ); - flipX = false; - flipY = false; - break; - } - - case 3: - { - VectorSet( angles, 0, -90, 0 ); - flipX = true; - flipY = true; - break; - } - - case 4: - { - VectorSet( angles, -90, 90, 0 ); - flipX = false; - flipY = false; - break; - } - - case 5: - { - VectorSet( angles, 90, 90, 0 ); - flipX = true; - flipY = true; - break; - } - - default: - { - // shut up compiler - VectorSet( angles, 0, 0, 0 ); - flipX = false; - flipY = false; - break; - } - } - - // Quake -> OpenGL view matrix from light perspective - MatrixFromAngles( rotationMatrix, angles[ PITCH ], angles[ YAW ], angles[ ROLL ] ); - MatrixSetupTransformFromRotation( transformMatrix, rotationMatrix, light->origin ); - MatrixAffineInverse( transformMatrix, viewMatrix ); - - // convert from our coordinate system (looking down X) - // to OpenGL's coordinate system (looking down -Z) - MatrixMultiply( quakeToOpenGLMatrix, viewMatrix, light->viewMatrix ); - - // OpenGL projection matrix - fovX = 90; - fovY = 90; - - zNear = 1.0; - zFar = light->sphereRadius; - - if ( flipX ) - { - fovX = -fovX; - } - - if ( flipY ) - { - fovY = -fovY; - } - - MatrixPerspectiveProjectionFovXYRH( light->projectionMatrix, fovX, fovY, zNear, zFar ); - - GL_LoadProjectionMatrix( light->projectionMatrix ); - break; - } - - case refLightType_t::RL_PROJ: - { - GLIMP_LOGCOMMENT( "--- Rendering projective shadowMap ---" ); - - R_BindFBO( tr.shadowMapFBO[ light->shadowLOD ] ); - if( shadowClip ) - { - R_AttachFBOTexture2D( GL_TEXTURE_2D, tr.shadowClipMapFBOImage[ light->shadowLOD ]->texnum, 0 ); - } - else - { - R_AttachFBOTexture2D( GL_TEXTURE_2D, tr.shadowMapFBOImage[ light->shadowLOD ]->texnum, 0 ); - } - - if ( checkGLErrors() ) - { - R_CheckFBO( tr.shadowMapFBO[ light->shadowLOD ] ); - } - - // set the window clipping - GL_Viewport( 0, 0, shadowMapResolutions[ light->shadowLOD ], shadowMapResolutions[ light->shadowLOD ] ); - GL_Scissor( 0, 0, shadowMapResolutions[ light->shadowLOD ], shadowMapResolutions[ light->shadowLOD ] ); - - glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); - - GL_LoadProjectionMatrix( light->projectionMatrix ); - break; - } - - case refLightType_t::RL_DIRECTIONAL: - { - int j; - vec3_t angles; - vec4_t forward, side, up; - vec3_t lightDirection; - vec3_t viewOrigin, viewDirection; - matrix_t rotationMatrix, transformMatrix, viewMatrix, projectionMatrix, viewProjectionMatrix; - matrix_t cropMatrix; - vec3_t splitFrustumNearCorners[ 4 ]; - vec3_t splitFrustumFarCorners[ 4 ]; - vec3_t splitFrustumBounds[ 2 ]; - vec3_t splitFrustumClipBounds[ 2 ]; - int numCasters; - vec3_t casterBounds[ 2 ]; - vec3_t receiverBounds[ 2 ]; - vec3_t cropBounds[ 2 ]; - vec4_t point; - vec4_t transf; - - GLIMP_LOGCOMMENT( "--- Rendering directional shadowMap ---" ); - - R_BindFBO( tr.sunShadowMapFBO[ splitFrustumIndex ] ); - - if( shadowClip ) - { - R_AttachFBOTexture2D( GL_TEXTURE_2D, tr.sunShadowClipMapFBOImage[ splitFrustumIndex ]->texnum, 0 ); - } - else if ( !r_evsmPostProcess->integer ) - { - R_AttachFBOTexture2D( GL_TEXTURE_2D, tr.sunShadowMapFBOImage[ splitFrustumIndex ]->texnum, 0 ); - } - else - { - R_AttachFBOTextureDepth( tr.sunShadowMapFBOImage[ splitFrustumIndex ]->texnum ); - } - - if ( checkGLErrors() ) - { - R_CheckFBO( tr.sunShadowMapFBO[ splitFrustumIndex ] ); - } - - // set the window clipping - GL_Viewport( 0, 0, sunShadowMapResolutions[ splitFrustumIndex ], sunShadowMapResolutions[ splitFrustumIndex ] ); - GL_Scissor( 0, 0, sunShadowMapResolutions[ splitFrustumIndex ], sunShadowMapResolutions[ splitFrustumIndex ] ); - - glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); - - VectorCopy( tr.sunDirection, lightDirection ); - - if ( r_parallelShadowSplits->integer ) - { - // original light direction is from surface to light - VectorInverse( lightDirection ); - VectorNormalize( lightDirection ); - - VectorCopy( backEnd.viewParms.orientation.origin, viewOrigin ); - VectorCopy( backEnd.viewParms.orientation.axis[ 0 ], viewDirection ); - VectorNormalize( viewDirection ); - - // calculate new up dir - CrossProduct( lightDirection, viewDirection, side ); - VectorNormalize( side ); - - CrossProduct( side, lightDirection, up ); - VectorNormalize( up ); - - vectoangles( lightDirection, angles ); - MatrixFromAngles( rotationMatrix, angles[ PITCH ], angles[ YAW ], angles[ ROLL ] ); - AngleVectors( angles, forward, side, up ); - - MatrixLookAtRH( light->viewMatrix, viewOrigin, lightDirection, up ); - - plane_t splitFrustum[ 6 ]; - for ( j = 0; j < 6; j++ ) - { - VectorCopy( backEnd.viewParms.frustums[ 1 + splitFrustumIndex ][ j ].normal, splitFrustum[ j ].normal ); - splitFrustum[ j ].dist = backEnd.viewParms.frustums[ 1 + splitFrustumIndex ][ j ].dist; - } - - R_CalcFrustumNearCorners( splitFrustum, splitFrustumNearCorners ); - R_CalcFrustumFarCorners( splitFrustum, splitFrustumFarCorners ); - - if ( GLimp_isLogging() ) - { - vec3_t rayIntersectionNear, rayIntersectionFar; - float zNear, zFar; - - PlaneIntersectRay( viewOrigin, viewDirection, splitFrustum[ FRUSTUM_FAR ], rayIntersectionFar ); - zFar = Distance( viewOrigin, rayIntersectionFar ); - - VectorInverse( viewDirection ); - - PlaneIntersectRay( rayIntersectionFar, viewDirection, splitFrustum[ FRUSTUM_NEAR ], rayIntersectionNear ); - zNear = Distance( viewOrigin, rayIntersectionNear ); - - VectorInverse( viewDirection ); - - GLIMP_LOGCOMMENT( "split frustum %i: near = %5.3f, far = %5.3f", - splitFrustumIndex, zNear, zFar ); - - GLIMP_LOGCOMMENT( "pyramid nearCorners" ); - - for ( auto nearCorner : splitFrustumNearCorners ) - { - GLIMP_LOGCOMMENT( "(%5.3f, %5.3f, %5.3f)", - nearCorner[ 0 ], nearCorner[ 1 ], nearCorner[ 2 ] ); - } - - GLIMP_LOGCOMMENT( "pyramid farCorners" ); - - for ( auto farCorner : splitFrustumFarCorners ) - { - GLIMP_LOGCOMMENT( "(%5.3f, %5.3f, %5.3f)", - farCorner[ 0 ], farCorner[ 1 ], farCorner[ 2 ] ); - } - } - - ClearBounds( splitFrustumBounds[ 0 ], splitFrustumBounds[ 1 ] ); - - for ( auto nearCorner : splitFrustumNearCorners ) - { - AddPointToBounds( nearCorner, splitFrustumBounds[ 0 ], splitFrustumBounds[ 1 ] ); - } - - for ( auto farCorner : splitFrustumFarCorners ) - { - AddPointToBounds( farCorner, splitFrustumBounds[ 0 ], splitFrustumBounds[ 1 ] ); - } - - // - // Scene-Dependent Projection - // - - // find the bounding box of the current split in the light's view space - ClearBounds( cropBounds[ 0 ], cropBounds[ 1 ] ); - - const auto pointsToViewBounds = [&]( vec_t *c ) { - VectorCopy( c, point ); - point[ 3 ] = 1; - MatrixTransform4( light->viewMatrix, point, transf ); - transf[ 0 ] /= transf[ 3 ]; - transf[ 1 ] /= transf[ 3 ]; - transf[ 2 ] /= transf[ 3 ]; - - AddPointToBounds( transf, cropBounds[ 0 ], cropBounds[ 1 ] ); - }; - - for ( auto nearCorner : splitFrustumNearCorners ) - { - pointsToViewBounds( nearCorner ); - } - - for ( auto farCorner : splitFrustumFarCorners ) - { - pointsToViewBounds( farCorner ); - } - - MatrixOrthogonalProjectionRH( projectionMatrix, cropBounds[ 0 ][ 0 ], cropBounds[ 1 ][ 0 ], cropBounds[ 0 ][ 1 ], cropBounds[ 1 ][ 1 ], -cropBounds[ 1 ][ 2 ], -cropBounds[ 0 ][ 2 ] ); - - MatrixMultiply( projectionMatrix, light->viewMatrix, viewProjectionMatrix ); - - numCasters = MergeInteractionBounds( viewProjectionMatrix, ia, iaCount, casterBounds, true ); - MergeInteractionBounds( viewProjectionMatrix, ia, iaCount, receiverBounds, false ); - - // find the bounding box of the current split in the light's clip space - ClearBounds( splitFrustumClipBounds[ 0 ], splitFrustumClipBounds[ 1 ] ); - - const auto pointsToViewProjectionBounds = [&]( vec_t* c ) { - VectorCopy( c, point ); - point[ 3 ] = 1; - - MatrixTransform4( viewProjectionMatrix, point, transf ); - transf[ 0 ] /= transf[ 3 ]; - transf[ 1 ] /= transf[ 3 ]; - transf[ 2 ] /= transf[ 3 ]; - - AddPointToBounds( transf, splitFrustumClipBounds[ 0 ], splitFrustumClipBounds[ 1 ] ); - }; - - for ( auto nearCorner : splitFrustumNearCorners ) - { - pointsToViewProjectionBounds( nearCorner ); - } - - for ( auto farCorner : splitFrustumFarCorners ) - { - pointsToViewProjectionBounds( farCorner ); - } - - if ( GLimp_isLogging() ) - { - GLIMP_LOGCOMMENT( "shadow casters = %i", numCasters ); - - GLIMP_LOGCOMMENT( "split frustum light space clip bounds (%5.3f, %5.3f, %5.3f) (%5.3f, %5.3f, %5.3f)", - splitFrustumClipBounds[ 0 ][ 0 ], splitFrustumClipBounds[ 0 ][ 1 ], splitFrustumClipBounds[ 0 ][ 2 ], - splitFrustumClipBounds[ 1 ][ 0 ], splitFrustumClipBounds[ 1 ][ 1 ], splitFrustumClipBounds[ 1 ][ 2 ] ); - - GLIMP_LOGCOMMENT( "shadow caster light space clip bounds (%5.3f, %5.3f, %5.3f) (%5.3f, %5.3f, %5.3f)", - casterBounds[ 0 ][ 0 ], casterBounds[ 0 ][ 1 ], casterBounds[ 0 ][ 2 ], - casterBounds[ 1 ][ 0 ], casterBounds[ 1 ][ 1 ], casterBounds[ 1 ][ 2 ] ); - - GLIMP_LOGCOMMENT( "light receiver light space clip bounds (%5.3f, %5.3f, %5.3f) (%5.3f, %5.3f, %5.3f)", - receiverBounds[ 0 ][ 0 ], receiverBounds[ 0 ][ 1 ], receiverBounds[ 0 ][ 2 ], - receiverBounds[ 1 ][ 0 ], receiverBounds[ 1 ][ 1 ], receiverBounds[ 1 ][ 2 ] ); - } - - // scene-dependent bounding volume - cropBounds[ 0 ][ 0 ] = std::max( std::max( casterBounds[ 0 ][ 0 ], receiverBounds[ 0 ][ 0 ] ), splitFrustumClipBounds[ 0 ][ 0 ] ); - cropBounds[ 0 ][ 1 ] = std::max( std::max( casterBounds[ 0 ][ 1 ], receiverBounds[ 0 ][ 1 ] ), splitFrustumClipBounds[ 0 ][ 1 ] ); - - cropBounds[ 1 ][ 0 ] = std::min( std::min( casterBounds[ 1 ][ 0 ], receiverBounds[ 1 ][ 0 ] ), splitFrustumClipBounds[ 1 ][ 0 ] ); - cropBounds[ 1 ][ 1 ] = std::min( std::min( casterBounds[ 1 ][ 1 ], receiverBounds[ 1 ][ 1 ] ), splitFrustumClipBounds[ 1 ][ 1 ] ); - - cropBounds[ 0 ][ 2 ] = std::min( casterBounds[ 0 ][ 2 ], splitFrustumClipBounds[ 0 ][ 2 ] ); - cropBounds[ 1 ][ 2 ] = std::min( receiverBounds[ 1 ][ 2 ], splitFrustumClipBounds[ 1 ][ 2 ] ); - - if ( numCasters == 0 ) - { - VectorCopy( splitFrustumClipBounds[ 0 ], cropBounds[ 0 ] ); - VectorCopy( splitFrustumClipBounds[ 1 ], cropBounds[ 1 ] ); - } - - MatrixCrop( cropMatrix, cropBounds[ 0 ], cropBounds[ 1 ] ); - - MatrixMultiply( cropMatrix, projectionMatrix, light->projectionMatrix ); - - GL_LoadProjectionMatrix( light->projectionMatrix ); - } - else - { - // original light direction is from surface to light - VectorInverse( lightDirection ); - - // Quake -> OpenGL view matrix from light perspective - vectoangles( lightDirection, angles ); - MatrixFromAngles( rotationMatrix, angles[ PITCH ], angles[ YAW ], angles[ ROLL ] ); - MatrixSetupTransformFromRotation( transformMatrix, rotationMatrix, backEnd.viewParms.orientation.origin ); - MatrixAffineInverse( transformMatrix, viewMatrix ); - MatrixMultiply( quakeToOpenGLMatrix, viewMatrix, light->viewMatrix ); - - ClearBounds( splitFrustumBounds[ 0 ], splitFrustumBounds[ 1 ] ); - //BoundsAdd(splitFrustumBounds[0], splitFrustumBounds[1], backEnd.viewParms.visBounds[0], backEnd.viewParms.visBounds[1]); - BoundsAdd( splitFrustumBounds[ 0 ], splitFrustumBounds[ 1 ], light->worldBounds[ 0 ], light->worldBounds[ 1 ] ); - - ClearBounds( cropBounds[ 0 ], cropBounds[ 1 ] ); - - for ( j = 0; j < 8; j++ ) - { - point[ 0 ] = splitFrustumBounds[ j & 1 ][ 0 ]; - point[ 1 ] = splitFrustumBounds[( j >> 1 ) & 1 ][ 1 ]; - point[ 2 ] = splitFrustumBounds[( j >> 2 ) & 1 ][ 2 ]; - point[ 3 ] = 1; - - MatrixTransform4( light->viewMatrix, point, transf ); - transf[ 0 ] /= transf[ 3 ]; - transf[ 1 ] /= transf[ 3 ]; - transf[ 2 ] /= transf[ 3 ]; - - AddPointToBounds( transf, cropBounds[ 0 ], cropBounds[ 1 ] ); - } - - MatrixOrthogonalProjectionRH( light->projectionMatrix, cropBounds[ 0 ][ 0 ], cropBounds[ 1 ][ 0 ], cropBounds[ 0 ][ 1 ], cropBounds[ 1 ][ 1 ], -cropBounds[ 1 ][ 2 ], -cropBounds[ 0 ][ 2 ] ); - GL_LoadProjectionMatrix( light->projectionMatrix ); - } - - break; - } - - default: - break; - } - - GLIMP_LOGCOMMENT( "----- First Shadow Interaction: %i -----", - (int)( light->firstInteraction - backEnd.viewParms.interactions ) ); -} - -static void RB_SetupLightForLighting( trRefLight_t *light ) -{ - GLIMP_LOGCOMMENT( "--- Rendering lighting ---" ); - - GLIMP_LOGCOMMENT( "----- First Light Interaction: %i -----", - (int)( light->firstInteraction - backEnd.viewParms.interactions ) ); - - R_BindFBO( tr.mainFBO[ backEnd.currentMainFBO ] ); - - // set the window clipping - GL_Viewport( backEnd.viewParms.viewportX, backEnd.viewParms.viewportY, - backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight ); - - interaction_t *iaFirst = light->firstInteraction; - GL_Scissor( iaFirst->scissorX, iaFirst->scissorY, - iaFirst->scissorWidth, iaFirst->scissorHeight ); - - // restore camera matrices - GL_LoadProjectionMatrix( backEnd.viewParms.projectionMatrix ); - GL_LoadModelViewMatrix( backEnd.orientation.modelViewMatrix ); - - // reset light view and projection matrices - switch ( light->l.rlType ) - { - case refLightType_t::RL_OMNI: - { - MatrixAffineInverse( light->transformMatrix, light->viewMatrix ); - MatrixSetupScale( light->projectionMatrix, 1.0f / light->l.radius, 1.0f / light->l.radius, - 1.0f / light->l.radius ); - break; - } - - case refLightType_t::RL_DIRECTIONAL: - { - // draw split frustum shadow maps - if ( r_showShadowMaps->integer ) - { - int frustumIndex; - float x, y, w, h; - matrix_t ortho; - vec4_t quadVerts[ 4 ]; - - // set 2D virtual screen size - GL_PushMatrix(); - MatrixOrthogonalProjection( ortho, backEnd.viewParms.viewportX, - backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth, - backEnd.viewParms.viewportY, - backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight, -99999, 99999 ); - GL_LoadProjectionMatrix( ortho ); - - for ( frustumIndex = 0; frustumIndex <= r_parallelShadowSplits->integer; frustumIndex++ ) - { - GL_Cull( cullType_t::CT_TWO_SIDED ); - GL_State( GLS_DEPTHTEST_DISABLE ); - - gl_debugShadowMapShader->BindProgram( 0 ); - - gl_debugShadowMapShader->SetUniform_CurrentMapBindless( - GL_BindToTMU( 0, tr.sunShadowMapFBOImage[frustumIndex] ) - ); - - w = 200; - h = 200; - - x = 205 * frustumIndex; - y = 70; - - Tess_InstantQuad( *gl_debugShadowMapShader, x, y, w, h ); - - { - int j; - vec3_t farCorners[ 4 ]; - vec3_t nearCorners[ 4 ]; - - GL_Viewport( x, y, w, h ); - GL_Scissor( x, y, w, h ); - - GL_PushMatrix(); - - gl_genericShader->SetVertexSkinning( false ); - gl_genericShader->SetVertexAnimation( false ); - gl_genericShader->SetTCGenEnvironment( false ); - gl_genericShader->SetTCGenLightmap( false ); - gl_genericShader->SetDepthFade( false ); - gl_genericShader->BindProgram( 0 ); - - // set uniforms - gl_genericShader->SetUniform_AlphaTest( GLS_ATEST_NONE ); - SetUniform_ColorModulateColorGen( gl_genericShader, colorGen_t::CGEN_VERTEX, alphaGen_t::AGEN_VERTEX ); - SetUniform_Color( gl_genericShader, Color::Black ); - - GL_State( GLS_POLYMODE_LINE | GLS_DEPTHTEST_DISABLE ); - GL_Cull( cullType_t::CT_TWO_SIDED ); - - // bind u_ColorMap - gl_genericShader->SetUniform_ColorMapBindless( - GL_BindToTMU( 0, tr.whiteImage ) - ); - gl_genericShader->SetUniform_TextureMatrix( matrixIdentity ); - - gl_genericShader->SetUniform_ModelViewProjectionMatrix( light->shadowMatrices[ frustumIndex ] ); - - tess.multiDrawPrimitives = 0; - tess.numIndexes = 0; - tess.numVertexes = 0; - - plane_t splitFrustum[ 6 ]; - for ( j = 0; j < 6; j++ ) - { - VectorCopy( backEnd.viewParms.frustums[ 1 + frustumIndex ][ j ].normal, splitFrustum[ j ].normal ); - splitFrustum[ j ].dist = backEnd.viewParms.frustums[ 1 + frustumIndex ][ j ].dist; - } - - R_CalcFrustumNearCorners( splitFrustum, nearCorners ); - R_CalcFrustumFarCorners( splitFrustum, farCorners ); - - // draw outer surfaces - for ( j = 0; j < 4; j++ ) - { - Vector4Set( quadVerts[ 0 ], nearCorners[ j ][ 0 ], nearCorners[ j ][ 1 ], nearCorners[ j ][ 2 ], 1 ); - Vector4Set( quadVerts[ 1 ], farCorners[ j ][ 0 ], farCorners[ j ][ 1 ], farCorners[ j ][ 2 ], 1 ); - Vector4Set( quadVerts[ 2 ], farCorners[( j + 1 ) % 4 ][ 0 ], farCorners[( j + 1 ) % 4 ][ 1 ], farCorners[( j + 1 ) % 4 ][ 2 ], 1 ); - Vector4Set( quadVerts[ 3 ], nearCorners[( j + 1 ) % 4 ][ 0 ], nearCorners[( j + 1 ) % 4 ][ 1 ], nearCorners[( j + 1 ) % 4 ][ 2 ], 1 ); - Tess_AddQuadStamp2( quadVerts, Color::Cyan ); - } - - // draw far cap - Vector4Set( quadVerts[ 0 ], farCorners[ 3 ][ 0 ], farCorners[ 3 ][ 1 ], farCorners[ 3 ][ 2 ], 1 ); - Vector4Set( quadVerts[ 1 ], farCorners[ 2 ][ 0 ], farCorners[ 2 ][ 1 ], farCorners[ 2 ][ 2 ], 1 ); - Vector4Set( quadVerts[ 2 ], farCorners[ 1 ][ 0 ], farCorners[ 1 ][ 1 ], farCorners[ 1 ][ 2 ], 1 ); - Vector4Set( quadVerts[ 3 ], farCorners[ 0 ][ 0 ], farCorners[ 0 ][ 1 ], farCorners[ 0 ][ 2 ], 1 ); - Tess_AddQuadStamp2( quadVerts, Color::Blue ); - - // draw near cap - Vector4Set( quadVerts[ 0 ], nearCorners[ 0 ][ 0 ], nearCorners[ 0 ][ 1 ], nearCorners[ 0 ][ 2 ], 1 ); - Vector4Set( quadVerts[ 1 ], nearCorners[ 1 ][ 0 ], nearCorners[ 1 ][ 1 ], nearCorners[ 1 ][ 2 ], 1 ); - Vector4Set( quadVerts[ 2 ], nearCorners[ 2 ][ 0 ], nearCorners[ 2 ][ 1 ], nearCorners[ 2 ][ 2 ], 1 ); - Vector4Set( quadVerts[ 3 ], nearCorners[ 3 ][ 0 ], nearCorners[ 3 ][ 1 ], nearCorners[ 3 ][ 2 ], 1 ); - Tess_AddQuadStamp2( quadVerts, Color::Green ); - - Tess_UpdateVBOs( ); - GL_VertexAttribsState( ATTR_POSITION | ATTR_COLOR ); - Tess_DrawElements(); - - tess.multiDrawPrimitives = 0; - tess.numIndexes = 0; - tess.numVertexes = 0; - - GL_PopMatrix(); - - GL_Viewport( backEnd.viewParms.viewportX, backEnd.viewParms.viewportY, - backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight ); - - GL_Scissor( iaFirst->scissorX, iaFirst->scissorY, - iaFirst->scissorWidth, iaFirst->scissorHeight ); - } - } - - GL_PopMatrix(); - } - } - break; - - default: - break; - } -} - -static void RB_BlurShadowMap( const trRefLight_t *light, int i ) -{ - if ( !glConfig2.shadowMapping ) - { - return; - } - - if ( light->l.inverseShadows ) - { - return; - } - - if ( !r_softShadowsPP->integer ) - { - return; - } - - if ( light->l.rlType == refLightType_t::RL_OMNI ) - { - return; - } - - int index; - image_t **images; - FBO_t **fbos; - vec2_t texScale; - - fbos = ( light->l.rlType == refLightType_t::RL_DIRECTIONAL ) ? tr.sunShadowMapFBO : tr.shadowMapFBO; - images = ( light->l.rlType == refLightType_t::RL_DIRECTIONAL ) ? tr.sunShadowMapFBOImage : tr.shadowMapFBOImage; - index = ( light->l.rlType == refLightType_t::RL_DIRECTIONAL ) ? i : light->shadowLOD; - - texScale[ 0 ] = 1.0f / fbos[ index ]->width; - texScale[ 1 ] = 1.0f / fbos[ index ]->height; - - R_BindFBO( fbos[ index ] ); - R_AttachFBOTexture2D( images[ index + MAX_SHADOWMAPS ]->type, images[ index + MAX_SHADOWMAPS ]->texnum, 0 ); - - if ( checkGLErrors() ) - { - R_CheckFBO( fbos[ index ] ); - } - - // set the window clipping - GL_Viewport( 0, 0, fbos[index]->width, fbos[index]->height ); - GL_Scissor( 0, 0, fbos[index]->width, fbos[index]->height ); - - glClear( GL_COLOR_BUFFER_BIT ); - - GL_Cull( cullType_t::CT_TWO_SIDED ); - GL_State( GLS_DEPTHTEST_DISABLE ); - - gl_blurShader->BindProgram( 0 ); - gl_blurShader->SetUniform_DeformMagnitude( 1 ); - gl_blurShader->SetUniform_TexScale( texScale ); - gl_blurShader->SetUniform_Horizontal( true ); - - gl_blurShader->SetUniform_ColorMapBindless( - GL_BindToTMU( 0, images[index] ) - ); - - Tess_InstantScreenSpaceQuad(); - - R_AttachFBOTexture2D( images[ index ]->type, images[ index ]->texnum, 0 ); - - glClear( GL_COLOR_BUFFER_BIT ); - - gl_blurShader->BindProgram( 0 ); - gl_blurShader->SetUniform_DeformMagnitude( 1 ); - gl_blurShader->SetUniform_TexScale( texScale ); - gl_blurShader->SetUniform_Horizontal( false ); - - gl_blurShader->SetUniform_ColorMapBindless( - GL_BindToTMU( 0, images[index + MAX_SHADOWMAPS] ) - ); - - Tess_InstantScreenSpaceQuad(); -} - -/* -================= -RB_RenderInteractionsShadowMapped -================= -*/ - -static void RB_RenderInteractionsShadowMapped() -{ - shader_t *shader, *oldShader; - trRefEntity_t *entity, *oldEntity; - trRefLight_t *light; - const interaction_t *ia; - const interaction_t *iaFirst; - surfaceType_t *surface; - bool depthRange, oldDepthRange; - bool alphaTest, oldAlphaTest; - bool shadowClipFound; - - int startTime = 0, endTime = 0; - static const matrix_t bias = { 0.5, 0.0, 0.0, 0.0, - 0.0, 0.5, 0.0, 0.0, - 0.0, 0.0, 0.5, 0.0, - 0.5, 0.5, 0.5, 1.0 - }; - - DAEMON_ASSERT( glConfig2.shadowMapping ); - - GLIMP_LOGCOMMENT( "--- RB_RenderInteractionsShadowMapped ---" ); - - if ( r_speeds->integer == Util::ordinal(renderSpeeds_t::RSPEEDS_SHADING_TIMES) ) - { - glFinish(); - startTime = ri.Milliseconds(); - } - - // draw everything - oldEntity = nullptr; - oldShader = nullptr; - oldDepthRange = depthRange = false; - oldAlphaTest = alphaTest = false; - - // if we need to clear the FBO color buffers then it should be white - GL_ClearColor( 1.0f, 1.0f, 1.0f, 1.0f ); - - // render each light - iaFirst = nullptr; - - while ( ( iaFirst = IterateLights( iaFirst ) ) ) - { - backEnd.currentLight = light = iaFirst->light; - - // begin shadowing - int numMaps; - switch( light->l.rlType ) - { - case refLightType_t::RL_OMNI: - numMaps = 6; - break; - case refLightType_t::RL_DIRECTIONAL: - numMaps = std::max( r_parallelShadowSplits->integer + 1, 1 ); - break; - default: - numMaps = 1; - break; - } - - const interaction_t *iaLast = iaFirst; - for ( int i = 0; i < numMaps; i++ ) - { - entity = nullptr; - shader = nullptr; - oldEntity = nullptr; - oldShader = nullptr; - - if ( light->l.noShadows || light->shadowLOD < 0 ) - { - GLIMP_LOGCOMMENT( "----- Skipping shadowCube side: %i -----", i ); - - continue; - } - - RB_SetupLightForShadowing( light, i, false ); - - shadowClipFound = false; - for( ia = iaFirst; ia; ia = ia->next ) - { - iaLast = ia; - backEnd.currentEntity = entity = ia->entity; - surface = ia->surface; - shader = ia->shader; - alphaTest = shader->alphaTest; - - if ( entity->e.renderfx & ( RF_NOSHADOW | RF_DEPTHHACK ) ) - { - continue; - } - - if ( shader->isSky ) - { - continue; - } - - if ( shader->sort > Util::ordinal(shaderSort_t::SS_OPAQUE) ) - { - continue; - } - - if ( shader->noShadows ) - { - continue; - } - - if ( (ia->type & IA_SHADOWCLIP) ) { - shadowClipFound = true; - } - - if ( !(ia->type & IA_SHADOW) ) - { - continue; - } - - if ( light->l.rlType == refLightType_t::RL_OMNI && !( ia->cubeSideBits & ( 1 << i ) ) ) - { - continue; - } - - switch ( light->l.rlType ) - { - case refLightType_t::RL_OMNI: - case refLightType_t::RL_PROJ: - case refLightType_t::RL_DIRECTIONAL: - { - if ( entity == oldEntity && ( alphaTest ? shader == oldShader : alphaTest == oldAlphaTest ) ) - { - GLIMP_LOGCOMMENT( "----- Batching Shadow Interaction: %i -----", - (int)( ia - backEnd.viewParms.interactions ) ); - - // fast path, same as previous - rb_surfaceTable[ Util::ordinal(*surface) ]( surface ); - continue; - } - else - { - // draw the contents of the last shader batch - Tess_End(); - - GLIMP_LOGCOMMENT( "----- Beginning Shadow Interaction: %i -----", - (int)( ia - backEnd.viewParms.interactions ) ); - - // we don't need tangent space calculations here - Tess_Begin( Tess_StageIteratorShadowFill, shader, light->shader, true, -1, 0 ); - } - - break; - } - - default: - break; - } - - // change the modelview matrix if needed - if ( entity != oldEntity ) - { - depthRange = false; - - if ( entity != &tr.worldEntity ) - { - // set up the transformation matrix - R_RotateEntityForLight( entity, light, &backEnd.orientation ); - - if ( entity->e.renderfx & RF_DEPTHHACK ) - { - // hack the depth range to prevent view model from poking into walls - depthRange = true; - } - } - else - { - // set up the transformation matrix - backEnd.orientation = {}; - - backEnd.orientation.axis[ 0 ][ 0 ] = 1; - backEnd.orientation.axis[ 1 ][ 1 ] = 1; - backEnd.orientation.axis[ 2 ][ 2 ] = 1; - VectorCopy( light->l.origin, backEnd.orientation.viewOrigin ); - - MatrixIdentity( backEnd.orientation.transformMatrix ); - MatrixMultiply( light->viewMatrix, backEnd.orientation.transformMatrix, backEnd.orientation.viewMatrix ); - MatrixCopy( backEnd.orientation.viewMatrix, backEnd.orientation.modelViewMatrix ); - } - - GL_LoadModelViewMatrix( backEnd.orientation.modelViewMatrix ); - - // change depthrange if needed - if ( oldDepthRange != depthRange ) - { - if ( depthRange ) - { - glDepthRange( 0, 0.3 ); - } - else - { - glDepthRange( 0, 1 ); - } - - oldDepthRange = depthRange; - } - - RB_SetupLightAttenuationForEntity( light, entity ); - } - - switch ( light->l.rlType ) - { - case refLightType_t::RL_OMNI: - case refLightType_t::RL_PROJ: - case refLightType_t::RL_DIRECTIONAL: - { - // add the triangles for this surface - rb_surfaceTable[ Util::ordinal(*surface) ]( surface ); - break; - } - - default: - break; - } - oldEntity = entity; - oldShader = shader; - oldAlphaTest = alphaTest; - } - - GLIMP_LOGCOMMENT( "----- Last Interaction: %i -----", - (int)( iaLast - backEnd.viewParms.interactions ) ); - - Tess_End(); - - if( shadowClipFound ) - { - entity = nullptr; - shader = nullptr; - oldEntity = nullptr; - oldShader = nullptr; - - if ( light->l.noShadows || light->shadowLOD < 0 ) - { - GLIMP_LOGCOMMENT( "----- Skipping shadowCube side: %i -----", i ); - continue; - } - - RB_SetupLightForShadowing( light, i, true ); - - for( ia = iaFirst; ia; ia = ia->next ) - { - iaLast = ia; - backEnd.currentEntity = entity = ia->entity; - surface = ia->surface; - shader = ia->shader; - alphaTest = shader->alphaTest; - - if ( entity->e.renderfx & ( RF_NOSHADOW | RF_DEPTHHACK ) ) - { - continue; - } - - if ( shader->isSky ) - { - continue; - } - - if ( shader->sort > Util::ordinal(shaderSort_t::SS_OPAQUE) ) - { - continue; - } - - if ( shader->noShadows ) - { - continue; - } - - if ( !(ia->type & IA_SHADOWCLIP) ) - { - continue; - } - - if ( light->l.rlType == refLightType_t::RL_OMNI && !( ia->cubeSideBits & ( 1 << i ) ) ) - { - continue; - } - - switch ( light->l.rlType ) - { - case refLightType_t::RL_OMNI: - case refLightType_t::RL_PROJ: - case refLightType_t::RL_DIRECTIONAL: - { - if ( entity == oldEntity && ( alphaTest ? shader == oldShader : alphaTest == oldAlphaTest ) ) - { - GLIMP_LOGCOMMENT( "----- Batching Shadow Interaction: %i -----", - (int)( ia - backEnd.viewParms.interactions ) ); - - // fast path, same as previous - rb_surfaceTable[ Util::ordinal(*surface) ]( surface ); - continue; - } - else - { - // draw the contents of the last shader batch - Tess_End(); - - GLIMP_LOGCOMMENT( "----- Beginning Shadow Interaction: %i -----", - (int)( ia - backEnd.viewParms.interactions ) ); - - // we don't need tangent space calculations here - Tess_Begin( Tess_StageIteratorShadowFill, shader, light->shader, true, -1, 0 ); - } +static interaction_t *IterateLights( const interaction_t *prev ) +{ + if ( !prev && backEnd.viewParms.numInteractions > 0 ) + { + return backEnd.viewParms.interactions; + } - break; - } + if ( backEnd.viewParms.numInteractions <= 0 ) + { + return nullptr; + } - default: - break; - } + const interaction_t *next = prev; + const interaction_t *last = &backEnd.viewParms.interactions[ backEnd.viewParms.numInteractions - 1 ]; - // change the modelview matrix if needed - if ( entity != oldEntity ) - { - depthRange = false; + while ( next <= last && next->light == prev->light ) + { + next++; + } - if ( entity != &tr.worldEntity ) - { - // set up the transformation matrix - R_RotateEntityForLight( entity, light, &backEnd.orientation ); + if ( next > last ) + { + next = nullptr; + } - if ( entity->e.renderfx & RF_DEPTHHACK ) - { - // hack the depth range to prevent view model from poking into walls - depthRange = true; - } - } - else - { - // set up the transformation matrix - backEnd.orientation = {}; + return ( interaction_t * ) next; +} - backEnd.orientation.axis[ 0 ][ 0 ] = 1; - backEnd.orientation.axis[ 1 ][ 1 ] = 1; - backEnd.orientation.axis[ 2 ][ 2 ] = 1; - VectorCopy( light->l.origin, backEnd.orientation.viewOrigin ); +static void RB_SetupLightAttenuationForEntity( trRefLight_t *light, const trRefEntity_t *entity ) +{ + matrix_t modelToLight; - MatrixIdentity( backEnd.orientation.transformMatrix ); - MatrixMultiply( light->viewMatrix, backEnd.orientation.transformMatrix, backEnd.orientation.viewMatrix ); - MatrixCopy( backEnd.orientation.viewMatrix, backEnd.orientation.modelViewMatrix ); - } + // transform light origin into model space for u_LightOrigin parameter + if ( entity != &tr.worldEntity ) + { + vec3_t tmp; + VectorSubtract( light->origin, backEnd.orientation.origin, tmp ); + light->transformed[ 0 ] = DotProduct( tmp, backEnd.orientation.axis[ 0 ] ); + light->transformed[ 1 ] = DotProduct( tmp, backEnd.orientation.axis[ 1 ] ); + light->transformed[ 2 ] = DotProduct( tmp, backEnd.orientation.axis[ 2 ] ); + } + else + { + VectorCopy( light->origin, light->transformed ); + } - GL_LoadModelViewMatrix( backEnd.orientation.modelViewMatrix ); + MatrixMultiply( light->viewMatrix, backEnd.orientation.transformMatrix, modelToLight ); - // change depthrange if needed - if ( oldDepthRange != depthRange ) - { - if ( depthRange ) - { - glDepthRange( 0, 0.3 ); - } - else - { - glDepthRange( 0, 1 ); - } + // build the attenuation matrix using the entity transform + switch ( light->l.rlType ) + { + case refLightType_t::RL_OMNI: + { + MatrixSetupTranslation( light->attenuationMatrix, 0.5, 0.5, 0.5 ); // bias + MatrixMultiplyScale( light->attenuationMatrix, 0.5, 0.5, 0.5 ); // scale + MatrixMultiply2( light->attenuationMatrix, light->projectionMatrix ); + MatrixMultiply2( light->attenuationMatrix, modelToLight ); + break; + } - oldDepthRange = depthRange; - } + case refLightType_t::RL_PROJ: + { + MatrixSetupTranslation( light->attenuationMatrix, 0.5, 0.5, 0.0 ); // bias + MatrixMultiplyScale( light->attenuationMatrix, 0.5f, 0.5f, 1.0f / std::min( light->falloffLength, 1.0f ) ); // scale + MatrixMultiply2( light->attenuationMatrix, light->projectionMatrix ); + MatrixMultiply2( light->attenuationMatrix, modelToLight ); + break; + } - RB_SetupLightAttenuationForEntity( light, entity ); - } + case refLightType_t::RL_DIRECTIONAL: + { + MatrixSetupTranslation( light->attenuationMatrix, 0.5, 0.5, 0.5 ); // bias + MatrixMultiplyScale( light->attenuationMatrix, 0.5, 0.5, 0.5 ); // scale + MatrixMultiply2( light->attenuationMatrix, light->projectionMatrix ); + MatrixMultiply2( light->attenuationMatrix, modelToLight ); + break; + } - switch ( light->l.rlType ) - { - case refLightType_t::RL_OMNI: - case refLightType_t::RL_PROJ: - case refLightType_t::RL_DIRECTIONAL: - { - // add the triangles for this surface - rb_surfaceTable[ Util::ordinal(*surface) ]( surface ); - break; - } + case refLightType_t::RL_MAX_REF_LIGHT_TYPE: + { + //Nothing for right now... + break; + } + } +} - default: - break; - } - oldEntity = entity; - oldShader = shader; - oldAlphaTest = alphaTest; - } +/* +================= +RB_RenderInteractions +================= +*/ +static void RB_RenderInteractions() +{ + shader_t *shader, *oldShader; + trRefEntity_t *entity, *oldEntity; + trRefLight_t *light; + const interaction_t *ia; + const interaction_t *iaFirst; + bool depthRange, oldDepthRange; + surfaceType_t *surface; + int startTime = 0, endTime = 0; - GLIMP_LOGCOMMENT( "----- Last Interaction: %i -----", - (int)( iaLast - backEnd.viewParms.interactions ) ); + GLIMP_LOGCOMMENT( "--- RB_RenderInteractions ---" ); - Tess_End(); - } + if ( r_speeds->integer == Util::ordinal(renderSpeeds_t::RSPEEDS_SHADING_TIMES)) + { + glFinish(); + startTime = ri.Milliseconds(); + } - // set shadow matrix including scale + offset - if ( light->l.rlType == refLightType_t::RL_DIRECTIONAL ) - { - MatrixCopy( bias, light->shadowMatricesBiased[ i ] ); - MatrixMultiply2( light->shadowMatricesBiased[ i ], light->projectionMatrix ); - MatrixMultiply2( light->shadowMatricesBiased[ i ], light->viewMatrix ); + // draw everything + oldEntity = nullptr; + oldShader = nullptr; + oldDepthRange = false; + depthRange = false; + iaFirst = nullptr; - MatrixMultiply( light->projectionMatrix, light->viewMatrix, light->shadowMatrices[ i ] ); - } + // render interactions + while ( ( iaFirst = IterateLights( iaFirst ) ) ) + { + backEnd.currentLight = light = iaFirst->light; - RB_BlurShadowMap( light, i ); - } + // set light scissor to reduce fillrate + GL_Scissor( iaFirst->scissorX, iaFirst->scissorY, iaFirst->scissorWidth, iaFirst->scissorHeight ); - // begin lighting - RB_SetupLightForLighting( light ); - entity = nullptr; - shader = nullptr; - oldEntity = nullptr; - oldShader = nullptr; for ( ia = iaFirst; ia; ia = ia->next ) { - iaLast = ia; backEnd.currentEntity = entity = ia->entity; surface = ia->surface; shader = ia->shader; - alphaTest = shader->alphaTest; - if ( !shader->interactLight ) + if ( !shader || !shader->interactLight ) { + // skip this interaction because the surface shader has no ability to interact with light + // this will save texcoords and matrix calculations continue; } if ( !(ia->type & IA_LIGHT) ) { + // skip this interaction because the interaction is meant for shadowing only continue; } + GLIMP_LOGCOMMENT( "----- Rendering new light -----" ); + + // Tr3B: this should never happen in the first iteration if ( entity == oldEntity && shader == oldShader ) { - GLIMP_LOGCOMMENT( "----- Batching Light Interaction: %i -----", - (int)( ia - backEnd.viewParms.interactions ) ); - // fast path, same as previous - rb_surfaceTable[ Util::ordinal(*surface) ]( surface ); + rb_surfaceTable[Util::ordinal(*surface)](surface ); continue; } - else - { - // draw the contents of the last shader batch - Tess_End(); - GLIMP_LOGCOMMENT( "----- Beginning Light Interaction: %i -----", - (int)( ia - backEnd.viewParms.interactions ) ); + // draw the contents of the last shader batch + Tess_End(); - // begin a new batch - Tess_Begin( Tess_StageIteratorLighting, shader, light->shader, light->l.inverseShadows, -1, 0 ); - } + // begin a new batch + Tess_Begin( Tess_StageIteratorLighting, shader, light->shader, false, -1, 0 ); // change the modelview matrix if needed if ( entity != oldEntity ) @@ -2486,9 +1135,9 @@ static void RB_RenderInteractionsShadowMapped() if ( entity != &tr.worldEntity ) { // set up the transformation matrix - R_RotateEntityForViewParms( entity, &backEnd.viewParms, &backEnd.orientation ); + R_RotateEntityForViewParms( backEnd.currentEntity, &backEnd.viewParms, &backEnd.orientation ); - if ( entity->e.renderfx & RF_DEPTHHACK ) + if ( backEnd.currentEntity->e.renderfx & RF_DEPTHHACK ) { // hack the depth range to prevent view model from poking into walls depthRange = true; @@ -2496,8 +1145,6 @@ static void RB_RenderInteractionsShadowMapped() } else { - // set up the transformation matrix - // transform by the camera placement backEnd.orientation = backEnd.viewParms.world; } @@ -2522,19 +1169,19 @@ static void RB_RenderInteractionsShadowMapped() } // add the triangles for this surface - rb_surfaceTable[ Util::ordinal(*surface) ]( surface ); + rb_surfaceTable[Util::ordinal(*surface)](surface ); oldEntity = entity; oldShader = shader; - oldAlphaTest = alphaTest; } - GLIMP_LOGCOMMENT( "----- Last Interaction: %i -----", - (int)( iaLast - backEnd.viewParms.interactions ) ); - + // draw the contents of the last shader batch Tess_End(); + + // force updates + oldEntity = nullptr; + oldShader = nullptr; } - // draw the contents of the last shader batch Tess_End(); // go back to the world modelview matrix @@ -2545,13 +1192,10 @@ static void RB_RenderInteractionsShadowMapped() glDepthRange( 0, 1 ); } - // reset scissor clamping + // reset scissor GL_Scissor( backEnd.viewParms.scissorX, backEnd.viewParms.scissorY, backEnd.viewParms.scissorWidth, backEnd.viewParms.scissorHeight ); - // reset clear color - GL_ClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); - GL_CheckErrors(); if ( r_speeds->integer == Util::ordinal(renderSpeeds_t::RSPEEDS_SHADING_TIMES) ) @@ -3183,7 +1827,7 @@ static void RB_RenderDebugUtils() { GLIMP_LOGCOMMENT( "--- RB_RenderDebugUtils ---" ); - if ( r_showLightTransforms->integer || r_showShadowLod->integer ) + if ( r_showLightTransforms->integer ) { const interaction_t *ia; trRefLight_t *light; @@ -3218,42 +1862,7 @@ static void RB_RenderDebugUtils() { backEnd.currentLight = light = ia->light; - if ( r_showShadowLod->integer ) - { - if ( light->shadowLOD == 0 ) - { - lightColor = Color::Red; - } - else if ( light->shadowLOD == 1 ) - { - lightColor = Color::Green; - } - else if ( light->shadowLOD == 2 ) - { - lightColor = Color::Blue; - } - else if ( light->shadowLOD == 3 ) - { - lightColor = Color::Yellow; - } - else if ( light->shadowLOD == 4 ) - { - lightColor = Color::Magenta; - } - else if ( light->shadowLOD == 5 ) - { - lightColor = Color::Cyan; - } - else - { - lightColor = Color::MdGrey; - } - } - else - { - lightColor = Color::Blue; - } - + lightColor = Color::Blue; lightColor.SetAlpha( 0.2 ); SetUniform_Color( gl_genericShader, lightColor ); @@ -3321,8 +1930,6 @@ static void RB_RenderDebugUtils() if ( r_showLightInteractions->integer ) { - int i; - int cubeSides; interaction_t *ia; int iaCount; trRefLight_t *light; @@ -3373,25 +1980,6 @@ static void RB_RenderDebugUtils() GL_LoadModelViewMatrix( backEnd.orientation.modelViewMatrix ); gl_genericShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); - if ( glConfig2.shadowMapping && light->l.rlType == refLightType_t::RL_OMNI ) - { - // count how many cube sides are in use for this interaction - cubeSides = 0; - - for ( i = 0; i < 6; i++ ) - { - if ( ia->cubeSideBits & ( 1 << i ) ) - { - cubeSides++; - } - } - lightColor = Color::Color::Indexed( cubeSides ); - } - else - { - lightColor = Color::MdGrey; - } - lightColor = Color::White; Tess_Begin( Tess_StageIteratorDebug, nullptr, nullptr, true, -1, 0 ); @@ -4521,16 +3109,8 @@ static void RB_RenderView( bool depthPass ) backEnd.pc.c_forwardAmbientTime += endTime - startTime; } - if ( glConfig2.shadowMapping ) - { - // render dynamic shadowing and lighting using shadow mapping - RB_RenderInteractionsShadowMapped(); - } - else - { - // render dynamic lighting - RB_RenderInteractions(); - } + // render dynamic lighting + RB_RenderInteractions(); // render global fog post process effect RB_RenderGlobalFog(); @@ -5142,10 +3722,6 @@ const RenderCommand *SetupLightsCommand::ExecuteSelf( ) const for( int i = 0, j = 0; i < numLights; i++, j++ ) { trRefLight_t *light = &refdef.lights[j]; - while( light->l.inverseShadows ) { - light = &refdef.lights[++j]; - } - VectorCopy( light->l.origin, buffer[i].center ); buffer[i].radius = light->l.radius; VectorScale( light->l.color, 4.0f * light->l.scale, buffer[i].color ); diff --git a/src/engine/renderer/tr_cmds.cpp b/src/engine/renderer/tr_cmds.cpp index 6701d16ac..8003c9622 100644 --- a/src/engine/renderer/tr_cmds.cpp +++ b/src/engine/renderer/tr_cmds.cpp @@ -85,11 +85,6 @@ void R_PerformanceCounters() Log::Notice("dlights:%i interactions:%i", tr.pc.c_dlights, tr.pc.c_dlightInteractions ); } - else if ( r_speeds->integer == Util::ordinal(renderSpeeds_t::RSPEEDS_SHADOWCUBE_CULLING )) - { - Log::Notice("omni pyramid tests:%i bin:%i bclip:%i bout:%i", - tr.pc.c_pyramidTests, tr.pc.c_pyramid_cull_ent_in, tr.pc.c_pyramid_cull_ent_clip, tr.pc.c_pyramid_cull_ent_out ); - } else if ( r_speeds->integer == Util::ordinal(renderSpeeds_t::RSPEEDS_FOG )) { Log::Notice("fog srf:%i batches:%i", backEnd.pc.c_fogSurfaces, backEnd.pc.c_fogBatches ); diff --git a/src/engine/renderer/tr_fbo.cpp b/src/engine/renderer/tr_fbo.cpp index 28b116c3c..05a065104 100644 --- a/src/engine/renderer/tr_fbo.cpp +++ b/src/engine/renderer/tr_fbo.cpp @@ -451,55 +451,6 @@ void R_InitFBOs() R_CheckFBO( tr.lighttileFBO ); } - if ( glConfig2.shadowMapping ) - { - // shadowMap FBOs for shadow mapping offscreen rendering - for ( i = 0; i < MAX_SHADOWMAPS; i++ ) - { - width = height = shadowMapResolutions[ i ]; - - tr.shadowMapFBO[ i ] = R_CreateFBO( va( "_shadowMap%d", i ), width, height ); - R_BindFBO( tr.shadowMapFBO[ i ] ); - R_AttachFBOTexture2D( GL_TEXTURE_2D, - tr.shadowMapFBOImage[ i ]->texnum, - 0 ); - - R_CreateFBODepthBuffer( tr.shadowMapFBO[ i ], GL_DEPTH_COMPONENT24 ); - - R_CheckFBO( tr.shadowMapFBO[ i ] ); - } - - // sun requires different resolutions - for ( i = 0; i < MAX_SHADOWMAPS; i++ ) - { - width = height = sunShadowMapResolutions[ i ]; - - tr.sunShadowMapFBO[ i ] = R_CreateFBO( va( "_sunShadowMap%d", i ), width, height ); - R_BindFBO( tr.sunShadowMapFBO[ i ] ); - R_AttachFBOTexture2D( GL_TEXTURE_2D, - tr.sunShadowMapFBOImage[ i ]->texnum, - 0 ); - - R_CreateFBODepthBuffer( tr.sunShadowMapFBO[ i ], GL_DEPTH_COMPONENT24 ); - - if ( glConfig2.shadowingMode == shadowingMode_t::SHADOWING_EVSM32 - && r_evsmPostProcess->integer ) - { - R_AttachFBOTextureDepth( tr.sunShadowMapFBOImage[ i ]->texnum ); - - /* - Since we don't have a color attachment, the framebuffer will be considered incomplete. - Consequently, we must inform the driver that we do not wish to render to the color buffer. - We do this with a call to set the draw-buffer and read-buffer to GL_NONE: - */ - glDrawBuffer( GL_NONE ); - glReadBuffer( GL_NONE ); - } - - R_CheckFBO( tr.sunShadowMapFBO[ i ] ); - } - } - { width = glConfig.vidWidth; height = glConfig.vidHeight; diff --git a/src/engine/renderer/tr_image.cpp b/src/engine/renderer/tr_image.cpp index 60cfafab5..2ef92e11b 100644 --- a/src/engine/renderer/tr_image.cpp +++ b/src/engine/renderer/tr_image.cpp @@ -2684,156 +2684,6 @@ static void R_CreatePortalRenderImage() tr.portalRenderImage = R_CreateImage( "_portalRender", nullptr, width, height, 1, imageParams ); } -// *INDENT-OFF* -static void R_CreateShadowMapFBOImage() -{ - if ( !glConfig2.shadowMapping ) - { - return; - } - - int numFactor = 1; - int format = IF_NOPICMIP; - - // FIXME: We should test if those formats are supported. - switch( glConfig2.shadowingMode ) - { - case shadowingMode_t::SHADOWING_ESM16: - format |= IF_ONECOMP16F; - break; - case shadowingMode_t::SHADOWING_ESM32: - format |= IF_ONECOMP32F; - break; - case shadowingMode_t::SHADOWING_VSM16: - numFactor = 2; - format |= IF_TWOCOMP16F; - break; - case shadowingMode_t::SHADOWING_VSM32: - numFactor = 2; - format |= IF_TWOCOMP32F; - break; - case shadowingMode_t::SHADOWING_EVSM32: - numFactor = 2; - if ( r_evsmPostProcess->integer ) - { - format |= IF_ONECOMP32F; - } - else - { - format |= IF_RGBA32F; - } - break; - case shadowingMode_t::SHADOWING_NONE: - case shadowingMode_t::SHADOWING_BLOB: - default: - DAEMON_ASSERT( false ); - return; - } - - int numShadowMaps = MAX_SHADOWMAPS; - - if ( r_softShadowsPP->integer ) - { - numShadowMaps *= numFactor; - } - - filterType_t filter = filterType_t::FT_NEAREST; - - if( r_shadowMapLinearFilter->integer ) - { - filter = filterType_t::FT_LINEAR; - } - - imageParams_t imageParams = {}; - imageParams.bits = format; - imageParams.filterType = filter; - imageParams.wrapType = wrapTypeEnum_t::WT_ONE_CLAMP; - - for ( int i = 0; i < numShadowMaps; i++ ) - { - int size = shadowMapResolutions[ i % MAX_SHADOWMAPS ]; - - tr.shadowMapFBOImage[ i ] = R_CreateImage( va( "_shadowMapFBO%d", i ), nullptr, size, size, 1, imageParams ); - tr.shadowClipMapFBOImage[ i ] = R_CreateImage( va( "_shadowClipMapFBO%d", i ), nullptr, size, size, 1, imageParams ); - } - - // sun shadow maps - for ( int i = 0; i < numShadowMaps; i++ ) - { - int size = sunShadowMapResolutions[ i % MAX_SHADOWMAPS ]; - - tr.sunShadowMapFBOImage[ i ] = R_CreateImage( va( "_sunShadowMapFBO%d", i ), nullptr, size, size, 1, imageParams ); - tr.sunShadowClipMapFBOImage[ i ] = R_CreateImage( va( "_sunShadowClipMapFBO%d", i ), nullptr, size, size, 1, imageParams ); - } -} - -// *INDENT-ON* - -// *INDENT-OFF* -static void R_CreateShadowCubeFBOImage() -{ - if ( !glConfig2.shadowMapping ) - { - return; - } - - int format = IF_NOPICMIP; - - // FIXME: We should test if those formats are supported. - switch( glConfig2.shadowingMode ) - { - case shadowingMode_t::SHADOWING_ESM16: - format |= IF_ONECOMP16F; - break; - case shadowingMode_t::SHADOWING_ESM32: - format |= IF_ONECOMP32F; - break; - case shadowingMode_t::SHADOWING_VSM16: - format |= IF_TWOCOMP16F; - break; - case shadowingMode_t::SHADOWING_VSM32: - format |= IF_TWOCOMP32F; - break; - case shadowingMode_t::SHADOWING_EVSM32: - if ( r_evsmPostProcess->integer ) - { - format |= IF_ONECOMP32F; - } - else - { - format |= IF_RGBA32F; - } - break; - case shadowingMode_t::SHADOWING_NONE: - case shadowingMode_t::SHADOWING_BLOB: - default: - DAEMON_ASSERT( false ); - return; - } - - filterType_t filter = filterType_t::FT_NEAREST; - - if ( r_shadowMapLinearFilter->integer ) - { - filter = filterType_t::FT_LINEAR; - } - - imageParams_t imageParams = {}; - imageParams.bits = format; - imageParams.filterType = filter; - imageParams.wrapType = wrapTypeEnum_t::WT_EDGE_CLAMP; - - for ( int i = 0; i < 5; i++ ) - { - int size = shadowMapResolutions[ i ]; - - tr.shadowCubeFBOImage[ i ] = R_CreateCubeImage( va( "_shadowCubeFBO%d", i ), nullptr, size, size, imageParams ); - tr.shadowClipCubeFBOImage[ i ] = R_CreateCubeImage( va( "_shadowClipCubeFBO%d", i ), nullptr, size, size, imageParams ); - } -} - -// *INDENT-ON* - // *INDENT-OFF* static void R_CreateBlackCubeImage() { @@ -3033,8 +2883,6 @@ void R_CreateBuiltinImages() R_CreateCurrentRenderImage(); R_CreateDepthRenderImage(); R_CreatePortalRenderImage(); - R_CreateShadowMapFBOImage(); - R_CreateShadowCubeFBOImage(); R_CreateBlackCubeImage(); R_CreateWhiteCubeImage(); R_CreateColorGradeImage(); diff --git a/src/engine/renderer/tr_init.cpp b/src/engine/renderer/tr_init.cpp index 822cf317b..5b07a02ca 100644 --- a/src/engine/renderer/tr_init.cpp +++ b/src/engine/renderer/tr_init.cpp @@ -90,7 +90,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Cvar::Cvar r_realtimeLighting( "r_realtimeLighting", "Enable realtime light rendering", Cvar::NONE, true ); Cvar::Range> r_realtimeLightLayers( "r_realtimeLightLayers", "Dynamic light layers per tile, each layer holds 16 lights", Cvar::NONE, 4, 1, MAX_REF_LIGHTS / 16 ); - cvar_t *r_realtimeLightingCastShadows; cvar_t *r_precomputedLighting; Cvar::Cvar r_overbrightDefaultExponent("r_overbrightDefaultExponent", "default map light color shift (multiply by 2^x)", Cvar::NONE, 2); Cvar::Range> r_overbrightBits("r_overbrightBits", "clamp lightmap colors to 2^x", Cvar::NONE, 1, 0, 3); @@ -133,35 +132,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Cvar::Range> r_shadows( "cg_shadows", "shadowing mode", Cvar::NONE, Util::ordinal(shadowingMode_t::SHADOWING_BLOB), Util::ordinal(shadowingMode_t::SHADOWING_NONE), - Util::ordinal(shadowingMode_t::SHADOWING_EVSM32) ); - cvar_t *r_softShadows; - cvar_t *r_softShadowsPP; - cvar_t *r_shadowBlur; - - cvar_t *r_shadowMapSizeUltra; - cvar_t *r_shadowMapSizeVeryHigh; - cvar_t *r_shadowMapSizeHigh; - cvar_t *r_shadowMapSizeMedium; - cvar_t *r_shadowMapSizeLow; - - cvar_t *r_shadowMapSizeSunUltra; - cvar_t *r_shadowMapSizeSunVeryHigh; - cvar_t *r_shadowMapSizeSunHigh; - cvar_t *r_shadowMapSizeSunMedium; - cvar_t *r_shadowMapSizeSunLow; - - cvar_t *r_shadowLodBias; - cvar_t *r_shadowLodScale; - cvar_t *r_noShadowPyramids; - cvar_t *r_cullShadowPyramidFaces; - cvar_t *r_debugShadowMaps; + Util::ordinal(shadowingMode_t::SHADOWING_BLOB) ); + cvar_t *r_noLightFrustums; - cvar_t *r_shadowMapLinearFilter; - cvar_t *r_lightBleedReduction; - cvar_t *r_overDarkeningFactor; - cvar_t *r_shadowMapDepthScale; - cvar_t *r_parallelShadowSplits; - cvar_t *r_parallelShadowSplitWeight; cvar_t *r_mode; cvar_t *r_nobind; @@ -263,8 +236,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA cvar_t *r_showTris; cvar_t *r_showSky; - cvar_t *r_showShadowLod; - cvar_t *r_showShadowMaps; cvar_t *r_showSkeleton; cvar_t *r_showEntityTransforms; cvar_t *r_showLightTransforms; @@ -294,7 +265,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Util::ordinal( MaterialDebugMode::NONE ), Util::ordinal( MaterialDebugMode::OPAQUE_TRANSPARENT ) ); Cvar::Cvar r_materialDebug( "r_materialDebug", "Enable material debug SSBO", Cvar::NONE, false ); - cvar_t *r_showParallelShadowSplits; Cvar::Cvar r_profilerRenderSubGroups( "r_profilerRenderSubGroups", "Enable subgroup profiling in rendering shaders", Cvar::CHEAT, false ); Cvar::Range> r_profilerRenderSubGroupsMode( "r_profilerRenderSubGroupsMode", "Red: more wasted lanes, green: less wasted lanes; " @@ -1197,7 +1167,6 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p r_customwidth = Cvar_Get( "r_customwidth", "1600", CVAR_LATCH | CVAR_ARCHIVE ); r_customheight = Cvar_Get( "r_customheight", "1024", CVAR_LATCH | CVAR_ARCHIVE ); r_subdivisions = Cvar_Get( "r_subdivisions", "4", CVAR_LATCH ); - r_realtimeLightingCastShadows = Cvar_Get( "r_realtimeLightingCastShadows", "1", 0 ); r_precomputedLighting = Cvar_Get( "r_precomputedLighting", "1", CVAR_CHEAT | CVAR_LATCH ); Cvar::Latch( r_overbrightDefaultExponent ); Cvar::Latch( r_overbrightBits ); @@ -1221,15 +1190,6 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p // temporary latched variables that can only change over a restart r_singleShader = Cvar_Get( "r_singleShader", "0", CVAR_CHEAT | CVAR_LATCH ); r_stitchCurves = Cvar_Get( "r_stitchCurves", "1", CVAR_CHEAT | CVAR_LATCH ); - r_debugShadowMaps = Cvar_Get( "r_debugShadowMaps", "0", CVAR_CHEAT | CVAR_LATCH ); - r_shadowMapLinearFilter = Cvar_Get( "r_shadowMapLinearFilter", "1", CVAR_CHEAT | CVAR_LATCH ); - r_lightBleedReduction = Cvar_Get( "r_lightBleedReduction", "0", CVAR_CHEAT | CVAR_LATCH ); - r_overDarkeningFactor = Cvar_Get( "r_overDarkeningFactor", "30.0", CVAR_CHEAT | CVAR_LATCH ); - r_shadowMapDepthScale = Cvar_Get( "r_shadowMapDepthScale", "1.41", CVAR_CHEAT | CVAR_LATCH ); - - r_parallelShadowSplitWeight = Cvar_Get( "r_parallelShadowSplitWeight", "0.9", CVAR_CHEAT ); - r_parallelShadowSplits = Cvar_Get( "r_parallelShadowSplits", "2", CVAR_CHEAT | CVAR_LATCH ); - AssertCvarRange( r_parallelShadowSplits, 0, MAX_SHADOWMAPS - 1, true ); // archived variables that can change at any time r_lodBias = Cvar_Get( "r_lodBias", "0", 0 ); @@ -1327,59 +1287,6 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p Cvar::Latch( r_shadows ); - r_softShadows = Cvar_Get( "r_softShadows", "0", CVAR_LATCH ); - AssertCvarRange( r_softShadows, 0, 6, true ); - - r_softShadowsPP = Cvar_Get( "r_softShadowsPP", "0", CVAR_LATCH ); - - r_shadowBlur = Cvar_Get( "r_shadowBlur", "2", CVAR_LATCH ); - - r_shadowMapSizeUltra = Cvar_Get( "r_shadowMapSizeUltra", "1024", CVAR_LATCH ); - AssertCvarRange( r_shadowMapSizeUltra, 32, 2048, true ); - - r_shadowMapSizeVeryHigh = Cvar_Get( "r_shadowMapSizeVeryHigh", "512", CVAR_LATCH ); - AssertCvarRange( r_shadowMapSizeVeryHigh, 32, 2048, true ); - - r_shadowMapSizeHigh = Cvar_Get( "r_shadowMapSizeHigh", "256", CVAR_LATCH ); - AssertCvarRange( r_shadowMapSizeHigh, 32, 2048, true ); - - r_shadowMapSizeMedium = Cvar_Get( "r_shadowMapSizeMedium", "128", CVAR_LATCH ); - AssertCvarRange( r_shadowMapSizeMedium, 32, 2048, true ); - - r_shadowMapSizeLow = Cvar_Get( "r_shadowMapSizeLow", "64", CVAR_LATCH ); - AssertCvarRange( r_shadowMapSizeLow, 32, 2048, true ); - - shadowMapResolutions[ 0 ] = r_shadowMapSizeUltra->integer; - shadowMapResolutions[ 1 ] = r_shadowMapSizeVeryHigh->integer; - shadowMapResolutions[ 2 ] = r_shadowMapSizeHigh->integer; - shadowMapResolutions[ 3 ] = r_shadowMapSizeMedium->integer; - shadowMapResolutions[ 4 ] = r_shadowMapSizeLow->integer; - - r_shadowMapSizeSunUltra = Cvar_Get( "r_shadowMapSizeSunUltra", "1024", CVAR_LATCH ); - AssertCvarRange( r_shadowMapSizeSunUltra, 32, 2048, true ); - - r_shadowMapSizeSunVeryHigh = Cvar_Get( "r_shadowMapSizeSunVeryHigh", "1024", CVAR_LATCH ); - AssertCvarRange( r_shadowMapSizeSunVeryHigh, 512, 2048, true ); - - r_shadowMapSizeSunHigh = Cvar_Get( "r_shadowMapSizeSunHigh", "1024", CVAR_LATCH ); - AssertCvarRange( r_shadowMapSizeSunHigh, 512, 2048, true ); - - r_shadowMapSizeSunMedium = Cvar_Get( "r_shadowMapSizeSunMedium", "1024", CVAR_LATCH ); - AssertCvarRange( r_shadowMapSizeSunMedium, 512, 2048, true ); - - r_shadowMapSizeSunLow = Cvar_Get( "r_shadowMapSizeSunLow", "1024", CVAR_LATCH ); - AssertCvarRange( r_shadowMapSizeSunLow, 512, 2048, true ); - - sunShadowMapResolutions[ 0 ] = r_shadowMapSizeSunUltra->integer; - sunShadowMapResolutions[ 1 ] = r_shadowMapSizeSunVeryHigh->integer; - sunShadowMapResolutions[ 2 ] = r_shadowMapSizeSunHigh->integer; - sunShadowMapResolutions[ 3 ] = r_shadowMapSizeSunMedium->integer; - sunShadowMapResolutions[ 4 ] = r_shadowMapSizeSunLow->integer; - - r_shadowLodBias = Cvar_Get( "r_shadowLodBias", "0", CVAR_CHEAT ); - r_shadowLodScale = Cvar_Get( "r_shadowLodScale", "0.8", CVAR_CHEAT ); - r_noShadowPyramids = Cvar_Get( "r_noShadowPyramids", "0", CVAR_CHEAT ); - r_cullShadowPyramidFaces = Cvar_Get( "r_cullShadowPyramidFaces", "0", CVAR_CHEAT ); r_noLightFrustums = Cvar_Get( "r_noLightFrustums", "1", CVAR_CHEAT ); r_maxPolys = Cvar_Get( "r_maxpolys", "10000", CVAR_LATCH ); // 600 in vanilla Q3A @@ -1390,8 +1297,6 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p r_showTris = Cvar_Get( "r_showTris", "0", CVAR_CHEAT ); r_showSky = Cvar_Get( "r_showSky", "0", CVAR_CHEAT ); - r_showShadowLod = Cvar_Get( "r_showShadowLod", "0", CVAR_CHEAT ); - r_showShadowMaps = Cvar_Get( "r_showShadowMaps", "0", CVAR_CHEAT ); r_showSkeleton = Cvar_Get( "r_showSkeleton", "0", CVAR_CHEAT ); r_showEntityTransforms = Cvar_Get( "r_showEntityTransforms", "0", CVAR_CHEAT ); r_showLightTransforms = Cvar_Get( "r_showLightTransforms", "0", CVAR_CHEAT ); @@ -1410,7 +1315,6 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p r_showBspNodes = Cvar_Get( "r_showBspNodes", "0", CVAR_CHEAT ); Cvar::Latch( r_showGlobalMaterials ); Cvar::Latch( r_materialDebug ); - r_showParallelShadowSplits = Cvar_Get( "r_showParallelShadowSplits", "0", CVAR_CHEAT | CVAR_LATCH ); Cvar::Latch( r_profilerRenderSubGroups ); } diff --git a/src/engine/renderer/tr_light.cpp b/src/engine/renderer/tr_light.cpp index 4316a2e90..df0a4292e 100644 --- a/src/engine/renderer/tr_light.cpp +++ b/src/engine/renderer/tr_light.cpp @@ -49,26 +49,6 @@ void R_AddBrushModelInteractions( trRefEntity_t *ent, trRefLight_t *light, inter return; } - // avoid drawing of certain objects -#if defined( USE_REFENTITY_NOSHADOWID ) - - if ( light->l.inverseShadows ) - { - if ( (iaType & IA_SHADOW) && ( light->l.noShadowID && ( light->l.noShadowID != ent->e.noShadowID ) ) ) - { - return; - } - } - else - { - if ( (iaType & IA_SHADOW) && ( light->l.noShadowID && ( light->l.noShadowID == ent->e.noShadowID ) ) ) - { - return; - } - } - -#endif - pModel = R_GetModelByHandle( ent->e.hModel ); bspModel = pModel->bsp; @@ -97,7 +77,7 @@ void R_AddBrushModelInteractions( trRefEntity_t *ent, trRefLight_t *light, inter surf = bspModel->firstSurface + i; // skip all surfaces that don't matter for lighting only pass - if ( surf->shader->isSky || ( !surf->shader->interactLight && surf->shader->noShadows ) ) + if ( surf->shader->isSky || !surf->shader->interactLight ) { continue; } @@ -786,7 +766,7 @@ bool R_AddLightInteraction( trRefLight_t *light, surfaceType_t *surface, shader_ // skip all surfaces that don't matter for lighting only pass if ( surfaceShader ) { - if ( surfaceShader->isSky || ( !surfaceShader->interactLight && surfaceShader->noShadows ) ) + if ( surfaceShader->isSky || !surfaceShader->interactLight ) { return false; } @@ -820,13 +800,6 @@ bool R_AddLightInteraction( trRefLight_t *light, surfaceType_t *surface, shader_ // update counters light->numInteractions++; - if( !(iaType & IA_LIGHT) ) { - light->numShadowOnlyInteractions++; - } - if( !(iaType & (IA_SHADOW | IA_SHADOWCLIP) ) ) { - light->numLightOnlyInteractions++; - } - ia->next = nullptr; ia->type = iaType; @@ -1207,228 +1180,13 @@ R_CalcLightCubeSideBits ============= */ // *INDENT-OFF* -byte R_CalcLightCubeSideBits( trRefLight_t *light, vec3_t worldBounds[ 2 ] ) +byte R_CalcLightCubeSideBits( trRefLight_t *, vec3_t /*worldBounds*/[2]) { - int i; - int cubeSide; - byte cubeSideBits; - float xMin, xMax, yMin, yMax; - float zNear, zFar; - float fovX, fovY; - vec3_t angles; - matrix_t tmpMatrix, rotationMatrix, transformMatrix, viewMatrix, projectionMatrix, viewProjectionMatrix; - frustum_t frustum; - cplane_t *clipPlane; - int r; - bool anyClip; - bool culled; - - if ( light->l.rlType != refLightType_t::RL_OMNI || !glConfig2.shadowMapping || r_noShadowPyramids->integer ) - { - return CUBESIDE_CLIPALL; - } - - cubeSideBits = 0; - - for ( cubeSide = 0; cubeSide < 6; cubeSide++ ) - { - switch ( cubeSide ) - { - default: // 0 - { - // view parameters - VectorSet( angles, 0, 0, 0 ); - break; - } - - case 1: - { - VectorSet( angles, 0, 180, 0 ); - break; - } - - case 2: - { - VectorSet( angles, 0, 90, 0 ); - break; - } - - case 3: - { - VectorSet( angles, 0, 270, 0 ); - break; - } - - case 4: - { - VectorSet( angles, -90, 0, 0 ); - break; - } - - case 5: - { - VectorSet( angles, 90, 0, 0 ); - break; - } - } - - // Quake -> OpenGL view matrix from light perspective - MatrixFromAngles( rotationMatrix, angles[ PITCH ], angles[ YAW ], angles[ ROLL ] ); - MatrixSetupTransformFromRotation( transformMatrix, rotationMatrix, light->origin ); - MatrixAffineInverse( transformMatrix, tmpMatrix ); - - // convert from our coordinate system (looking down X) - // to OpenGL's coordinate system (looking down -Z) - MatrixMultiply( quakeToOpenGLMatrix, tmpMatrix, viewMatrix ); - - // OpenGL projection matrix - fovX = 90; - fovY = 90; - - zNear = 1.0f; - zFar = light->sphereRadius; - - xMax = zNear * tanf( fovX * M_PI / 360.0f ); - xMin = -xMax; - - yMax = zNear * tanf( fovY * M_PI / 360.0f ); - yMin = -yMax; - - MatrixPerspectiveProjection( projectionMatrix, xMin, xMax, yMin, yMax, zNear, zFar ); - - // calculate frustum planes using the modelview projection matrix - MatrixMultiply( projectionMatrix, viewMatrix, viewProjectionMatrix ); - R_SetupFrustum2( frustum, viewProjectionMatrix ); - - // use the frustum planes to cut off shadowmaps beyond the light volume - anyClip = false; - culled = false; - - for ( i = 0; i < 5; i++ ) - { - clipPlane = &frustum[ i ]; - - r = BoxOnPlaneSide( worldBounds[ 0 ], worldBounds[ 1 ], clipPlane ); - - if ( r == 2 ) - { - culled = true; - break; - } - - if ( r == 3 ) - { - anyClip = true; - } - } - - if ( !culled ) - { - if ( !anyClip ) - { - // completely inside frustum - tr.pc.c_pyramid_cull_ent_in++; - } - else - { - // partially clipped - tr.pc.c_pyramid_cull_ent_clip++; - } - - cubeSideBits |= ( 1 << cubeSide ); - } - else - { - // completely outside frustum - tr.pc.c_pyramid_cull_ent_out++; - } - } - - tr.pc.c_pyramidTests++; - - return cubeSideBits; + return CUBESIDE_CLIPALL; } // *INDENT-ON* -/* -================= -R_SetupLightLOD -================= -*/ -void R_SetupLightLOD( trRefLight_t *light ) -{ - float radius; - float flod, lodscale; - float projectedRadius; - int lod; - int numLods; - - if ( light->l.noShadows ) - { - light->shadowLOD = -1; - return; - } - - numLods = 5; - - // compute projected bounding sphere - // and use that as a criteria for selecting LOD - radius = light->sphereRadius; - - if ( ( projectedRadius = R_ProjectRadius( radius, light->l.origin ) ) != 0 ) - { - lodscale = r_shadowLodScale->value; - - if ( lodscale > 20 ) - { - lodscale = 20; - } - - flod = 1.0f - projectedRadius * lodscale; - } - else - { - // object intersects near view plane, e.g. view weapon - flod = 0; - } - - flod *= numLods; - lod = Q_ftol( flod ); - - if ( lod < 0 ) - { - lod = 0; - } - else if ( lod >= numLods ) - { - //lod = numLods - 1; - } - - lod += r_shadowLodBias->integer; - - if ( lod < 0 ) - { - lod = 0; - } - - if ( lod >= numLods ) - { - // don't draw any shadow - lod = -1; - - //lod = numLods - 1; - } - - // never give ultra quality for point lights - if ( lod == 0 && light->l.rlType == refLightType_t::RL_OMNI ) - { - lod = 1; - } - - light->shadowLOD = lod; -} - /* ================= R_SetupLightShader diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index 262e42892..032119b62 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -174,8 +174,6 @@ static inline void halfToFloat( const f16vec4_t in, vec4_t out ) #define MAX_VISCOUNTS 5 #define MAX_VIEWS 10 -#define MAX_SHADOWMAPS 5 - #define MAX_TEXTURE_MIPS 16 #define MAX_TEXTURE_LAYERS 256 @@ -332,7 +330,6 @@ enum class ssaoMode { RSPEEDS_CULLING, RSPEEDS_VIEWCLUSTER, RSPEEDS_LIGHTS, - RSPEEDS_SHADOWCUBE_CULLING, RSPEEDS_FOG, RSPEEDS_SHADING_TIMES, RSPEEDS_CHC, @@ -429,12 +426,6 @@ enum class ssaoMode { vec3_t projUp; vec3_t projStart; vec3_t projEnd; - - bool noShadows; - short noShadowID; // don't cast shadows of all entities with this id - - bool inverseShadows; // don't cast light and draw shadows by darken the scene - // this is useful for drawing player shadows with shadow mapping }; // a trRefLight_t has all the information passed in by @@ -455,8 +446,6 @@ enum class ssaoMode { float falloffLength; - matrix_t shadowMatrices[ MAX_SHADOWMAPS ]; - matrix_t shadowMatricesBiased[ MAX_SHADOWMAPS ]; matrix_t attenuationMatrix; // attenuation * (light view * entity transform) matrix_t attenuationMatrix2; // attenuation * tcMod matrices @@ -464,8 +453,6 @@ enum class ssaoMode { vec3_t worldBounds[ 2 ]; float sphereRadius; // calculated from localBounds - int8_t shadowLOD; // Level of Detail for shadow mapping - int restrictInteractionFirst; int restrictInteractionLast; @@ -481,8 +468,6 @@ enum class ssaoMode { struct interaction_t *lastInteraction; uint16_t numInteractions; // total interactions - uint16_t numShadowOnlyInteractions; - uint16_t numLightOnlyInteractions; bool noSort; // don't sort interactions by material int visCounts[ MAX_VISCOUNTS ]; // node needs to be traversed if current @@ -1163,7 +1148,6 @@ enum class ssaoMode { stageShaderBinder_t shaderBinder; stageMaterialProcessor_t materialProcessor; - bool doShadowFill; bool doForwardLighting; textureBundle_t bundle[ MAX_TEXTURE_BUNDLES ]; @@ -1316,7 +1300,6 @@ enum class ssaoMode { int contentFlags; bool entityMergable; // merge across entites optimizable (smoke, blood) - bool alphaTest; // helps merging shadowmap generating surfaces fogParms_t fogParms; fogPass_t fogPass; // draw a blended pass, possibly with depth test equals @@ -1326,7 +1309,6 @@ enum class ssaoMode { float reliefOffsetBias; // offset the heightmap top relatively to the floor float reliefDepthScale = 1.0f; // per-shader relief depth scale - bool noShadows; bool ambientLight; bool translucent; bool forceOpaque; @@ -1559,10 +1541,7 @@ enum class ssaoMode { matrix_t projectionMatrixNonPortal; // For skybox rendering in portals matrix_t unprojectionMatrix; // transform pixel window space -> world space - float parallelSplitDistances[ MAX_SHADOWMAPS + 1 ]; // distances in camera space - - frustum_t frustums[ MAX_SHADOWMAPS + 1 ]; // first frustum is the default one with complete zNear - zFar range - // and the other ones are for PSSM + frustum_t frustums[ 1 ]; // FIXME: need not be array (was for shadowmaps) vec3_t visBounds[ 2 ]; float zNear; @@ -1690,11 +1669,9 @@ enum class ssaoMode { enum interactionType_t { IA_LIGHT = 1 << 0, // the received light if not in shadow - IA_SHADOW = 1 << 1, // the surface shadows the light - IA_SHADOWCLIP = 1 << 2, // the surface clips the shadow - IA_DEFAULT = IA_LIGHT | IA_SHADOW, // lighting and shadowing - IA_DEFAULTCLIP = IA_LIGHT | IA_SHADOWCLIP + IA_DEFAULT = IA_LIGHT, // lighting and shadowing + IA_DEFAULTCLIP = IA_LIGHT }; // an interaction is a node between a light and any surface @@ -2327,9 +2304,6 @@ enum class ssaoMode { int c_box_cull_light_in, c_box_cull_light_clip, c_box_cull_light_out; int c_pvs_cull_light_out; - int c_pyramidTests; - int c_pyramid_cull_ent_in, c_pyramid_cull_ent_clip, c_pyramid_cull_ent_out; - int c_nodes; int c_leafs; @@ -2704,13 +2678,6 @@ enum class ssaoMode { image_t *lighttileRenderImage; image_t *portalRenderImage; - image_t *shadowMapFBOImage[ MAX_SHADOWMAPS * 2 ]; - image_t *shadowCubeFBOImage[ MAX_SHADOWMAPS ]; - image_t *sunShadowMapFBOImage[ MAX_SHADOWMAPS * 2 ]; - image_t *shadowClipMapFBOImage[ MAX_SHADOWMAPS * 2 ]; - image_t *shadowClipCubeFBOImage[ MAX_SHADOWMAPS ]; - image_t *sunShadowClipMapFBOImage[ MAX_SHADOWMAPS * 2 ]; - // external images image_t *colorGradeImage; GLuint colorGradePBO; @@ -2723,8 +2690,6 @@ enum class ssaoMode { FBO_t *portalRenderFBO; // holds a copy of the last currentRender that was rendered into a FBO FBO_t *contrastRenderFBO; FBO_t *bloomRenderFBO[ 2 ]; - FBO_t *shadowMapFBO[ MAX_SHADOWMAPS ]; - FBO_t *sunShadowMapFBO[ MAX_SHADOWMAPS ]; // vertex buffer objects VBO_t *lighttileVBO; @@ -2848,8 +2813,6 @@ enum class ssaoMode { extern const matrix_t quakeToOpenGLMatrix; extern const matrix_t openGLToQuakeMatrix; extern const matrix_t flipZMatrix; - extern int shadowMapResolutions[ 5 ]; - extern int sunShadowMapResolutions[ 5 ]; extern backEndState_t backEnd; extern trGlobals_t tr; @@ -2892,7 +2855,6 @@ enum class ssaoMode { extern Cvar::Range> r_realtimeLightingRenderer; extern Cvar::Cvar r_realtimeLighting; extern Cvar::Range> r_realtimeLightLayers; - extern cvar_t *r_realtimeLightingCastShadows; extern cvar_t *r_precomputedLighting; extern Cvar::Cvar r_overbrightDefaultExponent; extern Cvar::Range> r_overbrightBits; @@ -2974,34 +2936,8 @@ enum class ssaoMode { extern Cvar::Cvar r_highPrecisionRendering; extern Cvar::Range> r_shadows; - extern cvar_t *r_softShadows; - extern cvar_t *r_softShadowsPP; - extern cvar_t *r_shadowBlur; - - extern cvar_t *r_shadowMapSizeUltra; - extern cvar_t *r_shadowMapSizeVeryHigh; - extern cvar_t *r_shadowMapSizeHigh; - extern cvar_t *r_shadowMapSizeMedium; - extern cvar_t *r_shadowMapSizeLow; - - extern cvar_t *r_shadowMapSizeSunUltra; - extern cvar_t *r_shadowMapSizeSunVeryHigh; - extern cvar_t *r_shadowMapSizeSunHigh; - extern cvar_t *r_shadowMapSizeSunMedium; - extern cvar_t *r_shadowMapSizeSunLow; - - extern cvar_t *r_shadowLodBias; - extern cvar_t *r_shadowLodScale; - extern cvar_t *r_noShadowPyramids; - extern cvar_t *r_cullShadowPyramidFaces; - extern cvar_t *r_debugShadowMaps; + extern cvar_t *r_noLightFrustums; - extern cvar_t *r_shadowMapLinearFilter; - extern cvar_t *r_lightBleedReduction; - extern cvar_t *r_overDarkeningFactor; - extern cvar_t *r_shadowMapDepthScale; - extern cvar_t *r_parallelShadowSplits; - extern cvar_t *r_parallelShadowSplitWeight; extern cvar_t *r_lockpvs; extern cvar_t *r_noportals; @@ -3029,8 +2965,6 @@ enum class ssaoMode { extern cvar_t *r_showTris; // enables wireframe rendering of the world extern cvar_t *r_showSky; // forces sky in front of all surfaces - extern cvar_t *r_showShadowLod; - extern cvar_t *r_showShadowMaps; extern cvar_t *r_showSkeleton; extern cvar_t *r_showEntityTransforms; extern cvar_t *r_showLightTransforms; @@ -3051,7 +2985,6 @@ enum class ssaoMode { extern cvar_t *r_showBspNodes; extern Cvar::Range> r_showGlobalMaterials; extern Cvar::Cvar r_materialDebug; - extern cvar_t *r_showParallelShadowSplits; extern Cvar::Cvar r_forceRendererTime; @@ -3123,7 +3056,6 @@ inline bool checkGLErrors() void R_SetupEntityWorldBounds( trRefEntity_t *ent ); void R_RotateEntityForViewParms( const trRefEntity_t *ent, const viewParms_t *viewParms, orientationr_t *orien ); - void R_RotateEntityForLight( const trRefEntity_t *ent, const trRefLight_t *light, orientationr_t *orien ); void R_RotateLightForViewParms( const trRefLight_t *ent, const viewParms_t *viewParms, orientationr_t *orien ); void R_SetupFrustum2( frustum_t frustum, const matrix_t modelViewProjectionMatrix ); @@ -3480,7 +3412,6 @@ void GLimp_LogComment_( std::string comment ); void Tess_StageIteratorDebug(); void Tess_StageIteratorColor(); void Tess_StageIteratorPortal(); - void Tess_StageIteratorShadowFill(); void Tess_StageIteratorLighting(); void Tess_StageIteratorSky(); @@ -3578,7 +3509,6 @@ void GLimp_LogComment_( std::string comment ); void R_SortInteractions( trRefLight_t *light ); void R_SetupLightScissor( trRefLight_t *light ); - void R_SetupLightLOD( trRefLight_t *light ); void R_SetupLightShader( trRefLight_t *light ); diff --git a/src/engine/renderer/tr_main.cpp b/src/engine/renderer/tr_main.cpp index e6befc7ce..e1c5bebef 100644 --- a/src/engine/renderer/tr_main.cpp +++ b/src/engine/renderer/tr_main.cpp @@ -36,9 +36,6 @@ const matrix_t quakeToOpenGLMatrix = 0, 0, 0, 1 }; -int shadowMapResolutions[ 5 ] = { 2048, 1024, 512, 256, 128 }; -int sunShadowMapResolutions[ 5 ] = { 2048, 2048, 1024, 1024, 1024 }; - refimport_t ri; // entities that will have procedurally generated surfaces will just @@ -680,75 +677,6 @@ void R_RotateEntityForViewParms( const trRefEntity_t *ent, const viewParms_t *vi orientation ->viewOrigin[ 2 ] = DotProduct( delta, orientation ->axis[ 2 ] ) * axisLength; } -/* -================= -R_RotateEntityForLight - -Generates an orientation for an entity and light -Does NOT produce any GL calls -Called by both the front end and the back end -================= -*/ -void R_RotateEntityForLight( const trRefEntity_t *ent, const trRefLight_t *light, orientationr_t * orientation ) -{ - vec3_t delta; - float axisLength; - - if ( ent->e.reType != refEntityType_t::RT_MODEL ) - { - *orientation = {}; - - orientation ->axis[ 0 ][ 0 ] = 1; - orientation ->axis[ 1 ][ 1 ] = 1; - orientation ->axis[ 2 ][ 2 ] = 1; - - VectorCopy( light->l.origin, orientation ->viewOrigin ); - - MatrixIdentity( orientation ->transformMatrix ); - MatrixMultiply( light->viewMatrix, orientation ->transformMatrix, orientation ->viewMatrix ); - MatrixCopy( orientation ->viewMatrix, orientation ->modelViewMatrix ); - return; - } - - VectorCopy( ent->e.origin, orientation ->origin ); - - VectorCopy( ent->e.axis[ 0 ], orientation ->axis[ 0 ] ); - VectorCopy( ent->e.axis[ 1 ], orientation ->axis[ 1 ] ); - VectorCopy( ent->e.axis[ 2 ], orientation ->axis[ 2 ] ); - - MatrixSetupTransformFromVectorsFLU( orientation ->transformMatrix, orientation ->axis[ 0 ], orientation ->axis[ 1 ], orientation ->axis[ 2 ], orientation ->origin ); - MatrixAffineInverse( orientation ->transformMatrix, orientation ->viewMatrix ); - - MatrixMultiply( light->viewMatrix, orientation ->transformMatrix, orientation ->modelViewMatrix ); - - // calculate the viewer origin in the model's space - // needed for fog, specular, and environment mapping - VectorSubtract( light->l.origin, orientation ->origin, delta ); - - // compensate for scale in the axes if necessary - if ( ent->e.nonNormalizedAxes ) - { - axisLength = VectorLength( ent->e.axis[ 0 ] ); - - if ( !axisLength ) - { - axisLength = 0; - } - else - { - axisLength = 1.0f / axisLength; - } - } - else - { - axisLength = 1.0f; - } - - orientation ->viewOrigin[ 0 ] = DotProduct( delta, orientation ->axis[ 0 ] ) * axisLength; - orientation ->viewOrigin[ 1 ] = DotProduct( delta, orientation ->axis[ 1 ] ) * axisLength; - orientation ->viewOrigin[ 2 ] = DotProduct( delta, orientation ->axis[ 2 ] ) * axisLength; -} - /* ================= R_RotateLightForViewParms @@ -1111,68 +1039,6 @@ void R_CalcFrustumFarCornersUnsafe( const plane_t frustum[ FRUSTUM_FAR + 1 ], ve PlanesGetIntersectionPoint( frustum[ FRUSTUM_LEFT ], frustum[ FRUSTUM_BOTTOM ], frustum[ FRUSTUM_FAR ], corners[ 3 ] ); } -static void CopyPlane( const cplane_t *in, cplane_t *out ) -{ - VectorCopy( in->normal, out->normal ); - out->dist = in->dist; - out->type = in->type; - out->signbits = in->signbits; - out->pad[ 0 ] = in->pad[ 0 ]; - out->pad[ 1 ] = in->pad[ 1 ]; -} - -static void R_SetupSplitFrustums() -{ - int i, j; - float lambda; - float ratio; - vec3_t planeOrigin; - float zNear, zFar; - - lambda = r_parallelShadowSplitWeight->value; - ratio = tr.viewParms.zFar / tr.viewParms.zNear; - - for ( j = 0; j < 5; j++ ) - { - CopyPlane( &tr.viewParms.frustums[ 0 ][ j ], &tr.viewParms.frustums[ 1 ][ j ] ); - } - - for ( i = 1; i <= ( r_parallelShadowSplits->integer + 1 ); i++ ) - { - float si = i / ( float )( r_parallelShadowSplits->integer + 1 ); - - zFar = 1.005f * lambda * ( tr.viewParms.zNear * powf( ratio, si ) ) + ( 1 - lambda ) * ( tr.viewParms.zNear + ( tr.viewParms.zFar - tr.viewParms.zNear ) * si ); - - if ( i <= r_parallelShadowSplits->integer ) - { - tr.viewParms.parallelSplitDistances[ i - 1 ] = zFar; - } - - tr.viewParms.frustums[ i ][ FRUSTUM_FAR ].type = PLANE_NON_AXIAL; - VectorNegate( tr.viewParms.orientation.axis[ 0 ], tr.viewParms.frustums[ i ][ FRUSTUM_FAR ].normal ); - - VectorMA( tr.viewParms.orientation.origin, zFar, tr.viewParms.orientation.axis[ 0 ], planeOrigin ); - tr.viewParms.frustums[ i ][ FRUSTUM_FAR ].dist = DotProduct( planeOrigin, tr.viewParms.frustums[ i ][ FRUSTUM_FAR ].normal ); - SetPlaneSignbits( &tr.viewParms.frustums[ i ][ FRUSTUM_FAR ] ); - - if ( i <= ( r_parallelShadowSplits->integer ) ) - { - zNear = zFar - ( zFar * 0.005f ); - tr.viewParms.frustums[ i + 1 ][ FRUSTUM_NEAR ].type = PLANE_NON_AXIAL; - VectorCopy( tr.viewParms.orientation.axis[ 0 ], tr.viewParms.frustums[ i + 1 ][ FRUSTUM_NEAR ].normal ); - - VectorMA( tr.viewParms.orientation.origin, zNear, tr.viewParms.orientation.axis[ 0 ], planeOrigin ); - tr.viewParms.frustums[ i + 1 ][ FRUSTUM_NEAR ].dist = DotProduct( planeOrigin, tr.viewParms.frustums[ i + 1 ][ FRUSTUM_NEAR ].normal ); - SetPlaneSignbits( &tr.viewParms.frustums[ i + 1 ][ FRUSTUM_NEAR ] ); - } - - for ( j = 0; j < 4; j++ ) - { - CopyPlane( &tr.viewParms.frustums[ 0 ][ j ], &tr.viewParms.frustums[ i ][ j ] ); - } - } -} - /* ================= R_MirrorPoint @@ -1670,6 +1536,7 @@ static void R_SetupPortalFrustum( const viewParms_t& oldParms, const orientation frustum[FRUSTUM_NEAR].dist = DotProduct(worldNearPlane, newParms.orientation.origin) - worldNearPlane[3]; // calculate new znear for parallel split frustums in this view + // TODO get rid of this? "Parallel split" was a shadow mapping thing plane_t frustumPlanes[FRUSTUM_PLANES]; for (int i = 0; i < FRUSTUM_PLANES; i++) { @@ -2124,16 +1991,6 @@ void R_AddEntityInteractions( trRefLight_t *light ) { iaType = IA_DEFAULT; - if ( !glConfig2.shadowMapping || light->l.noShadows ) { - iaType = (interactionType_t) (iaType & (~IA_SHADOW)); - } - - if ( light->restrictInteractionFirst >= 0 && - ( i < light->restrictInteractionFirst || - i > light->restrictInteractionLast ) ) { - iaType = (interactionType_t) (iaType & (~IA_SHADOW)); - } - if ( light->restrictInteractionFirst >= 0 && i >= light->restrictInteractionFirst && i <= light->restrictInteractionLast ) @@ -2202,49 +2059,6 @@ void R_AddEntityInteractions( trRefLight_t *light ) } } -/* -============= -R_TransformShadowLight - -check if OMNI shadow light can be turned into PROJ for better shadow map quality -============= -*/ -void R_TransformShadowLight( trRefLight_t *light ) { - int i; - vec3_t mins, maxs, mids; - vec3_t forward, right, up; - float radius; - - if( !light->l.inverseShadows || light->l.rlType != refLightType_t::RL_OMNI || - light->restrictInteractionFirst < 0 ) - return; - - ClearBounds( mins, maxs ); - for( i = light->restrictInteractionFirst; i <= light->restrictInteractionLast; i++ ) { - trRefEntity_t *ent = &tr.refdef.entities[ i ]; - - BoundsAdd(ent->worldBounds[0], ent->worldBounds[1], mins, maxs); - } - - // if light origin is outside BBox of shadow receivers, build - // a projection light on the closest plane of the BBox - VectorAdd( mins, maxs, mids ); - VectorScale( mids, 0.5f, mids ); - radius = Distance( mids, maxs ); - - light->l.rlType = refLightType_t::RL_PROJ; - VectorSubtract( mids, light->l.origin, forward ); - VectorNormalize( forward ); - PerpendicularVector( right, forward ); - CrossProduct( forward, right, up ); - - VectorScale( right, 2.0f * radius, light->l.projRight ); - VectorScale( up, 2.0f * radius, light->l.projUp ); - VectorCopy( vec3_origin, light->l.projStart ); - VectorCopy( vec3_origin, light->l.projEnd ); - VectorScale( forward, light->l.radius, light->l.projTarget ); -} - /* ============= R_AddLightInteractions @@ -2263,19 +2077,14 @@ void R_AddLightInteractions() { light = tr.currentLight = &tr.refdef.lights[ i ]; - if ( !light->l.inverseShadows ) + if ( realtimeLightingRenderer == realtimeLightingRenderer_t::TILED ) { - if ( realtimeLightingRenderer == realtimeLightingRenderer_t::TILED ) - { - tr.refdef.numShaderLights++; - tr.pc.c_dlights++; + tr.refdef.numShaderLights++; + tr.pc.c_dlights++; - continue; - } + continue; } - R_TransformShadowLight( light ); - // we must set up parts of tr.or for light culling R_RotateLightForViewParms( light, &tr.viewParms, &tr.orientation ); @@ -2331,9 +2140,6 @@ void R_AddLightInteractions() // set up view dependent light scissor R_SetupLightScissor( light ); - // set up view dependent light Level of Detail - R_SetupLightLOD( light ); - // look for proper attenuation shader R_SetupLightShader( light ); @@ -2342,14 +2148,12 @@ void R_AddLightInteractions() light->lastInteraction = nullptr; light->numInteractions = 0; - light->numShadowOnlyInteractions = 0; - light->numLightOnlyInteractions = 0; light->noSort = false; R_AddWorldInteractions( light ); R_AddEntityInteractions( light ); - if ( light->numInteractions && light->numInteractions != light->numShadowOnlyInteractions ) + if ( light->numInteractions ) { R_SortInteractions( light ); @@ -2508,9 +2312,6 @@ void R_RenderView( viewParms_t *parms ) // set camera frustum planes in world space again, but this time including the far plane tr.orientation = tr.viewParms.world; - // for parallel split shadow mapping - R_SetupSplitFrustums(); - R_AddEntitySurfaces(); R_AddLightInteractions(); diff --git a/src/engine/renderer/tr_mesh.cpp b/src/engine/renderer/tr_mesh.cpp index 294aa0f01..d7f918cd2 100644 --- a/src/engine/renderer/tr_mesh.cpp +++ b/src/engine/renderer/tr_mesh.cpp @@ -368,26 +368,6 @@ void R_AddMDVInteractions( trRefEntity_t *ent, trRefLight_t *light, interactionT return; } - // avoid drawing of certain objects -#if defined( USE_REFENTITY_NOSHADOWID ) - - if ( light->l.inverseShadows ) - { - if ( (iaType & IA_SHADOW) && ( light->l.noShadowID && ( light->l.noShadowID != ent->e.noShadowID ) ) ) - { - return; - } - } - else - { - if ( (iaType & IA_SHADOW) && ( light->l.noShadowID && ( light->l.noShadowID == ent->e.noShadowID ) ) ) - { - return; - } - } - -#endif - // don't add third_person objects if not in a portal personalModel = ( ent->e.renderfx & RF_THIRD_PERSON ) && tr.viewParms.portalLevel == 0; @@ -431,7 +411,7 @@ void R_AddMDVInteractions( trRefEntity_t *ent, trRefLight_t *light, interactionT shader_t *shader = GetMDVSurfaceShader( ent, mdvSurface ); // skip all surfaces that don't matter for lighting only pass - if ( shader->isSky || ( !shader->interactLight && shader->noShadows ) ) + if ( shader->isSky || !shader->interactLight ) { continue; } @@ -454,7 +434,7 @@ void R_AddMDVInteractions( trRefEntity_t *ent, trRefLight_t *light, interactionT shader_t *shader = GetMDVSurfaceShader( ent, mdvSurface ); // skip all surfaces that don't matter for lighting only pass - if ( shader->isSky || ( !shader->interactLight && shader->noShadows ) ) + if ( shader->isSky || !shader->interactLight ) { continue; } diff --git a/src/engine/renderer/tr_public.h b/src/engine/renderer/tr_public.h index 1fbd173a6..5a0c4f115 100644 --- a/src/engine/renderer/tr_public.h +++ b/src/engine/renderer/tr_public.h @@ -142,8 +142,6 @@ struct glconfig2_t bool colorGrading; bool realtimeLighting; int realtimeLightLayers; - bool shadowMapping; - shadowingMode_t shadowingMode; bool deluxeMapping; bool normalMapping; bool specularMapping; diff --git a/src/engine/renderer/tr_scene.cpp b/src/engine/renderer/tr_scene.cpp index 97bde5c87..5ed8b3256 100644 --- a/src/engine/renderer/tr_scene.cpp +++ b/src/engine/renderer/tr_scene.cpp @@ -299,6 +299,12 @@ void RE_AddDynamicLightToSceneET( const vec3_t org, float radius, float intensit return; } + if ( flags & REF_INVERSE_DLIGHT ) + { + Log::Warn( "REF_INVERSE_DLIGHT not implemtented" ); + return; + } + // set last lights restrictInteractionEnd if needed if ( r_numLights > r_firstSceneLight ) { light = &backEndData[ tr.smpFrame ]->lights[ r_numLights - 1 ]; @@ -334,9 +340,6 @@ void RE_AddDynamicLightToSceneET( const vec3_t org, float radius, float intensit light->l.color[ 1 ] = g; light->l.color[ 2 ] = b; - light->l.inverseShadows = (flags & REF_INVERSE_DLIGHT) != 0; - light->l.noShadows = !r_realtimeLightingCastShadows->integer && !light->l.inverseShadows; - if( flags & REF_RESTRICT_DLIGHT ) { light->restrictInteractionFirst = r_numEntities - r_firstSceneEntity; light->restrictInteractionLast = 0; @@ -346,11 +349,7 @@ void RE_AddDynamicLightToSceneET( const vec3_t org, float radius, float intensit } light->additive = true; - - if( light->l.inverseShadows ) - light->l.scale = -intensity; - else - light->l.scale = intensity; + light->l.scale = intensity; } void RE_AddDynamicLightToSceneQ3A( const vec3_t org, float radius, float r, float g, float b ) diff --git a/src/engine/renderer/tr_shade.cpp b/src/engine/renderer/tr_shade.cpp index 03fa949d5..720b0e779 100644 --- a/src/engine/renderer/tr_shade.cpp +++ b/src/engine/renderer/tr_shade.cpp @@ -91,18 +91,6 @@ static void EnableAvailableFeatures() } } - glConfig2.shadowingMode = shadowingMode_t( r_shadows.Get() ); - glConfig2.shadowMapping = glConfig2.shadowingMode >= shadowingMode_t::SHADOWING_ESM16; - - if ( glConfig2.shadowMapping ) - { - if ( !glConfig2.textureFloatAvailable ) - { - Log::Warn( "Shadow mapping disabled because ARB_texture_float is not available." ); - glConfig2.shadowMapping = false; - } - } - glConfig2.deluxeMapping = r_deluxeMapping->integer; glConfig2.normalMapping = r_normalMapping->integer; glConfig2.specularMapping = r_specularMapping->integer; @@ -174,7 +162,6 @@ static void EnableAvailableFeatures() if ( !glConfig2.glCoreProfile && glConfig2.maxTexIndirections < 16 ) { static const std::pair indirectFeatures[] = { - { &glConfig2.shadowMapping, "Shadow mapping" }, { &glConfig2.bloom, "Bloom" }, { &glConfig2.motionBlur, "Motion blur" }, }; @@ -277,22 +264,7 @@ static void GLSL_InitGPUShadersOrError() gl_depthtile1Shader->MarkProgramForBuilding( 0 ); gl_depthtile2Shader->MarkProgramForBuilding( 0 ); gl_lighttileShader->MarkProgramForBuilding( 0 ); - DAEMON_FALLTHROUGH; - default: - /* Dynamic shadowing code also needs this shader. - This code is not well known, so there may be a bug, - but commit a09f03bc8e775d83ac5e057593eff4e88cdea7eb mentions this: - - > Use conventional shadow mapping code for inverse lights. - > This re-enables shadows for players in the tiled renderer. - > -- @gimhael - - See also https://github.com/DaemonEngine/Daemon/pull/606#pullrequestreview-912402293 */ - if ( glConfig2.shadowMapping ) - { - // projective lighting ( Doom3 style ) - gl_shaderManager.LoadShader( gl_forwardLightingShader_projXYZ ); - } + break; } } @@ -380,7 +352,7 @@ static void GLSL_InitGPUShadersOrError() gl_cameraEffectsShader->MarkProgramForBuilding( 0 ); - if ( glConfig2.bloom || glConfig2.shadowMapping ) + if ( glConfig2.bloom ) { // gaussian blur gl_shaderManager.LoadShader( gl_blurShader ); @@ -388,15 +360,6 @@ static void GLSL_InitGPUShadersOrError() gl_blurShader->MarkProgramForBuilding( 0 ); } - if ( glConfig2.shadowMapping ) - { - // shadowmap distance compression - gl_shaderManager.LoadShader( gl_shadowFillShader ); - - // debug utils - gl_shaderManager.LoadShader( gl_debugShadowMapShader ); - } - if ( r_liquidMapping->integer != 0 ) { gl_shaderManager.LoadShader( gl_liquidShader ); @@ -520,7 +483,6 @@ void GLSL_ShutdownGPUShaders() gl_forwardLightingShader_omniXYZ = nullptr; gl_forwardLightingShader_projXYZ = nullptr; gl_forwardLightingShader_directionalSun = nullptr; - gl_shadowFillShader = nullptr; gl_reflectionShader = nullptr; gl_reflectionShaderMaterial = nullptr; gl_skyboxShader = nullptr; @@ -536,7 +498,6 @@ void GLSL_ShutdownGPUShaders() gl_contrastShader = nullptr; gl_cameraEffectsShader = nullptr; gl_blurShader = nullptr; - gl_debugShadowMapShader = nullptr; gl_liquidShader = nullptr; gl_liquidShaderMaterial = nullptr; gl_motionblurShader = nullptr; @@ -1286,91 +1247,15 @@ void Render_lightMapping( shaderStage_t *pStage ) GL_CheckErrors(); } -static void Render_shadowFill( shaderStage_t *pStage ) -{ - uint32_t stateBits; - - GLIMP_LOGCOMMENT( "--- Render_shadowFill ---" ); - - // remove blend modes - stateBits = pStage->stateBits; - stateBits &= ~( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ); - - GL_State( stateBits ); - - gl_shadowFillShader->SetVertexSkinning( glConfig2.vboVertexSkinningAvailable && tess.vboVertexSkinning ); - gl_shadowFillShader->SetVertexAnimation( tess.vboVertexAnimation ); - - gl_shadowFillShader->SetMacro_LIGHT_DIRECTIONAL( backEnd.currentLight->l.rlType == refLightType_t::RL_DIRECTIONAL ); - - gl_shadowFillShader->BindProgram( pStage->deformIndex ); - - gl_shadowFillShader->SetRequiredVertexPointers(); - - if ( r_debugShadowMaps->integer ) - { - SetUniform_Color( gl_shadowFillShader, Color::Color::Indexed( backEnd.pc.c_batches % 8 ) ); - } - - // u_AlphaThreshold - gl_shadowFillShader->SetUniform_AlphaTest( pStage->stateBits ); - - if ( backEnd.currentLight->l.rlType != refLightType_t::RL_DIRECTIONAL ) - { - gl_shadowFillShader->SetUniform_LightOrigin( backEnd.currentLight->origin ); - gl_shadowFillShader->SetUniform_LightRadius( backEnd.currentLight->sphereRadius ); - } - - gl_shadowFillShader->SetUniform_ModelMatrix( backEnd.orientation.transformMatrix ); - gl_shadowFillShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); - - // u_Bones - if ( glConfig2.vboVertexSkinningAvailable && tess.vboVertexSkinning ) - { - gl_shadowFillShader->SetUniform_Bones( tess.numBones, tess.bones ); - } - - // u_VertexInterpolation - if ( tess.vboVertexAnimation ) - { - gl_shadowFillShader->SetUniform_VertexInterpolation( glState.vertexAttribsInterpolation ); - } - - // u_DeformGen - gl_shadowFillShader->SetUniform_Time( backEnd.refdef.floatTime - backEnd.currentEntity->e.shaderTime ); - - // bind u_ColorMap - if ( ( pStage->stateBits & GLS_ATEST_BITS ) != 0 ) - { - gl_shadowFillShader->SetUniform_ColorMapBindless( - GL_BindToTMU( 0, pStage->bundle[TB_COLORMAP].image[0] ) - ); - gl_shadowFillShader->SetUniform_TextureMatrix( tess.svars.texMatrices[ TB_COLORMAP ] ); - } - else - { - gl_shadowFillShader->SetUniform_ColorMapBindless( - GL_BindToTMU( 0, tr.whiteImage ) - ); - } - - Tess_DrawElements(); - - GL_CheckErrors(); -} - static void Render_forwardLighting_DBS_omni( shaderStage_t *pStage, shaderStage_t *attenuationXYStage, shaderStage_t *attenuationZStage, trRefLight_t *light ) { vec3_t viewOrigin; vec3_t lightOrigin; - float shadowTexelSize; GLIMP_LOGCOMMENT( "--- Render_forwardLighting_DBS_omni ---" ); - bool shadowCompare = ( glConfig2.shadowMapping && !light->l.noShadows && light->shadowLOD >= 0 ); - // choose right shader program ---------------------------------- gl_forwardLightingShader_omniXYZ->SetVertexSkinning( glConfig2.vboVertexSkinningAvailable && tess.vboVertexSkinning ); gl_forwardLightingShader_omniXYZ->SetVertexAnimation( tess.vboVertexAnimation ); @@ -1379,8 +1264,6 @@ static void Render_forwardLighting_DBS_omni( shaderStage_t *pStage, gl_forwardLightingShader_omniXYZ->SetReliefMapping( pStage->enableReliefMapping ); - gl_forwardLightingShader_omniXYZ->SetShadowing( shadowCompare ); - gl_forwardLightingShader_omniXYZ->BindProgram( pStage->deformIndex ); // end choose right shader program ------------------------------ @@ -1421,15 +1304,6 @@ static void Render_forwardLighting_DBS_omni( shaderStage_t *pStage, VectorCopy( light->origin, lightOrigin ); Color::Color lightColor = tess.svars.color; - if ( shadowCompare ) - { - shadowTexelSize = 1.0f / shadowMapResolutions[ light->shadowLOD ]; - } - else - { - shadowTexelSize = 1.0f; - } - gl_forwardLightingShader_omniXYZ->SetUniform_ViewOrigin( viewOrigin ); gl_forwardLightingShader_omniXYZ->SetUniform_LightOrigin( lightOrigin ); @@ -1440,14 +1314,6 @@ static void Render_forwardLighting_DBS_omni( shaderStage_t *pStage, GL_CheckErrors(); - if ( shadowCompare ) - { - gl_forwardLightingShader_omniXYZ->SetUniform_ShadowTexelSize( shadowTexelSize ); - gl_forwardLightingShader_omniXYZ->SetUniform_ShadowBlur( r_shadowBlur->value ); - } - - GL_CheckErrors(); - gl_forwardLightingShader_omniXYZ->SetUniform_ModelMatrix( backEnd.orientation.transformMatrix ); gl_forwardLightingShader_omniXYZ->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); @@ -1513,15 +1379,6 @@ static void Render_forwardLighting_DBS_omni( shaderStage_t *pStage, gl_forwardLightingShader_omniXYZ->SetUniform_AttenuationMapZBindless( BindAnimatedImage( 4, &attenuationZStage->bundle[TB_COLORMAP] ) ); - // bind u_ShadowMap - if ( shadowCompare ) - { - gl_forwardLightingShader_omniXYZ->SetUniform_ShadowMapBindless( - GL_BindToTMU( 5, tr.shadowCubeFBOImage[light->shadowLOD] ) ); - gl_forwardLightingShader_omniXYZ->SetUniform_ShadowClipMapBindless( - GL_BindToTMU( 7, tr.shadowClipCubeFBOImage[light->shadowLOD] ) ); - } - // bind u_RandomMap gl_forwardLightingShader_omniXYZ->SetUniform_RandomMapBindless( GL_BindToTMU( 6, tr.randomNormalsImage ) @@ -1540,12 +1397,9 @@ static void Render_forwardLighting_DBS_proj( shaderStage_t *pStage, { vec3_t viewOrigin; vec3_t lightOrigin; - float shadowTexelSize; GLIMP_LOGCOMMENT( "--- Render_forwardLighting_DBS_proj ---" ); - bool shadowCompare = ( glConfig2.shadowMapping && !light->l.noShadows && light->shadowLOD >= 0 ); - // choose right shader program ---------------------------------- gl_forwardLightingShader_projXYZ->SetVertexSkinning( glConfig2.vboVertexSkinningAvailable && tess.vboVertexSkinning ); gl_forwardLightingShader_projXYZ->SetVertexAnimation( tess.vboVertexAnimation ); @@ -1554,8 +1408,6 @@ static void Render_forwardLighting_DBS_proj( shaderStage_t *pStage, gl_forwardLightingShader_projXYZ->SetReliefMapping( pStage->enableReliefMapping ); - gl_forwardLightingShader_projXYZ->SetShadowing( shadowCompare ); - gl_forwardLightingShader_projXYZ->BindProgram( pStage->deformIndex ); // end choose right shader program ------------------------------ @@ -1596,15 +1448,6 @@ static void Render_forwardLighting_DBS_proj( shaderStage_t *pStage, VectorCopy( light->origin, lightOrigin ); Color::Color lightColor = tess.svars.color; - if ( shadowCompare ) - { - shadowTexelSize = 1.0f / shadowMapResolutions[ light->shadowLOD ]; - } - else - { - shadowTexelSize = 1.0f; - } - gl_forwardLightingShader_projXYZ->SetUniform_ViewOrigin( viewOrigin ); gl_forwardLightingShader_projXYZ->SetUniform_LightOrigin( lightOrigin ); @@ -1615,15 +1458,6 @@ static void Render_forwardLighting_DBS_proj( shaderStage_t *pStage, GL_CheckErrors(); - if ( shadowCompare ) - { - gl_forwardLightingShader_projXYZ->SetUniform_ShadowTexelSize( shadowTexelSize ); - gl_forwardLightingShader_projXYZ->SetUniform_ShadowBlur( r_shadowBlur->value ); - gl_forwardLightingShader_projXYZ->SetUniform_ShadowMatrix( light->shadowMatrices ); - } - - GL_CheckErrors(); - gl_forwardLightingShader_projXYZ->SetUniform_ModelMatrix( backEnd.orientation.transformMatrix ); gl_forwardLightingShader_projXYZ->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); @@ -1689,17 +1523,6 @@ static void Render_forwardLighting_DBS_proj( shaderStage_t *pStage, gl_forwardLightingShader_projXYZ->SetUniform_AttenuationMapZBindless( BindAnimatedImage( 4, &attenuationZStage->bundle[TB_COLORMAP] ) ); - // bind u_ShadowMap - if ( shadowCompare ) - { - gl_forwardLightingShader_projXYZ->SetUniform_ShadowMap0Bindless( - GL_BindToTMU( 5, tr.shadowMapFBOImage[light->shadowLOD] ) - ); - gl_forwardLightingShader_projXYZ->SetUniform_ShadowClipMap0Bindless( - GL_BindToTMU( 7, tr.shadowClipMapFBOImage[light->shadowLOD] ) - ); - } - // bind u_RandomMap gl_forwardLightingShader_projXYZ->SetUniform_RandomMapBindless( GL_BindToTMU( 6, tr.randomNormalsImage ) @@ -1716,12 +1539,9 @@ static void Render_forwardLighting_DBS_directional( shaderStage_t *pStage, trRef { vec3_t viewOrigin; vec3_t lightDirection; - float shadowTexelSize; GLIMP_LOGCOMMENT( "--- Render_forwardLighting_DBS_directional ---" ); - bool shadowCompare = ( glConfig2.shadowMapping && !light->l.noShadows && light->shadowLOD >= 0 ); - // choose right shader program ---------------------------------- gl_forwardLightingShader_directionalSun->SetVertexSkinning( glConfig2.vboVertexSkinningAvailable && tess.vboVertexSkinning ); gl_forwardLightingShader_directionalSun->SetVertexAnimation( tess.vboVertexAnimation ); @@ -1730,8 +1550,6 @@ static void Render_forwardLighting_DBS_directional( shaderStage_t *pStage, trRef gl_forwardLightingShader_directionalSun->SetReliefMapping( pStage->enableReliefMapping ); - gl_forwardLightingShader_directionalSun->SetShadowing( shadowCompare ); - gl_forwardLightingShader_directionalSun->BindProgram( pStage->deformIndex ); // end choose right shader program ------------------------------ @@ -1774,15 +1592,6 @@ static void Render_forwardLighting_DBS_directional( shaderStage_t *pStage, trRef Color::Color lightColor = tess.svars.color; - if ( shadowCompare ) - { - shadowTexelSize = 1.0f / sunShadowMapResolutions[ light->shadowLOD ]; - } - else - { - shadowTexelSize = 1.0f; - } - gl_forwardLightingShader_directionalSun->SetUniform_ViewOrigin( viewOrigin ); gl_forwardLightingShader_directionalSun->SetUniform_LightDir( lightDirection ); @@ -1793,16 +1602,6 @@ static void Render_forwardLighting_DBS_directional( shaderStage_t *pStage, trRef GL_CheckErrors(); - if ( shadowCompare ) - { - gl_forwardLightingShader_directionalSun->SetUniform_ShadowMatrix( light->shadowMatricesBiased ); - gl_forwardLightingShader_directionalSun->SetUniform_ShadowParallelSplitDistances( backEnd.viewParms.parallelSplitDistances ); - gl_forwardLightingShader_directionalSun->SetUniform_ShadowTexelSize( shadowTexelSize ); - gl_forwardLightingShader_directionalSun->SetUniform_ShadowBlur( r_shadowBlur->value ); - } - - GL_CheckErrors(); - gl_forwardLightingShader_directionalSun->SetUniform_ModelMatrix( backEnd.orientation.transformMatrix ); gl_forwardLightingShader_directionalSun->SetUniform_ViewMatrix( backEnd.viewParms.world.viewMatrix ); gl_forwardLightingShader_directionalSun->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); @@ -1860,57 +1659,6 @@ static void Render_forwardLighting_DBS_directional( shaderStage_t *pStage, trRef gl_forwardLightingShader_directionalSun->SetUniform_SpecularExponent( minSpec, maxSpec ); } - // bind u_ShadowMap - if ( shadowCompare ) - { - gl_forwardLightingShader_directionalSun->SetUniform_ShadowMap0Bindless( - GL_BindToTMU( 5, tr.sunShadowMapFBOImage[ 0 ] ) - ); - gl_forwardLightingShader_directionalSun->SetUniform_ShadowClipMap0Bindless( - GL_BindToTMU( 10, tr.sunShadowClipMapFBOImage[ 0 ] ) - ); - - if ( r_parallelShadowSplits->integer >= 1 ) - { - gl_forwardLightingShader_directionalSun->SetUniform_ShadowMap1Bindless( - GL_BindToTMU( 6, tr.sunShadowMapFBOImage[ 1 ] ) - ); - gl_forwardLightingShader_directionalSun->SetUniform_ShadowClipMap1Bindless( - GL_BindToTMU( 11, tr.sunShadowClipMapFBOImage[ 1 ] ) - ); - } - - if ( r_parallelShadowSplits->integer >= 2 ) - { - gl_forwardLightingShader_directionalSun->SetUniform_ShadowMap2Bindless( - GL_BindToTMU( 7, tr.sunShadowMapFBOImage[ 2 ] ) - ); - gl_forwardLightingShader_directionalSun->SetUniform_ShadowClipMap2Bindless( - GL_BindToTMU( 12, tr.sunShadowClipMapFBOImage[ 2 ] ) - ); - } - - if ( r_parallelShadowSplits->integer >= 3 ) - { - gl_forwardLightingShader_directionalSun->SetUniform_ShadowMap3Bindless( - GL_BindToTMU( 8, tr.sunShadowMapFBOImage[ 3 ] ) - ); - gl_forwardLightingShader_directionalSun->SetUniform_ShadowClipMap3Bindless( - GL_BindToTMU( 13, tr.sunShadowClipMapFBOImage[ 3 ] ) - ); - } - - if ( r_parallelShadowSplits->integer >= 4 ) - { - gl_forwardLightingShader_directionalSun->SetUniform_ShadowMap4Bindless( - GL_BindToTMU( 9, tr.sunShadowMapFBOImage[ 4 ] ) - ); - gl_forwardLightingShader_directionalSun->SetUniform_ShadowClipMap4Bindless( - GL_BindToTMU( 14, tr.sunShadowClipMapFBOImage[ 4 ] ) - ); - } - } - gl_forwardLightingShader_directionalSun->SetRequiredVertexPointers(); Tess_DrawElements(); @@ -2728,56 +2476,6 @@ void Tess_StageIteratorPortal() { } } -void Tess_StageIteratorShadowFill() -{ - GLIMP_LOGCOMMENT( "--- Tess_StageIteratorShadowFill( %s, %i vertices, %i triangles ) ---", - tess.surfaceShader->name, tess.numVertexes, tess.numIndexes / 3 ); - - GL_CheckErrors(); - - if ( tess.surfaceShader->autoSpriteMode != 0 ) - { - Tess_AutospriteDeform( tess.surfaceShader->autoSpriteMode ); - } - - if ( !glState.currentVBO || !glState.currentIBO || glState.currentVBO == tess.vbo || glState.currentIBO == tess.ibo ) - { - Tess_UpdateVBOs( ); - } - - // set face culling appropriately - if( backEnd.currentEntity->e.renderfx & RF_SWAPCULL ) - GL_Cull( ReverseCull( tess.surfaceShader->cullType ) ); - else - GL_Cull( tess.surfaceShader->cullType ); - - // set polygon offset if necessary - if ( tess.surfaceShader->polygonOffset ) - { - glEnable( GL_POLYGON_OFFSET_FILL ); - GL_PolygonOffset( r_offsetFactor->value, r_offsetUnits->value ); - } - - // call shader function - for ( shaderStage_t *pStage = tess.surfaceStages; pStage < tess.surfaceLastStage; pStage++ ) - { - if ( !RB_EvalExpression( &pStage->ifExp, 1.0 ) ) - { - continue; - } - - Tess_ComputeTexMatrices( pStage ); - - if ( pStage->doShadowFill ) - { - Render_shadowFill( pStage ); - } - } - - // reset polygon offset - glDisable( GL_POLYGON_OFFSET_FILL ); -} - void Tess_StageIteratorLighting() { trRefLight_t *light; @@ -2800,20 +2498,13 @@ void Tess_StageIteratorLighting() } // set OpenGL state for lighting - if ( light->l.inverseShadows ) + if ( tess.surfaceShader->sort > Util::ordinal(shaderSort_t::SS_OPAQUE) ) { - GL_State( GLS_SRCBLEND_ZERO | GLS_DSTBLEND_ONE_MINUS_SRC_COLOR ); + GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ); } else { - if ( tess.surfaceShader->sort > Util::ordinal(shaderSort_t::SS_OPAQUE) ) - { - GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ); - } - else - { - GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL ); - } + GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL ); } // set face culling appropriately @@ -2941,8 +2632,7 @@ void Tess_End() // call off to shader specific tess end function tess.stageIteratorFunc(); - if ( tess.stageIteratorFunc != Tess_StageIteratorShadowFill && - tess.stageIteratorFunc != Tess_StageIteratorDebug && + if ( tess.stageIteratorFunc != Tess_StageIteratorDebug && tess.stageIteratorFunc != Tess_StageIteratorDummy ) { // draw debugging stuff diff --git a/src/engine/renderer/tr_shader.cpp b/src/engine/renderer/tr_shader.cpp index 507639839..07a8e0aed 100644 --- a/src/engine/renderer/tr_shader.cpp +++ b/src/engine/renderer/tr_shader.cpp @@ -3266,12 +3266,6 @@ static bool ParseStage( shaderStage_t *stage, const char **text ) depthMaskBits = GLS_DEPTHMASK_TRUE; } - // tell shader if this stage has an alpha test - if ( atestBits & GLS_ATEST_BITS ) - { - shader.alphaTest = true; - } - // check that depthFade and depthWrite are mutually exclusive if ( depthMaskBits && stage->hasDepthFade ) { Log::Warn( "depth fade conflicts with depth mask in shader '%s'", shader.name ); @@ -4130,7 +4124,6 @@ static bool ParseShader( const char *_text ) // noShadows else if ( !Q_stricmp( token, "noShadows" ) ) { - shader.noShadows = true; continue; } // translucent @@ -5364,7 +5357,6 @@ static void SetStagesRenderers() stageMaterialProcessor_t materialProcessor; // Per-stage configuration. - bool doShadowFill; bool doForwardLighting; }; @@ -5375,18 +5367,16 @@ static void SetStagesRenderers() stageRendererOptions_t stageRendererOptions = { &Render_NONE, &MarkShaderBuildNONE, &UpdateSurfaceDataNONE, &BindShaderNONE, &ProcessMaterialNONE, - false, false, + false, }; - bool opaqueOrLess = shader.sort <= Util::ordinal(shaderSort_t::SS_OPAQUE); - switch ( stage->type ) { case stageType_t::ST_COLORMAP: stageRendererOptions = { &Render_generic, &MarkShaderBuildGeneric3D, &UpdateSurfaceDataGeneric3D, &BindShaderGeneric3D, &ProcessMaterialGeneric3D, - opaqueOrLess, false, + false, }; break; case stageType_t::ST_STYLELIGHTMAP: @@ -5394,7 +5384,7 @@ static void SetStagesRenderers() stageRendererOptions = { &Render_generic3D, &MarkShaderBuildGeneric3D, &UpdateSurfaceDataGeneric3D, &BindShaderGeneric3D, &ProcessMaterialGeneric3D, - true, false, + false, }; break; case stageType_t::ST_LIGHTMAP: @@ -5403,14 +5393,14 @@ static void SetStagesRenderers() stageRendererOptions = { &Render_lightMapping, &MarkShaderBuildLightMapping, &UpdateSurfaceDataLightMapping, &BindShaderLightMapping, &ProcessMaterialLightMapping, - true, true, + true, }; break; case stageType_t::ST_COLLAPSE_COLORMAP: stageRendererOptions = { &Render_lightMapping, &MarkShaderBuildLightMapping, &UpdateSurfaceDataLightMapping, &BindShaderLightMapping, &ProcessMaterialLightMapping, - true, false, + false, }; break; case stageType_t::ST_REFLECTIONMAP: @@ -5418,21 +5408,21 @@ static void SetStagesRenderers() stageRendererOptions = { &Render_reflection_CB, &MarkShaderBuildReflection, &UpdateSurfaceDataReflection, &BindShaderReflection, &ProcessMaterialReflection, - false, false, + false, }; break; case stageType_t::ST_SKYBOXMAP: stageRendererOptions = { &Render_skybox, &MarkShaderBuildSkybox, &UpdateSurfaceDataSkybox, &BindShaderSkybox, &ProcessMaterialSkybox, - false, false, + false, }; break; case stageType_t::ST_SCREENMAP: stageRendererOptions = { &Render_screen, &MarkShaderBuildScreen, &UpdateSurfaceDataScreen, &BindShaderScreen, &ProcessMaterialScreen, - false, false, + false, }; break; case stageType_t::ST_PORTALMAP: @@ -5441,28 +5431,28 @@ static void SetStagesRenderers() stageRendererOptions = { &Render_portal, &MarkShaderBuildPortal, &UpdateSurfaceDataNONE, &BindShaderNONE, &ProcessMaterialNONE, - false, false, + false, }; break; case stageType_t::ST_HEATHAZEMAP: stageRendererOptions = { &Render_heatHaze, &MarkShaderBuildHeatHaze, &UpdateSurfaceDataHeatHaze, &BindShaderHeatHaze, &ProcessMaterialHeatHaze, - false, false, + false, }; break; case stageType_t::ST_LIQUIDMAP: stageRendererOptions = { &Render_liquid, &MarkShaderBuildLiquid, &UpdateSurfaceDataLiquid, &BindShaderLiquid, &ProcessMaterialLiquid, - false, false, + false, }; break; case stageType_t::ST_FOGMAP: stageRendererOptions = { &Render_fog, &MarkShaderBuildFog, &UpdateSurfaceDataFog, &BindShaderFog, &ProcessMaterialFog, - false, false, + false, }; break; case stageType_t::ST_ATTENUATIONMAP_XY: @@ -5470,7 +5460,7 @@ static void SetStagesRenderers() stageRendererOptions = { &Render_NOP, &MarkShaderBuildNOP, &UpdateSurfaceDataNOP, &BindShaderNOP, &ProcessMaterialNOP, - false, true, + true, }; break; default: @@ -5479,7 +5469,7 @@ static void SetStagesRenderers() stageRendererOptions = { &Render_NOP, &MarkShaderBuildNOP, &UpdateSurfaceDataNOP, &BindShaderNOP, &ProcessMaterialNOP, - false, false, + false, }; break; } @@ -5491,7 +5481,6 @@ static void SetStagesRenderers() stage->shaderBinder = stageRendererOptions.shaderBinder; stage->materialProcessor = stageRendererOptions.materialProcessor; - stage->doShadowFill = stageRendererOptions.doShadowFill; stage->doForwardLighting = stageRendererOptions.doForwardLighting; // Disable stages that have no renderer yet. @@ -5911,15 +5900,6 @@ static shader_t *FinishShader() shader.sort = DetermineShaderSort(); - // HACK: allow alpha tested surfaces to create shadowmaps - if ( glConfig2.shadowMapping ) - { - if ( shader.noShadows && shader.alphaTest ) - { - shader.noShadows = false; - } - } - if ( shader.sort <= Util::ordinal( shaderSort_t::SS_OPAQUE ) ) { shader.fogPass = fogPass_t::FP_EQUAL; } else if ( shader.contentFlags & CONTENTS_FOG ) { diff --git a/src/engine/renderer/tr_types.h b/src/engine/renderer/tr_types.h index 16e414fdd..79f277c3f 100644 --- a/src/engine/renderer/tr_types.h +++ b/src/engine/renderer/tr_types.h @@ -45,6 +45,8 @@ Maryland 20850 USA. #define bool DO_NOT_USE_BOOL_IN_IPC_MESSAGE_TYPES using bool8_t = uint8_t; +// TODO(0.56): Remove all shadow stuff in here? + // XreaL BEGIN #define MAX_REF_LIGHTS 1024 #define MAX_REF_ENTITIES 1023 // can't be increased without changing drawsurf bit packing @@ -131,11 +133,6 @@ enum class refEntityType_t RT_MAX_REF_ENTITY_TYPE }; -// XreaL BEGIN - -// RB: defining any of the following macros would break the compatibility to old ET mods -//#define USE_REFENTITY_NOSHADOWID 1 - // RB: having bone names for each refEntity_t takes several MiBs // in backEndData_t so only use it for debugging and development // enabling this will show the bone names with r_showSkeleton 1 @@ -204,11 +201,6 @@ struct refEntity_t float radius; float rotation; -#if defined( USE_REFENTITY_NOSHADOWID ) - // extra light interaction information - short noShadowID; -#endif - int altShaderIndex; // KEEP SKELETON AT THE END OF THE STRUCTURE diff --git a/src/engine/renderer/tr_world.cpp b/src/engine/renderer/tr_world.cpp index 335e67f99..9c643156f 100644 --- a/src/engine/renderer/tr_world.cpp +++ b/src/engine/renderer/tr_world.cpp @@ -125,7 +125,7 @@ static bool R_CullSurface( surfaceType_t *surface, shader_t *shader, int planeBi return false; } -static bool R_CullLightSurface( surfaceType_t *surface, shader_t *shader, trRefLight_t *light, byte *cubeSideBits ) +static bool R_CullLightSurface( surfaceType_t *surface, shader_t *shader, trRefLight_t *light, byte */*cubeSideBits*/) { srfGeneric_t *gen; float d; @@ -195,11 +195,6 @@ static bool R_CullLightSurface( surfaceType_t *surface, shader_t *shader, trRefL } } - if ( r_cullShadowPyramidFaces->integer ) - { - *cubeSideBits = R_CalcLightCubeSideBits( light, gen->bounds ); - } - return false; } @@ -233,7 +228,7 @@ static void R_AddInteractionSurface( bspSurface_t *surf, trRefLight_t *light, in surf->interactionBits |= bits; // skip all surfaces that don't matter for lighting only pass - if ( surf->shader->isSky || ( !surf->shader->interactLight && surf->shader->noShadows ) ) + if ( surf->shader->isSky || !surf->shader->interactLight ) { return; } @@ -873,10 +868,7 @@ void R_AddWorldInteractions( trRefLight_t *light ) interactionBits = IA_DEFAULTCLIP; } - if ( !glConfig2.shadowMapping || light->l.noShadows ) - { - interactionBits &= IA_LIGHT; - } + interactionBits &= IA_LIGHT; R_RecursiveInteractionNode( tr.world->nodes, light, FRUSTUM_CLIPALL, interactionBits ); } From 220c3302c69bae4500e6dd9eff551f258a1a634f Mon Sep 17 00:00:00 2001 From: slipher Date: Tue, 20 May 2025 11:08:29 -0500 Subject: [PATCH 15/41] NUKE forward lighting dynamic light renderer It still kinda worked but we don't want to maintain it. Fixes #747. --- .../lights/mkintsquarelight1a.png | Bin 1169 -> 0 bytes .../lights/mkintsquarelight1b.png | Bin 1057 -> 0 bytes pkg/daemon_src.dpkdir/lights/round.png | Bin 24293 -> 0 bytes pkg/daemon_src.dpkdir/lights/squarelight1.png | Bin 8415 -> 0 bytes pkg/daemon_src.dpkdir/scripts/engine.shader | 43 - src.cmake | 2 - src/engine/qcommon/q_shared.h | 1 + src/engine/renderer/Material.cpp | 12 +- src/engine/renderer/gl_shader.cpp | 158 --- src/engine/renderer/gl_shader.h | 276 ----- .../renderer/glsl_source/computeLight_fp.glsl | 8 +- .../glsl_source/forwardLighting_fp.glsl | 215 ---- .../glsl_source/forwardLighting_vp.glsl | 92 -- .../renderer/glsl_source/lightMapping_fp.glsl | 4 +- src/engine/renderer/shaders.cpp | 4 - src/engine/renderer/tr_animation.cpp | 269 ---- src/engine/renderer/tr_backend.cpp | 554 +-------- src/engine/renderer/tr_cmds.cpp | 20 +- src/engine/renderer/tr_fbo.cpp | 3 +- src/engine/renderer/tr_image.cpp | 33 - src/engine/renderer/tr_init.cpp | 26 - src/engine/renderer/tr_light.cpp | 1103 ----------------- src/engine/renderer/tr_local.h | 169 +-- src/engine/renderer/tr_main.cpp | 244 ---- src/engine/renderer/tr_mesh.cpp | 108 -- src/engine/renderer/tr_scene.cpp | 29 - src/engine/renderer/tr_shade.cpp | 635 +--------- src/engine/renderer/tr_shade_calc.cpp | 28 +- src/engine/renderer/tr_shader.cpp | 135 +- src/engine/renderer/tr_types.h | 2 +- src/engine/renderer/tr_vbo.cpp | 12 - src/engine/renderer/tr_world.cpp | 265 ---- 32 files changed, 58 insertions(+), 4392 deletions(-) delete mode 100644 pkg/daemon_src.dpkdir/lights/mkintsquarelight1a.png delete mode 100644 pkg/daemon_src.dpkdir/lights/mkintsquarelight1b.png delete mode 100644 pkg/daemon_src.dpkdir/lights/round.png delete mode 100644 pkg/daemon_src.dpkdir/lights/squarelight1.png delete mode 100644 src/engine/renderer/glsl_source/forwardLighting_fp.glsl delete mode 100644 src/engine/renderer/glsl_source/forwardLighting_vp.glsl diff --git a/pkg/daemon_src.dpkdir/lights/mkintsquarelight1a.png b/pkg/daemon_src.dpkdir/lights/mkintsquarelight1a.png deleted file mode 100644 index 7953eb440e0cd0376643a2c4ba3aa33f639af97d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1169 zcmV;C1aA9@P)_0!DjwTvjNE(3X#A$0d(9I2M?q5Ir2iU<0$dF7ZQI8Y9KPNTvGu`BGG9I9+c7K z3swk4YSYJ~te!WZc{voh$LK5JN3c^$%(ayVq+X=<;675@P8|!DJeTF`n*VfS2C9zh zFcfU)|9^6>A7&VaC#cD0p@}WYX}ouiBv-9yalraVx^2x6z`g>CNszJALvk$gMMc0W zo3H{DVJ)su%wN&?K`=$0-H)Jfr4Eq4T<|^R z`sUAzKznqNRy;FEmGk*tpY`F-4jiZ;fFPhwD1^D~i;5}H8ii>;@XR>Te$FD8M(Crr zQ33D@!@fu=S)hurZHE4^drMC|RvFm=O^J*AFV^S2h5!Wb7x<>o=mp1P6VYOqO%hZ9 zsj{FiDcz~+FuY#KSLrdtClQ+^PZG+d!op+qS`ePsw@G)opAlbz7u%(O$FI*PjLMpr zOmn8fMcfW(@K=ZIycYUE2Vui-K;K*H96ge(>2n^e?qOehobTrTD1+O?-pmBV%`?sF z_PhfcEfBB)g&YaD6r8i=w8y}#0tI59O|)P$i{hAPVM)Kv#uvwtpdB$B30`r$Y3!yB zj+4F^3-k3^H3~rC+$$;2bLDo|N=vmwSOvDll5tN)81hYrBjdpMP#B;%i&Y0PSR$m| z0HtG71K^f1UjMGhRSBIFh2xm<-M~Qr*XT}QPUDZx;9d7Gg{Y31kT?BbFX37Iy2ew@ z`16M%?mkcUC+6&$P%OTQ>;84OvzA%2u+Zgo+Y!s=r#!nj0ouh1`r?mGuqcU>@oOO? z(Hd$Bj`f87V>8rrjeFFTj6f83+>=d)osROlJnZYvH9b#Koa=@c?Qi?K}iJ1OvBgtSh5n!PLu#Q*YNs0VS5>CfT4X5VEB+zR3Lx1%!Gf5JS{ jcQOigY*DY_M+@{Hyc^%Hj*1bK00000NkvXXu0mjfgl<8c diff --git a/pkg/daemon_src.dpkdir/lights/mkintsquarelight1b.png b/pkg/daemon_src.dpkdir/lights/mkintsquarelight1b.png deleted file mode 100644 index 489da8bd9e16faf2b04acb983ea3f58ffc213f11..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1057 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 VyQgu=#=L8A^2AxQGE>*c{{w}oyRiTO diff --git a/pkg/daemon_src.dpkdir/lights/squarelight1.png b/pkg/daemon_src.dpkdir/lights/squarelight1.png deleted file mode 100644 index e7b68341063adb577cff194f2df0aa344c3d5b67..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8415 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 W>PcV5Zdw80zra;NEAK29W&A&$YTLO0 diff --git a/pkg/daemon_src.dpkdir/scripts/engine.shader b/pkg/daemon_src.dpkdir/scripts/engine.shader index 57b77ef51..35c98039e 100644 --- a/pkg/daemon_src.dpkdir/scripts/engine.shader +++ b/pkg/daemon_src.dpkdir/scripts/engine.shader @@ -28,46 +28,3 @@ gfx/2d/bigchars rgbgen vertex } } - -lights/defaultDynamicLight -{ - { - stage attenuationMapZ - map lights/mkintsquarelight1a - edgeClamp - } - { - stage attenuationMapXY - forceHighQuality - map lights/round - colored - zeroClamp - } -} - -lights/defaultPointLight -{ - // this will also be the falloff for any - // point light shaders that don't specify one - lightFalloffImage lights/mkintsquarelight1a - { - stage attenuationMapXY - forceHighQuality - map lights/squarelight1 - colored - zeroClamp - } -} - -lights/defaultProjectedLight -{ - // by default, stay bright almost all the way to the end - lightFalloffImage lights/mkintsquarelight1b - { - stage attenuationMapXY - forceHighQuality - map lights/squarelight1 - colored - zeroClamp - } -} diff --git a/src.cmake b/src.cmake index 8cdef74b8..24d7d227a 100644 --- a/src.cmake +++ b/src.cmake @@ -185,8 +185,6 @@ set(GLSLSOURCELIST # Regular shaders ${ENGINE_DIR}/renderer/glsl_source/fogQuake3_vp.glsl ${ENGINE_DIR}/renderer/glsl_source/fogQuake3_fp.glsl - ${ENGINE_DIR}/renderer/glsl_source/forwardLighting_vp.glsl - ${ENGINE_DIR}/renderer/glsl_source/forwardLighting_fp.glsl ${ENGINE_DIR}/renderer/glsl_source/generic_vp.glsl ${ENGINE_DIR}/renderer/glsl_source/generic_fp.glsl ${ENGINE_DIR}/renderer/glsl_source/heatHaze_vp.glsl diff --git a/src/engine/qcommon/q_shared.h b/src/engine/qcommon/q_shared.h index 24bde5953..8ade82d37 100644 --- a/src/engine/qcommon/q_shared.h +++ b/src/engine/qcommon/q_shared.h @@ -1899,6 +1899,7 @@ inline vec_t VectorNormalize2( const vec3_t v, vec3_t out ) using GameStateCSs = std::array; +// TODO(0.56): NUKE all #define REF_FORCE_DLIGHT ( 1 << 31 ) // RF, passed in through overdraw parameter, force this dlight under all conditions #define REF_JUNIOR_DLIGHT ( 1 << 30 ) // (SA) this dlight does not light surfaces. it only affects dynamic light grid #define REF_DIRECTED_DLIGHT ( 1 << 29 ) // ydnar: global directional light, origin should be interpreted as a normal vector diff --git a/src/engine/renderer/Material.cpp b/src/engine/renderer/Material.cpp index 0e20486a2..b90e4fc1a 100644 --- a/src/engine/renderer/Material.cpp +++ b/src/engine/renderer/Material.cpp @@ -808,11 +808,9 @@ void BindShaderLightMapping( Material* material ) { gl_lightMappingShaderMaterial->SetUniformBlock_Lights( tr.dlightUBO ); // bind u_LightTiles - if ( r_realtimeLightingRenderer.Get() == Util::ordinal( realtimeLightingRenderer_t::TILED ) ) { - gl_lightMappingShaderMaterial->SetUniform_LightTilesBindless( - GL_BindToTMU( BIND_LIGHTTILES, tr.lighttileRenderImage ) - ); - } + gl_lightMappingShaderMaterial->SetUniform_LightTilesBindless( + GL_BindToTMU( BIND_LIGHTTILES, tr.lighttileRenderImage ) + ); } gl_lightMappingShaderMaterial->SetUniform_ViewOrigin( backEnd.orientation.viewOrigin ); @@ -1439,9 +1437,7 @@ void MaterialSystem::AddStageTextures( MaterialSurface* surface, shader_t* shade surface->texDataDynamic[stage] = dynamic; if ( glConfig2.realtimeLighting ) { - if ( r_realtimeLightingRenderer.Get() == Util::ordinal( realtimeLightingRenderer_t::TILED ) ) { - material->AddTexture( tr.lighttileRenderImage->texture ); - } + material->AddTexture( tr.lighttileRenderImage->texture ); } } diff --git a/src/engine/renderer/gl_shader.cpp b/src/engine/renderer/gl_shader.cpp index 9f812bf2c..e482edd41 100644 --- a/src/engine/renderer/gl_shader.cpp +++ b/src/engine/renderer/gl_shader.cpp @@ -64,9 +64,6 @@ GLShader_generic *gl_genericShader = nullptr; GLShader_genericMaterial *gl_genericShaderMaterial = nullptr; GLShader_lightMapping *gl_lightMappingShader = nullptr; GLShader_lightMappingMaterial *gl_lightMappingShaderMaterial = nullptr; -GLShader_forwardLighting_omniXYZ *gl_forwardLightingShader_omniXYZ = nullptr; -GLShader_forwardLighting_projXYZ *gl_forwardLightingShader_projXYZ = nullptr; -GLShader_forwardLighting_directionalSun *gl_forwardLightingShader_directionalSun = nullptr; GLShader_fogQuake3 *gl_fogQuake3Shader = nullptr; GLShader_fogQuake3Material *gl_fogQuake3ShaderMaterial = nullptr; GLShader_heatHaze *gl_heatHazeShader = nullptr; @@ -686,7 +683,6 @@ static std::string GenEngineConstants() { if ( glConfig2.realtimeLighting ) { AddDefine( str, "r_realtimeLighting", 1 ); - AddDefine( str, "r_realtimeLightingRenderer", r_realtimeLightingRenderer.Get() ); } if ( r_showNormalMaps->integer ) @@ -2553,160 +2549,6 @@ void GLShader_lightMappingMaterial::SetShaderProgramUniforms( ShaderProgramDescr } } -GLShader_forwardLighting_omniXYZ::GLShader_forwardLighting_omniXYZ(): - GLShader( "forwardLighting_omniXYZ", ATTR_POSITION | ATTR_TEXCOORD | ATTR_QTANGENT, - false, "forwardLighting", "forwardLighting" ), - u_DiffuseMap( this ), - u_NormalMap( this ), - u_MaterialMap( this ), - u_AttenuationMapXY( this ), - u_AttenuationMapZ( this ), - u_RandomMap( this ), - u_HeightMap( this ), - u_TextureMatrix( this ), - u_SpecularExponent( this ), - u_AlphaThreshold( this ), - u_ColorModulateColorGen_Float( this ), - u_ColorModulateColorGen_Uint( this ), - u_Color_Float( this ), - u_Color_Uint( this ), - u_ViewOrigin( this ), - u_LightOrigin( this ), - u_LightColor( this ), - u_LightRadius( this ), - u_LightScale( this ), - u_LightAttenuationMatrix( this ), - u_ModelMatrix( this ), - u_ModelViewProjectionMatrix( this ), - u_Bones( this ), - u_VertexInterpolation( this ), - u_ReliefDepthScale( this ), - u_ReliefOffsetBias( this ), - u_NormalScale( this ), - GLDeformStage( this ), - GLCompileMacro_USE_VERTEX_SKINNING( this ), - GLCompileMacro_USE_VERTEX_ANIMATION( this ), - GLCompileMacro_USE_HEIGHTMAP_IN_NORMALMAP( this ), - GLCompileMacro_USE_RELIEF_MAPPING( this ) -{ -} - -void GLShader_forwardLighting_omniXYZ::SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) -{ - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_DiffuseMap" ), 0 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_NormalMap" ), 1 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_MaterialMap" ), 2 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_AttenuationMapXY" ), 3 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_AttenuationMapZ" ), 4 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_RandomMap" ), 6 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_HeightMap" ), 15 ); -} - -GLShader_forwardLighting_projXYZ::GLShader_forwardLighting_projXYZ(): - GLShader( "forwardLighting_projXYZ", ATTR_POSITION | ATTR_TEXCOORD | ATTR_QTANGENT, - false, "forwardLighting", "forwardLighting" ), - u_DiffuseMap( this ), - u_NormalMap( this ), - u_MaterialMap( this ), - u_AttenuationMapXY( this ), - u_AttenuationMapZ( this ), - u_RandomMap( this ), - u_HeightMap( this ), - u_TextureMatrix( this ), - u_SpecularExponent( this ), - u_AlphaThreshold( this ), - u_ColorModulateColorGen_Float( this ), - u_ColorModulateColorGen_Uint( this ), - u_Color_Float( this ), - u_Color_Uint( this ), - u_ViewOrigin( this ), - u_LightOrigin( this ), - u_LightColor( this ), - u_LightRadius( this ), - u_LightScale( this ), - u_LightAttenuationMatrix( this ), - u_ModelMatrix( this ), - u_ModelViewProjectionMatrix( this ), - u_Bones( this ), - u_VertexInterpolation( this ), - u_ReliefDepthScale( this ), - u_ReliefOffsetBias( this ), - u_NormalScale( this ), - GLDeformStage( this ), - GLCompileMacro_USE_VERTEX_SKINNING( this ), - GLCompileMacro_USE_VERTEX_ANIMATION( this ), - GLCompileMacro_USE_HEIGHTMAP_IN_NORMALMAP( this ), - GLCompileMacro_USE_RELIEF_MAPPING( this ) -{ -} - -void GLShader_forwardLighting_projXYZ::BuildShaderCompileMacros( std::string& compileMacros ) -{ - compileMacros += "LIGHT_PROJ "; -} - -void GLShader_forwardLighting_projXYZ::SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) -{ - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_DiffuseMap" ), 0 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_NormalMap" ), 1 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_MaterialMap" ), 2 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_AttenuationMapXY" ), 3 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_AttenuationMapZ" ), 4 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_RandomMap" ), 6 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_HeightMap" ), 15 ); -} - -GLShader_forwardLighting_directionalSun::GLShader_forwardLighting_directionalSun(): - GLShader( "forwardLighting_directionalSun", ATTR_POSITION | ATTR_TEXCOORD | ATTR_QTANGENT, - false, "forwardLighting", "forwardLighting" ), - u_DiffuseMap( this ), - u_NormalMap( this ), - u_MaterialMap( this ), - u_HeightMap( this ), - u_TextureMatrix( this ), - u_SpecularExponent( this ), - u_AlphaThreshold( this ), - u_ColorModulateColorGen_Float( this ), - u_ColorModulateColorGen_Uint( this ), - u_Color_Float( this ), - u_Color_Uint( this ), - u_ViewOrigin( this ), - u_LightDir( this ), - u_LightColor( this ), - u_LightRadius( this ), - u_LightScale( this ), - u_LightAttenuationMatrix( this ), - u_ModelMatrix( this ), - u_ViewMatrix( this ), - u_ModelViewProjectionMatrix( this ), - u_Bones( this ), - u_VertexInterpolation( this ), - u_ReliefDepthScale( this ), - u_ReliefOffsetBias( this ), - u_NormalScale( this ), - GLDeformStage( this ), - GLCompileMacro_USE_VERTEX_SKINNING( this ), - GLCompileMacro_USE_VERTEX_ANIMATION( this ), - GLCompileMacro_USE_HEIGHTMAP_IN_NORMALMAP( this ), - GLCompileMacro_USE_RELIEF_MAPPING( this ) -{ -} - -void GLShader_forwardLighting_directionalSun::BuildShaderCompileMacros( std::string& compileMacros ) -{ - compileMacros += "LIGHT_DIRECTIONAL "; -} - -void GLShader_forwardLighting_directionalSun::SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) -{ - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_DiffuseMap" ), 0 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_NormalMap" ), 1 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_MaterialMap" ), 2 ); - //glUniform1i(glGetUniformLocation( shaderProgram->id, "u_AttenuationMapXY" ), 3); - //glUniform1i(glGetUniformLocation( shaderProgram->id, "u_AttenuationMapZ" ), 4); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_HeightMap" ), 15 ); -} - GLShader_reflection::GLShader_reflection(): GLShader( "reflection", ATTR_POSITION | ATTR_TEXCOORD | ATTR_QTANGENT, false, "reflection_CB", "reflection_CB" ), diff --git a/src/engine/renderer/gl_shader.h b/src/engine/renderer/gl_shader.h index fc0aa7d94..16fe16165 100644 --- a/src/engine/renderer/gl_shader.h +++ b/src/engine/renderer/gl_shader.h @@ -2201,22 +2201,6 @@ class u_GlowMap : } }; -class u_RandomMap : - GLUniformSampler2D { - public: - u_RandomMap( GLShader* shader ) : - GLUniformSampler2D( shader, "u_RandomMap" ) { - } - - void SetUniform_RandomMapBindless( GLuint64 bindlessHandle ) { - this->SetValueBindless( bindlessHandle ); - } - - GLint GetUniformLocation_RandomMap() { - return this->GetLocation(); - } -}; - class u_PortalMap : GLUniformSampler2D { public: @@ -2361,38 +2345,6 @@ class u_CurrentMap : } }; -class u_AttenuationMapXY : - GLUniformSampler2D { - public: - u_AttenuationMapXY( GLShader* shader ) : - GLUniformSampler2D( shader, "u_AttenuationMapXY" ) { - } - - void SetUniform_AttenuationMapXYBindless( GLuint64 bindlessHandle ) { - this->SetValueBindless( bindlessHandle ); - } - - GLint GetUniformLocation_AttenuationMapXY() { - return this->GetLocation(); - } -}; - -class u_AttenuationMapZ : - GLUniformSampler2D { - public: - u_AttenuationMapZ( GLShader* shader ) : - GLUniformSampler2D( shader, "u_AttenuationMapZ" ) { - } - - void SetUniform_AttenuationMapZBindless( GLuint64 bindlessHandle ) { - this->SetValueBindless( bindlessHandle ); - } - - GLint GetUniformLocation_AttenuationMapZ() { - return this->GetLocation(); - } -}; - class u_TextureMatrix : GLUniformMatrix32f { @@ -2490,111 +2442,6 @@ class u_ViewOrigin : } }; -class u_LightDir : - GLUniform3f -{ -public: - u_LightDir( GLShader *shader ) : - GLUniform3f( shader, "u_LightDir" ) - { - } - - void SetUniform_LightDir( const vec3_t v ) - { - this->SetValue( v ); - } -}; - -class u_LightOrigin : - GLUniform3f -{ -public: - u_LightOrigin( GLShader *shader ) : - GLUniform3f( shader, "u_LightOrigin" ) - { - } - - void SetUniform_LightOrigin( const vec3_t v ) - { - this->SetValue( v ); - } -}; - -class u_LightColor : - GLUniform3f -{ -public: - u_LightColor( GLShader *shader ) : - GLUniform3f( shader, "u_LightColor" ) - { - } - - void SetUniform_LightColor( const vec3_t v ) - { - this->SetValue( v ); - } -}; - -class u_LightRadius : - GLUniform1f -{ -public: - u_LightRadius( GLShader *shader ) : - GLUniform1f( shader, "u_LightRadius" ) - { - } - - void SetUniform_LightRadius( float value ) - { - this->SetValue( value ); - } -}; - -class u_LightScale : - GLUniform1f -{ -public: - u_LightScale( GLShader *shader ) : - GLUniform1f( shader, "u_LightScale" ) - { - } - - void SetUniform_LightScale( float value ) - { - this->SetValue( value ); - } -}; - -class u_LightAttenuationMatrix : - GLUniformMatrix4f -{ -public: - u_LightAttenuationMatrix( GLShader *shader ) : - GLUniformMatrix4f( shader, "u_LightAttenuationMatrix" ) - { - } - - void SetUniform_LightAttenuationMatrix( const matrix_t m ) - { - this->SetValue( GL_FALSE, m ); - } -}; - -class u_LightFrustum : - GLUniform4fv -{ -public: - u_LightFrustum( GLShader *shader ) : - GLUniform4fv( shader, "u_LightFrustum", 6 ) - { - } - - void SetUniform_LightFrustum( vec4_t lightFrustum[ 6 ] ) - { - this->SetValue( 6, lightFrustum ); - } -}; - class u_RefractionIndex : GLUniform1f { @@ -3919,126 +3766,6 @@ class GLShader_lightMappingMaterial : void SetShaderProgramUniforms( ShaderProgramDescriptor* shaderProgram ) override; }; -class GLShader_forwardLighting_omniXYZ : - public GLShader, - public u_DiffuseMap, - public u_NormalMap, - public u_MaterialMap, - public u_AttenuationMapXY, - public u_AttenuationMapZ, - public u_RandomMap, - public u_HeightMap, - public u_TextureMatrix, - public u_SpecularExponent, - public u_AlphaThreshold, - public u_ColorModulateColorGen_Float, - public u_ColorModulateColorGen_Uint, - public u_Color_Float, - public u_Color_Uint, - public u_ViewOrigin, - public u_LightOrigin, - public u_LightColor, - public u_LightRadius, - public u_LightScale, - public u_LightAttenuationMatrix, - public u_ModelMatrix, - public u_ModelViewProjectionMatrix, - public u_Bones, - public u_VertexInterpolation, - public u_ReliefDepthScale, - public u_ReliefOffsetBias, - public u_NormalScale, - public GLDeformStage, - public GLCompileMacro_USE_VERTEX_SKINNING, - public GLCompileMacro_USE_VERTEX_ANIMATION, - public GLCompileMacro_USE_HEIGHTMAP_IN_NORMALMAP, - public GLCompileMacro_USE_RELIEF_MAPPING -{ -public: - GLShader_forwardLighting_omniXYZ(); - void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; -}; - -class GLShader_forwardLighting_projXYZ : - public GLShader, - public u_DiffuseMap, - public u_NormalMap, - public u_MaterialMap, - public u_AttenuationMapXY, - public u_AttenuationMapZ, - public u_RandomMap, - public u_HeightMap, - public u_TextureMatrix, - public u_SpecularExponent, - public u_AlphaThreshold, - public u_ColorModulateColorGen_Float, - public u_ColorModulateColorGen_Uint, - public u_Color_Float, - public u_Color_Uint, - public u_ViewOrigin, - public u_LightOrigin, - public u_LightColor, - public u_LightRadius, - public u_LightScale, - public u_LightAttenuationMatrix, - public u_ModelMatrix, - public u_ModelViewProjectionMatrix, - public u_Bones, - public u_VertexInterpolation, - public u_ReliefDepthScale, - public u_ReliefOffsetBias, - public u_NormalScale, - public GLDeformStage, - public GLCompileMacro_USE_VERTEX_SKINNING, - public GLCompileMacro_USE_VERTEX_ANIMATION, - public GLCompileMacro_USE_HEIGHTMAP_IN_NORMALMAP, - public GLCompileMacro_USE_RELIEF_MAPPING -{ -public: - GLShader_forwardLighting_projXYZ(); - void BuildShaderCompileMacros( std::string& compileMacros ) override; - void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; -}; - -class GLShader_forwardLighting_directionalSun : - public GLShader, - public u_DiffuseMap, - public u_NormalMap, - public u_MaterialMap, - public u_HeightMap, - public u_TextureMatrix, - public u_SpecularExponent, - public u_AlphaThreshold, - public u_ColorModulateColorGen_Float, - public u_ColorModulateColorGen_Uint, - public u_Color_Float, - public u_Color_Uint, - public u_ViewOrigin, - public u_LightDir, - public u_LightColor, - public u_LightRadius, - public u_LightScale, - public u_LightAttenuationMatrix, - public u_ModelMatrix, - public u_ViewMatrix, - public u_ModelViewProjectionMatrix, - public u_Bones, - public u_VertexInterpolation, - public u_ReliefDepthScale, - public u_ReliefOffsetBias, - public u_NormalScale, - public GLDeformStage, - public GLCompileMacro_USE_VERTEX_SKINNING, - public GLCompileMacro_USE_VERTEX_ANIMATION, - public GLCompileMacro_USE_HEIGHTMAP_IN_NORMALMAP, - public GLCompileMacro_USE_RELIEF_MAPPING -{ -public: - GLShader_forwardLighting_directionalSun(); - void BuildShaderCompileMacros( std::string& compileMacros ) override; - void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; -}; - class GLShader_reflection : public GLShader, public u_ColorMapCube, @@ -4481,9 +4208,6 @@ extern GLShader_generic *gl_genericShader; extern GLShader_genericMaterial *gl_genericShaderMaterial; extern GLShader_lightMapping *gl_lightMappingShader; extern GLShader_lightMappingMaterial *gl_lightMappingShaderMaterial; -extern GLShader_forwardLighting_omniXYZ *gl_forwardLightingShader_omniXYZ; -extern GLShader_forwardLighting_projXYZ *gl_forwardLightingShader_projXYZ; -extern GLShader_forwardLighting_directionalSun *gl_forwardLightingShader_directionalSun; extern GLShader_fogQuake3 *gl_fogQuake3Shader; extern GLShader_fogQuake3Material *gl_fogQuake3ShaderMaterial; extern GLShader_heatHaze *gl_heatHazeShader; diff --git a/src/engine/renderer/glsl_source/computeLight_fp.glsl b/src/engine/renderer/glsl_source/computeLight_fp.glsl index 514fe4b27..a84acbd8f 100644 --- a/src/engine/renderer/glsl_source/computeLight_fp.glsl +++ b/src/engine/renderer/glsl_source/computeLight_fp.glsl @@ -70,7 +70,7 @@ vec4 EnvironmentalSpecularFactor( vec3 viewDir, vec3 normal ) #endif #endif -#if defined(USE_DELUXE_MAPPING) || defined(USE_GRID_DELUXE_MAPPING) || (defined(r_realtimeLighting) && r_realtimeLightingRenderer == 1) +#if defined(USE_DELUXE_MAPPING) || defined(USE_GRID_DELUXE_MAPPING) || defined(r_realtimeLighting) void computeDeluxeLight( vec3 lightDir, vec3 normal, vec3 viewDir, vec3 lightColor, vec4 diffuseColor, vec4 materialColor, inout vec4 color ) @@ -134,7 +134,7 @@ void computeDeluxeLight( vec3 lightDir, vec3 normal, vec3 viewDir, vec3 lightCol #endif // r_specularMapping #endif // !USE_PHYSICAL_MAPPING } -#endif // defined(USE_DELUXE_MAPPING) || defined(USE_GRID_DELUXE_MAPPING) || (defined(r_realtimeLighting) && r_realtimeLightingRenderer == 1) +#endif // defined(USE_DELUXE_MAPPING) || defined(USE_GRID_DELUXE_MAPPING) defined(r_realtimeLighting) #if !defined(USE_DELUXE_MAPPING) && !defined(USE_GRID_DELUXE_MAPPING) void computeLight( in vec3 lightColor, vec4 diffuseColor, inout vec4 color ) { @@ -142,7 +142,7 @@ void computeDeluxeLight( vec3 lightDir, vec3 normal, vec3 viewDir, vec3 lightCol } #endif // !defined(USE_DELUXE_MAPPING) && !defined(USE_GRID_DELUXE_MAPPING) -#if defined(r_realtimeLighting) && r_realtimeLightingRenderer == 1 +#if defined(r_realtimeLighting) struct Light { vec3 center; @@ -253,4 +253,4 @@ void computeDynamicLights( vec3 P, vec3 normal, vec3 viewDir, vec4 diffuse, vec4 #endif } -#endif // defined(r_realtimeLighting) && r_realtimeLightingRenderer == 1 +#endif // defined(r_realtimeLighting) diff --git a/src/engine/renderer/glsl_source/forwardLighting_fp.glsl b/src/engine/renderer/glsl_source/forwardLighting_fp.glsl deleted file mode 100644 index 21f0a19cf..000000000 --- a/src/engine/renderer/glsl_source/forwardLighting_fp.glsl +++ /dev/null @@ -1,215 +0,0 @@ -/* -=========================================================================== -Copyright (C) 2007-2011 Robert Beckebans - -This file is part of XreaL source code. - -XreaL source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -XreaL source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with XreaL source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -/* forwardLighting_fp.glsl */ - -// computeSpecularity is the only thing used from this file -#insert computeLight_fp - -#insert reliefMapping_fp - -/* swizzle one- and two-component textures to RG */ -#if defined(HAVE_ARB_texture_rg) -# define SWIZ1 r -# define SWIZ2 rg -#else -# define SWIZ1 a -# define SWIZ2 ar -#endif - -uniform sampler2D u_DiffuseMap; -uniform sampler2D u_MaterialMap; -uniform sampler2D u_AttenuationMapXY; -uniform sampler2D u_AttenuationMapZ; - -uniform sampler2D u_RandomMap; // random normals - -uniform vec3 u_ViewOrigin; - -#if defined(LIGHT_DIRECTIONAL) -uniform vec3 u_LightDir; -#else -uniform vec3 u_LightOrigin; -#endif -uniform vec3 u_LightColor; -uniform float u_LightRadius; -uniform float u_LightScale; -uniform float u_AlphaThreshold; - -uniform mat4 u_ViewMatrix; - -IN(smooth) vec3 var_Position; -IN(smooth) vec2 var_TexCoords; -IN(smooth) vec4 var_TexAttenuation; -IN(smooth) vec4 var_Tangent; -IN(smooth) vec4 var_Binormal; -IN(smooth) vec4 var_Normal; -IN(smooth) vec4 var_Color; - -DECLARE_OUTPUT(vec4) - -float Rand(vec2 co) -{ - return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); -} - -vec3 RandomVec3(vec2 uv) -{ - vec3 dir; - -#if 1 - float r = Rand(uv); - float angle = 2.0 * M_PI * r;// / 360.0; - - dir = normalize(vec3(cos(angle), sin(angle), r)); -#else - // dir = texture2D(u_NoiseMap, gl_FragCoord.st / r_FBufSize).rgb; - dir = normalize(2.0 * (texture2D(u_RandomMap, uv).xyz - 0.5)); -#endif - - return dir; -} - -/* -float log_conv(float x0, float X, float y0, float Y) -{ - return (X + log(x0 + (y0 * exp(Y - X)))); -} -*/ - -void main() -{ -#if 0 - // create random noise vector - vec3 rand = RandomVec3(gl_FragCoord.st / r_FBufSize); - - outputColor = vec4(rand * 0.5 + 0.5, 1.0); - return; -#endif - - // compute light direction in world space -#if defined(LIGHT_DIRECTIONAL) - vec3 lightDir = u_LightDir; -#else - vec3 lightDir = normalize(u_LightOrigin - var_Position); -#endif - - vec2 texCoords = var_TexCoords; - - mat3 tangentToWorldMatrix = mat3(var_Tangent.xyz, var_Binormal.xyz, var_Normal.xyz); - - // compute view direction in world space - vec3 viewDir = normalize(u_ViewOrigin - var_Position.xyz); - -#if defined(USE_RELIEF_MAPPING) - // compute texcoords offset from heightmap - #if defined(USE_HEIGHTMAP_IN_NORMALMAP) - vec2 texOffset = ReliefTexOffset(texCoords, viewDir, tangentToWorldMatrix, u_NormalMap); - #else - vec2 texOffset = ReliefTexOffset(texCoords, viewDir, tangentToWorldMatrix, u_HeightMap); - #endif - - texCoords += texOffset; -#endif // USE_RELIEF_MAPPING - - // compute half angle in world space - vec3 H = normalize(lightDir + viewDir); - - // compute normal in world space from normal map - vec3 normal = NormalInWorldSpace(texCoords, tangentToWorldMatrix, u_NormalMap); - - // compute the light term - float NL = clamp(dot(normal, lightDir), 0.0, 1.0); - - // compute the diffuse term - vec4 diffuse = texture2D(u_DiffuseMap, texCoords); - if( abs(diffuse.a + u_AlphaThreshold) <= 1.0 ) - { - discard; - return; - } - diffuse.rgb *= u_LightColor * NL; - -#if !defined(USE_PHYSICAL_MAPPING) -#if defined(r_specularMapping) - // compute the specular term - vec4 materialColor = texture2D(u_MaterialMap, texCoords); - float NdotH = clamp(dot(normal, H), 0.0, 1.0); - vec3 specular = computeSpecularity(u_LightColor, materialColor, NdotH); -#endif // r_specularMapping -#endif // !USE_PHYSICAL_MAPPING - - // compute light attenuation -#if defined(LIGHT_PROJ) - vec3 attenuationXY = texture2DProj(u_AttenuationMapXY, var_TexAttenuation.xyw).rgb; - vec3 attenuationZ = texture2D(u_AttenuationMapZ, vec2(var_TexAttenuation.z + 0.5, 0.0)).rgb; // FIXME - -#elif defined(LIGHT_DIRECTIONAL) - vec3 attenuationXY = vec3(1.0); - vec3 attenuationZ = vec3(1.0); - -#else - vec3 attenuationXY = texture2D(u_AttenuationMapXY, var_TexAttenuation.xy).rgb; - vec3 attenuationZ = texture2D(u_AttenuationMapZ, vec2(var_TexAttenuation.z, 0)).rgb; -#endif - - // compute final color - vec4 color = diffuse; - -#if !defined(USE_PHYSICAL_MAPPING) -#if defined(r_specularMapping) - color.rgb += specular; -#endif // r_specularMapping -#endif // !USE_PHYSICAL_MAPPING - -#if !defined(LIGHT_DIRECTIONAL) - color.rgb *= attenuationXY; - color.rgb *= attenuationZ; -#endif - color.rgb *= abs(u_LightScale); - - color.rgb *= var_Color.rgb; - - if( u_LightScale < 0.0 ) { - color.rgb = vec3( clamp(dot(color.rgb, vec3( 0.3333 ) ), 0.3, 0.7 ) ); - } - - outputColor = color; - -#if 0 -#if defined(USE_RELIEF_MAPPING) - outputColor = vec4(vec3(1.0, 0.0, 0.0), diffuse.a); -#else - outputColor = vec4(vec3(0.0, 0.0, 1.0), diffuse.a); -#endif -#endif - -#if 0 -#if defined(USE_VERTEX_SKINNING) - outputColor = vec4(vec3(1.0, 0.0, 0.0), diffuse.a); -#elif defined(USE_VERTEX_ANIMATION) - outputColor = vec4(vec3(0.0, 0.0, 1.0), diffuse.a); -#else - outputColor = vec4(vec3(0.0, 1.0, 0.0), diffuse.a); -#endif -#endif -} diff --git a/src/engine/renderer/glsl_source/forwardLighting_vp.glsl b/src/engine/renderer/glsl_source/forwardLighting_vp.glsl deleted file mode 100644 index dfaaf9be8..000000000 --- a/src/engine/renderer/glsl_source/forwardLighting_vp.glsl +++ /dev/null @@ -1,92 +0,0 @@ -/* -=========================================================================== -Copyright (C) 2006-2011 Robert Beckebans - -This file is part of XreaL source code. - -XreaL source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -XreaL source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with XreaL source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -/* forwardLighting_vp.glsl */ - -#insert common -#insert vertexSimple_vp -#insert vertexSkinning_vp -#insert vertexAnimation_vp - -uniform mat3x2 u_TextureMatrix; -uniform mat4 u_LightAttenuationMatrix; -uniform mat4 u_ModelMatrix; -uniform mat4 u_ModelViewProjectionMatrix; - -uniform colorModulatePack u_ColorModulateColorGen; -uniform colorPack u_Color; - -uniform float u_Time; - -OUT(smooth) vec3 var_Position; -OUT(smooth) vec2 var_TexCoords; - -OUT(smooth) vec4 var_TexAttenuation; - -OUT(smooth) vec4 var_Tangent; -OUT(smooth) vec4 var_Binormal; -OUT(smooth) vec4 var_Normal; - -OUT(smooth) vec4 var_Color; - -void DeformVertex( inout vec4 pos, - inout vec3 normal, - inout vec2 st, - inout vec4 color, - in float time); - -void main() -{ - vec4 position; - localBasis LB; - vec2 texCoord, lmCoord; - vec4 color; - - VertexFetch( position, LB, color, texCoord, lmCoord); - - // assign color - ColorModulateColor( u_ColorModulateColorGen, u_Color, color ); - - DeformVertex( position, - LB.normal, - texCoord.st, - color, - u_Time); - - // transform vertex position into homogenous clip-space - gl_Position = u_ModelViewProjectionMatrix * position; - - // transform position into world space - var_Position = (u_ModelMatrix * position).xyz; - - var_Tangent.xyz = mat3(u_ModelMatrix) * LB.tangent; - var_Binormal.xyz = mat3(u_ModelMatrix) * LB.binormal; - var_Normal.xyz = mat3(u_ModelMatrix) * LB.normal; - - // calc light xy,z attenuation in light space - var_TexAttenuation = u_LightAttenuationMatrix * position; - - // transform diffusemap texcoords - var_TexCoords = (u_TextureMatrix * vec3(texCoord, 1.0)).st; - - var_Color = color; -} diff --git a/src/engine/renderer/glsl_source/lightMapping_fp.glsl b/src/engine/renderer/glsl_source/lightMapping_fp.glsl index 1652e12b3..fee293836 100644 --- a/src/engine/renderer/glsl_source/lightMapping_fp.glsl +++ b/src/engine/renderer/glsl_source/lightMapping_fp.glsl @@ -119,7 +119,7 @@ void main() #if defined(r_specularMapping) || defined(r_physicalMapping) // Compute the material term. vec4 material = texture2D(u_MaterialMap, texCoords); - #elif ( defined(r_realtimeLighting) && r_realtimeLightingRenderer == 1 )\ + #elif defined(r_realtimeLighting) \ || defined( USE_DELUXE_MAPPING ) || defined(USE_GRID_DELUXE_MAPPING ) // The computeDynamicLights function requires this variable to exist. vec4 material = vec4( 0.0, 0.0, 0.0, 1.0 ); @@ -200,7 +200,7 @@ void main() #endif // Blend dynamic lights. - #if defined(r_realtimeLighting) && r_realtimeLightingRenderer == 1 + #if defined(r_realtimeLighting) computeDynamicLights(var_Position, normal, viewDir, diffuse, material, color, u_LightTiles); #endif diff --git a/src/engine/renderer/shaders.cpp b/src/engine/renderer/shaders.cpp index eab116bcd..d3cb0e622 100644 --- a/src/engine/renderer/shaders.cpp +++ b/src/engine/renderer/shaders.cpp @@ -39,8 +39,6 @@ #include "fogQuake3_vp.glsl.h" #include "fogQuake3_fp.glsl.h" -#include "forwardLighting_vp.glsl.h" -#include "forwardLighting_fp.glsl.h" #include "generic_vp.glsl.h" #include "generic_fp.glsl.h" #include "heatHaze_vp.glsl.h" @@ -103,8 +101,6 @@ std::unordered_map shadermap({ // Regular shaders { "fogQuake3_vp.glsl", std::string( reinterpret_cast< const char* >( fogQuake3_vp_glsl ), sizeof( fogQuake3_vp_glsl ) ) }, { "fogQuake3_fp.glsl", std::string( reinterpret_cast< const char* >( fogQuake3_fp_glsl ), sizeof( fogQuake3_fp_glsl ) ) }, - { "forwardLighting_vp.glsl", std::string( reinterpret_cast< const char* >( forwardLighting_vp_glsl ), sizeof( forwardLighting_vp_glsl ) ) }, - { "forwardLighting_fp.glsl", std::string( reinterpret_cast< const char* >( forwardLighting_fp_glsl ), sizeof( forwardLighting_fp_glsl ) ) }, { "generic_vp.glsl", std::string( reinterpret_cast< const char* >( generic_vp_glsl ), sizeof( generic_vp_glsl ) ) }, { "generic_fp.glsl", std::string( reinterpret_cast< const char* >( generic_fp_glsl ), sizeof( generic_fp_glsl ) ) }, { "heatHaze_vp.glsl", std::string( reinterpret_cast< const char* >( heatHaze_vp_glsl ), sizeof( heatHaze_vp_glsl ) ) }, diff --git a/src/engine/renderer/tr_animation.cpp b/src/engine/renderer/tr_animation.cpp index b77469b72..bd2853909 100644 --- a/src/engine/renderer/tr_animation.cpp +++ b/src/engine/renderer/tr_animation.cpp @@ -792,275 +792,6 @@ void R_AddMD5Surfaces( trRefEntity_t *ent ) } } -/* -================= -R_AddIQMInteractions -================= -*/ -void R_AddIQMInteractions( trRefEntity_t *ent, trRefLight_t *light, interactionType_t iaType ) -{ - int i; - IQModel_t *model; - srfIQModel_t *surface; - shader_t *shader = nullptr; - bool personalModel; - byte cubeSideBits = CUBESIDE_CLIPALL; - - // cull the entire model if merged bounding box of both frames - // is outside the view frustum and we don't care about proper shadowing - if ( ent->cull == cullResult_t::CULL_OUT ) - { - iaType = (interactionType_t) (iaType & ~IA_LIGHT); - - if( !iaType ) { - return; - } - } - - // don't add third_person objects if not in a portal - personalModel = ( ent->e.renderfx & RF_THIRD_PERSON ) && - tr.viewParms.portalLevel == 0; - - model = tr.currentModel->iqm; - - // do a quick AABB cull - if ( !BoundsIntersect( light->worldBounds[ 0 ], light->worldBounds[ 1 ], ent->worldBounds[ 0 ], ent->worldBounds[ 1 ] ) ) - { - tr.pc.c_dlightSurfacesCulled += model->num_surfaces; - return; - } - - // do a more expensive and precise light frustum cull - if ( !r_noLightFrustums->integer ) - { - if ( R_CullLightWorldBounds( light, ent->worldBounds ) == cullResult_t::CULL_OUT ) - { - tr.pc.c_dlightSurfacesCulled += model->num_surfaces; - return; - } - } - - cubeSideBits = R_CalcLightCubeSideBits( light, ent->worldBounds ); - - // generate interactions with all surfaces - for ( i = 0, surface = model->surfaces; i < model->num_surfaces; i++, surface++ ) - { - if ( ent->e.customShader ) - { - shader = R_GetShaderByHandle( ent->e.customShader ); - } - else if ( ent->e.customSkin > 0 && ent->e.customSkin < tr.numSkins ) - { - skin_t *skin; - - skin = R_GetSkinByHandle( ent->e.customSkin ); - - // match the surface name to something in the skin file - shader = tr.defaultShader; - - // FIXME: replace MD3_MAX_SURFACES for skin_t::surfaces - if ( i >= 0 && i < skin->numSurfaces && skin->surfaces[ i ] ) - { - shader = skin->surfaces[ i ]->shader; - } - - if ( shader == tr.defaultShader ) - { - Log::Warn("no shader for surface %i in skin %s", i, skin->name ); - } - else if ( shader->defaultShader ) - { - Log::Warn("shader %s in skin %s not found", shader->name, skin->name ); - } - } - else - { - shader = R_GetShaderByHandle( surface->shader->index ); - } - - // skip all surfaces that don't matter for lighting only pass - if ( shader->isSky || !shader->interactLight ) - { - continue; - } - - // we will add shadows even if the main object isn't visible in the view - - // don't add third_person objects if not viewing through a portal - if ( !personalModel ) - { - R_AddLightInteraction( light, ( surfaceType_t * ) surface, shader, cubeSideBits, iaType ); - tr.pc.c_dlightSurfaces++; - } - } -} - -/* -================= -R_AddMD5Interactions -================= -*/ -void R_AddMD5Interactions( trRefEntity_t *ent, trRefLight_t *light, interactionType_t iaType ) -{ - md5Model_t *model; - md5Surface_t *surface; - bool personalModel; - byte cubeSideBits = CUBESIDE_CLIPALL; - - // cull the entire model if merged bounding box of both frames - // is outside the view frustum and we don't care about proper shadowing - if ( ent->cull == cullResult_t::CULL_OUT ) - { - iaType = Util::enum_cast(iaType & ~IA_LIGHT); - } - - if( !iaType ) - { - return; - } - - // don't add third_person objects if not in a portal - personalModel = ( ent->e.renderfx & RF_THIRD_PERSON ) && - tr.viewParms.portalLevel == 0; - - model = tr.currentModel->md5; - - // do a quick AABB cull - if ( !BoundsIntersect( light->worldBounds[ 0 ], light->worldBounds[ 1 ], ent->worldBounds[ 0 ], ent->worldBounds[ 1 ] ) ) - { - tr.pc.c_dlightSurfacesCulled += model->numSurfaces; - return; - } - - // do a more expensive and precise light frustum cull - if ( !r_noLightFrustums->integer ) - { - if ( R_CullLightWorldBounds( light, ent->worldBounds ) == cullResult_t::CULL_OUT ) - { - tr.pc.c_dlightSurfacesCulled += model->numSurfaces; - return; - } - } - - cubeSideBits = R_CalcLightCubeSideBits( light, ent->worldBounds ); - - if ( !r_vboModels.Get() || !model->numVBOSurfaces || - ( !glConfig2.vboVertexSkinningAvailable && ent->e.skeleton.type == refSkeletonType_t::SK_ABSOLUTE ) ) - { - shader_t *shader = nullptr; - - // generate interactions with all surfaces - int i; - for ( i = 0, surface = model->surfaces; i < model->numSurfaces; i++, surface++ ) - { - if ( ent->e.customShader ) - { - shader = R_GetShaderByHandle( ent->e.customShader ); - } - else if ( ent->e.customSkin > 0 && ent->e.customSkin < tr.numSkins ) - { - skin_t *skin; - - skin = R_GetSkinByHandle( ent->e.customSkin ); - - // match the surface name to something in the skin file - shader = tr.defaultShader; - - // FIXME: replace MD3_MAX_SURFACES for skin_t::surfaces - if ( i >= 0 && i < skin->numSurfaces && skin->surfaces[ i ] ) - { - shader = skin->surfaces[ i ]->shader; - } - - if ( shader == tr.defaultShader ) - { - Log::Warn("no shader for surface %i in skin %s", i, skin->name ); - } - else if ( shader->defaultShader ) - { - Log::Warn("shader %s in skin %s not found", shader->name, skin->name ); - } - } - else - { - shader = R_GetShaderByHandle( surface->shaderIndex ); - } - - // skip all surfaces that don't matter for lighting only pass - if ( shader->isSky || !shader->interactLight ) - { - continue; - } - - // we will add shadows even if the main object isn't visible in the view - - // don't add third_person objects if not viewing through a portal - if ( !personalModel ) - { - R_AddLightInteraction( light, (surfaceType_t*) surface, shader, cubeSideBits, iaType ); - tr.pc.c_dlightSurfaces++; - } - } - } - else - { - int i; - srfVBOMD5Mesh_t *vboSurface; - shader_t *shader; - - for ( i = 0; i < model->numVBOSurfaces; i++ ) - { - vboSurface = model->vboSurfaces[ i ]; - - if ( ent->e.customShader ) - { - shader = R_GetShaderByHandle( ent->e.customShader ); - } - else if ( ent->e.customSkin > 0 && ent->e.customSkin < tr.numSkins ) - { - skin_t *skin; - - skin = R_GetSkinByHandle( ent->e.customSkin ); - - // match the surface name to something in the skin file - shader = tr.defaultShader; - - // FIXME: replace MD3_MAX_SURFACES for skin_t::surfaces - if ( i >= 0 && i < skin->numSurfaces && skin->surfaces[ i ] ) - { - shader = skin->surfaces[ i ]->shader; - } - - if ( shader == tr.defaultShader ) - { - Log::Warn("no shader for surface %i in skin %s", i, skin->name ); - } - else if ( shader->defaultShader ) - { - Log::Warn("shader %s in skin %s not found", shader->name, skin->name ); - } - } - else - { - shader = vboSurface->shader; - } - - // skip all surfaces that don't matter for lighting only pass - if ( shader->isSky || !shader->interactLight ) - { - continue; - } - - // don't add third_person objects if not viewing through a portal - if ( !personalModel ) - { - R_AddLightInteraction( light, (surfaceType_t*) vboSurface, shader, cubeSideBits, iaType ); - tr.pc.c_dlightSurfaces++; - } - } - } -} - /* ============== IQMCheckSkeleton diff --git a/src/engine/renderer/tr_backend.cpp b/src/engine/renderer/tr_backend.cpp index 10be006b8..a5bec27ba 100644 --- a/src/engine/renderer/tr_backend.cpp +++ b/src/engine/renderer/tr_backend.cpp @@ -847,7 +847,6 @@ static void RB_RenderDrawSurfaces( shaderSort_t fromSort, shaderSort_t toSort, oldFogNum = -1; oldDepthRange = false; depthRange = false; - backEnd.currentLight = nullptr; lastSurf = backEnd.viewParms.firstDrawSurf[ Util::ordinal(toSort) + 1 ]; for ( i = backEnd.viewParms.firstDrawSurf[ Util::ordinal(fromSort) ]; i < lastSurf; i++ ) @@ -967,245 +966,6 @@ static void RB_RenderDrawSurfaces( shaderSort_t fromSort, shaderSort_t toSort, GL_CheckErrors(); } -static interaction_t *IterateLights( const interaction_t *prev ) -{ - if ( !prev && backEnd.viewParms.numInteractions > 0 ) - { - return backEnd.viewParms.interactions; - } - - if ( backEnd.viewParms.numInteractions <= 0 ) - { - return nullptr; - } - - const interaction_t *next = prev; - const interaction_t *last = &backEnd.viewParms.interactions[ backEnd.viewParms.numInteractions - 1 ]; - - while ( next <= last && next->light == prev->light ) - { - next++; - } - - if ( next > last ) - { - next = nullptr; - } - - return ( interaction_t * ) next; -} - -static void RB_SetupLightAttenuationForEntity( trRefLight_t *light, const trRefEntity_t *entity ) -{ - matrix_t modelToLight; - - // transform light origin into model space for u_LightOrigin parameter - if ( entity != &tr.worldEntity ) - { - vec3_t tmp; - VectorSubtract( light->origin, backEnd.orientation.origin, tmp ); - light->transformed[ 0 ] = DotProduct( tmp, backEnd.orientation.axis[ 0 ] ); - light->transformed[ 1 ] = DotProduct( tmp, backEnd.orientation.axis[ 1 ] ); - light->transformed[ 2 ] = DotProduct( tmp, backEnd.orientation.axis[ 2 ] ); - } - else - { - VectorCopy( light->origin, light->transformed ); - } - - MatrixMultiply( light->viewMatrix, backEnd.orientation.transformMatrix, modelToLight ); - - // build the attenuation matrix using the entity transform - switch ( light->l.rlType ) - { - case refLightType_t::RL_OMNI: - { - MatrixSetupTranslation( light->attenuationMatrix, 0.5, 0.5, 0.5 ); // bias - MatrixMultiplyScale( light->attenuationMatrix, 0.5, 0.5, 0.5 ); // scale - MatrixMultiply2( light->attenuationMatrix, light->projectionMatrix ); - MatrixMultiply2( light->attenuationMatrix, modelToLight ); - break; - } - - case refLightType_t::RL_PROJ: - { - MatrixSetupTranslation( light->attenuationMatrix, 0.5, 0.5, 0.0 ); // bias - MatrixMultiplyScale( light->attenuationMatrix, 0.5f, 0.5f, 1.0f / std::min( light->falloffLength, 1.0f ) ); // scale - MatrixMultiply2( light->attenuationMatrix, light->projectionMatrix ); - MatrixMultiply2( light->attenuationMatrix, modelToLight ); - break; - } - - case refLightType_t::RL_DIRECTIONAL: - { - MatrixSetupTranslation( light->attenuationMatrix, 0.5, 0.5, 0.5 ); // bias - MatrixMultiplyScale( light->attenuationMatrix, 0.5, 0.5, 0.5 ); // scale - MatrixMultiply2( light->attenuationMatrix, light->projectionMatrix ); - MatrixMultiply2( light->attenuationMatrix, modelToLight ); - break; - } - - case refLightType_t::RL_MAX_REF_LIGHT_TYPE: - { - //Nothing for right now... - break; - } - } -} - -/* -================= -RB_RenderInteractions -================= -*/ -static void RB_RenderInteractions() -{ - shader_t *shader, *oldShader; - trRefEntity_t *entity, *oldEntity; - trRefLight_t *light; - const interaction_t *ia; - const interaction_t *iaFirst; - bool depthRange, oldDepthRange; - surfaceType_t *surface; - int startTime = 0, endTime = 0; - - GLIMP_LOGCOMMENT( "--- RB_RenderInteractions ---" ); - - if ( r_speeds->integer == Util::ordinal(renderSpeeds_t::RSPEEDS_SHADING_TIMES)) - { - glFinish(); - startTime = ri.Milliseconds(); - } - - // draw everything - oldEntity = nullptr; - oldShader = nullptr; - oldDepthRange = false; - depthRange = false; - iaFirst = nullptr; - - // render interactions - while ( ( iaFirst = IterateLights( iaFirst ) ) ) - { - backEnd.currentLight = light = iaFirst->light; - - // set light scissor to reduce fillrate - GL_Scissor( iaFirst->scissorX, iaFirst->scissorY, iaFirst->scissorWidth, iaFirst->scissorHeight ); - - for ( ia = iaFirst; ia; ia = ia->next ) - { - backEnd.currentEntity = entity = ia->entity; - surface = ia->surface; - shader = ia->shader; - - if ( !shader || !shader->interactLight ) - { - // skip this interaction because the surface shader has no ability to interact with light - // this will save texcoords and matrix calculations - continue; - } - - if ( !(ia->type & IA_LIGHT) ) - { - // skip this interaction because the interaction is meant for shadowing only - continue; - } - - GLIMP_LOGCOMMENT( "----- Rendering new light -----" ); - - // Tr3B: this should never happen in the first iteration - if ( entity == oldEntity && shader == oldShader ) - { - // fast path, same as previous - rb_surfaceTable[Util::ordinal(*surface)](surface ); - continue; - } - - // draw the contents of the last shader batch - Tess_End(); - - // begin a new batch - Tess_Begin( Tess_StageIteratorLighting, shader, light->shader, false, -1, 0 ); - - // change the modelview matrix if needed - if ( entity != oldEntity ) - { - depthRange = false; - - if ( entity != &tr.worldEntity ) - { - // set up the transformation matrix - R_RotateEntityForViewParms( backEnd.currentEntity, &backEnd.viewParms, &backEnd.orientation ); - - if ( backEnd.currentEntity->e.renderfx & RF_DEPTHHACK ) - { - // hack the depth range to prevent view model from poking into walls - depthRange = true; - } - } - else - { - backEnd.orientation = backEnd.viewParms.world; - } - - GL_LoadModelViewMatrix( backEnd.orientation.modelViewMatrix ); - - // change depthrange if needed - if ( oldDepthRange != depthRange ) - { - if ( depthRange ) - { - glDepthRange( 0, 0.3 ); - } - else - { - glDepthRange( 0, 1 ); - } - - oldDepthRange = depthRange; - } - - RB_SetupLightAttenuationForEntity( light, entity ); - } - - // add the triangles for this surface - rb_surfaceTable[Util::ordinal(*surface)](surface ); - oldEntity = entity; - oldShader = shader; - } - - // draw the contents of the last shader batch - Tess_End(); - - // force updates - oldEntity = nullptr; - oldShader = nullptr; - } - - Tess_End(); - - // go back to the world modelview matrix - GL_LoadModelViewMatrix( backEnd.viewParms.world.modelViewMatrix ); - - if ( depthRange ) - { - glDepthRange( 0, 1 ); - } - - // reset scissor - GL_Scissor( backEnd.viewParms.scissorX, backEnd.viewParms.scissorY, - backEnd.viewParms.scissorWidth, backEnd.viewParms.scissorHeight ); - - GL_CheckErrors(); - - if ( r_speeds->integer == Util::ordinal(renderSpeeds_t::RSPEEDS_SHADING_TIMES) ) - { - glFinish(); - endTime = ri.Milliseconds(); - backEnd.pc.c_forwardLightingTime += endTime - startTime; - } -} - /* ============= RB_RunVisTests @@ -1341,30 +1101,6 @@ void RB_RenderPostDepthLightTile() return; } - if ( r_realtimeLightingRenderer.Get() != Util::ordinal( realtimeLightingRenderer_t::TILED ) ) - { - /* Do not run lightTile code when the tiled renderer is not used. - - This computation is part of the tiled dynamic lighting renderer, - it's better to not run it and save CPU cycles when such effects - are disabled. - - Disabling this code also make possible to not compile the related - GLSL shaders at all when such effects are disabled. - - Not running the related GLSL shaders also helps older hardware to - run the game, for example the Radeon R300 Arithmetic Logic Unit is - too small to run the related GLSL code even if the shader itself - can be compiled. Such GPU are so old and slow that any kind of - dynamic lighting including the tiled implementation is expected to - be disabled anyway. Saving CPU cycles when a feature is not used is - welcome in any case. - - See https://github.com/DaemonEngine/Daemon/issues/344 */ - - return; - } - if ( !backEnd.refdef.numLights ) { return; } @@ -1827,208 +1563,6 @@ static void RB_RenderDebugUtils() { GLIMP_LOGCOMMENT( "--- RB_RenderDebugUtils ---" ); - if ( r_showLightTransforms->integer ) - { - const interaction_t *ia; - trRefLight_t *light; - vec3_t forward, left, up; - - static const vec3_t minSize = { -2, -2, -2 }; - static const vec3_t maxSize = { 2, 2, 2 }; - - gl_genericShader->SetVertexSkinning( false ); - gl_genericShader->SetVertexAnimation( false ); - gl_genericShader->SetTCGenEnvironment( false ); - gl_genericShader->SetTCGenLightmap( false ); - gl_genericShader->SetDepthFade( false ); - gl_genericShader->BindProgram( 0 ); - - GL_State( GLS_POLYMODE_LINE | GLS_DEPTHTEST_DISABLE ); - GL_Cull( cullType_t::CT_TWO_SIDED ); - - // set uniforms - gl_genericShader->SetUniform_AlphaTest( GLS_ATEST_NONE ); - SetUniform_ColorModulateColorGen( gl_genericShader, colorGen_t::CGEN_CUSTOM_RGB, alphaGen_t::AGEN_CUSTOM ); - - // bind u_ColorMap - gl_genericShader->SetUniform_ColorMapBindless( - GL_BindToTMU( 0, tr.whiteImage ) - ); - gl_genericShader->SetUniform_TextureMatrix( matrixIdentity ); - - ia = nullptr; - Color::Color lightColor; - while ( ( ia = IterateLights( ia ) ) ) - { - backEnd.currentLight = light = ia->light; - - lightColor = Color::Blue; - lightColor.SetAlpha( 0.2 ); - - SetUniform_Color( gl_genericShader, lightColor ); - - MatrixToVectorsFLU( matrixIdentity, forward, left, up ); - VectorMA( vec3_origin, 16, forward, forward ); - VectorMA( vec3_origin, 16, left, left ); - VectorMA( vec3_origin, 16, up, up ); - - Tess_Begin( Tess_StageIteratorDebug, nullptr, nullptr, true, -1, 0 ); - - { - // set up the transformation matrix - R_RotateLightForViewParms( light, &backEnd.viewParms, &backEnd.orientation ); - - GL_LoadModelViewMatrix( backEnd.orientation.modelViewMatrix ); - gl_genericShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); - gl_genericShader->SetUniform_ModelMatrix( backEnd.orientation.transformMatrix ); - - R_TessLight( light, lightColor ); - - switch ( light->l.rlType ) - { - case refLightType_t::RL_OMNI: - case refLightType_t::RL_DIRECTIONAL: - { - if ( !VectorCompare( light->l.center, vec3_origin ) ) - { - Tess_AddCube( light->l.center, minSize, maxSize, Color::Yellow ); - } - break; - } - - case refLightType_t::RL_PROJ: - { - // draw light_target - Tess_AddCube( light->l.projTarget, minSize, maxSize, Color::Red ); - Tess_AddCube( light->l.projRight, minSize, maxSize, Color::Green ); - Tess_AddCube( light->l.projUp, minSize, maxSize, Color::Blue ); - - if ( !VectorCompare( light->l.projStart, vec3_origin ) ) - { - Tess_AddCube( light->l.projStart, minSize, maxSize, Color::Yellow ); - } - - if ( !VectorCompare( light->l.projEnd, vec3_origin ) ) - { - Tess_AddCube( light->l.projEnd, minSize, maxSize, Color::Magenta ); - } - break; - } - - default: - break; - } - } - - Tess_End(); - } - - // go back to the world modelview matrix - backEnd.orientation = backEnd.viewParms.world; - GL_LoadModelViewMatrix( backEnd.viewParms.world.modelViewMatrix ); - } - - if ( r_showLightInteractions->integer ) - { - interaction_t *ia; - int iaCount; - trRefLight_t *light; - trRefEntity_t *entity; - surfaceType_t *surface; - Color::Color lightColor; - - static const vec3_t mins = { -1, -1, -1 }; - static const vec3_t maxs = { 1, 1, 1 }; - - gl_genericShader->SetVertexSkinning( false ); - gl_genericShader->SetVertexAnimation( false ); - gl_genericShader->SetTCGenEnvironment( false ); - gl_genericShader->SetTCGenLightmap( false ); - gl_genericShader->SetDepthFade( false ); - gl_genericShader->BindProgram( 0 ); - - GL_State( GLS_POLYMODE_LINE | GLS_DEPTHTEST_DISABLE ); - GL_Cull( cullType_t::CT_TWO_SIDED ); - - // set uniforms - gl_genericShader->SetUniform_AlphaTest( GLS_ATEST_NONE ); - SetUniform_ColorModulateColorGen( gl_genericShader, colorGen_t::CGEN_VERTEX, alphaGen_t::AGEN_VERTEX ); - SetUniform_Color( gl_genericShader, Color::Black ); - - // bind u_ColorMap - gl_genericShader->SetUniform_ColorMapBindless( - GL_BindToTMU( 0, tr.whiteImage ) - ); - gl_genericShader->SetUniform_TextureMatrix( matrixIdentity ); - - for ( iaCount = 0, ia = &backEnd.viewParms.interactions[ 0 ]; iaCount < backEnd.viewParms.numInteractions; ia++, iaCount++ ) - { - backEnd.currentEntity = entity = ia->entity; - light = ia->light; - surface = ia->surface; - - if ( entity != &tr.worldEntity ) - { - // set up the transformation matrix - R_RotateEntityForViewParms( backEnd.currentEntity, &backEnd.viewParms, &backEnd.orientation ); - } - else - { - backEnd.orientation = backEnd.viewParms.world; - } - - GL_LoadModelViewMatrix( backEnd.orientation.modelViewMatrix ); - gl_genericShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); - - lightColor = Color::White; - - Tess_Begin( Tess_StageIteratorDebug, nullptr, nullptr, true, -1, 0 ); - - if ( *surface == surfaceType_t::SF_FACE || *surface == surfaceType_t::SF_GRID || *surface == surfaceType_t::SF_TRIANGLES ) - { - srfGeneric_t *gen; - - gen = ( srfGeneric_t * ) surface; - - if ( *surface == surfaceType_t::SF_FACE ) - { - lightColor = Color::MdGrey; - } - else if ( *surface == surfaceType_t::SF_GRID ) - { - lightColor = Color::Cyan; - } - else if ( *surface == surfaceType_t::SF_TRIANGLES ) - { - lightColor = Color::Magenta; - } - else - { - lightColor = Color::MdGrey; - } - - Tess_AddCube( vec3_origin, gen->bounds[ 0 ], gen->bounds[ 1 ], lightColor ); - - Tess_AddCube( gen->origin, mins, maxs, Color::White ); - } - else if ( *surface == surfaceType_t::SF_VBO_MESH ) - { - srfVBOMesh_t *srf = ( srfVBOMesh_t * ) surface; - Tess_AddCube( vec3_origin, srf->bounds[ 0 ], srf->bounds[ 1 ], lightColor ); - } - else if ( *surface == surfaceType_t::SF_MDV ) - { - Tess_AddCube( vec3_origin, entity->localBounds[ 0 ], entity->localBounds[ 1 ], lightColor ); - } - - Tess_End(); - } - - // go back to the world modelview matrix - backEnd.orientation = backEnd.viewParms.world; - GL_LoadModelViewMatrix( backEnd.viewParms.world.modelViewMatrix ); - } - if ( r_showEntityTransforms->integer ) { trRefEntity_t *ent; @@ -2309,72 +1843,6 @@ static void RB_RenderDebugUtils() } } - if ( r_showLightScissors->integer ) - { - interaction_t *ia; - int iaCount; - matrix_t ortho; - - gl_genericShader->SetVertexSkinning( false ); - gl_genericShader->SetVertexAnimation( false ); - gl_genericShader->SetTCGenEnvironment( false ); - gl_genericShader->SetTCGenLightmap( false ); - gl_genericShader->SetDepthFade( false ); - gl_genericShader->BindProgram( 0 ); - - GL_State( GLS_POLYMODE_LINE | GLS_DEPTHTEST_DISABLE ); - GL_Cull( cullType_t::CT_TWO_SIDED ); - - // set uniforms - gl_genericShader->SetUniform_AlphaTest( GLS_ATEST_NONE ); - SetUniform_ColorModulateColorGen( gl_genericShader, colorGen_t::CGEN_CUSTOM_RGB, alphaGen_t::AGEN_CUSTOM ); - - // bind u_ColorMap - gl_genericShader->SetUniform_ColorMapBindless( - GL_BindToTMU( 0, tr.whiteImage ) - ); - gl_genericShader->SetUniform_TextureMatrix( matrixIdentity ); - - // set 2D virtual screen size - GL_PushMatrix(); - MatrixOrthogonalProjection( ortho, backEnd.viewParms.viewportX, - backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth, - backEnd.viewParms.viewportY, - backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight, -99999, 99999 ); - GL_LoadProjectionMatrix( ortho ); - - for ( iaCount = 0, ia = &backEnd.viewParms.interactions[ 0 ]; iaCount < backEnd.viewParms.numInteractions; ) - { - SetUniform_Color( gl_genericShader, Color::White ); - - Tess_InstantQuad( *gl_genericShader, - ia->scissorX, ia->scissorY, ia->scissorWidth - 1.0f, ia->scissorHeight - 1.0f ); - - if ( !ia->next ) - { - if ( iaCount < ( backEnd.viewParms.numInteractions - 1 ) ) - { - // jump to next interaction and continue - ia++; - iaCount++; - } - else - { - // increase last time to leave for loop - iaCount++; - } - } - else - { - // just continue - ia = ia->next; - iaCount++; - } - } - - GL_PopMatrix(); - } - // GLSL shader isn't built when reflection mapping is disabled. if ( r_showCubeProbes.Get() && glConfig2.reflectionMapping && !( backEnd.refdef.rdflags & ( RDF_NOWORLDMODEL | RDF_NOCUBEMAP ) ) ) @@ -3019,10 +2487,8 @@ RB_RenderView */ static void RB_RenderView( bool depthPass ) { - int startTime = 0, endTime = 0; - - GLIMP_LOGCOMMENT( "--- RB_RenderView( %i surfaces, %i interactions ) ---", - backEnd.viewParms.numDrawSurfs, backEnd.viewParms.numInteractions ); + GLIMP_LOGCOMMENT( "--- RB_RenderView( %i surfaces ) ---", + backEnd.viewParms.numDrawSurfs ); GL_CheckErrors(); @@ -3057,12 +2523,6 @@ static void RB_RenderView( bool depthPass ) GL_CheckErrors(); - if ( r_speeds->integer == Util::ordinal(renderSpeeds_t::RSPEEDS_SHADING_TIMES) ) - { - glFinish(); - startTime = ri.Milliseconds(); - } - if( depthPass ) { if ( glConfig2.usingMaterialSystem ) { materialSystem.RenderMaterials( shaderSort_t::SS_DEPTH, shaderSort_t::SS_DEPTH, backEnd.viewParms.viewID ); @@ -3102,16 +2562,6 @@ static void RB_RenderView( bool depthPass ) RB_RenderSSAO(); - if ( r_speeds->integer == Util::ordinal(renderSpeeds_t::RSPEEDS_SHADING_TIMES) ) - { - glFinish(); - endTime = ri.Milliseconds(); - backEnd.pc.c_forwardAmbientTime += endTime - startTime; - } - - // render dynamic lighting - RB_RenderInteractions(); - // render global fog post process effect RB_RenderGlobalFog(); diff --git a/src/engine/renderer/tr_cmds.cpp b/src/engine/renderer/tr_cmds.cpp index 8003c9622..ab9d8a937 100644 --- a/src/engine/renderer/tr_cmds.cpp +++ b/src/engine/renderer/tr_cmds.cpp @@ -46,12 +46,6 @@ void R_PerformanceCounters() backEnd.pc.c_views, backEnd.pc.c_portals, backEnd.pc.c_batches, backEnd.pc.c_surfaces, tr.pc.c_leafs, backEnd.pc.c_vertexes, backEnd.pc.c_indexes / 3 ); - Log::Notice("%i lights %i bout %i pvsout %i interactions", - tr.pc.c_dlights, - tr.pc.c_box_cull_light_out, - tr.pc.c_pvs_cull_light_out, - tr.pc.c_dlightInteractions ); - Log::Notice("%i draws %i vbos %i ibos %i verts %i tris", backEnd.pc.c_drawElements, backEnd.pc.c_vboVertexBuffers, backEnd.pc.c_vboIndexBuffers, @@ -79,21 +73,10 @@ void R_PerformanceCounters() { Log::Notice("viewcluster: %i", tr.visClusters[ tr.visIndex ] ); } - else if ( r_speeds->integer == Util::ordinal(renderSpeeds_t::RSPEEDS_LIGHTS )) - { - Log::Notice("dlight srf:%i culled:%i", tr.pc.c_dlightSurfaces, tr.pc.c_dlightSurfacesCulled ); - - Log::Notice("dlights:%i interactions:%i", tr.pc.c_dlights, tr.pc.c_dlightInteractions ); - } else if ( r_speeds->integer == Util::ordinal(renderSpeeds_t::RSPEEDS_FOG )) { Log::Notice("fog srf:%i batches:%i", backEnd.pc.c_fogSurfaces, backEnd.pc.c_fogBatches ); } - else if ( r_speeds->integer == Util::ordinal(renderSpeeds_t::RSPEEDS_SHADING_TIMES )) - { - Log::Notice("forward shading times: ambient:%i lighting:%i", backEnd.pc.c_forwardAmbientTime, - backEnd.pc.c_forwardLightingTime ); - } else if ( r_speeds->integer == Util::ordinal(renderSpeeds_t::RSPEEDS_NEAR_FAR )) { Log::Notice("zNear: %.0f zFar: %.0f", tr.viewParms.zNear, tr.viewParms.zFar ); @@ -240,8 +223,7 @@ R_AddSetupLightsCmd */ void R_AddSetupLightsCmd() { - if ( !glConfig2.realtimeLighting || - r_realtimeLightingRenderer.Get() != Util::ordinal( realtimeLightingRenderer_t::TILED ) ) + if ( !glConfig2.realtimeLighting ) { return; } diff --git a/src/engine/renderer/tr_fbo.cpp b/src/engine/renderer/tr_fbo.cpp index 05a065104..37833e7e4 100644 --- a/src/engine/renderer/tr_fbo.cpp +++ b/src/engine/renderer/tr_fbo.cpp @@ -429,8 +429,7 @@ void R_InitFBOs() R_AttachFBOTexturePackedDepthStencil( tr.currentDepthImage->texnum ); R_CheckFBO( tr.mainFBO[1] ); - if ( glConfig2.realtimeLighting - && r_realtimeLightingRenderer.Get() == Util::ordinal( realtimeLightingRenderer_t::TILED ) ) + if ( glConfig2.realtimeLighting ) { /* It's only required to create frame buffers only used by the tiled dynamic lighting renderer when this feature is enabled. */ diff --git a/src/engine/renderer/tr_image.cpp b/src/engine/renderer/tr_image.cpp index 2ef92e11b..5a694da0c 100644 --- a/src/engine/renderer/tr_image.cpp +++ b/src/engine/renderer/tr_image.cpp @@ -2514,22 +2514,6 @@ static void R_CreateRandomNormalsImage() tr.randomNormalsImage = R_CreateImage( "_randomNormals", ( const byte ** ) &dataPtr, DEFAULT_SIZE, DEFAULT_SIZE, 1, imageParams ); } -static void R_CreateNoFalloffImage() -{ - byte data[ DEFAULT_SIZE ][ DEFAULT_SIZE ][ 4 ]; - // we use a solid white image instead of disabling texturing - memset(data, 255, sizeof(data)); - - byte *dataPtr = &data[0][0][0]; - - imageParams_t imageParams = {}; - imageParams.bits = IF_NOPICMIP; - imageParams.filterType = filterType_t::FT_DEFAULT; - imageParams.wrapType = wrapTypeEnum_t::WT_EDGE_CLAMP; - - tr.noFalloffImage = R_CreateImage( "_noFalloff", ( const byte ** ) &dataPtr, 8, 8, 1, imageParams ); -} - static void R_CreateContrastRenderFBOImage() { if ( !glConfig2.bloom) @@ -2624,22 +2608,6 @@ static void R_CreateDepthRenderImage() return; } - if ( r_realtimeLightingRenderer.Get() != Util::ordinal( realtimeLightingRenderer_t::TILED ) ) - { - /* Do not create lightTile images when the tiled renderer is not used. - - Those images are part of the tiled dynamic lighting renderer, - it's better to not create them and save memory when such effects - are disabled. - - Some hardware not powerful enough to supported dynamic lighting may - even not support the related formats. - - See https://github.com/DaemonEngine/Daemon/issues/745 */ - - return; - } - { int width = glConfig.vidWidth; int height = glConfig.vidHeight; @@ -2877,7 +2845,6 @@ void R_CreateBuiltinImages() R_CreateRandomNormalsImage(); R_CreateFogImage(); - R_CreateNoFalloffImage(); R_CreateContrastRenderFBOImage(); R_CreateBloomRenderFBOImages(); R_CreateCurrentRenderImage(); diff --git a/src/engine/renderer/tr_init.cpp b/src/engine/renderer/tr_init.cpp index 5b07a02ca..b1d22dc6e 100644 --- a/src/engine/renderer/tr_init.cpp +++ b/src/engine/renderer/tr_init.cpp @@ -79,14 +79,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA cvar_t *r_nocull; cvar_t *r_facePlaneCull; cvar_t *r_nocurves; - cvar_t *r_lightScissors; - cvar_t *r_noLightVisCull; - cvar_t *r_noInteractionSort; - Cvar::Range> r_realtimeLightingRenderer( "r_realtimeLightingRenderer", - "renderer for real time lights: 0: legacy, 1: tiled", Cvar::NONE, - Util::ordinal(realtimeLightingRenderer_t::TILED), - Util::ordinal(realtimeLightingRenderer_t::LEGACY), - Util::ordinal(realtimeLightingRenderer_t::TILED) ); Cvar::Cvar r_realtimeLighting( "r_realtimeLighting", "Enable realtime light rendering", Cvar::NONE, true ); Cvar::Range> r_realtimeLightLayers( "r_realtimeLightLayers", "Dynamic light layers per tile, each layer holds 16 lights", Cvar::NONE, 4, 1, MAX_REF_LIGHTS / 16 ); @@ -134,8 +126,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Util::ordinal(shadowingMode_t::SHADOWING_NONE), Util::ordinal(shadowingMode_t::SHADOWING_BLOB) ); - cvar_t *r_noLightFrustums; - cvar_t *r_mode; cvar_t *r_nobind; cvar_t *r_singleShader; @@ -238,10 +228,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA cvar_t *r_showSky; cvar_t *r_showSkeleton; cvar_t *r_showEntityTransforms; - cvar_t *r_showLightTransforms; - cvar_t *r_showLightInteractions; - cvar_t *r_showLightScissors; - cvar_t *r_showLightBatches; cvar_t *r_showLightGrid; cvar_t *r_showLightTiles; cvar_t *r_showBatches; @@ -1225,13 +1211,7 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p r_debugSort = Cvar_Get( "r_debugSort", "0", CVAR_CHEAT ); r_nocurves = Cvar_Get( "r_nocurves", "0", CVAR_CHEAT ); - r_lightScissors = Cvar_Get( "r_lightScissors", "1", CVAR_ARCHIVE ); - AssertCvarRange( r_lightScissors, 0, 2, true ); - - r_noLightVisCull = Cvar_Get( "r_noLightVisCull", "0", CVAR_CHEAT ); - r_noInteractionSort = Cvar_Get( "r_noInteractionSort", "0", CVAR_CHEAT ); - Cvar::Latch( r_realtimeLightingRenderer ); Cvar::Latch( r_realtimeLighting ); Cvar::Latch( r_realtimeLightLayers ); Cvar::Latch( r_preferBindlessTextures ); @@ -1287,8 +1267,6 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p Cvar::Latch( r_shadows ); - r_noLightFrustums = Cvar_Get( "r_noLightFrustums", "1", CVAR_CHEAT ); - r_maxPolys = Cvar_Get( "r_maxpolys", "10000", CVAR_LATCH ); // 600 in vanilla Q3A AssertCvarRange( r_maxPolys, 600, 30000, true ); @@ -1299,10 +1277,6 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p r_showSky = Cvar_Get( "r_showSky", "0", CVAR_CHEAT ); r_showSkeleton = Cvar_Get( "r_showSkeleton", "0", CVAR_CHEAT ); r_showEntityTransforms = Cvar_Get( "r_showEntityTransforms", "0", CVAR_CHEAT ); - r_showLightTransforms = Cvar_Get( "r_showLightTransforms", "0", CVAR_CHEAT ); - r_showLightInteractions = Cvar_Get( "r_showLightInteractions", "0", CVAR_CHEAT ); - r_showLightScissors = Cvar_Get( "r_showLightScissors", "0", CVAR_CHEAT ); - r_showLightBatches = Cvar_Get( "r_showLightBatches", "0", CVAR_CHEAT ); r_showLightGrid = Cvar_Get( "r_showLightGrid", "0", CVAR_CHEAT ); r_showLightTiles = Cvar_Get("r_showLightTiles", "0", CVAR_CHEAT | CVAR_LATCH ); r_showBatches = Cvar_Get( "r_showBatches", "0", CVAR_CHEAT ); diff --git a/src/engine/renderer/tr_light.cpp b/src/engine/renderer/tr_light.cpp index df0a4292e..b7e074006 100644 --- a/src/engine/renderer/tr_light.cpp +++ b/src/engine/renderer/tr_light.cpp @@ -23,70 +23,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // tr_light.c #include "tr_local.h" -/* -============= -R_AddBrushModelInteractions - -Determine which dynamic lights may effect this bmodel -============= -*/ -void R_AddBrushModelInteractions( trRefEntity_t *ent, trRefLight_t *light, interactionType_t iaType ) -{ - bspSurface_t *surf; - bspModel_t *bspModel = nullptr; - model_t *pModel = nullptr; - byte cubeSideBits; - - // cull the entire model if it is outside the view frustum - // and we don't care about proper shadowing - if ( ent->cull == cullResult_t::CULL_OUT ) - { - iaType = (interactionType_t) (iaType & ~IA_LIGHT); - } - - if ( !iaType ) - { - return; - } - - pModel = R_GetModelByHandle( ent->e.hModel ); - bspModel = pModel->bsp; - - // do a quick AABB cull - if ( !BoundsIntersect( light->worldBounds[ 0 ], light->worldBounds[ 1 ], ent->worldBounds[ 0 ], ent->worldBounds[ 1 ] ) ) - { - tr.pc.c_dlightSurfacesCulled += bspModel->numSurfaces; - return; - } - - // do a more expensive and precise light frustum cull - if ( !r_noLightFrustums->integer ) - { - if ( R_CullLightWorldBounds( light, ent->worldBounds ) == cullResult_t::CULL_OUT ) - { - tr.pc.c_dlightSurfacesCulled += bspModel->numSurfaces; - return; - } - } - - cubeSideBits = R_CalcLightCubeSideBits( light, ent->worldBounds ); - - // set the light bits in all the surfaces - for (unsigned i = 0; i < bspModel->numSurfaces; i++ ) - { - surf = bspModel->firstSurface + i; - - // skip all surfaces that don't matter for lighting only pass - if ( surf->shader->isSky || !surf->shader->interactLight ) - { - continue; - } - - R_AddLightInteraction( light, surf->data, surf->shader, cubeSideBits, iaType ); - tr.pc.c_dlightSurfaces++; - } -} - /* ============================================================================= @@ -240,1042 +176,3 @@ int R_LightForPoint( vec3_t point, vec3_t ambientLight, vec3_t directedLight, ve return true; } -/* -================= -R_SetupLightOrigin -Tr3B - needs finished transformMatrix -================= -*/ -void R_SetupLightOrigin( trRefLight_t *light ) -{ - vec3_t transformed; - - if ( light->l.rlType == refLightType_t::RL_DIRECTIONAL ) - { - if ( !VectorCompare( light->l.center, vec3_origin ) ) - { - MatrixTransformPoint( light->transformMatrix, light->l.center, transformed ); - VectorSubtract( transformed, light->l.origin, light->direction ); - VectorNormalize( light->direction ); - - VectorMA( light->l.origin, 10000, light->direction, light->origin ); - } - else - { - vec3_t down = { 0, 0, 1 }; - - MatrixTransformPoint( light->transformMatrix, down, transformed ); - VectorSubtract( transformed, light->l.origin, light->direction ); - VectorNormalize( light->direction ); - - VectorMA( light->l.origin, 10000, light->direction, light->origin ); - - VectorCopy( light->l.origin, light->origin ); - } - } - else - { - MatrixTransformPoint( light->transformMatrix, light->l.center, light->origin ); - } -} - -/* -================= -R_SetupLightLocalBounds -================= -*/ -void R_SetupLightLocalBounds( trRefLight_t *light ) -{ - switch ( light->l.rlType ) - { - case refLightType_t::RL_OMNI: - case refLightType_t::RL_DIRECTIONAL: - { - light->localBounds[ 0 ][ 0 ] = -light->l.radius; - light->localBounds[ 0 ][ 1 ] = -light->l.radius; - light->localBounds[ 0 ][ 2 ] = -light->l.radius; - light->localBounds[ 1 ][ 0 ] = light->l.radius; - light->localBounds[ 1 ][ 1 ] = light->l.radius; - light->localBounds[ 1 ][ 2 ] = light->l.radius; - break; - } - - case refLightType_t::RL_PROJ: - { - int j; - vec3_t farCorners[ 4 ]; - - ClearBounds( light->localBounds[ 0 ], light->localBounds[ 1 ] ); - - // transform frustum from world space to local space - R_CalcFrustumFarCorners( light->localFrustum, farCorners ); - - if ( !VectorCompare( light->l.projStart, vec3_origin ) ) - { - vec3_t nearCorners[ 4 ]; - - // calculate the vertices defining the top area - R_CalcFrustumNearCorners( light->localFrustum, nearCorners ); - - for ( j = 0; j < 4; j++ ) - { - AddPointToBounds( farCorners[ j ], light->localBounds[ 0 ], light->localBounds[ 1 ] ); - AddPointToBounds( nearCorners[ j ], light->localBounds[ 0 ], light->localBounds[ 1 ] ); - } - } - else - { - vec3_t top; - const plane_t* frustum = light->localFrustum; - - PlanesGetIntersectionPoint( frustum[ FRUSTUM_LEFT ], frustum[ FRUSTUM_RIGHT ], frustum[ FRUSTUM_TOP ], top ); - AddPointToBounds( top, light->localBounds[ 0 ], light->localBounds[ 1 ] ); - - for ( j = 0; j < 4; j++ ) - { - AddPointToBounds( farCorners[ j ], light->localBounds[ 0 ], light->localBounds[ 1 ] ); - } - } - - break; - } - - default: - break; - } - - light->sphereRadius = RadiusFromBounds( light->localBounds[ 0 ], light->localBounds[ 1 ] ); -} - -/* -================= -R_SetupLightWorldBounds -Tr3B - needs finished transformMatrix -================= -*/ -void R_SetupLightWorldBounds( trRefLight_t *light ) -{ - MatrixTransformBounds(light->transformMatrix, light->localBounds[0], light->localBounds[1], light->worldBounds[0], light->worldBounds[1]); -} - -/* -================= -R_SetupLightView -================= -*/ -void R_SetupLightView( trRefLight_t *light ) -{ - switch ( light->l.rlType ) - { - case refLightType_t::RL_OMNI: - case refLightType_t::RL_PROJ: - case refLightType_t::RL_DIRECTIONAL: - { - MatrixAffineInverse( light->transformMatrix, light->viewMatrix ); - break; - } - default: - Sys::Drop( "R_SetupLightView: Bad rlType" ); - } -} - -void R_TessLight( const trRefLight_t *light, const Color::Color& color, bool use_default_color ) -{ - int j; - - switch( light->l.rlType ) - { - case refLightType_t::RL_OMNI: - case refLightType_t::RL_DIRECTIONAL: - Tess_AddCube( vec3_origin, light->localBounds[ 0 ], light->localBounds[ 1 ], use_default_color ? Color::White : color ); - break; - case refLightType_t::RL_PROJ: - { - vec3_t farCorners[ 4 ]; - vec4_t quadVerts[ 4 ]; - - R_CalcFrustumFarCorners( light->localFrustum, farCorners ); - - if ( !VectorCompare( light->l.projStart, vec3_origin ) ) - { - vec3_t nearCorners[ 4 ]; - - // calculate the vertices defining the top area - R_CalcFrustumNearCorners( light->localFrustum, nearCorners ); - - // draw outer surfaces - for ( j = 0; j < 4; j++ ) - { - Vector4Set( quadVerts[ 0 ], nearCorners[ j ][ 0 ], nearCorners[ j ][ 1 ], nearCorners[ j ][ 2 ], 1 ); - Vector4Set( quadVerts[ 1 ], farCorners[ j ][ 0 ], farCorners[ j ][ 1 ], farCorners[ j ][ 2 ], 1 ); - Vector4Set( quadVerts[ 2 ], farCorners[( j + 1 ) % 4 ][ 0 ], farCorners[( j + 1 ) % 4 ][ 1 ], farCorners[( j + 1 ) % 4 ][ 2 ], 1 ); - Vector4Set( quadVerts[ 3 ], nearCorners[( j + 1 ) % 4 ][ 0 ], nearCorners[( j + 1 ) % 4 ][ 1 ], nearCorners[( j + 1 ) % 4 ][ 2 ], 1 ); - Tess_AddQuadStamp2( quadVerts, use_default_color ? Color::Cyan : color ); - } - - // draw far cap - Vector4Set( quadVerts[ 0 ], farCorners[ 3 ][ 0 ], farCorners[ 3 ][ 1 ], farCorners[ 3 ][ 2 ], 1 ); - Vector4Set( quadVerts[ 1 ], farCorners[ 2 ][ 0 ], farCorners[ 2 ][ 1 ], farCorners[ 2 ][ 2 ], 1 ); - Vector4Set( quadVerts[ 2 ], farCorners[ 1 ][ 0 ], farCorners[ 1 ][ 1 ], farCorners[ 1 ][ 2 ], 1 ); - Vector4Set( quadVerts[ 3 ], farCorners[ 0 ][ 0 ], farCorners[ 0 ][ 1 ], farCorners[ 0 ][ 2 ], 1 ); - Tess_AddQuadStamp2( quadVerts, use_default_color ? Color::Red : color ); - - // draw near cap - Vector4Set( quadVerts[ 0 ], nearCorners[ 0 ][ 0 ], nearCorners[ 0 ][ 1 ], nearCorners[ 0 ][ 2 ], 1 ); - Vector4Set( quadVerts[ 1 ], nearCorners[ 1 ][ 0 ], nearCorners[ 1 ][ 1 ], nearCorners[ 1 ][ 2 ], 1 ); - Vector4Set( quadVerts[ 2 ], nearCorners[ 2 ][ 0 ], nearCorners[ 2 ][ 1 ], nearCorners[ 2 ][ 2 ], 1 ); - Vector4Set( quadVerts[ 3 ], nearCorners[ 3 ][ 0 ], nearCorners[ 3 ][ 1 ], nearCorners[ 3 ][ 2 ], 1 ); - Tess_AddQuadStamp2( quadVerts, use_default_color ? Color::Green : color ); - } - else - { - vec3_t top; - const plane_t* frustum = light->localFrustum; - - // no light_start, just use the top vertex (doesn't need to be mirrored) - PlanesGetIntersectionPoint( frustum[ FRUSTUM_LEFT ], frustum[ FRUSTUM_RIGHT ], frustum[ FRUSTUM_TOP ], top ); - - // draw pyramid - for ( j = 0; j < 4; j++ ) - { - Color::Color32Bit iColor = use_default_color ? Color::Cyan : color; - - VectorCopy( top, tess.verts[ tess.numVertexes ].xyz ); - tess.verts[ tess.numVertexes ].color = iColor; - tess.indexes[ tess.numIndexes++ ] = tess.numVertexes; - tess.numVertexes++; - - VectorCopy( farCorners[( j + 1 ) % 4 ], tess.verts[ tess.numVertexes ].xyz ); - tess.verts[ tess.numVertexes ].color = iColor; - tess.indexes[ tess.numIndexes++ ] = tess.numVertexes; - tess.numVertexes++; - - VectorCopy( farCorners[ j ], tess.verts[ tess.numVertexes ].xyz ); - tess.verts[ tess.numVertexes ].color = iColor; - tess.indexes[ tess.numIndexes++ ] = tess.numVertexes; - tess.numVertexes++; - } - - Vector4Set( quadVerts[ 0 ], farCorners[ 0 ][ 0 ], farCorners[ 0 ][ 1 ], farCorners[ 0 ][ 2 ], 1 ); - Vector4Set( quadVerts[ 1 ], farCorners[ 1 ][ 0 ], farCorners[ 1 ][ 1 ], farCorners[ 1 ][ 2 ], 1 ); - Vector4Set( quadVerts[ 2 ], farCorners[ 2 ][ 0 ], farCorners[ 2 ][ 1 ], farCorners[ 2 ][ 2 ], 1 ); - Vector4Set( quadVerts[ 3 ], farCorners[ 3 ][ 0 ], farCorners[ 3 ][ 1 ], farCorners[ 3 ][ 2 ], 1 ); - Tess_AddQuadStamp2( quadVerts, use_default_color ? Color::Red : color ); - } - } - break; - default: - break; - } -} - -void R_TessLight( const trRefLight_t *light, const Color::Color& color ) -{ - R_TessLight ( light, color, false ); -} - -void R_TessLight( const trRefLight_t *light ) -{ - R_TessLight ( light, Color::Color(), true ); -} - -/* -================= -R_SetupLightFrustum -================= -*/ -void R_SetupLightFrustum( trRefLight_t *light ) -{ - switch ( light->l.rlType ) - { - case refLightType_t::RL_OMNI: - case refLightType_t::RL_DIRECTIONAL: - { - int i; - vec3_t planeNormal; - vec3_t planeOrigin; - axis_t axis; - - QuatToAxis( light->l.rotation, axis ); - - for ( i = 0; i < 3; i++ ) - { - VectorMA( light->l.origin, light->l.radius, axis[ i ], planeOrigin ); - VectorNegate( axis[ i ], planeNormal ); - VectorNormalize( planeNormal ); - - VectorCopy( planeNormal, light->frustum[ i ].normal ); - light->frustum[ i ].dist = DotProduct( planeOrigin, planeNormal ); - } - - for ( i = 0; i < 3; i++ ) - { - VectorMA( light->l.origin, -light->l.radius, axis[ i ], planeOrigin ); - VectorCopy( axis[ i ], planeNormal ); - VectorNormalize( planeNormal ); - - VectorCopy( planeNormal, light->frustum[ i + 3 ].normal ); - light->frustum[ i + 3 ].dist = DotProduct( planeOrigin, planeNormal ); - } - - for ( i = 0; i < 6; i++ ) - { - vec_t length, ilength; - - light->frustum[ i ].type = PLANE_NON_AXIAL; - - // normalize - length = VectorLength( light->frustum[ i ].normal ); - - if ( length ) - { - ilength = 1.0f / length; - light->frustum[ i ].normal[ 0 ] *= ilength; - light->frustum[ i ].normal[ 1 ] *= ilength; - light->frustum[ i ].normal[ 2 ] *= ilength; - light->frustum[ i ].dist *= ilength; - } - - SetPlaneSignbits( &light->frustum[ i ] ); - } - - break; - } - - case refLightType_t::RL_PROJ: - { - int i; - - // transform local frustum to world space - plane_t worldFrustum[ 6 ]; - for ( i = 0; i < 6; i++ ) - { - MatrixTransformPlane( light->transformMatrix, light->localFrustum[ i ], worldFrustum[ i ] ); - } - - // normalize all frustum planes - for ( i = 0; i < 6; i++ ) - { - PlaneNormalize( worldFrustum[ i ] ); - - VectorCopy( worldFrustum[ i ].normal, light->frustum[ i ].normal ); - light->frustum[ i ].dist = worldFrustum[ i ].dist; - - light->frustum[ i ].type = PLANE_NON_AXIAL; - - SetPlaneSignbits( &light->frustum[ i ] ); - } - - break; - } - - default: - break; - } -} - -/* -================= -R_SetupLightProjection -================= -*/ -// *INDENT-OFF* -void R_SetupLightProjection( trRefLight_t *light ) -{ - switch ( light->l.rlType ) - { - case refLightType_t::RL_OMNI: - case refLightType_t::RL_DIRECTIONAL: - { - MatrixSetupScale( light->projectionMatrix, 1.0f / light->l.radius, 1.0f / light->l.radius, 1.0f / light->l.radius ); - break; - } - - case refLightType_t::RL_PROJ: - { - plane_t lightProject[ 4 ]; - - { - vec3_t right, up, normal; - - float rLen = VectorNormalize2( light->l.projRight, right ); - float uLen = VectorNormalize2( light->l.projUp, up ); - - CrossProduct( up, right, normal ); - VectorNormalize( normal ); - - vec_t dist = DotProduct( light->l.projTarget, normal ); - - if ( dist < 0 ) - { - dist = -dist; - VectorInverse( normal ); - } - - VectorScale( right, ( 0.5f * dist ) / rLen, right ); - VectorScale( up, - ( 0.5f * dist ) / uLen, up ); - - PlaneSet( lightProject[ 0 ], right[ 0 ], right[ 1 ], right[ 2 ], 0 ); - PlaneSet( lightProject[ 1 ], up[ 0 ], up[ 1 ], up[ 2 ], 0 ); - PlaneSet( lightProject[ 2 ], normal[ 0 ], normal[ 1 ], normal[ 2 ], 0 ); - } - - // now offset to center - { - vec3_t targetGlobal; - VectorSet( targetGlobal, - light->l.projTarget[ 0 ], light->l.projTarget[ 1 ], - light->l.projTarget[ 2 ] ); - - { - vec_t a = DotProduct( targetGlobal, lightProject[ 0 ].normal ); - vec_t b = DotProduct( targetGlobal, lightProject[ 2 ].normal ); - vec_t ofs = 0.5 - a / b; - - VectorMA( lightProject[ 0 ].normal, ofs, lightProject[ 2 ].normal, lightProject[ 0 ].normal ); - } - - { - vec_t a = DotProduct( targetGlobal, lightProject[ 1 ].normal ); - vec_t b = DotProduct( targetGlobal, lightProject[ 2 ].normal ); - vec_t ofs = 0.5 - a / b; - - VectorMA( lightProject[ 0 ].normal, ofs, lightProject[ 2 ].normal, lightProject[ 0 ].normal ); - } - } - - { - vec3_t start; - - if ( !VectorCompare( light->l.projStart, vec3_origin ) ) - { - VectorCopy( light->l.projStart, start ); - } - else - { - VectorClear( start ); - } - - vec3_t stop; - - if ( !VectorCompare( light->l.projEnd, vec3_origin ) ) - { - VectorCopy( light->l.projEnd, stop ); - } - else - { - VectorCopy( light->l.projTarget, stop ); - } - - // Calculate the falloff vector - vec3_t falloff; - - { - VectorSubtract( stop, start, falloff ); - - vec_t falloffLen = VectorNormalize( falloff ); - light->falloffLength = falloffLen; - - if ( falloffLen <= 0 ) - { - falloffLen = 1; - } - - //FIXME ? - VectorScale( falloff, 1.0f / falloffLen, falloff ); - } - - PlaneSet( lightProject[ 3 ], falloff, -DotProduct( start, falloff ) ); - } - - // we want the planes of s=0, s=q, t=0, and t=q - plane_t *frustum = light->localFrustum; - - frustum[ FRUSTUM_LEFT ] = lightProject[ 0 ]; - - frustum[ FRUSTUM_BOTTOM ] = lightProject[ 1 ]; - - { - vec3_t normal; - VectorSubtract( lightProject[ 2 ].normal, lightProject[ 0 ].normal, normal ); - - PlaneSet( frustum[ FRUSTUM_RIGHT ], normal, 0 ); - } - - { - vec3_t normal; - VectorSubtract( lightProject[ 2 ].normal, lightProject[ 1 ].normal, normal ); - - PlaneSet( frustum[ FRUSTUM_TOP ], normal, 0 ); - } - - { - // we want the planes of s=0 and s=1 for front and rear clipping planes - frustum[ FRUSTUM_NEAR ] = lightProject[ 3 ]; - } - - { - vec3_t normal; - VectorNegate( lightProject[ 3 ].normal, normal ); - vec_t dist = - lightProject[ 3 ].dist - 1.0f; - - PlaneSet( frustum[ FRUSTUM_FAR ], normal, dist ); - } - - { - // calculate the new projection matrix from the frustum planes - float *proj = light->projectionMatrix; - MatrixFromPlanes( proj, frustum[ FRUSTUM_LEFT ], frustum[ FRUSTUM_RIGHT ], frustum[ FRUSTUM_BOTTOM ], frustum[ FRUSTUM_TOP ], frustum[ FRUSTUM_NEAR ], frustum[ FRUSTUM_FAR ] ); - - //MatrixMultiply2(proj, newProjection); - - // scale the falloff texture coordinate so that 0.5 is at the apex and 0.0 - // as at the base of the pyramid. - // TODO: I don't like hacking the matrix like this, but all attempts to use - // a transformation seemed to affect too many other things. - //proj[10] *= 0.5f; - } - - // normalise all frustum planes - for ( int i = 0; i < 6; i++ ) - { - PlaneNormalize( frustum[ i ] ); - } - - break; - } - - default: - Sys::Drop( "R_SetupLightProjection: Bad rlType" ); - } -} - -// *INDENT-ON* - -/* -================= -R_AddLightInteraction -================= -*/ -bool R_AddLightInteraction( trRefLight_t *light, surfaceType_t *surface, shader_t *surfaceShader, byte cubeSideBits, - interactionType_t iaType ) -{ - int iaIndex; - interaction_t *ia; - - // skip all surfaces that don't matter for lighting only pass - if ( surfaceShader ) - { - if ( surfaceShader->isSky || !surfaceShader->interactLight ) - { - return false; - } - } - else - { - return false; - } - - // instead of checking for overflow, we just mask the index - // so it wraps around - iaIndex = tr.refdef.numInteractions & INTERACTION_MASK; - ia = &tr.refdef.interactions[ iaIndex ]; - tr.refdef.numInteractions++; - - light->noSort = iaIndex == 0; - - // connect to interaction grid - if ( !light->firstInteraction ) - { - light->firstInteraction = ia; - } - - if ( light->lastInteraction ) - { - light->lastInteraction->next = ia; - } - - light->lastInteraction = ia; - - // update counters - light->numInteractions++; - - ia->next = nullptr; - - ia->type = iaType; - - ia->light = light; - ia->entity = tr.currentEntity; - ia->surface = surface; - ia->shader = surfaceShader; - ia->shaderNum = surfaceShader->sortedIndex; - - ia->cubeSideBits = cubeSideBits; - - ia->scissorX = light->scissor.coords[ 0 ]; - ia->scissorY = light->scissor.coords[ 1 ]; - ia->scissorWidth = light->scissor.coords[ 2 ] - light->scissor.coords[ 0 ]; - ia->scissorHeight = light->scissor.coords[ 3 ] - light->scissor.coords[ 1 ]; - - tr.pc.c_dlightInteractions++; - - return true; -} - -/* -================= -InteractionCompare -compare function for qsort() -================= -*/ -static int InteractionCompare( const void *a, const void *b ) -{ - // shader first - if ( ( ( interaction_t * ) a )->shaderNum < ( ( interaction_t * ) b )->shaderNum ) - { - return -1; - } - - else if ( ( ( interaction_t * ) a )->shaderNum > ( ( interaction_t * ) b )->shaderNum ) - { - return 1; - } - - // then entity - if ( ( ( interaction_t * ) a )->entity == &tr.worldEntity && ( ( interaction_t * ) b )->entity != &tr.worldEntity ) - { - return -1; - } - - else if ( ( ( interaction_t * ) a )->entity != &tr.worldEntity && ( ( interaction_t * ) b )->entity == &tr.worldEntity ) - { - return 1; - } - - else if ( ( ( interaction_t * ) a )->entity < ( ( interaction_t * ) b )->entity ) - { - return -1; - } - - else if ( ( ( interaction_t * ) a )->entity > ( ( interaction_t * ) b )->entity ) - { - return 1; - } - - return 0; -} - -/* -================= -R_SortInteractions -================= -*/ -void R_SortInteractions( trRefLight_t *light ) -{ - int i; - int iaFirstIndex; - interaction_t *iaFirst; - interaction_t *ia; - interaction_t *iaLast; - - if ( r_noInteractionSort->integer ) - { - return; - } - - if ( !light->numInteractions || light->noSort ) - { - return; - } - - iaFirst = light->firstInteraction; - iaFirstIndex = light->firstInteraction - tr.refdef.interactions; - - // sort by material etc. for geometry batching in the renderer backend - qsort( iaFirst, light->numInteractions, sizeof( interaction_t ), InteractionCompare ); - - // fix linked list - iaLast = nullptr; - - for ( i = 0; i < light->numInteractions; i++ ) - { - ia = &tr.refdef.interactions[ iaFirstIndex + i ]; - - if ( iaLast ) - { - iaLast->next = ia; - } - - ia->next = nullptr; - - iaLast = ia; - } -} - -/* -================= -R_IntersectRayPlane -================= -*/ -static void R_IntersectRayPlane( const vec3_t v1, const vec3_t v2, cplane_t *plane, vec3_t res ) -{ - vec3_t v; - float sect; - - VectorSubtract( v1, v2, v ); - sect = - ( DotProduct( plane->normal, v1 ) - plane->dist ) / DotProduct( plane->normal, v ); - VectorScale( v, sect, v ); - VectorAdd( v1, v, res ); -} - -/* -================= -R_AddPointToLightScissor -================= -*/ -static void R_AddPointToLightScissor( trRefLight_t *light, const vec3_t world ) -{ - vec4_t eye, clip, normalized, window; - - R_TransformWorldToClip( world, tr.viewParms.world.viewMatrix, tr.viewParms.projectionMatrix, eye, clip ); - R_TransformClipToWindow( clip, &tr.viewParms, normalized, window ); - - light->scissor.coords[ 0 ] = std::min( light->scissor.coords[ 0 ], ( int ) window[ 0 ] ); - light->scissor.coords[ 1 ] = std::min( light->scissor.coords[ 1 ], ( int ) window[ 1 ] ); - light->scissor.coords[ 2 ] = std::max( light->scissor.coords[ 2 ], ( int ) window[ 0 ] ); - light->scissor.coords[ 3 ] = std::max( light->scissor.coords[ 3 ], ( int ) window[ 1 ] ); -} - -static int R_ClipEdgeToPlane( cplane_t plane, const vec3_t in_world1, const vec3_t in_world2, vec3_t out_world1, vec3_t out_world2 ) -{ - vec3_t intersect; - - // check edge to frustrum plane - int side1 = ( ( DotProduct( plane.normal, in_world1 ) - plane.dist ) >= 0.0f ); - int side2 = ( ( DotProduct( plane.normal, in_world2 ) - plane.dist ) >= 0.0f ); - - int sides = side1 | ( side2 << 1 ); - - // edge completely behind plane - if ( !sides ) - { - return 0; - } - - if ( !side1 || !side2 ) - { - R_IntersectRayPlane( in_world1, in_world2, &plane, intersect ); - } - - if ( !side1 ) - { - VectorCopy( intersect, out_world1 ); - VectorCopy( in_world2, out_world2 ); - } - else if ( !side2 ) - { - VectorCopy( in_world1, out_world1 ); - VectorCopy( intersect, out_world2 ); - } - else - { - // edge doesn't intersect plane - VectorCopy( in_world1, out_world1 ); - VectorCopy( in_world2, out_world2 ); - } - - return sides; -} - -/* -================= -R_AddEdgeToLightScissor -================= -*/ -static void R_AddEdgeToLightScissor( trRefLight_t *light, const vec3_t in_world1, const vec3_t in_world2 ) -{ - int i; - cplane_t *frust; - vec3_t clip1, clip2; - - if ( r_lightScissors->integer == 1 ) - { - // only clip against near plane - frust = &tr.viewParms.frustums[ 0 ][ FRUSTUM_NEAR ]; - int sides = R_ClipEdgeToPlane( *frust, in_world1, in_world2, clip1, clip2 ); - if ( !sides ) - { - return; - } - R_AddPointToLightScissor( light, clip1 ); - R_AddPointToLightScissor( light, clip2 ); - } - else if ( r_lightScissors->integer == 2 ) - { - // clip against all planes - for ( i = 0; i < FRUSTUM_PLANES; i++ ) - { - frust = &tr.viewParms.frustums[ 0 ][ i ]; - - int sides = R_ClipEdgeToPlane( *frust, in_world1, in_world2, clip1, clip2 ); - - if ( !sides ) - { - continue; // edge behind plane - } - - R_AddPointToLightScissor( light, clip1 ); - R_AddPointToLightScissor( light, clip2 ); - } - } -} - -/* -================= -R_SetupLightScissor -Recturns the screen space rectangle taken by the box. - (Clips the box to the near plane to have correct results even if the box intersects the near plane) -Tr3B - recoded from Tenebrae2 -================= -*/ -void R_SetupLightScissor( trRefLight_t *light ) -{ - vec3_t v1, v2; - - light->scissor.coords[ 0 ] = tr.viewParms.viewportX; - light->scissor.coords[ 1 ] = tr.viewParms.viewportY; - light->scissor.coords[ 2 ] = tr.viewParms.viewportX + tr.viewParms.viewportWidth; - light->scissor.coords[ 3 ] = tr.viewParms.viewportY + tr.viewParms.viewportHeight; - - // transform world light corners to eye space -> clip space -> window space - // and extend the light scissor's mins maxs by resulting window coords - light->scissor.coords[ 0 ] = 100000000; - light->scissor.coords[ 1 ] = 100000000; - light->scissor.coords[ 2 ] = -100000000; - light->scissor.coords[ 3 ] = -100000000; - - switch ( light->l.rlType ) - { - case refLightType_t::RL_OMNI: - { - // top plane - VectorSet( v1, light->worldBounds[ 1 ][ 0 ], light->worldBounds[ 1 ][ 1 ], light->worldBounds[ 1 ][ 2 ] ); - VectorSet( v2, light->worldBounds[ 0 ][ 0 ], light->worldBounds[ 1 ][ 1 ], light->worldBounds[ 1 ][ 2 ] ); - R_AddEdgeToLightScissor( light, v1, v2 ); - - VectorSet( v1, light->worldBounds[ 1 ][ 0 ], light->worldBounds[ 1 ][ 1 ], light->worldBounds[ 1 ][ 2 ] ); - VectorSet( v2, light->worldBounds[ 1 ][ 0 ], light->worldBounds[ 0 ][ 1 ], light->worldBounds[ 1 ][ 2 ] ); - R_AddEdgeToLightScissor( light, v1, v2 ); - - VectorSet( v1, light->worldBounds[ 0 ][ 0 ], light->worldBounds[ 0 ][ 1 ], light->worldBounds[ 1 ][ 2 ] ); - VectorSet( v2, light->worldBounds[ 0 ][ 0 ], light->worldBounds[ 1 ][ 1 ], light->worldBounds[ 1 ][ 2 ] ); - R_AddEdgeToLightScissor( light, v1, v2 ); - - VectorSet( v1, light->worldBounds[ 0 ][ 0 ], light->worldBounds[ 0 ][ 1 ], light->worldBounds[ 1 ][ 2 ] ); - VectorSet( v2, light->worldBounds[ 1 ][ 0 ], light->worldBounds[ 0 ][ 1 ], light->worldBounds[ 1 ][ 2 ] ); - R_AddEdgeToLightScissor( light, v1, v2 ); - - // bottom plane - VectorSet( v1, light->worldBounds[ 1 ][ 0 ], light->worldBounds[ 1 ][ 1 ], light->worldBounds[ 0 ][ 2 ] ); - VectorSet( v2, light->worldBounds[ 0 ][ 0 ], light->worldBounds[ 1 ][ 1 ], light->worldBounds[ 0 ][ 2 ] ); - R_AddEdgeToLightScissor( light, v1, v2 ); - - VectorSet( v1, light->worldBounds[ 1 ][ 0 ], light->worldBounds[ 1 ][ 1 ], light->worldBounds[ 0 ][ 2 ] ); - VectorSet( v2, light->worldBounds[ 1 ][ 0 ], light->worldBounds[ 0 ][ 1 ], light->worldBounds[ 0 ][ 2 ] ); - R_AddEdgeToLightScissor( light, v1, v2 ); - - VectorSet( v1, light->worldBounds[ 0 ][ 0 ], light->worldBounds[ 0 ][ 1 ], light->worldBounds[ 0 ][ 2 ] ); - VectorSet( v2, light->worldBounds[ 0 ][ 0 ], light->worldBounds[ 1 ][ 1 ], light->worldBounds[ 0 ][ 2 ] ); - R_AddEdgeToLightScissor( light, v1, v2 ); - - VectorSet( v1, light->worldBounds[ 0 ][ 0 ], light->worldBounds[ 0 ][ 1 ], light->worldBounds[ 0 ][ 2 ] ); - VectorSet( v2, light->worldBounds[ 1 ][ 0 ], light->worldBounds[ 0 ][ 1 ], light->worldBounds[ 0 ][ 2 ] ); - R_AddEdgeToLightScissor( light, v1, v2 ); - - // sides - VectorSet( v1, light->worldBounds[ 0 ][ 0 ], light->worldBounds[ 1 ][ 1 ], light->worldBounds[ 0 ][ 2 ] ); - VectorSet( v2, light->worldBounds[ 0 ][ 0 ], light->worldBounds[ 1 ][ 1 ], light->worldBounds[ 1 ][ 2 ] ); - R_AddEdgeToLightScissor( light, v1, v2 ); - - VectorSet( v1, light->worldBounds[ 1 ][ 0 ], light->worldBounds[ 1 ][ 1 ], light->worldBounds[ 0 ][ 2 ] ); - VectorSet( v2, light->worldBounds[ 1 ][ 0 ], light->worldBounds[ 1 ][ 1 ], light->worldBounds[ 1 ][ 2 ] ); - R_AddEdgeToLightScissor( light, v1, v2 ); - - VectorSet( v1, light->worldBounds[ 0 ][ 0 ], light->worldBounds[ 0 ][ 1 ], light->worldBounds[ 0 ][ 2 ] ); - VectorSet( v2, light->worldBounds[ 0 ][ 0 ], light->worldBounds[ 0 ][ 1 ], light->worldBounds[ 1 ][ 2 ] ); - R_AddEdgeToLightScissor( light, v1, v2 ); - - VectorSet( v1, light->worldBounds[ 1 ][ 0 ], light->worldBounds[ 0 ][ 1 ], light->worldBounds[ 0 ][ 2 ] ); - VectorSet( v2, light->worldBounds[ 1 ][ 0 ], light->worldBounds[ 0 ][ 1 ], light->worldBounds[ 1 ][ 2 ] ); - R_AddEdgeToLightScissor( light, v1, v2 ); - break; - } - - case refLightType_t::RL_PROJ: - { - int j; - vec3_t farCorners[ 4 ]; - plane_t frustum[ 6 ]; - for ( j = 0; j < 6; j++ ) - { - VectorCopy( light->frustum[ j ].normal, frustum[ j ].normal ); - frustum[ j ].dist = light->frustum[ j ].dist; - } - - R_CalcFrustumFarCorners( frustum, farCorners ); - - if ( !VectorCompare( light->l.projStart, vec3_origin ) ) - { - vec3_t nearCorners[ 4 ]; - - // calculate the vertices defining the top area - R_CalcFrustumNearCorners( frustum, nearCorners ); - - for ( j = 0; j < 4; j++ ) - { - // outer quad - R_AddEdgeToLightScissor( light, nearCorners[ j ], farCorners[ j ] ); - R_AddEdgeToLightScissor( light, farCorners[ j ], farCorners[( j + 1 ) % 4 ] ); - R_AddEdgeToLightScissor( light, farCorners[( j + 1 ) % 4 ], nearCorners[( j + 1 ) % 4 ] ); - R_AddEdgeToLightScissor( light, nearCorners[( j + 1 ) % 4 ], nearCorners[ j ] ); - - // far cap - R_AddEdgeToLightScissor( light, farCorners[ j ], farCorners[( j + 1 ) % 4 ] ); - - // near cap - R_AddEdgeToLightScissor( light, nearCorners[ j ], nearCorners[( j + 1 ) % 4 ] ); - } - } - else - { - vec3_t top; - - // no light_start, just use the top vertex (doesn't need to be mirrored) - PlanesGetIntersectionPoint( frustum[ FRUSTUM_LEFT ], frustum[ FRUSTUM_RIGHT ], frustum[ FRUSTUM_TOP ], top ); - - for ( j = 0; j < 4; j++ ) - { - R_AddEdgeToLightScissor( light, farCorners[ j ], farCorners[( j + 1 ) % 4 ] ); - R_AddEdgeToLightScissor( light, top, farCorners[ j ] ); - } - } - - break; - } - - default: - break; - } - - light->scissor.coords[ 0 ] = Math::Clamp( light->scissor.coords[ 0 ], tr.viewParms.viewportX, tr.viewParms.viewportX + tr.viewParms.viewportWidth ); - light->scissor.coords[ 2 ] = Math::Clamp( light->scissor.coords[ 2 ], tr.viewParms.viewportX, tr.viewParms.viewportX + tr.viewParms.viewportWidth ); - - light->scissor.coords[ 1 ] = Math::Clamp( light->scissor.coords[ 1 ], tr.viewParms.viewportY, tr.viewParms.viewportY + tr.viewParms.viewportHeight ); - light->scissor.coords[ 3 ] = Math::Clamp( light->scissor.coords[ 3 ], tr.viewParms.viewportY, tr.viewParms.viewportY + tr.viewParms.viewportHeight ); -} - -/* -============= -R_CalcLightCubeSideBits -============= -*/ -// *INDENT-OFF* -byte R_CalcLightCubeSideBits( trRefLight_t *, vec3_t /*worldBounds*/[2]) -{ - return CUBESIDE_CLIPALL; -} - -// *INDENT-ON* - -/* -================= -R_SetupLightShader -================= -*/ -void R_SetupLightShader( trRefLight_t *light ) -{ - if ( !light->l.attenuationShader ) - { - switch ( light->l.rlType ) - { - default: - case refLightType_t::RL_OMNI: - light->shader = tr.defaultDynamicLightShader; - break; - - case refLightType_t::RL_PROJ: - light->shader = tr.defaultProjectedLightShader; - break; - } - } - else - { - light->shader = R_GetShaderByHandle( light->l.attenuationShader ); - } -} - -/* -=============== -R_ComputeFinalAttenuation -=============== -*/ -void R_ComputeFinalAttenuation( shaderStage_t *pStage, trRefLight_t *light ) -{ - matrix_t matrix; - - GLIMP_LOGCOMMENT( "--- R_ComputeFinalAttenuation ---" ); - - RB_CalcTexMatrix( &pStage->bundle[ TB_COLORMAP ], matrix ); - - MatrixMultiply( matrix, light->attenuationMatrix, light->attenuationMatrix2 ); -} - -/* -================= -R_CullLightTriangle - -Returns CULL_IN, CULL_CLIP, or CULL_OUT -================= -*/ -cullResult_t R_CullLightWorldBounds( trRefLight_t *light, vec3_t worldBounds[ 2 ] ) -{ - int i; - cplane_t *frust; - bool anyClip; - int r; - - if ( r_nocull->integer ) - { - return cullResult_t::CULL_CLIP; - } - - // check against frustum planes - anyClip = false; - - for ( i = 0; i < 6; i++ ) - { - frust = &light->frustum[ i ]; - - r = BoxOnPlaneSide( worldBounds[ 0 ], worldBounds[ 1 ], frust ); - - if ( r == 2 ) - { - // completely outside frustum - return cullResult_t::CULL_OUT; - } - - if ( r == 3 ) - { - anyClip = true; - } - } - - if ( !anyClip ) - { - // completely inside frustum - return cullResult_t::CULL_IN; - } - - // partially clipped - return cullResult_t::CULL_CLIP; -} diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index 032119b62..ef662eca8 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -193,9 +193,6 @@ static inline void halfToFloat( const f16vec4_t in, vec4_t out ) #define MAX_DRAWSURFS 0x10000 #define DRAWSURF_MASK ( MAX_DRAWSURFS - 1 ) -#define MAX_INTERACTIONS ( MAX_DRAWSURFS * 8 ) -#define INTERACTION_MASK ( MAX_INTERACTIONS - 1 ) - // 16x16 pixels per tile #define TILE_SHIFT 4 #define TILE_SIZE (1 << TILE_SHIFT) @@ -295,8 +292,6 @@ static inline void glFboSetExt() enum class lightMode_t { FULLBRIGHT, VERTEX, GRID, MAP }; enum class deluxeMode_t { NONE, GRID, MAP }; -enum class realtimeLightingRenderer_t { LEGACY, TILED }; - enum class showCubeProbesMode { DISABLED, GRID, @@ -329,9 +324,7 @@ enum class ssaoMode { RSPEEDS_GENERAL = 1, RSPEEDS_CULLING, RSPEEDS_VIEWCLUSTER, - RSPEEDS_LIGHTS, RSPEEDS_FOG, - RSPEEDS_SHADING_TIMES, RSPEEDS_CHC, RSPEEDS_NEAR_FAR, }; @@ -384,17 +377,7 @@ enum class ssaoMode { using frustum_t = cplane_t[6]; - enum - { - CUBESIDE_PX = ( 1 << 0 ), - CUBESIDE_PY = ( 1 << 1 ), - CUBESIDE_PZ = ( 1 << 2 ), - CUBESIDE_NX = ( 1 << 3 ), - CUBESIDE_NY = ( 1 << 4 ), - CUBESIDE_NZ = ( 1 << 5 ), - CUBESIDE_CLIPALL = 1 | 2 | 4 | 8 | 16 | 32 - }; - + // FIXME: it is impossible for the game to create any type besides RL_OMNI enum class refLightType_t { RL_OMNI, // point light @@ -408,11 +391,7 @@ enum class ssaoMode { { refLightType_t rlType; - qhandle_t attenuationShader; - vec3_t origin; - quat_t rotation; - vec3_t center; vec3_t color; // range from 0.0 to 1.0, should be color normalized float scale; // r_lightScale if not set @@ -422,55 +401,13 @@ enum class ssaoMode { // projective light specific vec3_t projTarget; - vec3_t projRight; vec3_t projUp; - vec3_t projStart; - vec3_t projEnd; }; -// a trRefLight_t has all the information passed in by -// the client game, as well as some locally derived info + // TODO: remove useless struct struct trRefLight_t { refLight_t l; - - // local - bool additive; // texture detail is lost tho when the lightmap is dark - vec3_t origin; // l.origin + rotated l.center - vec3_t transformed; // origin in local coordinate system - vec3_t direction; // for directional lights (sun) - - matrix_t transformMatrix; // light to world - matrix_t viewMatrix; // object to light - matrix_t projectionMatrix; // light frustum - - float falloffLength; - - matrix_t attenuationMatrix; // attenuation * (light view * entity transform) - matrix_t attenuationMatrix2; // attenuation * tcMod matrices - - vec3_t localBounds[ 2 ]; - vec3_t worldBounds[ 2 ]; - float sphereRadius; // calculated from localBounds - - int restrictInteractionFirst; - int restrictInteractionLast; - - frustum_t frustum; - plane_t localFrustum[ 6 ]; - - screenRect_t scissor; - - struct shader_t *shader; - - struct interaction_t *firstInteraction; - - struct interaction_t *lastInteraction; - - uint16_t numInteractions; // total interactions - bool noSort; // don't sort interactions by material - - int visCounts[ MAX_VISCOUNTS ]; // node needs to be traversed if current }; // a structure matching the GLSL struct shaderLight in std140 layout @@ -1096,10 +1033,6 @@ enum class ssaoMode { ST_COLLAPSE_COLORMAP, ST_COLLAPSE_DIFFUSEMAP, ST_COLLAPSE_REFLECTIONMAP, // color cubemap + normalmap - - // light shader stage types - ST_ATTENUATIONMAP_XY, - ST_ATTENUATIONMAP_Z }; enum class collapseType_t @@ -1148,8 +1081,6 @@ enum class ssaoMode { stageShaderBinder_t shaderBinder; stageMaterialProcessor_t materialProcessor; - bool doForwardLighting; - textureBundle_t bundle[ MAX_TEXTURE_BUNDLES ]; expression_t ifExp; @@ -1277,7 +1208,6 @@ enum class ssaoMode { SHADER_2D, // surface material: shader is for 2D rendering (like GUI elements) SHADER_3D_DYNAMIC, // surface material: shader is for cGen diffuseLighting lighting SHADER_3D_STATIC, // surface material: pre-lit triangle models - SHADER_LIGHT // light material: attenuation }; struct shader_t @@ -1457,7 +1387,6 @@ enum class ssaoMode { trRefEntity_t *entities; int numLights; - int numShaderLights; trRefLight_t *lights; int numPolys; @@ -1466,9 +1395,6 @@ enum class ssaoMode { int numDrawSurfs; struct drawSurf_t *drawSurfs; - int numInteractions; - struct interaction_t *interactions; - byte *pixelTarget; //set this to Non Null to copy to a buffer after scene rendering int pixelTargetWidth; int pixelTargetHeight; @@ -1550,9 +1476,6 @@ enum class ssaoMode { int numDrawSurfs; struct drawSurf_t *drawSurfs; int firstDrawSurf[ Util::ordinal(shaderSort_t::SS_NUM_SORTS) + 1 ]; - - int numInteractions; - struct interaction_t *interactions; }; /* @@ -1666,33 +1589,6 @@ enum class ssaoMode { } }; - enum interactionType_t - { - IA_LIGHT = 1 << 0, // the received light if not in shadow - - IA_DEFAULT = IA_LIGHT, // lighting and shadowing - IA_DEFAULTCLIP = IA_LIGHT - }; - -// an interaction is a node between a light and any surface - struct interaction_t - { - interactionType_t type; - - trRefLight_t *light; - - trRefEntity_t *entity; - surfaceType_t *surface; // any of surface*_t - shader_t *shader; - int shaderNum; - - byte cubeSideBits; - - int16_t scissorX, scissorY, scissorWidth, scissorHeight; - - interaction_t *next; - }; - #define MAX_PATCH_SIZE 64 // max dimensions of a patch mesh in map file #define MAX_GRID_SIZE 65 // max dimensions of a grid mesh in memory @@ -1824,6 +1720,8 @@ enum class ssaoMode { struct bspSurface_t { int viewCount; // if == tr.viewCount, already added + + // FIXME not used for lighting int lightCount; int interactionBits; @@ -2301,16 +2199,9 @@ enum class ssaoMode { int c_sphere_cull_mdv_in, c_sphere_cull_mdv_clip, c_sphere_cull_mdv_out; int c_box_cull_mdv_in, c_box_cull_mdv_clip, c_box_cull_mdv_out; int c_box_cull_md5_in, c_box_cull_md5_clip, c_box_cull_md5_out; - int c_box_cull_light_in, c_box_cull_light_clip, c_box_cull_light_out; - int c_pvs_cull_light_out; int c_nodes; int c_leafs; - - int c_dlights; - int c_dlightSurfaces; - int c_dlightSurfacesCulled; - int c_dlightInteractions; }; #define FOG_TABLE_SIZE 256 @@ -2378,9 +2269,6 @@ enum class ssaoMode { int c_fogSurfaces; int c_fogBatches; - int c_forwardAmbientTime; - int c_forwardLightingTime; - int c_multiDrawElements; int c_multiDrawPrimitives; int c_multiVboIndexes; @@ -2407,7 +2295,6 @@ enum class ssaoMode { visTestQueries_t visTestQueries[ MAX_VISTESTS ]; bool isHyperspace; trRefEntity_t *currentEntity; - trRefLight_t *currentLight; // only used when lighting interactions bool skyRenderedThisView; // flag for drawing sun bool postDepthLightTileRendered = false; @@ -2625,7 +2512,6 @@ enum class ssaoMode { int sceneCount; // incremented every scene int viewCount; // incremented every view (twice a scene if portaled) int viewCountNoReset; // incremented when doing something that visits surfaces and sets their viewCount - int lightCount; // incremented every time a dlight traverses the world // and every R_MarkFragments call int smpFrame; // toggles from 0 to 1 every endFrame @@ -2665,7 +2551,6 @@ enum class ssaoMode { image_t *blueImage; image_t *flatImage; // use this as default normalmap image_t *randomNormalsImage; - image_t *noFalloffImage; image_t *blackCubeImage; image_t *whiteCubeImage; @@ -2716,9 +2601,6 @@ enum class ssaoMode { trRefEntity_t worldEntity; // point currentEntity at this when rendering world model_t *currentModel; - // render lights - trRefLight_t *currentLight; - // ----------------------------------------- viewParms_t viewParms; @@ -2852,7 +2734,6 @@ enum class ssaoMode { extern cvar_t *r_lightScale; extern Cvar::Cvar r_drawSky; // Controls whether sky should be drawn or cleared. - extern Cvar::Range> r_realtimeLightingRenderer; extern Cvar::Cvar r_realtimeLighting; extern Cvar::Range> r_realtimeLightLayers; extern cvar_t *r_precomputedLighting; @@ -2882,9 +2763,6 @@ enum class ssaoMode { extern cvar_t *r_nocull; extern cvar_t *r_facePlaneCull; // enables culling of planar surfaces with back side test extern cvar_t *r_nocurves; - extern cvar_t *r_lightScissors; - extern cvar_t *r_noLightVisCull; - extern cvar_t *r_noInteractionSort; extern cvar_t *r_mode; // video mode extern cvar_t *r_gamma; @@ -2937,8 +2815,6 @@ enum class ssaoMode { extern Cvar::Range> r_shadows; - extern cvar_t *r_noLightFrustums; - extern cvar_t *r_lockpvs; extern cvar_t *r_noportals; extern cvar_t *r_max_portal_levels; @@ -2967,10 +2843,6 @@ enum class ssaoMode { extern cvar_t *r_showSky; // forces sky in front of all surfaces extern cvar_t *r_showSkeleton; extern cvar_t *r_showEntityTransforms; - extern cvar_t *r_showLightTransforms; - extern cvar_t *r_showLightInteractions; - extern cvar_t *r_showLightScissors; - extern cvar_t *r_showLightBatches; extern cvar_t *r_showLightGrid; extern cvar_t *r_showLightTiles; extern cvar_t *r_showBatches; @@ -3037,7 +2909,6 @@ inline bool checkGLErrors() void R_RenderPostProcess(); void R_AddMDVSurfaces( trRefEntity_t *e ); - void R_AddMDVInteractions( trRefEntity_t *e, trRefLight_t *light, interactionType_t iaType ); void R_AddPolygonSurfaces(); @@ -3056,7 +2927,6 @@ inline bool checkGLErrors() void R_SetupEntityWorldBounds( trRefEntity_t *ent ); void R_RotateEntityForViewParms( const trRefEntity_t *ent, const viewParms_t *viewParms, orientationr_t *orien ); - void R_RotateLightForViewParms( const trRefLight_t *ent, const viewParms_t *viewParms, orientationr_t *orien ); void R_SetupFrustum2( frustum_t frustum, const matrix_t modelViewProjectionMatrix ); template @@ -3412,7 +3282,6 @@ void GLimp_LogComment_( std::string comment ); void Tess_StageIteratorDebug(); void Tess_StageIteratorColor(); void Tess_StageIteratorPortal(); - void Tess_StageIteratorLighting(); void Tess_StageIteratorSky(); void Tess_AddQuadStamp( vec3_t origin, vec3_t left, vec3_t up, const Color::Color& color ); @@ -3478,8 +3347,6 @@ void GLimp_LogComment_( std::string comment ); bool R_inPVS( const vec3_t p1, const vec3_t p2 ); bool R_inPVVS( const vec3_t p1, const vec3_t p2 ); - void R_AddWorldInteractions( trRefLight_t *light ); - /* ============================================================ @@ -3488,35 +3355,10 @@ void GLimp_LogComment_( std::string comment ); ============================================================ */ - void R_AddBrushModelInteractions( trRefEntity_t *ent, trRefLight_t *light, interactionType_t iaType ); float R_InterpolateLightGrid( world_t *w, int from[3], int to[3], float *factors[3], vec3_t ambientLight, vec3_t directedLight, vec3_t lightDir ); int R_LightForPoint( vec3_t point, vec3_t ambientLight, vec3_t directedLight, vec3_t lightDir ); - void R_TessLight( const trRefLight_t *light, const Color::Color& color ); - - void R_SetupLightOrigin( trRefLight_t *light ); - void R_SetupLightLocalBounds( trRefLight_t *light ); - void R_SetupLightWorldBounds( trRefLight_t *light ); - - void R_SetupLightView( trRefLight_t *light ); - void R_SetupLightFrustum( trRefLight_t *light ); - void R_SetupLightProjection( trRefLight_t *light ); - - bool R_AddLightInteraction( trRefLight_t *light, surfaceType_t *surface, shader_t *surfaceShader, byte cubeSideBits, - interactionType_t iaType ); - - void R_SortInteractions( trRefLight_t *light ); - - void R_SetupLightScissor( trRefLight_t *light ); - - void R_SetupLightShader( trRefLight_t *light ); - - byte R_CalcLightCubeSideBits( trRefLight_t *light, vec3_t worldBounds[ 2 ] ); - - cullResult_t R_CullLightWorldBounds( trRefLight_t *light, vec3_t worldBounds[ 2 ] ); - - void R_ComputeFinalAttenuation( shaderStage_t *pStage, trRefLight_t *light ); /* ============================================================ @@ -3650,10 +3492,8 @@ void GLimp_LogComment_( std::string comment ); skelAnimation_t *R_GetAnimationByHandle( qhandle_t hAnim ); void R_AddMD5Surfaces( trRefEntity_t *ent ); - void R_AddMD5Interactions( trRefEntity_t *ent, trRefLight_t *light, interactionType_t iaType ); void R_AddIQMSurfaces( trRefEntity_t *ent ); - void R_AddIQMInteractions( trRefEntity_t *ent, trRefLight_t *light, interactionType_t iaType ); int RE_CheckSkeleton( refSkeleton_t *skel, qhandle_t hModel, qhandle_t hAnim ); int RE_BuildSkeleton( refSkeleton_t *skel, qhandle_t anim, int startFrame, int endFrame, float frac, @@ -3880,7 +3720,6 @@ void GLimp_LogComment_( std::string comment ); struct backEndData_t { drawSurf_t drawSurfs[ MAX_DRAWSURFS ]; - interaction_t interactions[ MAX_INTERACTIONS ]; trRefLight_t lights[ MAX_REF_LIGHTS ]; trRefEntity_t entities[ MAX_REF_ENTITIES ]; diff --git a/src/engine/renderer/tr_main.cpp b/src/engine/renderer/tr_main.cpp index e1c5bebef..342910a7d 100644 --- a/src/engine/renderer/tr_main.cpp +++ b/src/engine/renderer/tr_main.cpp @@ -677,32 +677,6 @@ void R_RotateEntityForViewParms( const trRefEntity_t *ent, const viewParms_t *vi orientation ->viewOrigin[ 2 ] = DotProduct( delta, orientation ->axis[ 2 ] ) * axisLength; } -/* -================= -R_RotateLightForViewParms -================= -*/ -void R_RotateLightForViewParms( const trRefLight_t *light, const viewParms_t *viewParms, orientationr_t * orientation ) -{ - vec3_t delta; - - VectorCopy( light->l.origin, orientation ->origin ); - - QuatToAxis( light->l.rotation, orientation ->axis ); - - MatrixSetupTransformFromVectorsFLU( orientation ->transformMatrix, orientation ->axis[ 0 ], orientation ->axis[ 1 ], orientation ->axis[ 2 ], orientation ->origin ); - MatrixAffineInverse( orientation ->transformMatrix, orientation ->viewMatrix ); - MatrixMultiply( viewParms->world.viewMatrix, orientation ->transformMatrix, orientation ->modelViewMatrix ); - - // calculate the viewer origin in the light's space - // needed for fog, specular, and environment mapping - VectorSubtract( viewParms->orientation.origin, orientation ->origin, delta ); - - orientation ->viewOrigin[ 0 ] = DotProduct( delta, orientation ->axis[ 0 ] ); - orientation ->viewOrigin[ 1 ] = DotProduct( delta, orientation ->axis[ 1 ] ); - orientation ->viewOrigin[ 2 ] = DotProduct( delta, orientation ->axis[ 2 ] ); -} - /* ================= R_RotateForViewer @@ -1783,20 +1757,6 @@ static void R_SortDrawSurfs() tr.viewParms.numDrawSurfs = MAX_DRAWSURFS; } - // if we overflowed MAX_INTERACTIONS, the interactions - // wrapped around in the buffer and we will be missing - // the first interactions, not the last ones - if ( tr.viewParms.numInteractions > MAX_INTERACTIONS ) - { - interaction_t *ia; - - tr.viewParms.numInteractions = MAX_INTERACTIONS; - - // reset last interaction's next pointer - ia = &tr.viewParms.interactions[ tr.viewParms.numInteractions - 1 ]; - ia->next = nullptr; - } - std::sort( tr.viewParms.drawSurfs, tr.viewParms.drawSurfs + tr.viewParms.numDrawSurfs, []( const drawSurf_t &a, const drawSurf_t &b ) { return a.sort < b.sort; @@ -1971,203 +1931,6 @@ void R_AddEntitySurfaces() } } -/* -============= -R_AddEntityInteractions -============= -*/ -void R_AddEntityInteractions( trRefLight_t *light ) -{ - int i; - trRefEntity_t *ent; - interactionType_t iaType; - - if ( !r_drawentities->integer ) - { - return; - } - - for ( i = 0; i < tr.refdef.numEntities; i++ ) - { - iaType = IA_DEFAULT; - - if ( light->restrictInteractionFirst >= 0 && - i >= light->restrictInteractionFirst && - i <= light->restrictInteractionLast ) - { - iaType = (interactionType_t) (iaType & ~IA_LIGHT); - } - - ent = tr.currentEntity = &tr.refdef.entities[ i ]; - - // - // the weapon model must be handled special -- - // we don't want the hacked weapon position showing in - // mirrors, because the true body position will already be drawn - // - if ( ( ent->e.renderfx & RF_FIRST_PERSON ) && - ( tr.viewParms.portalLevel > 0 || tr.viewParms.isMirror ) ) - { - continue; - } - - // simple generated models, like sprites and beams, are not culled - switch ( ent->e.reType ) - { - case refEntityType_t::RT_PORTALSURFACE: - break; // don't draw anything - - case refEntityType_t::RT_SPRITE: - break; - - case refEntityType_t::RT_MODEL: - tr.currentModel = R_GetModelByHandle( ent->e.hModel ); - - if ( tr.currentModel ) - { - switch ( tr.currentModel->type ) - { - case modtype_t::MOD_MESH: - R_AddMDVInteractions( ent, light, iaType ); - break; - - case modtype_t::MOD_MD5: - R_AddMD5Interactions( ent, light, iaType ); - break; - - case modtype_t::MOD_IQM: - R_AddIQMInteractions( ent, light, iaType ); - break; - - case modtype_t::MOD_BSP: - R_AddBrushModelInteractions( ent, light, iaType ); - break; - - case modtype_t::MOD_BAD: // null model axis - break; - - default: - Sys::Drop( "R_AddEntityInteractions: Bad modeltype" ); - } - } - - break; - - default: - Sys::Drop( "R_AddEntityInteractions: Bad reType" ); - } - } -} - -/* -============= -R_AddLightInteractions -============= -*/ -void R_AddLightInteractions() -{ - int i; - trRefLight_t *light; - - realtimeLightingRenderer_t realtimeLightingRenderer = realtimeLightingRenderer_t( r_realtimeLightingRenderer.Get() ); - - tr.refdef.numShaderLights = 0; - - for ( i = 0; i < tr.refdef.numLights; i++ ) - { - light = tr.currentLight = &tr.refdef.lights[ i ]; - - if ( realtimeLightingRenderer == realtimeLightingRenderer_t::TILED ) - { - tr.refdef.numShaderLights++; - tr.pc.c_dlights++; - - continue; - } - - // we must set up parts of tr.or for light culling - R_RotateLightForViewParms( light, &tr.viewParms, &tr.orientation ); - - // calc local bounds for culling - { - // set up light transform matrix - MatrixSetupTransformFromQuat( light->transformMatrix, light->l.rotation, light->l.origin ); - - // set up light origin for lighting and shadowing - R_SetupLightOrigin( light ); - - // set up model to light view matrix - R_SetupLightView( light ); - - // set up projection - R_SetupLightProjection( light ); - - // calc local bounds for culling - R_SetupLightLocalBounds( light ); - - // look if we have to draw the light including its interactions - switch ( R_CullLocalBox( light->localBounds ) ) - { - case cullResult_t::CULL_IN: - default: - tr.pc.c_box_cull_light_in++; - break; - - case cullResult_t::CULL_CLIP: - tr.pc.c_box_cull_light_clip++; - break; - - case cullResult_t::CULL_OUT: - // light is not visible so skip other light setup stuff to save speed - tr.pc.c_box_cull_light_out++; - continue; - } - - // setup world bounds for intersection tests - R_SetupLightWorldBounds( light ); - - // setup frustum planes for intersection tests - R_SetupLightFrustum( light ); - - // ignore if not in visible bounds - if ( !BoundsIntersect - ( light->worldBounds[ 0 ], light->worldBounds[ 1 ], tr.viewParms.visBounds[ 0 ], tr.viewParms.visBounds[ 1 ] ) ) - { - continue; - } - } - - // set up view dependent light scissor - R_SetupLightScissor( light ); - - // look for proper attenuation shader - R_SetupLightShader( light ); - - // setup interactions - light->firstInteraction = nullptr; - light->lastInteraction = nullptr; - - light->numInteractions = 0; - light->noSort = false; - - R_AddWorldInteractions( light ); - R_AddEntityInteractions( light ); - - if ( light->numInteractions ) - { - R_SortInteractions( light ); - - tr.pc.c_dlights++; - } - else - { - // skip all interactions of this light because it caused only shadow volumes - // but no lighting - tr.refdef.numInteractions -= light->numInteractions; - } - } -} - static std::vector botDebugDrawCommands; void RE_SendBotDebugDrawCommands( std::vector commands ) { @@ -2258,7 +2021,6 @@ or a mirror / remote location void R_RenderView( viewParms_t *parms ) { int firstDrawSurf; - int firstInteraction; if ( parms->viewportWidth <= 0 || parms->viewportHeight <= 0 ) { @@ -2280,7 +2042,6 @@ void R_RenderView( viewParms_t *parms ) tr.viewParms.viewCount = tr.viewCount; // % MAX_VIEWS; firstDrawSurf = tr.refdef.numDrawSurfs; - firstInteraction = tr.refdef.numInteractions; // set viewParms.world R_RotateForViewer(); @@ -2314,8 +2075,6 @@ void R_RenderView( viewParms_t *parms ) R_AddEntitySurfaces(); - R_AddLightInteractions(); - // Transform the blur vector in view space, FIXME for some we need reason invert its Z component MatrixTransformNormal2( tr.viewParms.world.viewMatrix, tr.refdef.blurVec ); tr.refdef.blurVec[2] *= -1; @@ -2323,9 +2082,6 @@ void R_RenderView( viewParms_t *parms ) tr.viewParms.drawSurfs = tr.refdef.drawSurfs + firstDrawSurf; tr.viewParms.numDrawSurfs = tr.refdef.numDrawSurfs - firstDrawSurf; - tr.viewParms.interactions = tr.refdef.interactions + firstInteraction; - tr.viewParms.numInteractions = tr.refdef.numInteractions - firstInteraction; - R_SortDrawSurfs(); // draw main system development information (surface outlines, etc) diff --git a/src/engine/renderer/tr_mesh.cpp b/src/engine/renderer/tr_mesh.cpp index d7f918cd2..ecb0105eb 100644 --- a/src/engine/renderer/tr_mesh.cpp +++ b/src/engine/renderer/tr_mesh.cpp @@ -343,114 +343,6 @@ void R_AddMDVSurfaces( trRefEntity_t *ent ) } } -/* -================= -R_AddMDVInteractions -================= -*/ -void R_AddMDVInteractions( trRefEntity_t *ent, trRefLight_t *light, interactionType_t iaType ) -{ - mdvModel_t *model = nullptr; - mdvSurface_t *mdvSurface = nullptr; - int lod; - bool personalModel; - byte cubeSideBits; - - // cull the entire model if merged bounding box of both frames - // is outside the view frustum and we don't care about proper shadowing - if ( ent->cull == CULL_OUT ) - { - iaType = (interactionType_t) (iaType & ~IA_LIGHT); - } - - if ( !iaType ) - { - return; - } - - // don't add third_person objects if not in a portal - personalModel = ( ent->e.renderfx & RF_THIRD_PERSON ) && - tr.viewParms.portalLevel == 0; - - // compute LOD - lod = R_ComputeLOD( ent ); - - model = tr.currentModel->mdv[ lod ]; - - // do a quick AABB cull - if ( !BoundsIntersect( light->worldBounds[ 0 ], light->worldBounds[ 1 ], ent->worldBounds[ 0 ], ent->worldBounds[ 1 ] ) ) - { - tr.pc.c_dlightSurfacesCulled += model->numSurfaces; - return; - } - - // do a more expensive and precise light frustum cull - if ( !r_noLightFrustums->integer ) - { - if ( R_CullLightWorldBounds( light, ent->worldBounds ) == CULL_OUT ) - { - tr.pc.c_dlightSurfacesCulled += model->numSurfaces; - return; - } - } - - cubeSideBits = R_CalcLightCubeSideBits( light, ent->worldBounds ); - - // generate interactions with all surfaces - if ( r_vboModels.Get() && model->numVBOSurfaces ) - { - // new brute force method: just render everthing with static VBOs - srfVBOMDVMesh_t *vboSurface; - - // static VBOs are fine for lighting and shadow mapping - for ( int i = 0; i < model->numVBOSurfaces; i++ ) - { - vboSurface = model->vboSurfaces[ i ]; - mdvSurface = vboSurface->mdvSurface; - - shader_t *shader = GetMDVSurfaceShader( ent, mdvSurface ); - - // skip all surfaces that don't matter for lighting only pass - if ( shader->isSky || !shader->interactLight ) - { - continue; - } - - // we will add shadows even if the main object isn't visible in the view - - // don't add third_person objects if not viewing through a portal - if ( !personalModel ) - { - R_AddLightInteraction( light, ( surfaceType_t * ) vboSurface, shader, cubeSideBits, iaType ); - tr.pc.c_dlightSurfaces++; - } - } - } - else - { - int i; - for ( i = 0, mdvSurface = model->surfaces; i < model->numSurfaces; i++, mdvSurface++ ) - { - shader_t *shader = GetMDVSurfaceShader( ent, mdvSurface ); - - // skip all surfaces that don't matter for lighting only pass - if ( shader->isSky || !shader->interactLight ) - { - continue; - } - - // we will add shadows even if the main object isn't visible in the view - - // don't add third_person objects if not viewing through a portal - if ( !personalModel ) - { - R_AddLightInteraction( light, ( surfaceType_t * ) mdvSurface, shader, cubeSideBits, iaType ); - tr.pc.c_dlightSurfaces++; - } - } - } -} - void MarkShaderBuildMDV( const mdvModel_t* model ) { for ( int i = 0; i < model->numVBOSurfaces; i++ ) { srfVBOMDVMesh_t* surface = model->vboSurfaces[i]; diff --git a/src/engine/renderer/tr_scene.cpp b/src/engine/renderer/tr_scene.cpp index 5ed8b3256..c3a524fa5 100644 --- a/src/engine/renderer/tr_scene.cpp +++ b/src/engine/renderer/tr_scene.cpp @@ -28,7 +28,6 @@ static Cvar::Cvar r_drawDynamicLights( "r_drawDynamicLights", "render dynamic lights (if realtime lighting is enabled)", Cvar::NONE, true ); static int r_firstSceneDrawSurf; -static int r_firstSceneInteraction; static int r_numLights; static int r_firstSceneLight; @@ -66,7 +65,6 @@ void R_ToggleSmpFrame() backEndData[ tr.smpFrame ]->commands.used = 0; r_firstSceneDrawSurf = 0; - r_firstSceneInteraction = 0; r_numLights = 0; r_firstSceneLight = 0; @@ -305,14 +303,6 @@ void RE_AddDynamicLightToSceneET( const vec3_t org, float radius, float intensit return; } - // set last lights restrictInteractionEnd if needed - if ( r_numLights > r_firstSceneLight ) { - light = &backEndData[ tr.smpFrame ]->lights[ r_numLights - 1 ]; - if( light->restrictInteractionFirst >= 0 ) { - light->restrictInteractionLast = r_numEntities - r_firstSceneEntity - 1; - } - } - if ( r_numLights >= MAX_REF_LIGHTS ) { return; @@ -328,27 +318,12 @@ void RE_AddDynamicLightToSceneET( const vec3_t org, float radius, float intensit light->l.rlType = refLightType_t::RL_OMNI; VectorCopy( org, light->l.origin ); - QuatClear( light->l.rotation ); - VectorClear( light->l.center ); - - // HACK: this will tell the renderer backend to use tr.defaultLightShader - light->l.attenuationShader = 0; - light->l.radius = radius; light->l.color[ 0 ] = r; light->l.color[ 1 ] = g; light->l.color[ 2 ] = b; - if( flags & REF_RESTRICT_DLIGHT ) { - light->restrictInteractionFirst = r_numEntities - r_firstSceneEntity; - light->restrictInteractionLast = 0; - } else { - light->restrictInteractionFirst = -1; - light->restrictInteractionLast = -1; - } - - light->additive = true; light->l.scale = intensity; } @@ -571,9 +546,6 @@ void RE_RenderScene( const refdef_t *fd ) tr.refdef.numDrawSurfs = r_firstSceneDrawSurf; tr.refdef.drawSurfs = backEndData[ tr.smpFrame ]->drawSurfs; - tr.refdef.numInteractions = r_firstSceneInteraction; - tr.refdef.interactions = backEndData[ tr.smpFrame ]->interactions; - tr.refdef.numEntities = r_numEntities - r_firstSceneEntity; tr.refdef.entities = &backEndData[ tr.smpFrame ]->entities[ r_firstSceneEntity ]; @@ -661,7 +633,6 @@ void RE_RenderScene( const refdef_t *fd ) // the next scene rendered in this frame will tack on after this one r_firstSceneDrawSurf = tr.refdef.numDrawSurfs; - r_firstSceneInteraction = tr.refdef.numInteractions; r_firstSceneEntity = r_numEntities; r_firstSceneLight = r_numLights; r_firstScenePoly = r_numPolys; diff --git a/src/engine/renderer/tr_shade.cpp b/src/engine/renderer/tr_shade.cpp index 720b0e779..abb1a2a8d 100644 --- a/src/engine/renderer/tr_shade.cpp +++ b/src/engine/renderer/tr_shade.cpp @@ -41,30 +41,27 @@ static void EnableAvailableFeatures() if ( glConfig2.realtimeLighting ) { - if ( r_realtimeLightingRenderer.Get() == Util::ordinal( realtimeLightingRenderer_t::TILED ) ) - { - if ( !glConfig2.uniformBufferObjectAvailable ) { - Log::Warn( "Tiled dynamic light renderer disabled because GL_ARB_uniform_buffer_object is not available." ); - glConfig2.realtimeLighting = false; - } + if ( !glConfig2.uniformBufferObjectAvailable ) { + Log::Warn( "Tiled dynamic light renderer disabled because GL_ARB_uniform_buffer_object is not available." ); + glConfig2.realtimeLighting = false; + } - if ( !glConfig2.textureIntegerAvailable ) { - Log::Warn( "Tiled dynamic light renderer disabled because GL_EXT_texture_integer is not available." ); - glConfig2.realtimeLighting = false; - } + if ( !glConfig2.textureIntegerAvailable ) { + Log::Warn( "Tiled dynamic light renderer disabled because GL_EXT_texture_integer is not available." ); + glConfig2.realtimeLighting = false; + } - if ( glConfig2.max3DTextureSize == 0 ) - { - Log::Warn( "Tiled dynamic light renderer disabled because of missing 3D texture support." ); - glConfig2.realtimeLighting = false; - } + if ( glConfig2.max3DTextureSize == 0 ) + { + Log::Warn( "Tiled dynamic light renderer disabled because of missing 3D texture support." ); + glConfig2.realtimeLighting = false; + } - // See below about ALU instructions on ATI R300 and Intel GMA 3. - if ( !glConfig2.glCoreProfile && glConfig2.maxAluInstructions < 128 ) - { - Log::Warn( "Tiled dynamic light rendered disabled because GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB is too small: %d", glConfig2.maxAluInstructions ); - glConfig2.realtimeLighting = false; - } + // See below about ALU instructions on ATI R300 and Intel GMA 3. + if ( !glConfig2.glCoreProfile && glConfig2.maxAluInstructions < 128 ) + { + Log::Warn( "Tiled dynamic light rendered disabled because GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB is too small: %d", glConfig2.maxAluInstructions ); + glConfig2.realtimeLighting = false; } } @@ -242,30 +239,13 @@ static void GLSL_InitGPUShadersOrError() if ( glConfig2.realtimeLighting ) { - realtimeLightingRenderer_t realtimeLightingRenderer = realtimeLightingRenderer_t( r_realtimeLightingRenderer.Get() ); - - switch( realtimeLightingRenderer ) - { - case realtimeLightingRenderer_t::LEGACY: - // projective lighting ( Doom3 style ) - gl_shaderManager.LoadShader( gl_forwardLightingShader_projXYZ ); + gl_shaderManager.LoadShader( gl_depthtile1Shader ); + gl_shaderManager.LoadShader( gl_depthtile2Shader ); + gl_shaderManager.LoadShader( gl_lighttileShader ); - // omni-directional specular bump mapping ( Doom3 style ) - gl_shaderManager.LoadShader( gl_forwardLightingShader_omniXYZ ); - - // directional sun lighting ( Doom3 style ) - gl_shaderManager.LoadShader( gl_forwardLightingShader_directionalSun ); - break; - case realtimeLightingRenderer_t::TILED: - gl_shaderManager.LoadShader( gl_depthtile1Shader ); - gl_shaderManager.LoadShader( gl_depthtile2Shader ); - gl_shaderManager.LoadShader( gl_lighttileShader ); - - gl_depthtile1Shader->MarkProgramForBuilding( 0 ); - gl_depthtile2Shader->MarkProgramForBuilding( 0 ); - gl_lighttileShader->MarkProgramForBuilding( 0 ); - break; - } + gl_depthtile1Shader->MarkProgramForBuilding( 0 ); + gl_depthtile2Shader->MarkProgramForBuilding( 0 ); + gl_lighttileShader->MarkProgramForBuilding( 0 ); } if ( glConfig2.reflectionMappingAvailable ) @@ -480,9 +460,6 @@ void GLSL_ShutdownGPUShaders() gl_processSurfacesShader = nullptr; gl_lightMappingShader = nullptr; gl_lightMappingShaderMaterial = nullptr; - gl_forwardLightingShader_omniXYZ = nullptr; - gl_forwardLightingShader_projXYZ = nullptr; - gl_forwardLightingShader_directionalSun = nullptr; gl_reflectionShader = nullptr; gl_reflectionShaderMaterial = nullptr; gl_skyboxShader = nullptr; @@ -650,7 +627,7 @@ static void DrawTris() // u_AlphaThreshold gl_genericShader->SetUniform_AlphaTest( GLS_ATEST_NONE ); - if ( r_showBatches->integer || r_showLightBatches->integer ) + if ( r_showBatches->integer ) { SetUniform_Color( gl_genericShader, Color::Color::Indexed( backEnd.pc.c_batches % 8 ) ); } @@ -1061,12 +1038,11 @@ void Render_lightMapping( shaderStage_t *pStage ) gl_lightMappingShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); - if ( glConfig2.realtimeLighting && - r_realtimeLightingRenderer.Get() == Util::ordinal( realtimeLightingRenderer_t::TILED ) ) + if ( glConfig2.realtimeLighting ) { gl_lightMappingShader->SetUniform_numLights( tr.refdef.numLights ); - if ( backEnd.refdef.numShaderLights > 0 ) + if ( backEnd.refdef.numLights > 0 ) { gl_lightMappingShader->SetUniformBlock_Lights( tr.dlightUBO ); @@ -1247,425 +1223,6 @@ void Render_lightMapping( shaderStage_t *pStage ) GL_CheckErrors(); } -static void Render_forwardLighting_DBS_omni( shaderStage_t *pStage, - shaderStage_t *attenuationXYStage, - shaderStage_t *attenuationZStage, trRefLight_t *light ) -{ - vec3_t viewOrigin; - vec3_t lightOrigin; - - GLIMP_LOGCOMMENT( "--- Render_forwardLighting_DBS_omni ---" ); - - // choose right shader program ---------------------------------- - gl_forwardLightingShader_omniXYZ->SetVertexSkinning( glConfig2.vboVertexSkinningAvailable && tess.vboVertexSkinning ); - gl_forwardLightingShader_omniXYZ->SetVertexAnimation( tess.vboVertexAnimation ); - - gl_forwardLightingShader_omniXYZ->SetHeightMapInNormalMap( pStage->hasHeightMapInNormalMap ); - - gl_forwardLightingShader_omniXYZ->SetReliefMapping( pStage->enableReliefMapping ); - - gl_forwardLightingShader_omniXYZ->BindProgram( pStage->deformIndex ); - // end choose right shader program ------------------------------ - - // now we are ready to set the shader program uniforms - - // u_ColorModulate - colorGen_t rgbGen = SetRgbGen( pStage ); - alphaGen_t alphaGen = SetAlphaGen( pStage ); - - SetUniform_ColorModulateColorGen( gl_forwardLightingShader_omniXYZ, rgbGen, alphaGen ); - - // u_Color - SetUniform_Color( gl_forwardLightingShader_omniXYZ, tess.svars.color ); - - // u_AlphaThreshold - gl_forwardLightingShader_omniXYZ->SetUniform_AlphaTest( pStage->stateBits ); - - // bind u_HeightMap - if ( pStage->enableReliefMapping ) - { - float depthScale = RB_EvalExpression( &pStage->depthScaleExp, r_reliefDepthScale->value ); - depthScale *= tess.surfaceShader->reliefDepthScale; - - gl_forwardLightingShader_omniXYZ->SetUniform_ReliefDepthScale( depthScale ); - gl_forwardLightingShader_omniXYZ->SetUniform_ReliefOffsetBias( tess.surfaceShader->reliefOffsetBias ); - - // FIXME: if there is both, embedded heightmap in normalmap is used instead of standalone heightmap - if ( !pStage->hasHeightMapInNormalMap ) - { - gl_forwardLightingShader_omniXYZ->SetUniform_HeightMapBindless( - GL_BindToTMU( 15, pStage->bundle[TB_HEIGHTMAP].image[0] ) - ); - } - } - - // set uniforms - VectorCopy( backEnd.viewParms.orientation.origin, viewOrigin ); - VectorCopy( light->origin, lightOrigin ); - Color::Color lightColor = tess.svars.color; - - gl_forwardLightingShader_omniXYZ->SetUniform_ViewOrigin( viewOrigin ); - - gl_forwardLightingShader_omniXYZ->SetUniform_LightOrigin( lightOrigin ); - gl_forwardLightingShader_omniXYZ->SetUniform_LightColor( lightColor.ToArray() ); - gl_forwardLightingShader_omniXYZ->SetUniform_LightRadius( light->sphereRadius ); - gl_forwardLightingShader_omniXYZ->SetUniform_LightScale( light->l.scale ); - gl_forwardLightingShader_omniXYZ->SetUniform_LightAttenuationMatrix( light->attenuationMatrix2 ); - - GL_CheckErrors(); - - gl_forwardLightingShader_omniXYZ->SetUniform_ModelMatrix( backEnd.orientation.transformMatrix ); - gl_forwardLightingShader_omniXYZ->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); - - // u_Bones - if ( glConfig2.vboVertexSkinningAvailable && tess.vboVertexSkinning ) - { - gl_forwardLightingShader_omniXYZ->SetUniform_Bones( tess.numBones, tess.bones ); - } - - // u_VertexInterpolation - if ( tess.vboVertexAnimation ) - { - gl_forwardLightingShader_omniXYZ->SetUniform_VertexInterpolation( glState.vertexAttribsInterpolation ); - } - - gl_forwardLightingShader_omniXYZ->SetUniform_Time( backEnd.refdef.floatTime - backEnd.currentEntity->e.shaderTime ); - - GL_CheckErrors(); - - // bind u_DiffuseMap - gl_forwardLightingShader_omniXYZ->SetUniform_DiffuseMapBindless( - GL_BindToTMU( 0, pStage->bundle[TB_DIFFUSEMAP].image[0] ) - ); - - if ( pStage->type != stageType_t::ST_LIGHTMAP ) - { - gl_forwardLightingShader_omniXYZ->SetUniform_TextureMatrix( tess.svars.texMatrices[ TB_DIFFUSEMAP ] ); - } - - // bind u_NormalMap - gl_forwardLightingShader_omniXYZ->SetUniform_NormalMapBindless( - GL_BindToTMU( 1, pStage->bundle[TB_NORMALMAP].image[0] ) - ); - - // bind u_NormalScale - if ( pStage->enableNormalMapping ) - { - vec3_t normalScale; - SetNormalScale( pStage, normalScale ); - - gl_forwardLightingShader_omniXYZ->SetUniform_NormalScale( normalScale ); - } - - // FIXME: physical mapping is not implemented. - if ( pStage->enableSpecularMapping ) - { - float minSpec = RB_EvalExpression( &pStage->specularExponentMin, r_specularExponentMin->value ); - float maxSpec = RB_EvalExpression( &pStage->specularExponentMax, r_specularExponentMax->value ); - - gl_forwardLightingShader_omniXYZ->SetUniform_SpecularExponent( minSpec, maxSpec ); - - // bind u_MaterialMap - gl_forwardLightingShader_omniXYZ->SetUniform_MaterialMapBindless( - GL_BindToTMU( 2, pStage->bundle[TB_MATERIALMAP].image[0] ) - ); - } - - // bind u_AttenuationMapXY - gl_forwardLightingShader_omniXYZ->SetUniform_AttenuationMapXYBindless( - BindAnimatedImage( 3, &attenuationXYStage->bundle[TB_COLORMAP]) ); - - // bind u_AttenuationMapZ - gl_forwardLightingShader_omniXYZ->SetUniform_AttenuationMapZBindless( - BindAnimatedImage( 4, &attenuationZStage->bundle[TB_COLORMAP] ) ); - - // bind u_RandomMap - gl_forwardLightingShader_omniXYZ->SetUniform_RandomMapBindless( - GL_BindToTMU( 6, tr.randomNormalsImage ) - ); - - gl_forwardLightingShader_omniXYZ->SetRequiredVertexPointers(); - - Tess_DrawElements(); - - GL_CheckErrors(); -} - -static void Render_forwardLighting_DBS_proj( shaderStage_t *pStage, - shaderStage_t *attenuationXYStage, - shaderStage_t *attenuationZStage, trRefLight_t *light ) -{ - vec3_t viewOrigin; - vec3_t lightOrigin; - - GLIMP_LOGCOMMENT( "--- Render_forwardLighting_DBS_proj ---" ); - - // choose right shader program ---------------------------------- - gl_forwardLightingShader_projXYZ->SetVertexSkinning( glConfig2.vboVertexSkinningAvailable && tess.vboVertexSkinning ); - gl_forwardLightingShader_projXYZ->SetVertexAnimation( tess.vboVertexAnimation ); - - gl_forwardLightingShader_projXYZ->SetHeightMapInNormalMap( pStage->hasHeightMapInNormalMap ); - - gl_forwardLightingShader_projXYZ->SetReliefMapping( pStage->enableReliefMapping ); - - gl_forwardLightingShader_projXYZ->BindProgram( pStage->deformIndex ); - // end choose right shader program ------------------------------ - - // now we are ready to set the shader program uniforms - - // u_ColorModulate - colorGen_t rgbGen = SetRgbGen( pStage ); - alphaGen_t alphaGen = SetAlphaGen( pStage ); - - SetUniform_ColorModulateColorGen( gl_forwardLightingShader_projXYZ, rgbGen, alphaGen ); - - // u_Color - SetUniform_Color( gl_forwardLightingShader_projXYZ, tess.svars.color ); - - // u_AlphaThreshold - gl_forwardLightingShader_projXYZ->SetUniform_AlphaTest( pStage->stateBits ); - - // bind u_HeightMap - if ( pStage->enableReliefMapping ) - { - float depthScale = RB_EvalExpression( &pStage->depthScaleExp, r_reliefDepthScale->value ); - depthScale *= tess.surfaceShader->reliefDepthScale; - - gl_forwardLightingShader_projXYZ->SetUniform_ReliefDepthScale( depthScale ); - gl_forwardLightingShader_projXYZ->SetUniform_ReliefOffsetBias( tess.surfaceShader->reliefOffsetBias ); - - // FIXME: if there is both, embedded heightmap in normalmap is used instead of standalone heightmap - if ( !pStage->hasHeightMapInNormalMap ) - { - gl_forwardLightingShader_projXYZ->SetUniform_HeightMapBindless( - GL_BindToTMU( 15, pStage->bundle[TB_HEIGHTMAP].image[0] ) - ); - } - } - - // set uniforms - VectorCopy( backEnd.viewParms.orientation.origin, viewOrigin ); - VectorCopy( light->origin, lightOrigin ); - Color::Color lightColor = tess.svars.color; - - gl_forwardLightingShader_projXYZ->SetUniform_ViewOrigin( viewOrigin ); - - gl_forwardLightingShader_projXYZ->SetUniform_LightOrigin( lightOrigin ); - gl_forwardLightingShader_projXYZ->SetUniform_LightColor( lightColor.ToArray() ); - gl_forwardLightingShader_projXYZ->SetUniform_LightRadius( light->sphereRadius ); - gl_forwardLightingShader_projXYZ->SetUniform_LightScale( light->l.scale ); - gl_forwardLightingShader_projXYZ->SetUniform_LightAttenuationMatrix( light->attenuationMatrix2 ); - - GL_CheckErrors(); - - gl_forwardLightingShader_projXYZ->SetUniform_ModelMatrix( backEnd.orientation.transformMatrix ); - gl_forwardLightingShader_projXYZ->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); - - // u_Bones - if ( glConfig2.vboVertexSkinningAvailable && tess.vboVertexSkinning ) - { - gl_forwardLightingShader_projXYZ->SetUniform_Bones( tess.numBones, tess.bones ); - } - - // u_VertexInterpolation - if ( tess.vboVertexAnimation ) - { - gl_forwardLightingShader_projXYZ->SetUniform_VertexInterpolation( glState.vertexAttribsInterpolation ); - } - - gl_forwardLightingShader_projXYZ->SetUniform_Time( backEnd.refdef.floatTime - backEnd.currentEntity->e.shaderTime ); - - GL_CheckErrors(); - - // bind u_DiffuseMap - gl_forwardLightingShader_projXYZ->SetUniform_DiffuseMapBindless( - GL_BindToTMU( 0, pStage->bundle[TB_DIFFUSEMAP].image[0] ) - ); - - if ( pStage->type != stageType_t::ST_LIGHTMAP ) - { - gl_forwardLightingShader_projXYZ->SetUniform_TextureMatrix( tess.svars.texMatrices[ TB_DIFFUSEMAP ] ); - } - - // bind u_NormalMap - gl_forwardLightingShader_projXYZ->SetUniform_NormalMapBindless( - GL_BindToTMU( 1, pStage->bundle[TB_NORMALMAP].image[0] ) - ); - - // bind u_NormalScale - if ( pStage->enableNormalMapping ) - { - vec3_t normalScale; - SetNormalScale( pStage, normalScale ); - - gl_forwardLightingShader_projXYZ->SetUniform_NormalScale( normalScale ); - } - - // bind u_MaterialMap - gl_forwardLightingShader_projXYZ->SetUniform_MaterialMapBindless( - GL_BindToTMU( 2, pStage->bundle[TB_MATERIALMAP].image[0] ) - ); - - // FIXME: physical mapping is not implemented. - if ( pStage->enableSpecularMapping ) - { - float minSpec = RB_EvalExpression( &pStage->specularExponentMin, r_specularExponentMin->value ); - float maxSpec = RB_EvalExpression( &pStage->specularExponentMax, r_specularExponentMax->value ); - - gl_forwardLightingShader_projXYZ->SetUniform_SpecularExponent( minSpec, maxSpec ); - } - - // bind u_AttenuationMapXY - gl_forwardLightingShader_projXYZ->SetUniform_AttenuationMapXYBindless( - BindAnimatedImage( 3, &attenuationXYStage->bundle[TB_COLORMAP] ) ); - - // bind u_AttenuationMapZ - gl_forwardLightingShader_projXYZ->SetUniform_AttenuationMapZBindless( - BindAnimatedImage( 4, &attenuationZStage->bundle[TB_COLORMAP] ) ); - - // bind u_RandomMap - gl_forwardLightingShader_projXYZ->SetUniform_RandomMapBindless( - GL_BindToTMU( 6, tr.randomNormalsImage ) - ); - - gl_forwardLightingShader_projXYZ->SetRequiredVertexPointers(); - - Tess_DrawElements(); - - GL_CheckErrors(); -} - -static void Render_forwardLighting_DBS_directional( shaderStage_t *pStage, trRefLight_t *light ) -{ - vec3_t viewOrigin; - vec3_t lightDirection; - - GLIMP_LOGCOMMENT( "--- Render_forwardLighting_DBS_directional ---" ); - - // choose right shader program ---------------------------------- - gl_forwardLightingShader_directionalSun->SetVertexSkinning( glConfig2.vboVertexSkinningAvailable && tess.vboVertexSkinning ); - gl_forwardLightingShader_directionalSun->SetVertexAnimation( tess.vboVertexAnimation ); - - gl_forwardLightingShader_directionalSun->SetHeightMapInNormalMap( pStage->hasHeightMapInNormalMap ); - - gl_forwardLightingShader_directionalSun->SetReliefMapping( pStage->enableReliefMapping ); - - gl_forwardLightingShader_directionalSun->BindProgram( pStage->deformIndex ); - // end choose right shader program ------------------------------ - - // now we are ready to set the shader program uniforms - - // u_ColorModulate - colorGen_t rgbGen = SetRgbGen( pStage ); - alphaGen_t alphaGen = SetAlphaGen( pStage ); - - SetUniform_ColorModulateColorGen( gl_forwardLightingShader_directionalSun, rgbGen, alphaGen ); - - // u_Color - SetUniform_Color( gl_forwardLightingShader_directionalSun, tess.svars.color ); - - // u_AlphaThreshold - gl_forwardLightingShader_directionalSun->SetUniform_AlphaTest( pStage->stateBits ); - - // bind u_HeightMap - if ( pStage->enableReliefMapping ) - { - float depthScale = RB_EvalExpression( &pStage->depthScaleExp, r_reliefDepthScale->value ); - depthScale *= tess.surfaceShader->reliefDepthScale; - - gl_forwardLightingShader_directionalSun->SetUniform_ReliefDepthScale( depthScale ); - gl_forwardLightingShader_directionalSun->SetUniform_ReliefOffsetBias( tess.surfaceShader->reliefOffsetBias ); - - // FIXME: if there is both, embedded heightmap in normalmap is used instead of standalone heightmap - if ( !pStage->hasHeightMapInNormalMap ) - { - gl_forwardLightingShader_directionalSun->SetUniform_HeightMapBindless( - GL_BindToTMU( 15, pStage->bundle[TB_HEIGHTMAP].image[0] ) - ); - } - } - - // set uniforms - VectorCopy( backEnd.viewParms.orientation.origin, viewOrigin ); - - VectorCopy( tr.sunDirection, lightDirection ); - - Color::Color lightColor = tess.svars.color; - - gl_forwardLightingShader_directionalSun->SetUniform_ViewOrigin( viewOrigin ); - - gl_forwardLightingShader_directionalSun->SetUniform_LightDir( lightDirection ); - gl_forwardLightingShader_directionalSun->SetUniform_LightColor( lightColor.ToArray() ); - gl_forwardLightingShader_directionalSun->SetUniform_LightRadius( light->sphereRadius ); - gl_forwardLightingShader_directionalSun->SetUniform_LightScale( light->l.scale ); - gl_forwardLightingShader_directionalSun->SetUniform_LightAttenuationMatrix( light->attenuationMatrix2 ); - - GL_CheckErrors(); - - gl_forwardLightingShader_directionalSun->SetUniform_ModelMatrix( backEnd.orientation.transformMatrix ); - gl_forwardLightingShader_directionalSun->SetUniform_ViewMatrix( backEnd.viewParms.world.viewMatrix ); - gl_forwardLightingShader_directionalSun->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); - - // u_Bones - if ( glConfig2.vboVertexSkinningAvailable && tess.vboVertexSkinning ) - { - gl_forwardLightingShader_directionalSun->SetUniform_Bones( tess.numBones, tess.bones ); - } - - // u_VertexInterpolation - if ( tess.vboVertexAnimation ) - { - gl_forwardLightingShader_directionalSun->SetUniform_VertexInterpolation( glState.vertexAttribsInterpolation ); - } - - gl_forwardLightingShader_directionalSun->SetUniform_Time( backEnd.refdef.floatTime - backEnd.currentEntity->e.shaderTime ); - - GL_CheckErrors(); - - // bind u_DiffuseMap - gl_forwardLightingShader_directionalSun->SetUniform_DiffuseMapBindless( - GL_BindToTMU( 0, pStage->bundle[TB_DIFFUSEMAP].image[0] ) - ); - - if ( pStage->type != stageType_t::ST_LIGHTMAP ) - { - gl_forwardLightingShader_directionalSun->SetUniform_TextureMatrix( tess.svars.texMatrices[ TB_DIFFUSEMAP ] ); - } - - // bind u_NormalMap - gl_forwardLightingShader_directionalSun->SetUniform_NormalMapBindless( - GL_BindToTMU( 1, pStage->bundle[TB_NORMALMAP].image[0] ) - ); - - // bind u_NormalScale - if ( pStage->enableNormalMapping ) - { - vec3_t normalScale; - SetNormalScale( pStage, normalScale ); - - gl_forwardLightingShader_directionalSun->SetUniform_NormalScale( normalScale ); - } - - // bind u_MaterialMap - gl_forwardLightingShader_directionalSun->SetUniform_MaterialMapBindless( - GL_BindToTMU( 2, pStage->bundle[TB_MATERIALMAP].image[0] ) - ); - - // FIXME: physical mapping is not implemented. - if ( pStage->enableSpecularMapping ) - { - float minSpec = RB_EvalExpression( &pStage->specularExponentMin, r_specularExponentMin->value ); - float maxSpec = RB_EvalExpression( &pStage->specularExponentMax, r_specularExponentMax->value ); - gl_forwardLightingShader_directionalSun->SetUniform_SpecularExponent( minSpec, maxSpec ); - } - - gl_forwardLightingShader_directionalSun->SetRequiredVertexPointers(); - - Tess_DrawElements(); - - GL_CheckErrors(); -} - void Render_reflection_CB( shaderStage_t *pStage ) { GLIMP_LOGCOMMENT( "--- Render_reflection_CB ---" ); @@ -2145,12 +1702,7 @@ void Tess_ComputeColor( shaderStage_t *pStage ) case colorGen_t::CGEN_ENTITY: { - if ( backEnd.currentLight ) - { - tess.svars.color = Color::Adapt( backEnd.currentLight->l.color ); - tess.svars.color.Clamp(); - } - else if ( backEnd.currentEntity ) + if ( backEnd.currentEntity ) { tess.svars.color = backEnd.currentEntity->e.shaderRGBA; tess.svars.color.Clamp(); @@ -2165,13 +1717,7 @@ void Tess_ComputeColor( shaderStage_t *pStage ) case colorGen_t::CGEN_ONE_MINUS_ENTITY: { - if ( backEnd.currentLight ) - { - tess.svars.color.SetRed( 1.0 - Math::Clamp( backEnd.currentLight->l.color[ 0 ], 0.0f, 1.0f ) ); - tess.svars.color.SetGreen( 1.0 - Math::Clamp( backEnd.currentLight->l.color[ 1 ], 0.0f, 1.0f ) ); - tess.svars.color.SetBlue( 1.0 - Math::Clamp( backEnd.currentLight->l.color[ 2 ], 0.0f, 1.0f ) ); - } - else if ( backEnd.currentEntity ) + if ( backEnd.currentEntity ) { tess.svars.color = backEnd.currentEntity->e.shaderRGBA; tess.svars.color.Clamp(); @@ -2221,13 +1767,7 @@ void Tess_ComputeColor( shaderStage_t *pStage ) case colorGen_t::CGEN_CUSTOM_RGBs: { - if ( backEnd.currentLight ) - { - red = Math::Clamp( RB_EvalExpression( &pStage->redExp, backEnd.currentLight->l.color[ 0 ] ), 0.0f, 1.0f ); - green = Math::Clamp( RB_EvalExpression( &pStage->greenExp, backEnd.currentLight->l.color[ 1 ] ), 0.0f, 1.0f ); - blue = Math::Clamp( RB_EvalExpression( &pStage->blueExp, backEnd.currentLight->l.color[ 2 ] ), 0.0f, 1.0f ); - } - else if ( backEnd.currentEntity ) + if ( backEnd.currentEntity ) { red = Math::Clamp( RB_EvalExpression( &pStage->redExp, backEnd.currentEntity->e.shaderRGBA.Red() * ( 1.0 / 255.0 ) ), 0.0f, 1.0f ); @@ -2278,11 +1818,7 @@ void Tess_ComputeColor( shaderStage_t *pStage ) case alphaGen_t::AGEN_ENTITY: { - if ( backEnd.currentLight ) - { - tess.svars.color.SetAlpha( 1.0 ); // FIXME ? - } - else if ( backEnd.currentEntity ) + if ( backEnd.currentEntity ) { tess.svars.color.SetAlpha( Math::Clamp( backEnd.currentEntity->e.shaderRGBA.Alpha() * ( 1.0 / 255.0 ), 0.0, 1.0 ) ); } @@ -2296,11 +1832,7 @@ void Tess_ComputeColor( shaderStage_t *pStage ) case alphaGen_t::AGEN_ONE_MINUS_ENTITY: { - if ( backEnd.currentLight ) - { - tess.svars.color.SetAlpha( 0.0 ); // FIXME ? - } - else if ( backEnd.currentEntity ) + if ( backEnd.currentEntity ) { tess.svars.color.SetAlpha( 1.0 - Math::Clamp( backEnd.currentEntity->e.shaderRGBA.Alpha() * ( 1.0 / 255.0 ), 0.0, 1.0 ) ); } @@ -2476,107 +2008,6 @@ void Tess_StageIteratorPortal() { } } -void Tess_StageIteratorLighting() -{ - trRefLight_t *light; - - GLIMP_LOGCOMMENT( "--- Tess_StageIteratorLighting( %s, %s, %i vertices, %i triangles ) ---", - tess.surfaceShader->name, tess.lightShader->name, tess.numVertexes, tess.numIndexes / 3 ); - - GL_CheckErrors(); - - light = backEnd.currentLight; - - if ( tess.surfaceShader->autoSpriteMode != 0 ) - { - Tess_AutospriteDeform( tess.surfaceShader->autoSpriteMode ); - } - - if ( !glState.currentVBO || !glState.currentIBO || glState.currentVBO == tess.vbo || glState.currentIBO == tess.ibo ) - { - Tess_UpdateVBOs( ); - } - - // set OpenGL state for lighting - if ( tess.surfaceShader->sort > Util::ordinal(shaderSort_t::SS_OPAQUE) ) - { - GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ); - } - else - { - GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL ); - } - - // set face culling appropriately - if( backEnd.currentEntity->e.renderfx & RF_SWAPCULL ) - GL_Cull( ReverseCull( tess.surfaceShader->cullType ) ); - else - GL_Cull( tess.surfaceShader->cullType ); - - // set polygon offset if necessary - if ( tess.surfaceShader->polygonOffset ) - { - glEnable( GL_POLYGON_OFFSET_FILL ); - GL_PolygonOffset( r_offsetFactor->value, r_offsetUnits->value ); - } - - // call shader function - shaderStage_t *attenuationZStage = &tess.lightShader->stages[ 0 ]; - - for ( shaderStage_t *pStage = tess.surfaceStages; pStage < tess.surfaceLastStage; pStage++ ) - { - if ( !RB_EvalExpression( &pStage->ifExp, 1.0 ) ) - { - continue; - } - - Tess_ComputeTexMatrices( pStage ); - - for ( shaderStage_t *attenuationXYStage = tess.lightShader->stages; - attenuationXYStage < tess.lightShader->lastStage; - attenuationXYStage++ ) - { - if ( attenuationXYStage->type != stageType_t::ST_ATTENUATIONMAP_XY ) - { - continue; - } - - if ( !RB_EvalExpression( &attenuationXYStage->ifExp, 1.0 ) ) - { - continue; - } - - Tess_ComputeColor( attenuationXYStage ); - R_ComputeFinalAttenuation( attenuationXYStage, light ); - - if ( pStage->doForwardLighting ) - { - switch( light->l.rlType ) - { - case refLightType_t::RL_OMNI: - Render_forwardLighting_DBS_omni( pStage, attenuationXYStage, attenuationZStage, light ); - break; - case refLightType_t::RL_PROJ: - Render_forwardLighting_DBS_proj( pStage, attenuationXYStage, attenuationZStage, light ); - break; - case refLightType_t::RL_DIRECTIONAL: - Render_forwardLighting_DBS_directional( pStage, light ); - break; - default: - ASSERT_UNREACHABLE(); - break; - }; - } - } - } - - // reset polygon offset - if ( tess.surfaceShader->polygonOffset ) - { - glDisable( GL_POLYGON_OFFSET_FILL ); - } -} - void Tess_Clear() { tess.vboVertexSkinning = false; @@ -2636,7 +2067,7 @@ void Tess_End() tess.stageIteratorFunc != Tess_StageIteratorDummy ) { // draw debugging stuff - if ( r_showTris->integer || r_showBatches->integer || ( r_showLightBatches->integer && ( tess.stageIteratorFunc == Tess_StageIteratorLighting ) ) ) + if ( r_showTris->integer || r_showBatches->integer ) { // Skybox triangle rendering is done in Tess_StageIteratorSky() if ( tess.stageIteratorFunc != Tess_StageIteratorSky ) { diff --git a/src/engine/renderer/tr_shade_calc.cpp b/src/engine/renderer/tr_shade_calc.cpp index 5afa74112..6329c71f0 100644 --- a/src/engine/renderer/tr_shade_calc.cpp +++ b/src/engine/renderer/tr_shade_calc.cpp @@ -99,12 +99,7 @@ static float GetOpValue( const expOperation_t *op ) break; case opcode_t::OP_PARM0: - if ( backEnd.currentLight ) - { - value = backEnd.currentLight->l.color[ 0 ]; - break; - } - else if ( backEnd.currentEntity ) + if ( backEnd.currentEntity ) { value = backEnd.currentEntity->e.shaderRGBA.Red() * inv255; } @@ -116,12 +111,7 @@ static float GetOpValue( const expOperation_t *op ) break; case opcode_t::OP_PARM1: - if ( backEnd.currentLight ) - { - value = backEnd.currentLight->l.color[ 1 ]; - break; - } - else if ( backEnd.currentEntity ) + if ( backEnd.currentEntity ) { value = backEnd.currentEntity->e.shaderRGBA.Green() * inv255; } @@ -133,12 +123,7 @@ static float GetOpValue( const expOperation_t *op ) break; case opcode_t::OP_PARM2: - if ( backEnd.currentLight ) - { - value = backEnd.currentLight->l.color[ 2 ]; - break; - } - else if ( backEnd.currentEntity ) + if ( backEnd.currentEntity ) { value = backEnd.currentEntity->e.shaderRGBA.Blue() * inv255; } @@ -150,12 +135,7 @@ static float GetOpValue( const expOperation_t *op ) break; case opcode_t::OP_PARM3: - if ( backEnd.currentLight ) - { - value = 1.0; - break; - } - else if ( backEnd.currentEntity ) + if ( backEnd.currentEntity ) { value = backEnd.currentEntity->e.shaderRGBA.Alpha() * inv255; } diff --git a/src/engine/renderer/tr_shader.cpp b/src/engine/renderer/tr_shader.cpp index 07a8e0aed..518c4021e 100644 --- a/src/engine/renderer/tr_shader.cpp +++ b/src/engine/renderer/tr_shader.cpp @@ -1781,23 +1781,6 @@ static void ParseReflectionStageBlended( shaderStage_t *stage, const char **text ParseReflectionMap( stage, text, TB_COLORMAP ); } -static void ParseLightFalloffImage( shaderStage_t *stage, const char **text ) -{ - char buffer[ 1024 ] = ""; - - stage->active = true; - stage->type = stageType_t::ST_ATTENUATIONMAP_Z; - stage->rgbGen = colorGen_t::CGEN_IDENTITY; - stage->stateBits = GLS_DEFAULT; - stage->overrideWrapType = true; - stage->wrapType = wrapTypeEnum_t::WT_EDGE_CLAMP; - - if ( ParseMap( text, buffer, sizeof( buffer ) ) ) - { - LoadMap( stage, buffer, stageType_t::ST_COLORMAP ); - } -} - static bool HasNormalFormat( shaderStage_t *stage ) { return stage->normalFormat[ 0 ]; @@ -2142,8 +2125,6 @@ static bool ParseStage( shaderStage_t *stage, const char **text ) else if ( !Q_stricmp( token, "portalMap" ) ) else if ( !Q_stricmp( token, "heathazeMap" ) ) else if ( !Q_stricmp( token, "liquidMap" ) ) - else if ( !Q_stricmp( token, "attenuationMapXY" ) ) - else if ( !Q_stricmp( token, "attenuationMapZ" ) ) */ // lightmap // What is the use case for this? @@ -2647,14 +2628,6 @@ static bool ParseStage( shaderStage_t *stage, const char **text ) stage->type = stageType_t::ST_LIQUIDMAP; SetNormalFormat( stage, dxNormalFormat ); } - else if ( !Q_stricmp( token, "attenuationMapXY" ) ) - { - stage->type = stageType_t::ST_ATTENUATIONMAP_XY; - } - else if ( !Q_stricmp( token, "attenuationMapZ" ) ) - { - stage->type = stageType_t::ST_ATTENUATIONMAP_Z; - } else { Log::Warn("unknown stage parameter '%s' in shader '%s'", token, shader.name ); @@ -4638,13 +4611,6 @@ static bool ParseShader( const char *_text ) } continue; } - // lightFalloffImage - else if ( !Q_stricmp( token, "lightFalloffImage" ) ) - { - ParseLightFalloffImage( &stages[ s ], text ); - s++; - continue; - } // Doom 3 DECAL_MACRO else if ( !Q_stricmp( token, "DECAL_MACRO" ) ) { @@ -5208,11 +5174,6 @@ static void FinishStages() lightStageFound = true; break; - case stageType_t::ST_ATTENUATIONMAP_XY: - case stageType_t::ST_ATTENUATIONMAP_Z: - stage->active = ( glConfig2.realtimeLighting && r_realtimeLightingRenderer.Get() == Util::ordinal( realtimeLightingRenderer_t::LEGACY ) ); - break; - default: break; } @@ -5355,9 +5316,6 @@ static void SetStagesRenderers() surfaceDataUpdater_t surfaceDataUpdater; stageShaderBinder_t shaderBinder; stageMaterialProcessor_t materialProcessor; - - // Per-stage configuration. - bool doForwardLighting; }; for ( size_t s = 0; s < numStages; s++ ) @@ -5367,7 +5325,6 @@ static void SetStagesRenderers() stageRendererOptions_t stageRendererOptions = { &Render_NONE, &MarkShaderBuildNONE, &UpdateSurfaceDataNONE, &BindShaderNONE, &ProcessMaterialNONE, - false, }; switch ( stage->type ) @@ -5376,7 +5333,6 @@ static void SetStagesRenderers() stageRendererOptions = { &Render_generic, &MarkShaderBuildGeneric3D, &UpdateSurfaceDataGeneric3D, &BindShaderGeneric3D, &ProcessMaterialGeneric3D, - false, }; break; case stageType_t::ST_STYLELIGHTMAP: @@ -5384,7 +5340,6 @@ static void SetStagesRenderers() stageRendererOptions = { &Render_generic3D, &MarkShaderBuildGeneric3D, &UpdateSurfaceDataGeneric3D, &BindShaderGeneric3D, &ProcessMaterialGeneric3D, - false, }; break; case stageType_t::ST_LIGHTMAP: @@ -5393,14 +5348,12 @@ static void SetStagesRenderers() stageRendererOptions = { &Render_lightMapping, &MarkShaderBuildLightMapping, &UpdateSurfaceDataLightMapping, &BindShaderLightMapping, &ProcessMaterialLightMapping, - true, }; break; case stageType_t::ST_COLLAPSE_COLORMAP: stageRendererOptions = { &Render_lightMapping, &MarkShaderBuildLightMapping, &UpdateSurfaceDataLightMapping, &BindShaderLightMapping, &ProcessMaterialLightMapping, - false, }; break; case stageType_t::ST_REFLECTIONMAP: @@ -5408,21 +5361,18 @@ static void SetStagesRenderers() stageRendererOptions = { &Render_reflection_CB, &MarkShaderBuildReflection, &UpdateSurfaceDataReflection, &BindShaderReflection, &ProcessMaterialReflection, - false, }; break; case stageType_t::ST_SKYBOXMAP: stageRendererOptions = { &Render_skybox, &MarkShaderBuildSkybox, &UpdateSurfaceDataSkybox, &BindShaderSkybox, &ProcessMaterialSkybox, - false, }; break; case stageType_t::ST_SCREENMAP: stageRendererOptions = { &Render_screen, &MarkShaderBuildScreen, &UpdateSurfaceDataScreen, &BindShaderScreen, &ProcessMaterialScreen, - false, }; break; case stageType_t::ST_PORTALMAP: @@ -5431,36 +5381,24 @@ static void SetStagesRenderers() stageRendererOptions = { &Render_portal, &MarkShaderBuildPortal, &UpdateSurfaceDataNONE, &BindShaderNONE, &ProcessMaterialNONE, - false, }; break; case stageType_t::ST_HEATHAZEMAP: stageRendererOptions = { &Render_heatHaze, &MarkShaderBuildHeatHaze, &UpdateSurfaceDataHeatHaze, &BindShaderHeatHaze, &ProcessMaterialHeatHaze, - false, }; break; case stageType_t::ST_LIQUIDMAP: stageRendererOptions = { &Render_liquid, &MarkShaderBuildLiquid, &UpdateSurfaceDataLiquid, &BindShaderLiquid, &ProcessMaterialLiquid, - false, }; break; case stageType_t::ST_FOGMAP: stageRendererOptions = { &Render_fog, &MarkShaderBuildFog, &UpdateSurfaceDataFog, &BindShaderFog, &ProcessMaterialFog, - false, - }; - break; - case stageType_t::ST_ATTENUATIONMAP_XY: - case stageType_t::ST_ATTENUATIONMAP_Z: - stageRendererOptions = { - &Render_NOP, &MarkShaderBuildNOP, - &UpdateSurfaceDataNOP, &BindShaderNOP, &ProcessMaterialNOP, - true, }; break; default: @@ -5469,7 +5407,6 @@ static void SetStagesRenderers() stageRendererOptions = { &Render_NOP, &MarkShaderBuildNOP, &UpdateSurfaceDataNOP, &BindShaderNOP, &ProcessMaterialNOP, - false, }; break; } @@ -5481,8 +5418,6 @@ static void SetStagesRenderers() stage->shaderBinder = stageRendererOptions.shaderBinder; stage->materialProcessor = stageRendererOptions.materialProcessor; - stage->doForwardLighting = stageRendererOptions.doForwardLighting; - // Disable stages that have no renderer yet. if ( stage->colorRenderer == &Render_NONE ) { @@ -5667,8 +5602,6 @@ static void ValidateStage( shaderStage_t *pStage ) { stageType_t::ST_STYLECOLORMAP, { true, true, false, "style color map" } }, { stageType_t::ST_COLLAPSE_COLORMAP, { true, true, true, "collapsed color map" } }, { stageType_t::ST_COLLAPSE_DIFFUSEMAP, { true, true, true, "collapsed diffuseMap" } }, - { stageType_t::ST_ATTENUATIONMAP_XY, { true, true, false, "attenuationMapXY" } }, - { stageType_t::ST_ATTENUATIONMAP_Z, { true, true, false, "attenuationMapZ" } }, // TODO: Document the remaining stage types. }; @@ -5824,40 +5757,6 @@ static shader_t *FinishShader() shader.portalRange = r_portalDefaultRange.Get(); } - // all light materials need at least one z attenuation stage as first stage - if ( shader.type == shaderType_t::SHADER_LIGHT ) - { - if ( stages[ 0 ].type != stageType_t::ST_ATTENUATIONMAP_Z ) - { - // move up subsequent stages - memmove( &stages[ 1 ], &stages[ 0 ], sizeof( stages[ 0 ] ) * ( MAX_SHADER_STAGES - 1 ) ); - - stages[ 0 ].active = true; - stages[ 0 ].type = stageType_t::ST_ATTENUATIONMAP_Z; - stages[ 0 ].rgbGen = colorGen_t::CGEN_IDENTITY; - stages[ 0 ].stateBits = GLS_DEFAULT; - stages[ 0 ].overrideWrapType = true; - stages[ 0 ].wrapType = wrapTypeEnum_t::WT_EDGE_CLAMP; - - const char *squarelight1a = "lights/squarelight1a"; - Log::Debug( "loading '%s' image as shader", squarelight1a ); - LoadMap( &stages[ 0 ], squarelight1a, stageType_t::ST_COLORMAP ); - } - - // force following shader stages to be xy attenuation stages - for ( int i = 1; i < MAX_SHADER_STAGES; i++ ) - { - shaderStage_t *pStage = &stages[ i ]; - - if ( !pStage->active ) - { - break; - } - - pStage->type = stageType_t::ST_ATTENUATIONMAP_XY; - } - } - numStages = MAX_SHADER_STAGES; GroupActiveStages(); @@ -6340,22 +6239,6 @@ shader_t *R_FindShader( const char *name, shaderType_t type, int flags ) break; } - case shaderType_t::SHADER_LIGHT: - { - stages[ 0 ].type = stageType_t::ST_ATTENUATIONMAP_Z; - stages[ 0 ].bundle[ 0 ].image[ 0 ] = tr.noFalloffImage; // FIXME should be attenuationZImage - stages[ 0 ].active = true; - stages[ 0 ].rgbGen = colorGen_t::CGEN_IDENTITY; - stages[ 0 ].stateBits = GLS_DEFAULT; - - stages[ 1 ].type = stageType_t::ST_ATTENUATIONMAP_XY; - stages[ 1 ].bundle[ 0 ].image[ 0 ] = image; - stages[ 1 ].active = true; - stages[ 1 ].rgbGen = colorGen_t::CGEN_IDENTITY; - stages[ 1 ].stateBits = GLS_DEFAULT; - break; - } - default: break; } @@ -6435,9 +6318,7 @@ qhandle_t RE_RegisterShader( const char *name, int flags ) return 0; } - sh = R_FindShader( name, - (flags & RSF_LIGHT_ATTENUATION) ? shaderType_t::SHADER_LIGHT : shaderType_t::SHADER_2D, - flags ); + sh = R_FindShader( name, shaderType_t::SHADER_2D, flags ); // we want to return 0 if the shader failed to // load for some reason, but R_FindShader should @@ -6495,7 +6376,6 @@ class ListShadersCmd : public Cmd::StaticCmd { shaderType_t::SHADER_2D, "2D" }, { shaderType_t::SHADER_3D_DYNAMIC, "3D_DYNAMIC" }, { shaderType_t::SHADER_3D_STATIC, "3D_STATIC" }, - { shaderType_t::SHADER_LIGHT, "LIGHT" }, }; static const std::unordered_map shaderSortName = { @@ -6545,8 +6425,6 @@ class ListShadersCmd : public Cmd::StaticCmd { stageType_t::ST_COLLAPSE_COLORMAP, "COLLAPSE_COLORMAP" }, { stageType_t::ST_COLLAPSE_DIFFUSEMAP, "COLLAPSE_DIFFUSEMAP" }, { stageType_t::ST_COLLAPSE_REFLECTIONMAP, "COLLAPSE_REFLECTIONMAP" }, - { stageType_t::ST_ATTENUATIONMAP_XY, "ATTENUATIONMAP_XY" }, - { stageType_t::ST_ATTENUATIONMAP_Z, "ATTENUATIONMAP_XZ" }, }; const char *prefix = args.Argc() > 1 ? args.Argv( 1 ).c_str() : nullptr; @@ -7003,15 +6881,6 @@ static void CreateInternalShaders() tr.fogLEShader = FinishShader(); } -static void CreateExternalShaders() -{ - Log::Debug("----- CreateExternalShaders -----" ); - - tr.defaultPointLightShader = R_FindShader( "lights/defaultPointLight", shaderType_t::SHADER_LIGHT, RSF_DEFAULT ); - tr.defaultProjectedLightShader = R_FindShader( "lights/defaultProjectedLight", shaderType_t::SHADER_LIGHT, RSF_DEFAULT ); - tr.defaultDynamicLightShader = R_FindShader( "lights/defaultDynamicLight", shaderType_t::SHADER_LIGHT, RSF_DEFAULT ); -} - /* ================== R_InitShaders @@ -7029,8 +6898,6 @@ void R_InitShaders() CreateInternalShaders(); ScanAndLoadShaderFiles(); - - CreateExternalShaders(); } /* diff --git a/src/engine/renderer/tr_types.h b/src/engine/renderer/tr_types.h index 79f277c3f..e6a56639c 100644 --- a/src/engine/renderer/tr_types.h +++ b/src/engine/renderer/tr_types.h @@ -54,7 +54,6 @@ using bool8_t = uint8_t; #define MAX_WEIGHTS 4 // GPU vertex skinning limit, never change this without rewriting many GLSL shaders // XreaL END -#define MAX_DLIGHTS 32 // can't be increased, because bit flags are used on surfaces #define MAX_ENTITIES MAX_REF_ENTITIES // RB: for compatibility // renderfx flags @@ -95,6 +94,7 @@ using bool8_t = uint8_t; #define GL_INDEX_TYPE GL_UNSIGNED_INT using glIndex_t = unsigned int; +// TODO(0.56): drop RSF_LIGHT_ATTENUATION enum RegisterShaderFlags_t { RSF_DEFAULT = BIT( 0 ), RSF_2D = BIT( 1 ), diff --git a/src/engine/renderer/tr_vbo.cpp b/src/engine/renderer/tr_vbo.cpp index b355ca37a..5868845d2 100644 --- a/src/engine/renderer/tr_vbo.cpp +++ b/src/engine/renderer/tr_vbo.cpp @@ -662,18 +662,6 @@ static void R_InitTileVBO() return; } - if ( r_realtimeLightingRenderer.Get() != Util::ordinal( realtimeLightingRenderer_t::TILED ) ) - { - /* This computation is part of the tiled dynamic lighting renderer, - it's better to not run it and save CPU cycles when such effects - are disabled. - - There is no need to create vertex buffers that are only used by the - tiled dynamic lighting renderer when this feature is disabled. */ - - return; - } - R_SyncRenderThread(); int x, y, w, h; diff --git a/src/engine/renderer/tr_world.cpp b/src/engine/renderer/tr_world.cpp index 9c643156f..b482743f6 100644 --- a/src/engine/renderer/tr_world.cpp +++ b/src/engine/renderer/tr_world.cpp @@ -125,131 +125,6 @@ static bool R_CullSurface( surfaceType_t *surface, shader_t *shader, int planeBi return false; } -static bool R_CullLightSurface( surfaceType_t *surface, shader_t *shader, trRefLight_t *light, byte */*cubeSideBits*/) -{ - srfGeneric_t *gen; - float d; - - // allow culling to be disabled - if ( r_nocull->integer ) - { - return false; - } - - // ydnar: made surface culling generic, inline with q3map2 surface classification - if ( *surface == surfaceType_t::SF_GRID && r_nocurves->integer ) - { - return true; - } - - if ( *surface != surfaceType_t::SF_FACE && *surface != surfaceType_t::SF_TRIANGLES && *surface != surfaceType_t::SF_VBO_MESH && *surface != surfaceType_t::SF_GRID ) - { - return true; - } - - gen = ( srfGeneric_t * ) surface; - - // do a quick AABB cull - if ( !BoundsIntersect( light->worldBounds[ 0 ], light->worldBounds[ 1 ], gen->bounds[ 0 ], gen->bounds[ 1 ] ) ) - { - return true; - } - - // do a more expensive and precise light frustum cull - if ( !r_noLightFrustums->integer ) - { - if ( R_CullLightWorldBounds( light, gen->bounds ) == CULL_OUT ) - { - return true; - } - } - - // plane cull - if ( *surface == surfaceType_t::SF_FACE && r_facePlaneCull->integer ) - { - srfGeneric_t* srf = ( srfGeneric_t* ) gen; - if ( light->l.rlType == refLightType_t::RL_DIRECTIONAL ) - { - d = DotProduct( tr.sunDirection, srf->plane.normal ); - } - else - { - d = DotProduct( light->origin, srf->plane.normal ) - srf->plane.dist; - } - // don't cull exactly on the plane, because there are levels of rounding - // through the BSP, ICD, and hardware that may cause pixel gaps if an - // epsilon isn't allowed here - if ( shader->cullType == CT_FRONT_SIDED ) - { - if ( d < -8.0f ) - { - return true; - } - } - else if ( shader->cullType == CT_BACK_SIDED ) - { - if ( d > 8.0f ) - { - return true; - } - } - } - - return false; -} - -/* -====================== -R_AddInteractionSurface -====================== -*/ -static void R_AddInteractionSurface( bspSurface_t *surf, trRefLight_t *light, int interactionBits ) -{ - byte cubeSideBits = CUBESIDE_CLIPALL; - bool firstAddition = false; - int bits; - - if ( surf->lightCount != tr.lightCount ) - { - surf->interactionBits = 0; - surf->lightCount = tr.lightCount; - firstAddition = true; - } - - // only add interactions we haven't already added - bits = interactionBits & ~surf->interactionBits; - - if ( !bits ) - { - // already added these interactions - return; - } - - surf->interactionBits |= bits; - - // skip all surfaces that don't matter for lighting only pass - if ( surf->shader->isSky || !surf->shader->interactLight ) - { - return; - } - - if ( R_CullLightSurface( surf->data, surf->shader, light, &cubeSideBits ) ) - { - if ( firstAddition ) - { - tr.pc.c_dlightSurfacesCulled++; - } - return; - } - - R_AddLightInteraction( light, surf->data, surf->shader, cubeSideBits, ( interactionType_t ) bits ); - - if ( firstAddition ) - { - tr.pc.c_dlightSurfaces++; - } -} - /* ====================== R_AddWorldSurface @@ -463,110 +338,6 @@ static void R_RecursiveWorldNode( bspNode_t *node, int planeBits ) } } -/* -================ -R_RecursiveInteractionNode -================ -*/ -static void R_RecursiveInteractionNode( bspNode_t *node, trRefLight_t *light, int planeBits, int interactionBits ) -{ - int i; - int r; - - do - { - // surfaces that arn't potentially visible may still cast shadows - // but we don't bother lighting them since there will be no visible effect - if ( node->visCounts[ tr.visIndex ] != tr.visCounts[ tr.visIndex ] ) - { - interactionBits &= ~IA_LIGHT; - } - - // if the bounding volume is outside the frustum, nothing - // inside can be visible OPTIMIZE: don't do this all the way to leafs? - - // Tr3B - even surfaces that belong to nodes that are outside of the view frustum - // can cast shadows into the view frustum - if ( !r_nocull->integer ) - { - for ( i = 0; i < FRUSTUM_PLANES; i++ ) - { - if ( planeBits & ( 1 << i ) ) - { - r = BoxOnPlaneSide( node->mins, node->maxs, &tr.viewParms.frustums[ 0 ][ i ] ); - - if ( r == 2 ) - { - // this node cannot be lighted, but may cast shadows - interactionBits &= ~IA_LIGHT; - break; - } - - if ( r == 1 ) - { - planeBits &= ~( 1 << i ); // all descendants will also be in front - } - } - } - } - - // don't waste time on nodes with no interactions - if ( !interactionBits ) - { - return; - } - - if ( node->contents != -1 ) - { - break; - } - - // node is just a decision point, so go down both sides - // since we don't care about sort orders, just go positive to negative - r = BoxOnPlaneSide( light->worldBounds[ 0 ], light->worldBounds[ 1 ], node->plane ); - - switch ( r ) - { - case 1: - node = node->children[ 0 ]; - break; - - case 2: - node = node->children[ 1 ]; - break; - - case 3: - default: - // recurse down the children, front side first - R_RecursiveInteractionNode( node->children[ 0 ], light, planeBits, interactionBits ); - - // tail recurse - node = node->children[ 1 ]; - break; - } - } - while ( true ); - - { - // leaf node, so add mark surfaces - int c; - bspSurface_t *surf, **mark; - - // add the individual surfaces - mark = tr.world->markSurfaces + node->firstMarkSurface; - c = node->numMarkSurfaces; - - while ( c-- ) - { - // the surface may have already been added if it - // spans multiple leafs - surf = *mark; - R_AddInteractionSurface( surf, light, interactionBits ); - mark++; - } - } -} - /* =============== R_PointInLeaf @@ -836,39 +607,3 @@ void R_AddWorldSurfaces() // update visbounds and add surfaces that weren't cached with VBOs R_RecursiveWorldNode( tr.world->nodes, FRUSTUM_CLIPALL ); } - -/* -============= -R_AddWorldInteractions -============= -*/ -void R_AddWorldInteractions( trRefLight_t *light ) -{ - int interactionBits; - - if ( !r_drawworld->integer ) - { - return; - } - - if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) - { - return; - } - - tr.currentEntity = &tr.worldEntity; - - // perform frustum culling and add all the potentially visible surfaces - tr.lightCount++; - - interactionBits = IA_DEFAULT; - - if ( light->restrictInteractionFirst >= 0 ) - { - interactionBits = IA_DEFAULTCLIP; - } - - interactionBits &= IA_LIGHT; - - R_RecursiveInteractionNode( tr.world->nodes, light, FRUSTUM_CLIPALL, interactionBits ); -} From fe20e6cc32933fe7aea841f10aa7485c177e1b6d Mon Sep 17 00:00:00 2001 From: slipher Date: Tue, 20 May 2025 11:24:48 -0500 Subject: [PATCH 16/41] Additional cleanup after NUKING forward lighting --- src/engine/renderer/GeometryOptimiser.cpp | 22 +++++------ src/engine/renderer/gl_shader.cpp | 2 - src/engine/renderer/gl_shader.h | 1 - src/engine/renderer/tr_backend.cpp | 22 +++++------ src/engine/renderer/tr_bsp.cpp | 2 - src/engine/renderer/tr_local.h | 16 ++------ src/engine/renderer/tr_main.cpp | 46 +++++++++++------------ src/engine/renderer/tr_scene.cpp | 16 ++++---- src/engine/renderer/tr_world.cpp | 2 +- 9 files changed, 58 insertions(+), 71 deletions(-) diff --git a/src/engine/renderer/GeometryOptimiser.cpp b/src/engine/renderer/GeometryOptimiser.cpp index aa1b9237d..4de4c4e05 100644 --- a/src/engine/renderer/GeometryOptimiser.cpp +++ b/src/engine/renderer/GeometryOptimiser.cpp @@ -61,16 +61,16 @@ static int LeafSurfaceCompare( const void* a, const void* b ) { } // sort by leaf - if ( aa->interactionBits < bb->interactionBits ) { + if ( aa->scratch2 < bb->scratch2 ) { return -1; - } else if ( aa->interactionBits > bb->interactionBits ) { + } else if ( aa->scratch2 > bb->scratch2 ) { return 1; } // sort by leaf marksurfaces index to increase the likelihood of multidraw merging in the backend - if ( aa->lightCount < bb->lightCount ) { + if ( aa->scratch1 < bb->scratch1 ) { return -1; - } else if ( aa->lightCount > bb->lightCount ) { + } else if ( aa->scratch1 > bb->scratch1 ) { return 1; } return 0; @@ -150,8 +150,8 @@ static void CoreResetSurfaceViewCounts( bspSurface_t** rendererSurfaces, int num bspSurface_t* surface = rendererSurfaces[i]; surface->viewCount = -1; - surface->lightCount = -1; - surface->interactionBits = 0; + surface->scratch1 = -1; + surface->scratch2 = 0; } } @@ -178,8 +178,8 @@ void OptimiseMapGeometryCore( world_t* world, bspSurface_t** rendererSurfaces, i int fogIndex1 = surf1->fogIndex; int lightMapNum1 = surf1->lightmapNum; surf1->viewCount = surf1 - world->surfaces; - surf1->lightCount = j; - surf1->interactionBits = i; + surf1->scratch1 = j; + surf1->scratch2 = i; bool merged = false; for ( int k = j + 1; k < leaf->numMarkSurfaces; k++ ) { @@ -201,14 +201,14 @@ void OptimiseMapGeometryCore( world_t* world, bspSurface_t** rendererSurfaces, i } surf2->viewCount = surf1->viewCount; - surf2->lightCount = k; - surf2->interactionBits = i; + surf2->scratch1 = k; + surf2->scratch2 = i; merged = true; } if ( !merged ) { surf1->viewCount = -1; - surf1->lightCount = -1; + surf1->scratch1 = -1; // don't clear the leaf number so // surfaces that arn't merged are placed // closer to other leafs in the vbo diff --git a/src/engine/renderer/gl_shader.cpp b/src/engine/renderer/gl_shader.cpp index e482edd41..b6635e88c 100644 --- a/src/engine/renderer/gl_shader.cpp +++ b/src/engine/renderer/gl_shader.cpp @@ -1326,8 +1326,6 @@ void GLShaderManager::InitShader( GLShader* shader ) { continue; } - shader->BuildShaderCompileMacros( compileMacros ); - const uint32_t uniqueMacros = shader->GetUniqueCompileMacros( i, shaderType.type ); ShaderDescriptor* desc = FindShader( shader->_name, shaderType.mainText, shaderType.GLType, shaderType.headers, diff --git a/src/engine/renderer/gl_shader.h b/src/engine/renderer/gl_shader.h index 16fe16165..bcf4980db 100644 --- a/src/engine/renderer/gl_shader.h +++ b/src/engine/renderer/gl_shader.h @@ -181,7 +181,6 @@ class GLShader { void PostProcessUniforms(); uint32_t GetUniqueCompileMacros( size_t permutation, const int type ) const; bool GetCompileMacrosString( size_t permutation, std::string &compileMacrosOut, const int type ) const; - virtual void BuildShaderCompileMacros( std::string& /*vertexInlines*/ ) { }; virtual void SetShaderProgramUniforms( ShaderProgramDescriptor* /*shaderProgram*/ ) { }; int SelectProgram(); public: diff --git a/src/engine/renderer/tr_backend.cpp b/src/engine/renderer/tr_backend.cpp index a5bec27ba..087c629b3 100644 --- a/src/engine/renderer/tr_backend.cpp +++ b/src/engine/renderer/tr_backend.cpp @@ -2208,8 +2208,8 @@ static void RB_RenderDebugUtils() plane_t splitFrustum[ 6 ]; for ( j = 0; j < 6; j++ ) { - VectorCopy( backEnd.viewParms.frustums[ 0 ][ j ].normal, splitFrustum[ j ].normal ); - splitFrustum[ j ].dist = backEnd.viewParms.frustums[ 0 ][ j ].dist; + VectorCopy( backEnd.viewParms.frustum[ j ].normal, splitFrustum[ j ].normal ); + splitFrustum[ j ].dist = backEnd.viewParms.frustum[ j ].dist; } // calculate split frustum corner points @@ -3170,20 +3170,20 @@ const RenderCommand *SetupLightsCommand::ExecuteSelf( ) const GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT ); for( int i = 0, j = 0; i < numLights; i++, j++ ) { - trRefLight_t *light = &refdef.lights[j]; + refLight_t *light = &refdef.lights[j]; - VectorCopy( light->l.origin, buffer[i].center ); - buffer[i].radius = light->l.radius; - VectorScale( light->l.color, 4.0f * light->l.scale, buffer[i].color ); - buffer[i].type = Util::ordinal( light->l.rlType ); - switch( light->l.rlType ) { + VectorCopy( light->origin, buffer[i].center ); + buffer[i].radius = light->radius; + VectorScale( light->color, 4.0f * light->scale, buffer[i].color ); + buffer[i].type = Util::ordinal( light->rlType ); + switch( light->rlType ) { case refLightType_t::RL_PROJ: - VectorCopy( light->l.projTarget, + VectorCopy( light->projTarget, buffer[i].direction ); - buffer[i].angle = cosf( atan2f( VectorLength( light->l.projUp), VectorLength( light->l.projTarget ) ) ); + buffer[i].angle = cosf( atan2f( VectorLength( light->projUp), VectorLength( light->projTarget ) ) ); break; case refLightType_t::RL_DIRECTIONAL: - VectorCopy( light->l.projTarget, + VectorCopy( light->projTarget, buffer[i].direction ); break; default: diff --git a/src/engine/renderer/tr_bsp.cpp b/src/engine/renderer/tr_bsp.cpp index 36f98d2c4..23b85e2cd 100644 --- a/src/engine/renderer/tr_bsp.cpp +++ b/src/engine/renderer/tr_bsp.cpp @@ -2753,8 +2753,6 @@ static void R_CreateWorldVBO() { // clear data used for sorting surface->viewCount = -1; - surface->lightCount = -1; - surface->interactionBits = 0; } ri.Hunk_FreeTempMemory( rendererSurfaces ); diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index ef662eca8..a1405e9fd 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -404,12 +404,6 @@ enum class ssaoMode { vec3_t projUp; }; - // TODO: remove useless struct - struct trRefLight_t - { - refLight_t l; - }; - // a structure matching the GLSL struct shaderLight in std140 layout struct shaderLight_t { vec3_t center; @@ -1387,7 +1381,7 @@ enum class ssaoMode { trRefEntity_t *entities; int numLights; - trRefLight_t *lights; + refLight_t *lights; int numPolys; struct srfPoly_t *polys; @@ -1467,7 +1461,7 @@ enum class ssaoMode { matrix_t projectionMatrixNonPortal; // For skybox rendering in portals matrix_t unprojectionMatrix; // transform pixel window space -> world space - frustum_t frustums[ 1 ]; // FIXME: need not be array (was for shadowmaps) + frustum_t frustum; vec3_t visBounds[ 2 ]; float zNear; @@ -1721,9 +1715,7 @@ enum class ssaoMode { { int viewCount; // if == tr.viewCount, already added - // FIXME not used for lighting - int lightCount; - int interactionBits; + int scratch1, scratch2; struct shader_t *shader; @@ -3721,7 +3713,7 @@ void GLimp_LogComment_( std::string comment ); { drawSurf_t drawSurfs[ MAX_DRAWSURFS ]; - trRefLight_t lights[ MAX_REF_LIGHTS ]; + refLight_t lights[ MAX_REF_LIGHTS ]; trRefEntity_t entities[ MAX_REF_ENTITIES ]; srfPoly_t *polys; //[MAX_POLYS]; diff --git a/src/engine/renderer/tr_main.cpp b/src/engine/renderer/tr_main.cpp index 342910a7d..77259a2aa 100644 --- a/src/engine/renderer/tr_main.cpp +++ b/src/engine/renderer/tr_main.cpp @@ -349,7 +349,7 @@ cullResult_t R_CullBox( vec3_t worldBounds[ 2 ] ) for ( i = 0; i < FRUSTUM_PLANES; i++ ) { - frust = &tr.viewParms.frustums[ 0 ][ i ]; + frust = &tr.viewParms.frustum[ i ]; r = BoxOnPlaneSide( worldBounds[ 0 ], worldBounds[ 1 ], frust ); @@ -426,7 +426,7 @@ cullResult_t R_CullPointAndRadius( vec3_t pt, float radius ) // check against frustum planes for ( i = 0; i < Util::ordinal(frustumBits_t::FRUSTUM_PLANES); i++ ) { - frust = &tr.viewParms.frustums[ 0 ][ i ]; + frust = &tr.viewParms.frustum[ i ]; dist = DotProduct( pt, frust->normal ) - frust->dist; @@ -878,11 +878,11 @@ static void R_SetupFrustum() MatrixTransformPlane2(invTransform, plane); - VectorCopy(plane.normal, tr.viewParms.frustums[0][i].normal); - tr.viewParms.frustums[0][i].dist = plane.dist; + VectorCopy(plane.normal, tr.viewParms.frustum[i].normal); + tr.viewParms.frustum[i].dist = plane.dist; - SetPlaneSignbits(&tr.viewParms.frustums[0][i]); - tr.viewParms.frustums[0][i].type = PLANE_NON_AXIAL; + SetPlaneSignbits(&tr.viewParms.frustum[i]); + tr.viewParms.frustum[i].type = PLANE_NON_AXIAL; } } else @@ -891,36 +891,36 @@ static void R_SetupFrustum() xs = sinf( ang ); xc = cosf( ang ); - VectorScale( tr.viewParms.orientation.axis[ 0 ], xs, tr.viewParms.frustums[ 0 ][ 0 ].normal ); - VectorMA( tr.viewParms.frustums[ 0 ][ 0 ].normal, xc, tr.viewParms.orientation.axis[ 1 ], tr.viewParms.frustums[ 0 ][ 0 ].normal ); + VectorScale( tr.viewParms.orientation.axis[ 0 ], xs, tr.viewParms.frustum[ 0 ].normal ); + VectorMA( tr.viewParms.frustum[ 0 ].normal, xc, tr.viewParms.orientation.axis[ 1 ], tr.viewParms.frustum[ 0 ].normal ); - VectorScale( tr.viewParms.orientation.axis[ 0 ], xs, tr.viewParms.frustums[ 0 ][ 1 ].normal ); - VectorMA( tr.viewParms.frustums[ 0 ][ 1 ].normal, -xc, tr.viewParms.orientation.axis[ 1 ], tr.viewParms.frustums[ 0 ][ 1 ].normal ); + VectorScale( tr.viewParms.orientation.axis[ 0 ], xs, tr.viewParms.frustum[ 1 ].normal ); + VectorMA( tr.viewParms.frustum[ 1 ].normal, -xc, tr.viewParms.orientation.axis[ 1 ], tr.viewParms.frustum[ 1 ].normal ); ang = DEG2RAD( tr.viewParms.fovY * 0.5f ); xs = sinf( ang ); xc = cosf( ang ); - VectorScale( tr.viewParms.orientation.axis[ 0 ], xs, tr.viewParms.frustums[ 0 ][ 2 ].normal ); - VectorMA( tr.viewParms.frustums[ 0 ][ 2 ].normal, xc, tr.viewParms.orientation.axis[ 2 ], tr.viewParms.frustums[ 0 ][ 2 ].normal ); + VectorScale( tr.viewParms.orientation.axis[ 0 ], xs, tr.viewParms.frustum[ 2 ].normal ); + VectorMA( tr.viewParms.frustum[ 2 ].normal, xc, tr.viewParms.orientation.axis[ 2 ], tr.viewParms.frustum[ 2 ].normal ); - VectorScale( tr.viewParms.orientation.axis[ 0 ], xs, tr.viewParms.frustums[ 0 ][ 3 ].normal ); - VectorMA( tr.viewParms.frustums[ 0 ][ 3 ].normal, -xc, tr.viewParms.orientation.axis[ 2 ], tr.viewParms.frustums[ 0 ][ 3 ].normal ); + VectorScale( tr.viewParms.orientation.axis[ 0 ], xs, tr.viewParms.frustum[ 3 ].normal ); + VectorMA( tr.viewParms.frustum[ 3 ].normal, -xc, tr.viewParms.orientation.axis[ 2 ], tr.viewParms.frustum[ 3 ].normal ); for ( int i = 0; i < 4; i++ ) { - tr.viewParms.frustums[ 0 ][ i ].type = PLANE_NON_AXIAL; - tr.viewParms.frustums[ 0 ][ i ].dist = DotProduct( tr.viewParms.orientation.origin, tr.viewParms.frustums[ 0 ][ i ].normal ); - SetPlaneSignbits( &tr.viewParms.frustums[ 0 ][ i ] ); + tr.viewParms.frustum[ i ].type = PLANE_NON_AXIAL; + tr.viewParms.frustum[ i ].dist = DotProduct( tr.viewParms.orientation.origin, tr.viewParms.frustum[ i ].normal ); + SetPlaneSignbits( &tr.viewParms.frustum[ i ] ); } // Tr3B: set extra near plane which is required by the dynamic occlusion culling - tr.viewParms.frustums[ 0 ][ FRUSTUM_NEAR ].type = PLANE_NON_AXIAL; - VectorCopy( tr.viewParms.orientation.axis[ 0 ], tr.viewParms.frustums[ 0 ][ FRUSTUM_NEAR ].normal ); + tr.viewParms.frustum[ FRUSTUM_NEAR ].type = PLANE_NON_AXIAL; + VectorCopy( tr.viewParms.orientation.axis[ 0 ], tr.viewParms.frustum[ FRUSTUM_NEAR ].normal ); - VectorMA( tr.viewParms.orientation.origin, r_znear->value, tr.viewParms.frustums[ 0 ][ FRUSTUM_NEAR ].normal, planeOrigin ); - tr.viewParms.frustums[ 0 ][ FRUSTUM_NEAR ].dist = DotProduct( planeOrigin, tr.viewParms.frustums[ 0 ][ FRUSTUM_NEAR ].normal ); - SetPlaneSignbits( &tr.viewParms.frustums[ 0 ][ FRUSTUM_NEAR ] ); + VectorMA( tr.viewParms.orientation.origin, r_znear->value, tr.viewParms.frustum[ FRUSTUM_NEAR ].normal, planeOrigin ); + tr.viewParms.frustum[ FRUSTUM_NEAR ].dist = DotProduct( planeOrigin, tr.viewParms.frustum[ FRUSTUM_NEAR ].normal ); + SetPlaneSignbits( &tr.viewParms.frustum[ FRUSTUM_NEAR ] ); } } @@ -2054,7 +2054,7 @@ void R_RenderView( viewParms_t *parms ) if ( glConfig2.usingMaterialSystem && !r_materialSystemSkip.Get() ) { tr.viewParms.viewID = tr.viewCount; - materialSystem.QueueSurfaceCull( tr.viewCount, tr.viewParms.pvsOrigin, (frustum_t*) tr.viewParms.frustums[0] ); + materialSystem.QueueSurfaceCull( tr.viewCount, tr.viewParms.pvsOrigin, (frustum_t*) tr.viewParms.frustum ); materialSystem.AddAutospriteSurfaces(); } else { R_AddWorldSurfaces(); diff --git a/src/engine/renderer/tr_scene.cpp b/src/engine/renderer/tr_scene.cpp index c3a524fa5..388d8a16a 100644 --- a/src/engine/renderer/tr_scene.cpp +++ b/src/engine/renderer/tr_scene.cpp @@ -285,7 +285,7 @@ ydnar: modified dlight system to support separate radius and intensity */ void RE_AddDynamicLightToSceneET( const vec3_t org, float radius, float intensity, float r, float g, float b, qhandle_t, int flags ) { - trRefLight_t *light; + refLight_t *light; if ( !glConfig2.realtimeLighting || !r_drawDynamicLights.Get() ) { @@ -315,16 +315,16 @@ void RE_AddDynamicLightToSceneET( const vec3_t org, float radius, float intensit light = &backEndData[ tr.smpFrame ]->lights[ r_numLights++ ]; - light->l.rlType = refLightType_t::RL_OMNI; - VectorCopy( org, light->l.origin ); + light->rlType = refLightType_t::RL_OMNI; + VectorCopy( org, light->origin ); - light->l.radius = radius; + light->radius = radius; - light->l.color[ 0 ] = r; - light->l.color[ 1 ] = g; - light->l.color[ 2 ] = b; + light->color[ 0 ] = r; + light->color[ 1 ] = g; + light->color[ 2 ] = b; - light->l.scale = intensity; + light->scale = intensity; } void RE_AddDynamicLightToSceneQ3A( const vec3_t org, float radius, float r, float g, float b ) diff --git a/src/engine/renderer/tr_world.cpp b/src/engine/renderer/tr_world.cpp index b482743f6..2f846d410 100644 --- a/src/engine/renderer/tr_world.cpp +++ b/src/engine/renderer/tr_world.cpp @@ -297,7 +297,7 @@ static void R_RecursiveWorldNode( bspNode_t *node, int planeBits ) { if ( planeBits & ( 1 << i ) ) { - r = BoxOnPlaneSide( node->mins, node->maxs, &tr.viewParms.frustums[ 0 ][ i ] ); + r = BoxOnPlaneSide( node->mins, node->maxs, &tr.viewParms.frustum[ i ] ); if ( r == 2 ) { From c17a648ba15a2d6f193c23404323ce92a60e4a7d Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Sun, 25 May 2025 13:37:42 +0000 Subject: [PATCH 17/41] bump version number to 0.55.4 --- src/common/Defs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/Defs.h b/src/common/Defs.h index dd5e1dce6..35da643c5 100644 --- a/src/common/Defs.h +++ b/src/common/Defs.h @@ -37,7 +37,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** No case, No spaces */ #define PRODUCT_NAME_LOWER "unvanquished" -#define PRODUCT_VERSION "0.55.3" +#define PRODUCT_VERSION "0.55.4" /** Default base package */ #define DEFAULT_BASE_PAK PRODUCT_NAME_LOWER From f9d9aaae222d5de30240f0466a42e993fab30b17 Mon Sep 17 00:00:00 2001 From: slipher Date: Tue, 8 Apr 2025 20:34:45 -0500 Subject: [PATCH 18/41] Python 3 migration: external_deps/cygtar.py --- external_deps/cygtar.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/external_deps/cygtar.py b/external_deps/cygtar.py index e1cfd1ef4..1a5d5211f 100755 --- a/external_deps/cygtar.py +++ b/external_deps/cygtar.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 # Copyright (c) 2012 The Native Client Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -78,12 +78,12 @@ def CreateCygwinSymlink(filepath, target): lnk.close() break except EnvironmentError: - print 'Try %d: Failed open %s -> %s\n' % (cnt, filepath, target) + print('Try %d: Failed open %s -> %s\n' % (cnt, filepath, target)) # Verify the file was created if not os.path.isfile(filepath): - print 'Try %d: Failed create %s -> %s\n' % (cnt, filepath, target) - print 'Giving up.' + print('Try %d: Failed create %s -> %s\n' % (cnt, filepath, target)) + print('Giving up.') return False # Now set the system attribute bit so that Cygwin knows it's a link. @@ -92,8 +92,8 @@ def CreateCygwinSymlink(filepath, target): return subprocess.call(['cmd', '/C', 'C:\\Windows\\System32\\attrib.exe', '+S', ToNativePath(filepath)]) except EnvironmentError: - print 'Try %d: Failed attrib %s -> %s\n' % (cnt, filepath, target) - print 'Giving up.' + print('Try %d: Failed attrib %s -> %s\n' % (cnt, filepath, target)) + print('Giving up.') return False @@ -122,8 +122,8 @@ def CreateWin32Hardlink(filepath, targpath, try_mklink): shutil.copyfile(targpath, filepath) return False except EnvironmentError: - print 'Try %d: Failed hardlink %s -> %s\n' % (cnt, filepath, targpath) - print 'Giving up.' + print('Try %d: Failed hardlink %s -> %s\n' % (cnt, filepath, targpath)) + print('Giving up.') return try_mklink @@ -170,7 +170,7 @@ def __DumpInfo(self, tarinfo): if tarinfo.isfile(): typeinfo = 'F' reable_size = ReadableSizeOf(tarinfo.size) - print '%s %s : %s %s' % (reable_size, typeinfo, tarinfo.name, lnk) + print('%s %s : %s %s' % (reable_size, typeinfo, tarinfo.name, lnk)) return tarinfo def __AddFile(self, tarinfo, fileobj=None): @@ -232,7 +232,7 @@ def Add(self, filepath, prefix=None): # At this point we only allow addition of "FILES" if not tarinfo.isfile(): - print 'Failed to add non real file: %s' % filepath + print('Failed to add non real file: %s' % filepath) return False # Now check if it is a Cygwin style link disguised as a file. From 528fc2266ec663db90feea87dc2cda6409a0ca71 Mon Sep 17 00:00:00 2001 From: slipher Date: Thu, 10 Apr 2025 09:50:42 -0500 Subject: [PATCH 19/41] external_deps: fix script incompatible with Mac's bash --- external_deps/build.sh | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/external_deps/build.sh b/external_deps/build.sh index 5af307622..2e0739fdb 100755 --- a/external_deps/build.sh +++ b/external_deps/build.sh @@ -85,8 +85,8 @@ LDFLAGS='' log() { level="${1}"; shift - printf '%s: %s\n' "${level^^}" "${@}" >&2 - [ "${level}" != 'error' ] + printf '%s: %s\n' "${level}" "${@}" >&2 + [ "${level}" != 'ERROR' ] } # Extract an archive into the given subdirectory of the build dir and cd to it @@ -120,7 +120,7 @@ extract() { rmdir "${2}-dmg" ;; *) - log error "Unknown archive type for ${1}" + log ERROR "Unknown archive type for ${1}" ;; esac cd "${2}" @@ -132,13 +132,13 @@ download() { while [ ! -f "${tarball_file}" ]; do if [ -z "${1:-}" ] then - log error "No more mirror to download ${tarball_file} from" + log ERROR "No more mirror to download ${tarball_file} from" fi local download_url="${1}"; shift log status "Downloading ${download_url}" if ! "${CURL}" -R -L --fail -o "${tarball_file}" "${download_url}" then - log warning "Failed to download ${download_url}" + log WARNING "Failed to download ${download_url}" rm -f "${tarball_file}" fi done @@ -198,7 +198,7 @@ build_nasm() { cp "${dir_name}/nasm" "${PREFIX}/bin" ;; *) - log error 'Unsupported platform for NASM' + log ERROR 'Unsupported platform for NASM' ;; esac } @@ -357,7 +357,7 @@ build_sdl2() { local sdl2_lib_dir='lib/x64' ;; *) - log error 'Unsupported platform for SDL2' + log ERROR 'Unsupported platform for SDL2' ;; esac @@ -414,7 +414,7 @@ build_glew() { make install GLEW_DEST="${PREFIX}" CC="${CC}" LD="${CC}" CFLAGS.EXTRA="${CFLAGS}" LDFLAGS.EXTRA="${LDFLAGS}" LIBDIR="${PREFIX}/lib" ;; *) - log error 'Unsupported platform for GLEW' + log ERROR 'Unsupported platform for GLEW' ;; esac } @@ -460,7 +460,7 @@ build_jpeg() { # Other platforms can build but we need need to explicitly # set CMAKE_SYSTEM_NAME for CMAKE_CROSSCOMPILING to be set # and CMAKE_SYSTEM_PROCESSOR to not be ignored by cmake. - log error 'Unsupported platform for JPEG' + log ERROR 'Unsupported platform for JPEG' ;; esac @@ -482,7 +482,7 @@ build_jpeg() { local SYSTEM_PROCESSOR='arm' ;; *) - log error 'Unsupported platform for JPEG' + log ERROR 'Unsupported platform for JPEG' ;; esac @@ -539,7 +539,7 @@ build_openal() { -DCMAKE_BUILD_TYPE=Release -DALSOFT_EXAMPLES=OFF) ;; *) - log error 'Unsupported platform for OpenAL' + log ERROR 'Unsupported platform for OpenAL' ;; esac @@ -695,7 +695,7 @@ build_wasisdk() { *-amd64-*) ;; *) - log error "wasi doesn't have release for ${PLATFORM}" + log ERROR "wasi doesn't have release for ${PLATFORM}" ;; esac @@ -735,7 +735,7 @@ build_wasmtime() { local WASMTIME_ARCH=aarch64 ;; *) - log error "wasmtime doesn't have release for ${PLATFORM}" + log ERROR "wasmtime doesn't have release for ${PLATFORM}" ;; esac @@ -863,7 +863,7 @@ build_naclruntime() { local NACL_ARCH=x86-64 ;; *) - log error 'Unsupported platform for naclruntime' + log ERROR 'Unsupported platform for naclruntime' ;; esac @@ -903,7 +903,7 @@ build_genlib() { local MACHINE='i386:x86-64' ;; *) - log error 'Unsupported platform for genlib' + log ERROR 'Unsupported platform for genlib' ;; esac @@ -917,7 +917,7 @@ build_genlib() { done ;; *) - log error 'Unsupported platform for genlib' + log ERROR 'Unsupported platform for genlib' ;; esac } @@ -1038,7 +1038,7 @@ common_setup_arch() { CXXFLAGS+=' -march=armv7-a -mfpu=neon' ;; *) - log error 'Unsupported platform' + log ERROR 'Unsupported platform' ;; esac } From 54d119af4644d3ba9b5dfe89f8c52bca88ec0862 Mon Sep 17 00:00:00 2001 From: slipher Date: Thu, 10 Apr 2025 12:26:09 -0500 Subject: [PATCH 20/41] external_deps: fix pkgconfig macos build --- external_deps/build.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/external_deps/build.sh b/external_deps/build.sh index 2e0739fdb..18e02c27c 100755 --- a/external_deps/build.sh +++ b/external_deps/build.sh @@ -167,6 +167,7 @@ download_extract() { } # Build pkg-config +# Still needed, at least on macos, for opusfile build_pkgconfig() { local dir_name="pkg-config-${PKGCONFIG_VERSION}" local archive_name="${dir_name}.tar.gz" @@ -178,7 +179,7 @@ build_pkgconfig() { cd "${dir_name}" # The default -O2 is dropped when there's user-provided CFLAGS. - CFLAGS="${CFLAGS} -O2" ./configure --host="${HOST}" --prefix="${PREFIX}" --libdir="${PREFIX}/lib" --with-internal-glib + CFLAGS="${CFLAGS} -O2 -Wno-error=int-conversion" ./configure --host="${HOST}" --prefix="${PREFIX}" --libdir="${PREFIX}/lib" --with-internal-glib make make install } From 6941b6f09a26bbf89922e5511d35012f3b65622a Mon Sep 17 00:00:00 2001 From: slipher Date: Tue, 8 Apr 2025 20:32:47 -0500 Subject: [PATCH 21/41] external_deps: remove pkgconfig from Windows list There was a stray pkgconfig in the list of required packages for one of the Windows platforms. pkgconfig only makes sense as a host-mode dependency. Also it crashes the compiler. --- external_deps/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external_deps/build.sh b/external_deps/build.sh index 18e02c27c..2039f57f6 100755 --- a/external_deps/build.sh +++ b/external_deps/build.sh @@ -1141,7 +1141,7 @@ setup_linux-arm64-default() { common_setup linux aarch64-unknown-linux-gnu } -base_windows_amd64_msvc_packages='pkgconfig zlib gmp nettle curl sdl2 glew png jpeg webp openal ogg vorbis opus opusfile naclsdk genlib' +base_windows_amd64_msvc_packages='zlib gmp nettle curl sdl2 glew png jpeg webp openal ogg vorbis opus opusfile naclsdk genlib' all_windows_amd64_msvc_packages="${base_windows_amd64_msvc_packages}" base_windows_i686_msvc_packages="${base_windows_amd64_msvc_packages}" From 758f196fe0eee9195d71ec225160fb8282b98fbf Mon Sep 17 00:00:00 2001 From: slipher Date: Sun, 20 Apr 2025 01:19:27 -0500 Subject: [PATCH 22/41] external_deps: don't munge SDL config The build script for mingw sdl2 uses prebuilt binaries, but calls a makefile which only substitutes some hard-coded paths into some build config helpers and copies the files. Just copy the files ourselves and don't munge the configs: the unmunged cmake uses a relative path which is actually what we want. In newer SDL versions the makefile munges the cmake configs (in addition to the shell-based one) which breaks us. --- external_deps/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external_deps/build.sh b/external_deps/build.sh index 2039f57f6..0d8165725 100755 --- a/external_deps/build.sh +++ b/external_deps/build.sh @@ -341,7 +341,7 @@ build_sdl2() { case "${PLATFORM}" in windows-*-mingw) cd "${dir_name}" - make install-package arch="${HOST}" prefix="${PREFIX}" + cp -rv "${HOST}"/* "${PREFIX}/" ;; windows-*-msvc) cd "${dir_name}" From 7f9abc78bcbb2f3c9cbea9c2c0837cd617e03412 Mon Sep 17 00:00:00 2001 From: slipher Date: Tue, 22 Apr 2025 01:49:04 -0500 Subject: [PATCH 23/41] external_deps: fix import lib paths for MSVC In the cmake config files in lib/cmake, substitute .dll.a -> .lib when targeting MSVC. --- external_deps/build.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/external_deps/build.sh b/external_deps/build.sh index 0d8165725..047a7611d 100755 --- a/external_deps/build.sh +++ b/external_deps/build.sh @@ -972,6 +972,9 @@ build_install() { find "${PKG_PREFIX}/bin" -name '*.dll' -execdir "${HOST}-strip" --strip-unneeded -- {} \; find "${PKG_PREFIX}/lib" -name '*.a' -execdir rm -f -- {} \; find "${PKG_PREFIX}/lib" -name '*.exp' -execdir rm -f -- {} \; + + # Fix import lib paths to use MSVC-style instead of MinGW ones (see 'genlib' target) + find "${PKG_PREFIX}/lib/cmake" -name '*.cmake' -execdir sed -i -E 's@[.]dll[.]a\b@.lib@g' {} \; ;; esac From ab623ab73a5a2df67ceaa38298c2b38ce07f9aab Mon Sep 17 00:00:00 2001 From: slipher Date: Tue, 22 Apr 2025 01:51:50 -0500 Subject: [PATCH 24/41] external_deps: check for bad DLL dependencies We don't want the DLLs we build to depend on the MinGW standard library DLLs. --- external_deps/build.sh | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/external_deps/build.sh b/external_deps/build.sh index 047a7611d..5eaac75d8 100755 --- a/external_deps/build.sh +++ b/external_deps/build.sh @@ -882,6 +882,30 @@ build_naclruntime() { cp "scons-out/opt-linux-${NACL_ARCH}/staging/sel_ldr" "${PREFIX}/nacl_loader" } +# Check for DLL dependencies on MinGW stuff. For MSVC platforms this is bad because it should work +# without having MinGW installed. For MinGW platforms it is still bad because it might not work +# when building with different flavors, or newer/older versions. +build_depcheck() { + "${download_only}" && return + + case "${PLATFORM}" in + windows-*-*) + local good=true + for dll in $(find "${PREFIX}/bin" -type f -name '*.dll'); do + # https://wiki.unvanquished.net/wiki/MinGW#Built-in_DLL_dependencies + if objdump -p "${dll}" | grep -oP '(?<=DLL Name: )(libgcc_s|libstdc|libssp|libwinpthread).*'; then + echo "${dll} depends on above DLLs" + good=false + fi + done + "${good}" || log ERROR 'Built DLLs depend on MinGW runtime DLLs' + ;; + *) + log ERROR 'Unsupported platform for depcheck' + ;; + esac +} + # The import libraries generated by MinGW seem to have issues, so we use LLVM's version instead. # So LLVM must be installed, e.g. 'sudo apt install llvm' build_genlib() { @@ -1144,13 +1168,13 @@ setup_linux-arm64-default() { common_setup linux aarch64-unknown-linux-gnu } -base_windows_amd64_msvc_packages='zlib gmp nettle curl sdl2 glew png jpeg webp openal ogg vorbis opus opusfile naclsdk genlib' +base_windows_amd64_msvc_packages='zlib gmp nettle curl sdl2 glew png jpeg webp openal ogg vorbis opus opusfile naclsdk depcheck genlib' all_windows_amd64_msvc_packages="${base_windows_amd64_msvc_packages}" base_windows_i686_msvc_packages="${base_windows_amd64_msvc_packages}" all_windows_i686_msvc_packages="${base_windows_amd64_msvc_packages}" -base_windows_amd64_mingw_packages='zlib gmp nettle curl sdl2 glew png jpeg webp openal ogg vorbis opus opusfile naclsdk' +base_windows_amd64_mingw_packages='zlib gmp nettle curl sdl2 glew png jpeg webp openal ogg vorbis opus opusfile naclsdk depcheck' all_windows_amd64_mingw_packages="${base_windows_amd64_mingw_packages}" base_windows_i686_mingw_packages="${base_windows_amd64_mingw_packages}" From c72b425e3255df479dbfc7deab70fb857e619891 Mon Sep 17 00:00:00 2001 From: slipher Date: Fri, 4 Apr 2025 00:47:06 -0500 Subject: [PATCH 25/41] external_deps: Fix GLEW armhf build --- external_deps/build.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/external_deps/build.sh b/external_deps/build.sh index 5eaac75d8..74ba16b2f 100755 --- a/external_deps/build.sh +++ b/external_deps/build.sh @@ -411,7 +411,8 @@ build_glew() { install_name_tool -id "@rpath/libGLEW.${GLEW_VERSION}.dylib" "${PREFIX}/lib/libGLEW.${GLEW_VERSION}.dylib" ;; linux-*-*) - make GLEW_DEST="${PREFIX}" CC="${CC}" LD="${CC}" CFLAGS.EXTRA="${CFLAGS}" LDFLAGS.EXTRA="${LDFLAGS}" + local strip="${HOST/-unknown-/-}-strip" + make GLEW_DEST="${PREFIX}" CC="${CC}" LD="${CC}" STRIP="${strip}" CFLAGS.EXTRA="${CFLAGS}" LDFLAGS.EXTRA="${LDFLAGS}" make install GLEW_DEST="${PREFIX}" CC="${CC}" LD="${CC}" CFLAGS.EXTRA="${CFLAGS}" LDFLAGS.EXTRA="${LDFLAGS}" LIBDIR="${PREFIX}/lib" ;; *) From 5f654ff26bd1280b87a7ad931ea1492a1b80e511 Mon Sep 17 00:00:00 2001 From: slipher Date: Tue, 8 Apr 2025 20:29:36 -0500 Subject: [PATCH 26/41] external_deps: fix GLEW windows build Building glew for windows-i686-mingw resulted in a link error about undefined strlen. This happend because setting CFLAGS.EXTRA on the Make command line clobbers some required flags. Pass the flags in a different way so they append rather than clobbering. --- external_deps/build.sh | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/external_deps/build.sh b/external_deps/build.sh index 74ba16b2f..b78a9f529 100755 --- a/external_deps/build.sh +++ b/external_deps/build.sh @@ -397,10 +397,16 @@ build_glew() { "${download_only}" && return cd "${dir_name}" + # env hack: CFLAGS.EXTRA is populated with some flags, which are sometimess necessary for + # compilation, in the makefile with +=. If CFLAGS.EXTRA is set on the command line, those + # += will be ignored. But if it is set via the environment, the two sources are actually + # concatenated how we would like. Bash doesn't allow variables with a dot so use env. + # The hack doesn't work on Mac's ancient Make (the env var has no effect), so we have to + # manually re-add the required flags there. case "${PLATFORM}" in windows-*-*) - make SYSTEM="linux-mingw${BITNESS}" GLEW_DEST="${PREFIX}" CC="${CC}" AR="${AR}" RANLIB="${RANLIB}" STRIP="${HOST}-strip" LD="${LD}" CFLAGS.EXTRA="${CFLAGS}" LDFLAGS.EXTRA="${LDFLAGS}" - make install SYSTEM="linux-mingw${BITNESS}" GLEW_DEST="${PREFIX}" CC="${CC}" AR="${AR}" RANLIB="${RANLIB}" STRIP="${HOST}-strip" LD="${LD}" CFLAGS.EXTRA="${CFLAGS}" LDFLAGS.EXTRA="${LDFLAGS}" + env CFLAGS.EXTRA="${CFLAGS}" LDFLAGS.EXTRA="${LDFLAGS}" make SYSTEM="linux-mingw${BITNESS}" GLEW_DEST="${PREFIX}" CC="${CC}" AR="${AR}" RANLIB="${RANLIB}" STRIP="${HOST}-strip" LD="${LD}" + env CFLAGS.EXTRA="${CFLAGS}" LDFLAGS.EXTRA="${LDFLAGS}" make install SYSTEM="linux-mingw${BITNESS}" GLEW_DEST="${PREFIX}" CC="${CC}" AR="${AR}" RANLIB="${RANLIB}" STRIP="${HOST}-strip" LD="${LD}" mv "${PREFIX}/lib/glew32.dll" "${PREFIX}/bin/" rm "${PREFIX}/lib/libglew32.a" cp lib/libglew32.dll.a "${PREFIX}/lib/" @@ -412,8 +418,8 @@ build_glew() { ;; linux-*-*) local strip="${HOST/-unknown-/-}-strip" - make GLEW_DEST="${PREFIX}" CC="${CC}" LD="${CC}" STRIP="${strip}" CFLAGS.EXTRA="${CFLAGS}" LDFLAGS.EXTRA="${LDFLAGS}" - make install GLEW_DEST="${PREFIX}" CC="${CC}" LD="${CC}" CFLAGS.EXTRA="${CFLAGS}" LDFLAGS.EXTRA="${LDFLAGS}" LIBDIR="${PREFIX}/lib" + env CFLAGS.EXTRA="${CFLAGS}" LDFLAGS.EXTRA="${LDFLAGS}" make GLEW_DEST="${PREFIX}" CC="${CC}" LD="${CC}" STRIP="${strip}" + env CFLAGS.EXTRA="${CFLAGS}" LDFLAGS.EXTRA="${LDFLAGS}" make install GLEW_DEST="${PREFIX}" CC="${CC}" LD="${CC}" LIBDIR="${PREFIX}/lib" ;; *) log ERROR 'Unsupported platform for GLEW' From d9e756c51d66e405aa39acf7a85fd98134e78c91 Mon Sep 17 00:00:00 2001 From: VReaperV Date: Fri, 23 May 2025 23:09:09 +0300 Subject: [PATCH 27/41] Make BufferBind less noisy --- src/engine/renderer/Material.h | 32 ++++++++++++++------------ src/engine/renderer/gl_shader.cpp | 38 +++++++++++++++++-------------- 2 files changed, 38 insertions(+), 32 deletions(-) diff --git a/src/engine/renderer/Material.h b/src/engine/renderer/Material.h index d11b3abb5..46b7e5638 100644 --- a/src/engine/renderer/Material.h +++ b/src/engine/renderer/Material.h @@ -306,21 +306,23 @@ struct SurfaceCommandBatch { uint32_t materialIDs[2] { 0, 0 }; }; -enum class BufferBind { - MATERIALS = 1, // LightTile UBO uses binding point 0, so avoid it here - TEX_DATA = 6, - LIGHTMAP_DATA = 2, - SURFACE_DESCRIPTORS = 0, - SURFACE_COMMANDS = 1, - CULLED_COMMANDS = 2, - SURFACE_BATCHES = 3, - COMMAND_COUNTERS_ATOMIC = 0, - COMMAND_COUNTERS_STORAGE = 4, // Avoid needlessly rebinding buffers - PORTAL_SURFACES = 5, - GEOMETRY_CACHE_INPUT_VBO = 6, - GEOMETRY_CACHE_VBO = 7, - DEBUG = 10, - UNUSED = INT32_MAX +namespace BufferBind { + enum : uint32_t { + MATERIALS = 1, // LightTile UBO uses binding point 0, so avoid it here + TEX_DATA = 6, + LIGHTMAP_DATA = 2, + SURFACE_DESCRIPTORS = 0, + SURFACE_COMMANDS = 1, + CULLED_COMMANDS = 2, + SURFACE_BATCHES = 3, + COMMAND_COUNTERS_ATOMIC = 0, + COMMAND_COUNTERS_STORAGE = 4, // Avoid needlessly rebinding buffers + PORTAL_SURFACES = 5, + GEOMETRY_CACHE_INPUT_VBO = 6, + GEOMETRY_CACHE_VBO = 7, + DEBUG = 10, + UNUSED = INT32_MAX + }; }; class MaterialSystem { diff --git a/src/engine/renderer/gl_shader.cpp b/src/engine/renderer/gl_shader.cpp index b6635e88c..dff1f0cbe 100644 --- a/src/engine/renderer/gl_shader.cpp +++ b/src/engine/renderer/gl_shader.cpp @@ -303,6 +303,10 @@ static inline void AddDefine( std::string& defines, const std::string& define, i defines += Str::Format("#ifndef %s\n#define %s %d\n#endif\n", define, define, value); } +static inline void AddDefine( std::string& defines, const std::string& define, uint32_t value ) { + defines += Str::Format( "#ifndef %s\n#define %s %d\n#endif\n", define, define, value ); +} + // Epsilon for float is 5.96e-08, so exponential notation with 8 decimal places should give exact values. static inline void AddDefine( std::string& defines, const std::string& define, float value ) @@ -577,9 +581,9 @@ static std::string GenVertexHeader() { } if ( glConfig2.usingMaterialSystem ) { - AddDefine( str, "BIND_MATERIALS", Util::ordinal( BufferBind::MATERIALS ) ); - AddDefine( str, "BIND_TEX_DATA", Util::ordinal( BufferBind::TEX_DATA ) ); - AddDefine( str, "BIND_LIGHTMAP_DATA", Util::ordinal( BufferBind::LIGHTMAP_DATA ) ); + AddDefine( str, "BIND_MATERIALS", BufferBind::MATERIALS ); + AddDefine( str, "BIND_TEX_DATA", BufferBind::TEX_DATA ); + AddDefine( str, "BIND_LIGHTMAP_DATA", BufferBind::LIGHTMAP_DATA ); } return str; @@ -617,9 +621,9 @@ static std::string GenFragmentHeader() { } if ( glConfig2.usingMaterialSystem ) { - AddDefine( str, "BIND_MATERIALS", Util::ordinal( BufferBind::MATERIALS ) ); - AddDefine( str, "BIND_TEX_DATA", Util::ordinal( BufferBind::TEX_DATA ) ); - AddDefine( str, "BIND_LIGHTMAP_DATA", Util::ordinal( BufferBind::LIGHTMAP_DATA ) ); + AddDefine( str, "BIND_MATERIALS", BufferBind::MATERIALS ); + AddDefine( str, "BIND_TEX_DATA", BufferBind::TEX_DATA ); + AddDefine( str, "BIND_LIGHTMAP_DATA", BufferBind::LIGHTMAP_DATA ); } return str; @@ -636,15 +640,15 @@ static std::string GenComputeHeader() { AddDefine( str, "MAX_SURFACE_COMMAND_BATCHES", MAX_SURFACE_COMMAND_BATCHES ); AddDefine( str, "MAX_COMMAND_COUNTERS", MAX_COMMAND_COUNTERS ); - AddDefine( str, "BIND_SURFACE_DESCRIPTORS", Util::ordinal( BufferBind::SURFACE_DESCRIPTORS ) ); - AddDefine( str, "BIND_SURFACE_COMMANDS", Util::ordinal( BufferBind::SURFACE_COMMANDS ) ); - AddDefine( str, "BIND_CULLED_COMMANDS", Util::ordinal( BufferBind::CULLED_COMMANDS ) ); - AddDefine( str, "BIND_SURFACE_BATCHES", Util::ordinal( BufferBind::SURFACE_BATCHES ) ); - AddDefine( str, "BIND_COMMAND_COUNTERS_ATOMIC", Util::ordinal( BufferBind::COMMAND_COUNTERS_ATOMIC ) ); - AddDefine( str, "BIND_COMMAND_COUNTERS_STORAGE", Util::ordinal( BufferBind::COMMAND_COUNTERS_STORAGE ) ); - AddDefine( str, "BIND_PORTAL_SURFACES", Util::ordinal( BufferBind::PORTAL_SURFACES ) ); + AddDefine( str, "BIND_SURFACE_DESCRIPTORS", BufferBind::SURFACE_DESCRIPTORS ); + AddDefine( str, "BIND_SURFACE_COMMANDS", BufferBind::SURFACE_COMMANDS ); + AddDefine( str, "BIND_CULLED_COMMANDS", BufferBind::CULLED_COMMANDS ); + AddDefine( str, "BIND_SURFACE_BATCHES", BufferBind::SURFACE_BATCHES ); + AddDefine( str, "BIND_COMMAND_COUNTERS_ATOMIC", BufferBind::COMMAND_COUNTERS_ATOMIC ); + AddDefine( str, "BIND_COMMAND_COUNTERS_STORAGE", BufferBind::COMMAND_COUNTERS_STORAGE ); + AddDefine( str, "BIND_PORTAL_SURFACES", BufferBind::PORTAL_SURFACES ); - AddDefine( str, "BIND_DEBUG", Util::ordinal( BufferBind::DEBUG ) ); + AddDefine( str, "BIND_DEBUG", BufferBind::DEBUG ); } if ( glConfig2.usingBindlessTextures ) { @@ -1510,19 +1514,19 @@ std::string GLShaderManager::ShaderPostProcess( GLShader *shader, const std::str // 6 kb for materials const uint32_t count = ( 4096 + 2048 ) / shader->GetPaddedSize(); std::string materialBlock = "layout(std140, binding = " - + std::to_string( Util::ordinal( BufferBind::MATERIALS ) ) + + std::to_string( BufferBind::MATERIALS ) + ") uniform materialsUBO {\n" " Material materials[" + std::to_string( count ) + "]; \n" "};\n\n"; std::string texBuf = glConfig2.maxUniformBlockSize >= MIN_MATERIAL_UBO_SIZE ? "layout(std140, binding = " - + std::to_string( Util::ordinal( BufferBind::TEX_DATA ) ) + + std::to_string( BufferBind::TEX_DATA ) + ") uniform texDataUBO {\n" " TexData texData[" + std::to_string( MAX_TEX_BUNDLES ) + "]; \n" "};\n\n" : "layout(std430, binding = " - + std::to_string( Util::ordinal( BufferBind::TEX_DATA ) ) + + std::to_string( BufferBind::TEX_DATA ) + ") restrict readonly buffer texDataSSBO {\n" " TexData texData[];\n" "};\n\n"; From 6dbbd9b5f253cdc277b49a0be92892fcc7e7b8e1 Mon Sep 17 00:00:00 2001 From: VReaperV Date: Sat, 24 May 2025 11:45:44 +0300 Subject: [PATCH 28/41] Use explicit bind for u_Lights UBO when possible Get rid of the requirement to not use binding point 0 for UBOs explicitly. --- src/engine/renderer/Material.h | 3 ++- src/engine/renderer/gl_shader.cpp | 7 ++++++- src/engine/renderer/gl_shader.h | 18 ++++++++++++------ .../renderer/glsl_source/computeLight_fp.glsl | 4 ++++ .../renderer/glsl_source/lighttile_fp.glsl | 4 ++++ 5 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/engine/renderer/Material.h b/src/engine/renderer/Material.h index 46b7e5638..bd9df42b5 100644 --- a/src/engine/renderer/Material.h +++ b/src/engine/renderer/Material.h @@ -308,9 +308,10 @@ struct SurfaceCommandBatch { namespace BufferBind { enum : uint32_t { - MATERIALS = 1, // LightTile UBO uses binding point 0, so avoid it here + MATERIALS = 1, TEX_DATA = 6, LIGHTMAP_DATA = 2, + LIGHTS = 0, SURFACE_DESCRIPTORS = 0, SURFACE_COMMANDS = 1, CULLED_COMMANDS = 2, diff --git a/src/engine/renderer/gl_shader.cpp b/src/engine/renderer/gl_shader.cpp index dff1f0cbe..32b22dd60 100644 --- a/src/engine/renderer/gl_shader.cpp +++ b/src/engine/renderer/gl_shader.cpp @@ -286,7 +286,7 @@ void GLShaderManager::UpdateShaderProgramUniformLocations( GLShader* shader, Sha uniform->UpdateShaderProgramUniformLocation( shaderProgram ); } - if( glConfig2.uniformBufferObjectAvailable ) { + if( glConfig2.uniformBufferObjectAvailable && !glConfig2.shadingLanguage420PackAvailable ) { // create buffer for storing uniform block indexes shaderProgram->uniformBlockIndexes = ( GLuint* ) Z_Malloc( sizeof( GLuint ) * numUniformBlocks ); @@ -416,6 +416,7 @@ struct addedExtension_t { static const std::vector fragmentVertexAddedExtensions = { { glConfig2.gpuShader4Available, 130, "EXT_gpu_shader4" }, { glConfig2.gpuShader5Available, 400, "ARB_gpu_shader5" }, + { glConfig2.shadingLanguage420PackAvailable, 420, "ARB_shading_language_420pack" }, { glConfig2.textureFloatAvailable, 130, "ARB_texture_float" }, { glConfig2.textureGatherAvailable, 400, "ARB_texture_gather" }, { glConfig2.textureIntegerAvailable, 0, "EXT_texture_integer" }, @@ -620,6 +621,10 @@ static std::string GenFragmentHeader() { str += "#define baseInstance in_baseInstance\n\n"; } + if ( glConfig2.shadingLanguage420PackAvailable ) { + AddDefine( str, "BIND_LIGHTS", BufferBind::LIGHTS ); + } + if ( glConfig2.usingMaterialSystem ) { AddDefine( str, "BIND_MATERIALS", BufferBind::MATERIALS ); AddDefine( str, "BIND_TEX_DATA", BufferBind::TEX_DATA ); diff --git a/src/engine/renderer/gl_shader.h b/src/engine/renderer/gl_shader.h index bcf4980db..72aecc2e8 100644 --- a/src/engine/renderer/gl_shader.h +++ b/src/engine/renderer/gl_shader.h @@ -1231,12 +1231,13 @@ class GLUniformBlock protected: GLShader *_shader; std::string _name; - size_t _locationIndex; + size_t _locationIndex; // Only valid if GL_ARB_shading_language_420pack is not available + const GLuint _bindingPoint; // Only valid if GL_ARB_shading_language_420pack is available - GLUniformBlock( GLShader *shader, const char *name ) : + GLUniformBlock( GLShader *shader, const char *name, const GLuint bindingPoint ) : _shader( shader ), _name( name ), - _locationIndex( 0 ) + _bindingPoint( bindingPoint ) { _shader->RegisterUniformBlock( this ); } @@ -1258,10 +1259,15 @@ class GLUniformBlock } void SetBuffer( GLuint buffer ) { + if ( glConfig2.shadingLanguage420PackAvailable ) { + glBindBufferBase( GL_UNIFORM_BUFFER, _bindingPoint, buffer ); + return; + } + ShaderProgramDescriptor *p = _shader->GetProgram(); - GLuint blockIndex = p->uniformBlockIndexes[ _locationIndex ]; + GLuint blockIndex = p->uniformBlockIndexes[_locationIndex]; - ASSERT_EQ(p, glState.currentProgram); + ASSERT_EQ( p, glState.currentProgram ); if( blockIndex != GL_INVALID_INDEX ) { glBindBufferBase( GL_UNIFORM_BUFFER, blockIndex, buffer ); @@ -3599,7 +3605,7 @@ class u_Lights : { public: u_Lights( GLShader *shader ) : - GLUniformBlock( shader, "u_Lights" ) + GLUniformBlock( shader, "u_Lights", BufferBind::LIGHTS ) { } diff --git a/src/engine/renderer/glsl_source/computeLight_fp.glsl b/src/engine/renderer/glsl_source/computeLight_fp.glsl index a84acbd8f..633fb6ff8 100644 --- a/src/engine/renderer/glsl_source/computeLight_fp.glsl +++ b/src/engine/renderer/glsl_source/computeLight_fp.glsl @@ -153,7 +153,11 @@ struct Light { float angle; }; +#if defined( HAVE_ARB_shading_language_420pack ) +layout(std140, binding = BIND_LIGHTS) uniform u_Lights { +#else layout(std140) uniform u_Lights { +#endif Light lights[MAX_REF_LIGHTS]; }; diff --git a/src/engine/renderer/glsl_source/lighttile_fp.glsl b/src/engine/renderer/glsl_source/lighttile_fp.glsl index 331d46ca4..559199a29 100644 --- a/src/engine/renderer/glsl_source/lighttile_fp.glsl +++ b/src/engine/renderer/glsl_source/lighttile_fp.glsl @@ -45,7 +45,11 @@ struct Light { float angle; }; +#if defined( HAVE_ARB_shading_language_420pack ) +layout(std140, binding = BIND_LIGHTS) uniform u_Lights { +#else layout(std140) uniform u_Lights { +#endif Light lights[MAX_REF_LIGHTS]; }; From 8f4c7fe009c4f6b9c2303d15378994e92e5ef25f Mon Sep 17 00:00:00 2001 From: VReaperV Date: Sat, 24 May 2025 12:23:48 +0300 Subject: [PATCH 29/41] Clean-up buffer binds --- src.cmake | 1 + src/engine/renderer/BufferBind.h | 70 +++++++++++++++++++++++++++++++ src/engine/renderer/Material.cpp | 13 ++++-- src/engine/renderer/Material.h | 21 +--------- src/engine/renderer/gl_shader.cpp | 2 + src/engine/renderer/gl_shader.h | 1 + 6 files changed, 85 insertions(+), 23 deletions(-) create mode 100644 src/engine/renderer/BufferBind.h diff --git a/src.cmake b/src.cmake index 24d7d227a..8f5f4773d 100644 --- a/src.cmake +++ b/src.cmake @@ -78,6 +78,7 @@ set(COMMONTESTLIST ) set(RENDERERLIST + ${ENGINE_DIR}/renderer/BufferBind.h ${ENGINE_DIR}/renderer/DetectGLVendors.cpp ${ENGINE_DIR}/renderer/DetectGLVendors.h ${ENGINE_DIR}/renderer/gl_shader.cpp diff --git a/src/engine/renderer/BufferBind.h b/src/engine/renderer/BufferBind.h new file mode 100644 index 000000000..0245487d5 --- /dev/null +++ b/src/engine/renderer/BufferBind.h @@ -0,0 +1,70 @@ +/* +=========================================================================== + +Daemon BSD Source Code +Copyright (c) 2025 Daemon Developers +All rights reserved. + +This file is part of the Daemon BSD Source Code (Daemon Source Code). + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Daemon developers nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL DAEMON DEVELOPERS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=========================================================================== +*/ +// BufferBind.h + +#ifndef BUFFERBIND_H +#define BUFFERBIND_H + +namespace BufferBind { + enum : uint32_t { + // UBO + MATERIALS = 0, + TEX_DATA = 1, + LIGHTMAP_DATA = 2, + LIGHTS = 3, + + SURFACE_BATCHES = 4, + + // SSBO + SURFACE_DESCRIPTORS = 0, + SURFACE_COMMANDS = 1, + CULLED_COMMANDS = 2, + PORTAL_SURFACES = 4, + + GEOMETRY_CACHE_INPUT_VBO = 5, + GEOMETRY_CACHE_VBO = 6, + + COMMAND_COUNTERS_STORAGE = 9, + TEX_DATA_STORAGE = 11, + + DEBUG = 10, + + // Atomic + COMMAND_COUNTERS_ATOMIC = 0, + + UNUSED = INT32_MAX + }; +}; + +#endif // BUFFERBIND_H diff --git a/src/engine/renderer/Material.cpp b/src/engine/renderer/Material.cpp index b90e4fc1a..15fd68992 100644 --- a/src/engine/renderer/Material.cpp +++ b/src/engine/renderer/Material.cpp @@ -35,6 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "tr_local.h" #include "Material.h" +#include "BufferBind.h" #include "ShadeCommon.h" #include "GeometryCache.h" @@ -541,7 +542,13 @@ void MaterialSystem::GenerateWorldCommandBuffer( std::vector& s surfaceDescriptorsSSBO.BufferData( surfaceDescriptorsCount * descriptorSize, nullptr, GL_STATIC_DRAW ); uint32_t* surfaceDescriptors = surfaceDescriptorsSSBO.MapBufferRange( surfaceDescriptorsCount * descriptorSize ); - texDataBufferType = glConfig2.maxUniformBlockSize >= MIN_MATERIAL_UBO_SIZE ? GL_UNIFORM_BUFFER : GL_SHADER_STORAGE_BUFFER; + if ( glConfig2.maxUniformBlockSize >= MIN_MATERIAL_UBO_SIZE ) { + texDataBufferType = GL_UNIFORM_BUFFER; + texDataBindingPoint = BufferBind::TEX_DATA; + } else { + texDataBufferType = GL_SHADER_STORAGE_BUFFER; + texDataBindingPoint = BufferBind::TEX_DATA_STORAGE; + } texDataBuffer.BufferStorage( ( texData.size() + dynamicTexData.size() ) * TEX_BUNDLE_SIZE, 1, nullptr ); texDataBuffer.MapAll(); @@ -2023,7 +2030,7 @@ void MaterialSystem::RenderMaterial( Material& material, const uint32_t viewID ) atomicCommandCountersBuffer.BindBuffer( GL_PARAMETER_BUFFER_ARB ); - texDataBuffer.BindBufferBase( texDataBufferType ); + texDataBuffer.BindBufferBase( texDataBufferType, texDataBindingPoint ); lightMapDataUBO.BindBufferBase(); if ( r_showGlobalMaterials.Get() && material.sort != 0 @@ -2140,7 +2147,7 @@ void MaterialSystem::RenderMaterial( Material& material, const uint32_t viewID ) atomicCommandCountersBuffer.UnBindBuffer( GL_PARAMETER_BUFFER_ARB ); - texDataBuffer.UnBindBufferBase( texDataBufferType ); + texDataBuffer.UnBindBufferBase( texDataBufferType, texDataBindingPoint ); lightMapDataUBO.UnBindBufferBase(); if ( material.usePolygonOffset ) { diff --git a/src/engine/renderer/Material.h b/src/engine/renderer/Material.h index bd9df42b5..e960af3ad 100644 --- a/src/engine/renderer/Material.h +++ b/src/engine/renderer/Material.h @@ -306,26 +306,6 @@ struct SurfaceCommandBatch { uint32_t materialIDs[2] { 0, 0 }; }; -namespace BufferBind { - enum : uint32_t { - MATERIALS = 1, - TEX_DATA = 6, - LIGHTMAP_DATA = 2, - LIGHTS = 0, - SURFACE_DESCRIPTORS = 0, - SURFACE_COMMANDS = 1, - CULLED_COMMANDS = 2, - SURFACE_BATCHES = 3, - COMMAND_COUNTERS_ATOMIC = 0, - COMMAND_COUNTERS_STORAGE = 4, // Avoid needlessly rebinding buffers - PORTAL_SURFACES = 5, - GEOMETRY_CACHE_INPUT_VBO = 6, - GEOMETRY_CACHE_VBO = 7, - DEBUG = 10, - UNUSED = INT32_MAX - }; -}; - class MaterialSystem { public: vec3_t worldViewBounds[2]; @@ -431,6 +411,7 @@ class MaterialSystem { std::vector dynamicStages; GLenum texDataBufferType; + GLuint texDataBindingPoint; std::vector texData; std::vector dynamicTexData; diff --git a/src/engine/renderer/gl_shader.cpp b/src/engine/renderer/gl_shader.cpp index 32b22dd60..d681cb925 100644 --- a/src/engine/renderer/gl_shader.cpp +++ b/src/engine/renderer/gl_shader.cpp @@ -584,6 +584,7 @@ static std::string GenVertexHeader() { if ( glConfig2.usingMaterialSystem ) { AddDefine( str, "BIND_MATERIALS", BufferBind::MATERIALS ); AddDefine( str, "BIND_TEX_DATA", BufferBind::TEX_DATA ); + AddDefine( str, "BIND_TEX_DATA_STORAGE", BufferBind::TEX_DATA_STORAGE ); AddDefine( str, "BIND_LIGHTMAP_DATA", BufferBind::LIGHTMAP_DATA ); } @@ -628,6 +629,7 @@ static std::string GenFragmentHeader() { if ( glConfig2.usingMaterialSystem ) { AddDefine( str, "BIND_MATERIALS", BufferBind::MATERIALS ); AddDefine( str, "BIND_TEX_DATA", BufferBind::TEX_DATA ); + AddDefine( str, "BIND_TEX_DATA_STORAGE", BufferBind::TEX_DATA_STORAGE ); AddDefine( str, "BIND_LIGHTMAP_DATA", BufferBind::LIGHTMAP_DATA ); } diff --git a/src/engine/renderer/gl_shader.h b/src/engine/renderer/gl_shader.h index 72aecc2e8..40e55dccd 100644 --- a/src/engine/renderer/gl_shader.h +++ b/src/engine/renderer/gl_shader.h @@ -24,6 +24,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define GL_SHADER_H #include "tr_local.h" +#include "BufferBind.h" #include #define USE_UNIFORM_FIREWALL 1 From 633b45a357490ae6fd065c3a07b74f32e1f05cf4 Mon Sep 17 00:00:00 2001 From: VReaperV Date: Sat, 24 May 2025 12:41:44 +0300 Subject: [PATCH 30/41] Only bind the GL buffers once per map Less useless API calls, though for lightMapping shader on entities, which uses the core renderer at all times, this is till not the case. --- src/engine/renderer/GeometryOptimiser.cpp | 2 + src/engine/renderer/Material.cpp | 85 +++++++++-------------- src/engine/renderer/Material.h | 2 + 3 files changed, 36 insertions(+), 53 deletions(-) diff --git a/src/engine/renderer/GeometryOptimiser.cpp b/src/engine/renderer/GeometryOptimiser.cpp index 4de4c4e05..7b8793803 100644 --- a/src/engine/renderer/GeometryOptimiser.cpp +++ b/src/engine/renderer/GeometryOptimiser.cpp @@ -716,6 +716,8 @@ std::vector OptimiseMapGeometryMaterial( world_t* world, bspSur materialSystem.GeneratePortalBoundingSpheres(); materialSystem.GenerateWorldCommandBuffer( processedMaterialSurfaces ); + materialSystem.BindBuffers(); + vertexAttributeSpec_t attrs[] { { ATTR_INDEX_POSITION, GL_FLOAT, GL_FLOAT, &vertices[0].xyz, 3, sizeof( *vertices ), 0 }, { ATTR_INDEX_COLOR, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE, &vertices[0].lightColor, 4, sizeof( *vertices ), ATTR_OPTION_NORMALIZE }, diff --git a/src/engine/renderer/Material.cpp b/src/engine/renderer/Material.cpp index 15fd68992..5ffce4524 100644 --- a/src/engine/renderer/Material.cpp +++ b/src/engine/renderer/Material.cpp @@ -725,6 +725,36 @@ void MaterialSystem::GenerateWorldCommandBuffer( std::vector& s GL_CheckErrors(); } +void MaterialSystem::BindBuffers() { + materialsUBO.BindBufferBase(); + texDataBuffer.BindBufferBase( texDataBufferType, texDataBindingPoint ); + lightMapDataUBO.BindBufferBase(); + + if ( glConfig2.realtimeLighting ) { + // UBOs are actually completely independent of shaders since we set the binding points explicitly here + gl_lightMappingShaderMaterial->SetUniformBlock_Lights( tr.dlightUBO ); + } + + culledCommandsBuffer.BindBuffer( GL_DRAW_INDIRECT_BUFFER ); + atomicCommandCountersBuffer.BindBuffer( GL_PARAMETER_BUFFER_ARB ); + + atomicCommandCountersBuffer.BindBufferBase( GL_SHADER_STORAGE_BUFFER, Util::ordinal( BufferBind::COMMAND_COUNTERS_STORAGE ) ); + + surfaceDescriptorsSSBO.BindBufferBase(); + surfaceCommandsSSBO.BindBufferBase(); + culledCommandsBuffer.BindBufferBase( GL_SHADER_STORAGE_BUFFER ); + surfaceBatchesUBO.BindBufferBase(); + atomicCommandCountersBuffer.BindBufferBase( GL_ATOMIC_COUNTER_BUFFER ); + + if ( totalPortals > 0 ) { + portalSurfacesSSBO.BindBufferBase(); + } + + if ( r_materialDebug.Get() ) { + debugSSBO.BindBufferBase(); + } +} + void MaterialSystem::GenerateDepthImages( const int width, const int height, imageParams_t imageParms ) { imageParms.bits ^= ( IF_NOPICMIP | IF_PACKED_DEPTH24_STENCIL8 ); imageParms.bits |= IF_ONECOMP32F; @@ -812,8 +842,6 @@ void BindShaderLightMapping( Material* material ) { } if ( glConfig2.realtimeLighting ) { - gl_lightMappingShaderMaterial->SetUniformBlock_Lights( tr.dlightUBO ); - // bind u_LightTiles gl_lightMappingShaderMaterial->SetUniform_LightTilesBindless( GL_BindToTMU( BIND_LIGHTTILES, tr.lighttileRenderImage ) @@ -1471,14 +1499,10 @@ void MaterialSystem::UpdateDynamicSurfaces() { } void MaterialSystem::UpdateFrameData() { - atomicCommandCountersBuffer.BindBufferBase( GL_SHADER_STORAGE_BUFFER, Util::ordinal( BufferBind::COMMAND_COUNTERS_STORAGE ) ); - gl_clearSurfacesShader->BindProgram( 0 ); gl_clearSurfacesShader->SetUniform_Frame( nextFrame ); gl_clearSurfacesShader->DispatchCompute( MAX_VIEWS, 1, 1 ); - atomicCommandCountersBuffer.UnBindBufferBase( GL_SHADER_STORAGE_BUFFER, Util::ordinal( BufferBind::COMMAND_COUNTERS_STORAGE ) ); - GL_CheckErrors(); } @@ -1530,6 +1554,8 @@ void MaterialSystem::DepthReduction() { glMemoryBarrier( GL_SHADER_IMAGE_ACCESS_BARRIER_BIT ); } + + GL_CheckErrors(); } void MaterialSystem::CullSurfaces() { @@ -1537,22 +1563,6 @@ void MaterialSystem::CullSurfaces() { DepthReduction(); } - surfaceDescriptorsSSBO.BindBufferBase(); - surfaceCommandsSSBO.BindBufferBase(); - culledCommandsBuffer.BindBufferBase( GL_SHADER_STORAGE_BUFFER ); - surfaceBatchesUBO.BindBufferBase(); - atomicCommandCountersBuffer.BindBufferBase( GL_ATOMIC_COUNTER_BUFFER ); - - if ( totalPortals > 0 ) { - portalSurfacesSSBO.BindBufferBase(); - } - - if ( r_materialDebug.Get() ) { - debugSSBO.BindBufferBase(); - } - - GL_CheckErrors(); - for ( uint32_t view = 0; view < frames[nextFrame].viewCount; view++ ) { vec3_t origin; frustum_t* frustum = &frames[nextFrame].viewFrames[view].frustum; @@ -1623,20 +1633,6 @@ void MaterialSystem::CullSurfaces() { gl_processSurfacesShader->DispatchCompute( totalBatchCount, 1, 1 ); } - surfaceDescriptorsSSBO.UnBindBufferBase(); - surfaceCommandsSSBO.UnBindBufferBase(); - culledCommandsBuffer.UnBindBufferBase( GL_SHADER_STORAGE_BUFFER ); - surfaceBatchesUBO.UnBindBufferBase(); - atomicCommandCountersBuffer.UnBindBufferBase( GL_ATOMIC_COUNTER_BUFFER ); - - if ( totalPortals > 0 ) { - portalSurfacesSSBO.UnBindBufferBase(); - } - - if ( r_materialDebug.Get() ) { - debugSSBO.UnBindBufferBase(); - } - GL_CheckErrors(); } @@ -1855,7 +1851,6 @@ void MaterialSystem::AddPortalSurfaces() { return; } - portalSurfacesSSBO.BindBufferBase(); PortalSurface* portalSurfs = ( PortalSurface* ) portalSurfacesSSBO.GetCurrentAreaData(); viewCount = 0; // This will recursively find potentially visible portals in each view based on the data read back from the GPU @@ -1894,8 +1889,6 @@ void MaterialSystem::RenderMaterials( const shaderSort_t fromSort, const shaderS frameStart = false; } - materialsUBO.BindBufferBase(); - geometryCache.Bind(); for ( MaterialPack& materialPack : materialPacks ) { @@ -2026,13 +2019,6 @@ void MaterialSystem::RenderMaterial( Material& material, const uint32_t viewID ) } material.texturesResident = true; - culledCommandsBuffer.BindBuffer( GL_DRAW_INDIRECT_BUFFER ); - - atomicCommandCountersBuffer.BindBuffer( GL_PARAMETER_BUFFER_ARB ); - - texDataBuffer.BindBufferBase( texDataBufferType, texDataBindingPoint ); - lightMapDataUBO.BindBufferBase(); - if ( r_showGlobalMaterials.Get() && material.sort != 0 && ( material.shaderBinder == BindShaderLightMapping || material.shaderBinder == BindShaderGeneric3D ) ) { vec3_t color; @@ -2143,13 +2129,6 @@ void MaterialSystem::RenderMaterial( Material& material, const uint32_t viewID ) } } - culledCommandsBuffer.UnBindBuffer( GL_DRAW_INDIRECT_BUFFER ); - - atomicCommandCountersBuffer.UnBindBuffer( GL_PARAMETER_BUFFER_ARB ); - - texDataBuffer.UnBindBufferBase( texDataBufferType, texDataBindingPoint ); - lightMapDataUBO.UnBindBufferBase(); - if ( material.usePolygonOffset ) { glDisable( GL_POLYGON_OFFSET_FILL ); } diff --git a/src/engine/renderer/Material.h b/src/engine/renderer/Material.h index e960af3ad..2ab9d2fad 100644 --- a/src/engine/renderer/Material.h +++ b/src/engine/renderer/Material.h @@ -364,6 +364,8 @@ class MaterialSystem { void InitGLBuffers(); void FreeGLBuffers(); + void BindBuffers(); + uint32_t GetTexDataSize() const { return texData.size(); } From 2bc7f51ed764467e9173a2bcf48c17da80b27013 Mon Sep 17 00:00:00 2001 From: VReaperV Date: Sat, 24 May 2025 12:53:07 +0300 Subject: [PATCH 31/41] Bind the u_Lights UBO only once if GL_ARB_shading_language_420pack is available --- src/engine/renderer/Material.cpp | 5 ----- src/engine/renderer/gl_shader.cpp | 4 ++++ src/engine/renderer/gl_shader.h | 3 ++- src/engine/renderer/tr_init.cpp | 4 ++++ 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/engine/renderer/Material.cpp b/src/engine/renderer/Material.cpp index 5ffce4524..0779a20a6 100644 --- a/src/engine/renderer/Material.cpp +++ b/src/engine/renderer/Material.cpp @@ -730,11 +730,6 @@ void MaterialSystem::BindBuffers() { texDataBuffer.BindBufferBase( texDataBufferType, texDataBindingPoint ); lightMapDataUBO.BindBufferBase(); - if ( glConfig2.realtimeLighting ) { - // UBOs are actually completely independent of shaders since we set the binding points explicitly here - gl_lightMappingShaderMaterial->SetUniformBlock_Lights( tr.dlightUBO ); - } - culledCommandsBuffer.BindBuffer( GL_DRAW_INDIRECT_BUFFER ); atomicCommandCountersBuffer.BindBuffer( GL_PARAMETER_BUFFER_ARB ); diff --git a/src/engine/renderer/gl_shader.cpp b/src/engine/renderer/gl_shader.cpp index d681cb925..895e3f76e 100644 --- a/src/engine/renderer/gl_shader.cpp +++ b/src/engine/renderer/gl_shader.cpp @@ -1181,6 +1181,10 @@ void GLShaderManager::BuildAll( const bool buildOnlyMarked ) { cacheLoadCount, cacheLoadTime, cacheSaveCount, cacheSaveTime ); } +void GLShaderManager::BindBuffers() { + glBindBufferBase( GL_UNIFORM_BUFFER, BufferBind::LIGHTS, tr.dlightUBO ); +} + std::string GLShaderManager::ProcessInserts( const std::string& shaderText ) const { std::string out; std::istringstream shaderTextStream( shaderText ); diff --git a/src/engine/renderer/gl_shader.h b/src/engine/renderer/gl_shader.h index 40e55dccd..0499697c7 100644 --- a/src/engine/renderer/gl_shader.h +++ b/src/engine/renderer/gl_shader.h @@ -368,6 +368,8 @@ class GLShaderManager { bool BuildPermutation( GLShader* shader, int macroIndex, int deformIndex, const bool buildOneShader ); void BuildAll( const bool buildOnlyMarked ); void FreeAll(); + + void BindBuffers(); private: struct InfoLogEntry { int line; @@ -1261,7 +1263,6 @@ class GLUniformBlock void SetBuffer( GLuint buffer ) { if ( glConfig2.shadingLanguage420PackAvailable ) { - glBindBufferBase( GL_UNIFORM_BUFFER, _bindingPoint, buffer ); return; } diff --git a/src/engine/renderer/tr_init.cpp b/src/engine/renderer/tr_init.cpp index b1d22dc6e..65c645624 100644 --- a/src/engine/renderer/tr_init.cpp +++ b/src/engine/renderer/tr_init.cpp @@ -1540,6 +1540,10 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p GLSL_FinishGPUShaders(); } + if ( glConfig2.shadingLanguage420PackAvailable ) { + gl_shaderManager.BindBuffers(); + } + /* TODO: Move this into a loading step and don't render it to the screen For now though do it here to avoid the ugly square rendering appearing on top of the loading screen */ if ( glConfig2.reflectionMappingAvailable ) { From 03499db774293db1575e450cdd5332ffec760574 Mon Sep 17 00:00:00 2001 From: VReaperV Date: Sat, 24 May 2025 20:00:15 +0300 Subject: [PATCH 32/41] More BufferBind clean-up --- src/engine/renderer/BufferBind.h | 5 ++--- src/engine/renderer/GeometryCache.h | 6 +++--- src/engine/renderer/Material.cpp | 22 +++++++++++----------- src/engine/renderer/gl_shader.cpp | 2 +- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/engine/renderer/BufferBind.h b/src/engine/renderer/BufferBind.h index 0245487d5..7f4b2c7c8 100644 --- a/src/engine/renderer/BufferBind.h +++ b/src/engine/renderer/BufferBind.h @@ -54,6 +54,7 @@ namespace BufferBind { GEOMETRY_CACHE_INPUT_VBO = 5, GEOMETRY_CACHE_VBO = 6, + GEOMETRY_CACHE_IBO = 7, COMMAND_COUNTERS_STORAGE = 9, TEX_DATA_STORAGE = 11, @@ -61,9 +62,7 @@ namespace BufferBind { DEBUG = 10, // Atomic - COMMAND_COUNTERS_ATOMIC = 0, - - UNUSED = INT32_MAX + COMMAND_COUNTERS_ATOMIC = 0 }; }; diff --git a/src/engine/renderer/GeometryCache.h b/src/engine/renderer/GeometryCache.h index 42f6d5c72..7709540e2 100644 --- a/src/engine/renderer/GeometryCache.h +++ b/src/engine/renderer/GeometryCache.h @@ -58,9 +58,9 @@ class GeometryCache { GLVAO VAO = GLVAO( 0 ); - GLBuffer inputVBO = GLBuffer( "geometryCacheInputVBO", Util::ordinal( BufferBind::GEOMETRY_CACHE_INPUT_VBO ), GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_RANGE_BIT ); - GLBuffer VBO = GLBuffer( "geometryCacheVBO", Util::ordinal( BufferBind::GEOMETRY_CACHE_VBO ), GL_MAP_WRITE_BIT, GL_MAP_FLUSH_EXPLICIT_BIT ); - GLBuffer IBO = GLBuffer( "geometryCacheIBO", Util::ordinal( BufferBind::UNUSED ), GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_RANGE_BIT ); + GLBuffer inputVBO = GLBuffer( "geometryCacheInputVBO", BufferBind::GEOMETRY_CACHE_INPUT_VBO, GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_RANGE_BIT ); + GLBuffer VBO = GLBuffer( "geometryCacheVBO", BufferBind::GEOMETRY_CACHE_VBO, GL_MAP_WRITE_BIT, GL_MAP_FLUSH_EXPLICIT_BIT ); + GLBuffer IBO = GLBuffer( "geometryCacheIBO", BufferBind::GEOMETRY_CACHE_IBO, GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_RANGE_BIT ); }; extern GeometryCache geometryCache; diff --git a/src/engine/renderer/Material.cpp b/src/engine/renderer/Material.cpp index 0779a20a6..c27ac58f0 100644 --- a/src/engine/renderer/Material.cpp +++ b/src/engine/renderer/Material.cpp @@ -39,18 +39,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "ShadeCommon.h" #include "GeometryCache.h" -GLUBO materialsUBO( "materials", Util::ordinal( BufferBind::MATERIALS ), GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_RANGE_BIT ); -GLBuffer texDataBuffer( "texData", Util::ordinal( BufferBind::TEX_DATA ), GL_MAP_WRITE_BIT, GL_MAP_FLUSH_EXPLICIT_BIT ); -GLUBO lightMapDataUBO( "lightMapData", Util::ordinal( BufferBind::LIGHTMAP_DATA ), GL_MAP_WRITE_BIT, GL_MAP_FLUSH_EXPLICIT_BIT ); +GLUBO materialsUBO( "materials", BufferBind::MATERIALS, GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_RANGE_BIT ); +GLBuffer texDataBuffer( "texData", BufferBind::TEX_DATA, GL_MAP_WRITE_BIT, GL_MAP_FLUSH_EXPLICIT_BIT ); +GLUBO lightMapDataUBO( "lightMapData", BufferBind::LIGHTMAP_DATA, GL_MAP_WRITE_BIT, GL_MAP_FLUSH_EXPLICIT_BIT ); -GLSSBO surfaceDescriptorsSSBO( "surfaceDescriptors", Util::ordinal( BufferBind::SURFACE_DESCRIPTORS ), GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_RANGE_BIT ); -GLSSBO surfaceCommandsSSBO( "surfaceCommands", Util::ordinal( BufferBind::SURFACE_COMMANDS ), GL_MAP_WRITE_BIT, GL_MAP_FLUSH_EXPLICIT_BIT ); -GLBuffer culledCommandsBuffer( "culledCommands", Util::ordinal( BufferBind::CULLED_COMMANDS ), GL_MAP_WRITE_BIT, GL_MAP_FLUSH_EXPLICIT_BIT ); -GLUBO surfaceBatchesUBO( "surfaceBatches", Util::ordinal( BufferBind::SURFACE_BATCHES ), GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_RANGE_BIT ); -GLBuffer atomicCommandCountersBuffer( "atomicCommandCounters", Util::ordinal( BufferBind::COMMAND_COUNTERS_ATOMIC ), GL_MAP_WRITE_BIT, GL_MAP_FLUSH_EXPLICIT_BIT ); -GLSSBO portalSurfacesSSBO( "portalSurfaces", Util::ordinal( BufferBind::PORTAL_SURFACES ), GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT, 0 ); +GLSSBO surfaceDescriptorsSSBO( "surfaceDescriptors", BufferBind::SURFACE_DESCRIPTORS, GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_RANGE_BIT ); +GLSSBO surfaceCommandsSSBO( "surfaceCommands", BufferBind::SURFACE_COMMANDS, GL_MAP_WRITE_BIT, GL_MAP_FLUSH_EXPLICIT_BIT ); +GLBuffer culledCommandsBuffer( "culledCommands", BufferBind::CULLED_COMMANDS, GL_MAP_WRITE_BIT, GL_MAP_FLUSH_EXPLICIT_BIT ); +GLUBO surfaceBatchesUBO( "surfaceBatches", BufferBind::SURFACE_BATCHES, GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_RANGE_BIT ); +GLBuffer atomicCommandCountersBuffer( "atomicCommandCounters", BufferBind::COMMAND_COUNTERS_ATOMIC, GL_MAP_WRITE_BIT, GL_MAP_FLUSH_EXPLICIT_BIT ); +GLSSBO portalSurfacesSSBO( "portalSurfaces", BufferBind::PORTAL_SURFACES, GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT, 0 ); -GLSSBO debugSSBO( "debug", Util::ordinal( BufferBind::DEBUG ), GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_RANGE_BIT ); +GLSSBO debugSSBO( "debug", BufferBind::DEBUG, GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_RANGE_BIT ); PortalView portalStack[MAX_VIEWS]; @@ -733,7 +733,7 @@ void MaterialSystem::BindBuffers() { culledCommandsBuffer.BindBuffer( GL_DRAW_INDIRECT_BUFFER ); atomicCommandCountersBuffer.BindBuffer( GL_PARAMETER_BUFFER_ARB ); - atomicCommandCountersBuffer.BindBufferBase( GL_SHADER_STORAGE_BUFFER, Util::ordinal( BufferBind::COMMAND_COUNTERS_STORAGE ) ); + atomicCommandCountersBuffer.BindBufferBase( GL_SHADER_STORAGE_BUFFER, BufferBind::COMMAND_COUNTERS_STORAGE ); surfaceDescriptorsSSBO.BindBufferBase(); surfaceCommandsSSBO.BindBufferBase(); diff --git a/src/engine/renderer/gl_shader.cpp b/src/engine/renderer/gl_shader.cpp index 895e3f76e..498aaff20 100644 --- a/src/engine/renderer/gl_shader.cpp +++ b/src/engine/renderer/gl_shader.cpp @@ -1563,7 +1563,7 @@ std::string GLShaderManager::ShaderPostProcess( GLShader *shader, const std::str " uvec2 u_DeluxeMap;\n" "};\n\n" "layout(std140, binding = " - + std::to_string( Util::ordinal( BufferBind::LIGHTMAP_DATA ) ) + + std::to_string( BufferBind::LIGHTMAP_DATA ) + ") uniform lightMapDataUBO {\n" " LightMapData lightMapData[256];\n" "};\n\n" From 9a9a5c2b520e205a82b16eab654ba28065d318a5 Mon Sep 17 00:00:00 2001 From: slipher Date: Mon, 9 Jun 2025 02:05:58 -0500 Subject: [PATCH 33/41] Fix r_showEntityTransforms drawing garbage for sprites For RT_SPRITE entities the bounds are not valid and it would draw something using garbage data from a previous entity. Skip anything that is not RT_MODEL. --- src/engine/renderer/tr_backend.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/engine/renderer/tr_backend.cpp b/src/engine/renderer/tr_backend.cpp index 087c629b3..670d611d2 100644 --- a/src/engine/renderer/tr_backend.cpp +++ b/src/engine/renderer/tr_backend.cpp @@ -1595,6 +1595,11 @@ static void RB_RenderDebugUtils() for ( i = 0; i < backEnd.refdef.numEntities; i++, ent++ ) { + if ( ent->e.reType != refEntityType_t::RT_MODEL ) + { + continue; + } + if ( ( ent->e.renderfx & RF_THIRD_PERSON ) && backEnd.viewParms.portalLevel == 0 ) { From 429171d9ff491b97c6047eaa59ad4d815a8e7708 Mon Sep 17 00:00:00 2001 From: slipher Date: Mon, 9 Jun 2025 00:58:35 -0500 Subject: [PATCH 34/41] Fix wrong culling with r_showEntityTransforms Sometimes I look directly at a door and its bbox is not shown. Looks like ent->cull is only used for IQM/MD5/MD3 models. --- src/engine/renderer/tr_backend.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/engine/renderer/tr_backend.cpp b/src/engine/renderer/tr_backend.cpp index 670d611d2..565a5d4e5 100644 --- a/src/engine/renderer/tr_backend.cpp +++ b/src/engine/renderer/tr_backend.cpp @@ -1606,11 +1606,6 @@ static void RB_RenderDebugUtils() continue; } - if ( ent->cull == cullResult_t::CULL_OUT ) - { - continue; - } - // set up the transformation matrix R_RotateEntityForViewParms( ent, &backEnd.viewParms, &backEnd.orientation ); GL_LoadModelViewMatrix( backEnd.orientation.modelViewMatrix ); From c934bb87d68a4be02bed4441685ec4285a351abe Mon Sep 17 00:00:00 2001 From: slipher Date: Mon, 9 Jun 2025 01:13:56 -0500 Subject: [PATCH 35/41] Remove field trRefEntity_t::cull It was pointless since it was only read immediately after being written. --- src/engine/renderer/tr_animation.cpp | 15 +++++---------- src/engine/renderer/tr_local.h | 1 - src/engine/renderer/tr_mesh.cpp | 27 +++++++++------------------ src/engine/renderer/tr_model_iqm.cpp | 18 +++++------------- src/engine/renderer/tr_world.cpp | 4 +--- 5 files changed, 20 insertions(+), 45 deletions(-) diff --git a/src/engine/renderer/tr_animation.cpp b/src/engine/renderer/tr_animation.cpp index bd2853909..617a233c3 100644 --- a/src/engine/renderer/tr_animation.cpp +++ b/src/engine/renderer/tr_animation.cpp @@ -610,7 +610,7 @@ static ListAnimationsCmd listAnimationsCmdRegistration; R_CullMD5 ============= */ -static void R_CullMD5( trRefEntity_t *ent ) +static cullResult_t R_CullMD5( trRefEntity_t *ent ) { int i; @@ -638,19 +638,16 @@ static void R_CullMD5( trRefEntity_t *ent ) { case cullResult_t::CULL_IN: tr.pc.c_box_cull_md5_in++; - ent->cull = cullResult_t::CULL_IN; - return; + return cullResult_t::CULL_IN; case cullResult_t::CULL_CLIP: tr.pc.c_box_cull_md5_clip++; - ent->cull = cullResult_t::CULL_CLIP; - return; + return cullResult_t::CULL_CLIP; case cullResult_t::CULL_OUT: default: tr.pc.c_box_cull_md5_out++; - ent->cull = cullResult_t::CULL_OUT; - return; + return cullResult_t::CULL_OUT; } } @@ -674,9 +671,7 @@ void R_AddMD5Surfaces( trRefEntity_t *ent ) // cull the entire model if merged bounding box of both frames // is outside the view frustum - R_CullMD5( ent ); - - if ( ent->cull == cullResult_t::CULL_OUT ) + if ( R_CullMD5( ent ) == cullResult_t::CULL_OUT ) { return; } diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index a1405e9fd..ac4885f75 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -424,7 +424,6 @@ enum class ssaoMode { // local float axisLength; // compensate for non-normalized axis - cullResult_t cull; vec3_t localBounds[ 2 ]; vec3_t worldBounds[ 2 ]; }; diff --git a/src/engine/renderer/tr_mesh.cpp b/src/engine/renderer/tr_mesh.cpp index ecb0105eb..be367a213 100644 --- a/src/engine/renderer/tr_mesh.cpp +++ b/src/engine/renderer/tr_mesh.cpp @@ -29,7 +29,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA R_CullMDV ============= */ -static void R_CullMDV( mdvModel_t *model, trRefEntity_t *ent ) +static cullResult_t R_CullMDV( mdvModel_t *model, trRefEntity_t *ent ) { mdvFrame_t *oldFrame, *newFrame; int i; @@ -59,13 +59,11 @@ static void R_CullMDV( mdvModel_t *model, trRefEntity_t *ent ) { case cullResult_t::CULL_OUT: tr.pc.c_sphere_cull_mdv_out++; - ent->cull = cullResult_t::CULL_OUT; - return; + return cullResult_t::CULL_OUT; case cullResult_t::CULL_IN: tr.pc.c_sphere_cull_mdv_in++; - ent->cull = cullResult_t::CULL_IN; - return; + return cullResult_t::CULL_IN; case cullResult_t::CULL_CLIP: tr.pc.c_sphere_cull_mdv_clip++; @@ -91,14 +89,12 @@ static void R_CullMDV( mdvModel_t *model, trRefEntity_t *ent ) if ( sphereCull == cullResult_t::CULL_OUT ) { tr.pc.c_sphere_cull_mdv_out++; - ent->cull = cullResult_t::CULL_OUT; - return; + return cullResult_t::CULL_OUT; } else if ( sphereCull == cullResult_t::CULL_IN ) { tr.pc.c_sphere_cull_mdv_in++; - ent->cull = cullResult_t::CULL_IN; - return; + return cullResult_t::CULL_IN; } else { @@ -112,19 +108,16 @@ static void R_CullMDV( mdvModel_t *model, trRefEntity_t *ent ) { case cullResult_t::CULL_IN: tr.pc.c_box_cull_mdv_in++; - ent->cull = cullResult_t::CULL_IN; - return; + return cullResult_t::CULL_IN; case cullResult_t::CULL_CLIP: tr.pc.c_box_cull_mdv_clip++; - ent->cull = cullResult_t::CULL_CLIP; - return; + return cullResult_t::CULL_CLIP; case cullResult_t::CULL_OUT: default: tr.pc.c_box_cull_mdv_out++; - ent->cull = cullResult_t::CULL_OUT; - return; + return cullResult_t::CULL_OUT; } } @@ -296,9 +289,7 @@ void R_AddMDVSurfaces( trRefEntity_t *ent ) // cull the entire model if merged bounding box of both frames // is outside the view frustum. - R_CullMDV( model, ent ); - - if ( ent->cull == CULL_OUT ) + if ( R_CullMDV( model, ent ) == CULL_OUT ) { return; } diff --git a/src/engine/renderer/tr_model_iqm.cpp b/src/engine/renderer/tr_model_iqm.cpp index a23d0d56e..d6a9413be 100644 --- a/src/engine/renderer/tr_model_iqm.cpp +++ b/src/engine/renderer/tr_model_iqm.cpp @@ -930,7 +930,7 @@ bool R_LoadIQModel( model_t *mod, const void *buffer, int filesize, R_CullIQM ============= */ -static void R_CullIQM( trRefEntity_t *ent ) { +static cullResult_t R_CullIQM( trRefEntity_t *ent ) { vec3_t localBounds[ 2 ]; float scale = ent->e.skeleton.scale; IQModel_t *model = tr.currentModel->iqm; @@ -962,17 +962,14 @@ static void R_CullIQM( trRefEntity_t *ent ) { { case cullResult_t::CULL_IN: tr.pc.c_box_cull_md5_in++; - ent->cull = cullResult_t::CULL_IN; - return; + return cullResult_t::CULL_IN; case cullResult_t::CULL_CLIP: tr.pc.c_box_cull_md5_clip++; - ent->cull = cullResult_t::CULL_CLIP; - return; + return cullResult_t::CULL_CLIP; case cullResult_t::CULL_OUT: default: tr.pc.c_box_cull_md5_out++; - ent->cull = cullResult_t::CULL_OUT; - return; + return cullResult_t::CULL_OUT; } } @@ -999,14 +996,9 @@ void R_AddIQMSurfaces( trRefEntity_t *ent ) { personalModel = (ent->e.renderfx & RF_THIRD_PERSON) && tr.viewParms.portalLevel == 0; - // cull the entire model if merged bounding box of both frames - // is outside the view frustum. - R_CullIQM( ent ); - // HACK: Never cull first-person models, due to issues with a certain model's bounds // A first-person model not in the player's sight seems like something that should not happen in any case - // But R_CullIQM is always called because it sets some fields used by other code - if ( ent->cull == cullResult_t::CULL_OUT && !( ent->e.renderfx & RF_FIRST_PERSON ) ) + if ( !( ent->e.renderfx & RF_FIRST_PERSON ) && R_CullIQM( ent ) == cullResult_t::CULL_OUT ) { return; } diff --git a/src/engine/renderer/tr_world.cpp b/src/engine/renderer/tr_world.cpp index 2f846d410..a8bac11e4 100644 --- a/src/engine/renderer/tr_world.cpp +++ b/src/engine/renderer/tr_world.cpp @@ -185,9 +185,7 @@ void R_AddBSPModelSurfaces( trRefEntity_t *ent ) VectorAdd( ent->worldBounds[ 0 ], ent->worldBounds[ 1 ], boundsCenter ); VectorScale( boundsCenter, 0.5f, boundsCenter ); - ent->cull = R_CullBox( ent->worldBounds ); - - if ( ent->cull == CULL_OUT ) + if ( R_CullBox( ent->worldBounds ) == CULL_OUT ) { return; } From 0fa128fb43c8492cb66f7f3803be3ff9f3ed71cc Mon Sep 17 00:00:00 2001 From: slipher Date: Wed, 4 Jun 2025 19:55:26 -0500 Subject: [PATCH 36/41] Add translucent solid option for showing cull bbox Rename r_showEntityTransforms to r_showEntityBounds and add a new option (2) for showing the culling bounding boxes as a solid translucent surface, in addition to the old wireframe option. This makes it easier to see when the model is poking out of the box. --- src/engine/renderer/tr_backend.cpp | 31 ++++++++++++++++++++++++------ src/engine/renderer/tr_init.cpp | 2 -- src/engine/renderer/tr_local.h | 1 - 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/engine/renderer/tr_backend.cpp b/src/engine/renderer/tr_backend.cpp index 565a5d4e5..b0dbce22c 100644 --- a/src/engine/renderer/tr_backend.cpp +++ b/src/engine/renderer/tr_backend.cpp @@ -34,6 +34,8 @@ backEndState_t backEnd; static Cvar::Cvar r_clear( "r_clear", "Clear screen before painting over it on every frame", Cvar::NONE, false ); Cvar::Cvar r_drawSky( "r_drawSky", "Draw the sky (clear the sky if disabled)", Cvar::NONE, true ); +static Cvar::Cvar r_showEntityBounds( + "r_showEntityBounds", "show bboxes used for culling (1: wireframe; 2: translucent solid)", Cvar::CHEAT, 0); void GL_Bind( image_t *image ) { @@ -1563,7 +1565,7 @@ static void RB_RenderDebugUtils() { GLIMP_LOGCOMMENT( "--- RB_RenderDebugUtils ---" ); - if ( r_showEntityTransforms->integer ) + if ( r_showEntityBounds.Get() ) { trRefEntity_t *ent; int i; @@ -1577,13 +1579,23 @@ static void RB_RenderDebugUtils() gl_genericShader->SetDepthFade( false ); gl_genericShader->BindProgram( 0 ); - GL_State( GLS_POLYMODE_LINE | GLS_DEPTHTEST_DISABLE ); + if ( r_showEntityBounds.Get() == 2 ) + { + GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA ); + glEnable( GL_POLYGON_OFFSET_FILL ); + GL_PolygonOffset( r_offsetFactor->value, r_offsetUnits->value ); + } + else + { + GL_State( GLS_POLYMODE_LINE | GLS_DEPTHTEST_DISABLE ); + } + GL_Cull( cullType_t::CT_TWO_SIDED ); // set uniforms gl_genericShader->SetUniform_AlphaTest( GLS_ATEST_NONE ); SetUniform_ColorModulateColorGen( gl_genericShader, colorGen_t::CGEN_VERTEX, alphaGen_t::AGEN_VERTEX ); - SetUniform_Color( gl_genericShader, Color::Black ); + SetUniform_Color( gl_genericShader, Color::Color(0, 0, 0, 0) ); // bind u_ColorMap gl_genericShader->SetUniform_ColorMapBindless( @@ -1613,9 +1625,15 @@ static void RB_RenderDebugUtils() Tess_Begin( Tess_StageIteratorDebug, nullptr, nullptr, true, -1, 0 ); - Tess_AddCube( vec3_origin, ent->localBounds[ 0 ], ent->localBounds[ 1 ], Color::Blue ); - - Tess_AddCube( vec3_origin, mins, maxs,Color::White ); + if ( r_showEntityBounds.Get() == 2) + { + Tess_AddCube( vec3_origin, ent->localBounds[ 0 ], ent->localBounds[ 1 ], Color::Color(0, 0, 0.5, 0.4) ); + } + else + { + Tess_AddCube( vec3_origin, ent->localBounds[ 0 ], ent->localBounds[ 1 ], Color::Blue ); + Tess_AddCube( vec3_origin, mins, maxs,Color::White ); + } Tess_End(); } @@ -1623,6 +1641,7 @@ static void RB_RenderDebugUtils() // go back to the world modelview matrix backEnd.orientation = backEnd.viewParms.world; GL_LoadModelViewMatrix( backEnd.viewParms.world.modelViewMatrix ); + glDisable( GL_POLYGON_OFFSET_FILL ); } if ( r_showSkeleton->integer ) diff --git a/src/engine/renderer/tr_init.cpp b/src/engine/renderer/tr_init.cpp index 65c645624..76c31833b 100644 --- a/src/engine/renderer/tr_init.cpp +++ b/src/engine/renderer/tr_init.cpp @@ -227,7 +227,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA cvar_t *r_showTris; cvar_t *r_showSky; cvar_t *r_showSkeleton; - cvar_t *r_showEntityTransforms; cvar_t *r_showLightGrid; cvar_t *r_showLightTiles; cvar_t *r_showBatches; @@ -1276,7 +1275,6 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p r_showTris = Cvar_Get( "r_showTris", "0", CVAR_CHEAT ); r_showSky = Cvar_Get( "r_showSky", "0", CVAR_CHEAT ); r_showSkeleton = Cvar_Get( "r_showSkeleton", "0", CVAR_CHEAT ); - r_showEntityTransforms = Cvar_Get( "r_showEntityTransforms", "0", CVAR_CHEAT ); r_showLightGrid = Cvar_Get( "r_showLightGrid", "0", CVAR_CHEAT ); r_showLightTiles = Cvar_Get("r_showLightTiles", "0", CVAR_CHEAT | CVAR_LATCH ); r_showBatches = Cvar_Get( "r_showBatches", "0", CVAR_CHEAT ); diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index ac4885f75..2c29878b9 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -2833,7 +2833,6 @@ enum class ssaoMode { extern cvar_t *r_showTris; // enables wireframe rendering of the world extern cvar_t *r_showSky; // forces sky in front of all surfaces extern cvar_t *r_showSkeleton; - extern cvar_t *r_showEntityTransforms; extern cvar_t *r_showLightGrid; extern cvar_t *r_showLightTiles; extern cvar_t *r_showBatches; From e6583735ef242ecc58f5d3ed3e9cac7c39197b9a Mon Sep 17 00:00:00 2001 From: slipher Date: Thu, 12 Jun 2025 04:42:14 -0500 Subject: [PATCH 37/41] Fix r_showLightTiles GLSL code --- .../renderer/glsl_source/computeLight_fp.glsl | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/engine/renderer/glsl_source/computeLight_fp.glsl b/src/engine/renderer/glsl_source/computeLight_fp.glsl index 633fb6ff8..f3c23bf9e 100644 --- a/src/engine/renderer/glsl_source/computeLight_fp.glsl +++ b/src/engine/renderer/glsl_source/computeLight_fp.glsl @@ -227,6 +227,10 @@ void computeDynamicLights( vec3 P, vec3 normal, vec3 viewDir, vec4 diffuse, vec4 return; } + #if defined(r_showLightTiles) + uint totalLights = 0u; + #endif + vec2 tile = floor( gl_FragCoord.xy * ( 1.0 / float( TILE_SIZE ) ) ) + 0.5; for( uint layer = 0u; layer < uint( NUM_LIGHT_LAYERS ); layer++ ) { @@ -247,12 +251,15 @@ void computeDynamicLights( vec3 P, vec3 normal, vec3 viewDir, vec4 diffuse, vec4 computeDynamicLight( idx, P, normal, viewDir, diffuse, material, color ); lightCount++; } + #if defined(r_showLightTiles) + totalLights += lightCount; + #endif } #if defined(r_showLightTiles) - if ( lightCount > 0 ) { - color = vec4( float( lightCount ) / u_numLights, float( lightCount ) / u_numLights, - float( lightCount ) / u_numLights, 1.0 ); + if ( totalLights > 0 ) { + color = vec4( float( totalLights ) / u_numLights, float( totalLights ) / u_numLights, + float( totalLights ) / u_numLights, 1.0 ); } #endif } From d3786bef52db29629ac3e265b26fc0b20b5b64bd Mon Sep 17 00:00:00 2001 From: VReaperV Date: Fri, 30 May 2025 00:06:59 +0300 Subject: [PATCH 38/41] Implement staging buffer and use it for material system Adds `GLStagingBuffer` and `GLBufferCopy()`. `GLStagingBuffer` allows setting buffer storage and map flags to 0 on the destination buffers, which pretty much guarantees that they will go into VRAM. The data is uploaded through mapping `stagingBuffer` and doing a copy of the data on the GPU. --- src.cmake | 2 + src/engine/renderer/BufferBind.h | 1 + src/engine/renderer/GLMemory.cpp | 128 +++++++++++++++++++++++++++++++ src/engine/renderer/GLMemory.h | 78 +++++++++++++++++++ src/engine/renderer/Material.cpp | 117 +++++++++++++++------------- src/engine/renderer/gl_shader.h | 11 ++- src/engine/renderer/shaders.cpp | 2 +- src/engine/renderer/tr_vbo.cpp | 9 +++ 8 files changed, 290 insertions(+), 58 deletions(-) create mode 100644 src/engine/renderer/GLMemory.cpp create mode 100644 src/engine/renderer/GLMemory.h diff --git a/src.cmake b/src.cmake index 8f5f4773d..e5e4f4974 100644 --- a/src.cmake +++ b/src.cmake @@ -97,6 +97,8 @@ set(RENDERERLIST ${ENGINE_DIR}/renderer/GeometryCache.h ${ENGINE_DIR}/renderer/GeometryOptimiser.cpp ${ENGINE_DIR}/renderer/GeometryOptimiser.h + ${ENGINE_DIR}/renderer/GLMemory.cpp + ${ENGINE_DIR}/renderer/GLMemory.h ${ENGINE_DIR}/renderer/InternalImage.cpp ${ENGINE_DIR}/renderer/InternalImage.h ${ENGINE_DIR}/renderer/Material.cpp diff --git a/src/engine/renderer/BufferBind.h b/src/engine/renderer/BufferBind.h index 7f4b2c7c8..3c4d53766 100644 --- a/src/engine/renderer/BufferBind.h +++ b/src/engine/renderer/BufferBind.h @@ -58,6 +58,7 @@ namespace BufferBind { COMMAND_COUNTERS_STORAGE = 9, TEX_DATA_STORAGE = 11, + STAGING = 12, DEBUG = 10, diff --git a/src/engine/renderer/GLMemory.cpp b/src/engine/renderer/GLMemory.cpp new file mode 100644 index 000000000..e1efaa554 --- /dev/null +++ b/src/engine/renderer/GLMemory.cpp @@ -0,0 +1,128 @@ +/* +=========================================================================== + +Daemon BSD Source Code +Copyright (c) 2025 Daemon Developers +All rights reserved. + +This file is part of the Daemon BSD Source Code (Daemon Source Code). + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Daemon developers nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL DAEMON DEVELOPERS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=========================================================================== +*/ +// GLMemory.cpp + +#include "common/Common.h" + +#include "GLMemory.h" + +// 128 MB, should be enough to fit anything in BAR without going overboard +const GLsizeiptr GLStagingBuffer::SIZE = 128 * 1024 * 1024 / sizeof( uint32_t ); + +GLStagingBuffer stagingBuffer; + +void GLBufferCopy( GLBuffer* src, GLBuffer* dst, GLintptr srcOffset, GLintptr dstOffset, GLsizeiptr size ) { + glCopyNamedBufferSubData( src->id, dst->id, + srcOffset * sizeof( uint32_t ), dstOffset * sizeof( uint32_t ), size * sizeof( uint32_t ) ); +} + +uint32_t* GLStagingBuffer::MapBuffer( const GLsizeiptr size ) { + if ( size > SIZE ) { + Sys::Drop( "Couldn't map GL staging buffer: size too large (%u/%u)", size, SIZE ); + } + + if ( pointer + size > SIZE ) { + FlushAll(); + + GLsync sync = glFenceSync( GL_SYNC_GPU_COMMANDS_COMPLETE, 0 ); + + constexpr GLuint64 SYNC_TIMEOUT = 10000000000; // 10 seconds + if ( glClientWaitSync( sync, GL_SYNC_FLUSH_COMMANDS_BIT, SYNC_TIMEOUT ) == GL_TIMEOUT_EXPIRED ) { + Sys::Drop( "Failed GL staging buffer copy sync" ); + } + glDeleteSync( sync ); + + pointer = 0; + current = 0; + last = 0; + } + + uint32_t* ret = buffer.GetData() + pointer; + last = pointer; + pointer += size; + + return ret; +} + +void GLStagingBuffer::FlushBuffer() { + buffer.FlushRange( current, pointer - current ); + + GL_CheckErrors(); + + current = pointer; +} + +void GLStagingBuffer::QueueStagingCopy( GLBuffer* dst, const GLsizeiptr dstOffset ) { + copyQueue[currentCopy].dst = dst; + copyQueue[currentCopy].dstOffset = dstOffset; + copyQueue[currentCopy].stagingOffset = last; + copyQueue[currentCopy].size = pointer - last; + + currentCopy++; + + if ( currentCopy == MAX_COPIES ) { + FlushStagingCopyQueue(); + } +} + +void GLStagingBuffer::FlushStagingCopyQueue() { + for ( GLStagingCopy& copy : copyQueue ) { + if ( copy.dst ) { + GLBufferCopy( &buffer, copy.dst, copy.stagingOffset, copy.dstOffset, copy.size ); + copy.dst = nullptr; + } + } + + currentCopy = 0; + + GL_CheckErrors(); +} + +void GLStagingBuffer::FlushAll() { + FlushBuffer(); + FlushStagingCopyQueue(); +} + +void GLStagingBuffer::InitGLBuffer() { + buffer.GenBuffer(); + + buffer.BufferStorage( SIZE, 1, nullptr ); + buffer.MapAll(); + + GL_CheckErrors(); +} + +void GLStagingBuffer::FreeGLBuffer() { + buffer.DelBuffer(); +} diff --git a/src/engine/renderer/GLMemory.h b/src/engine/renderer/GLMemory.h new file mode 100644 index 000000000..faba711ec --- /dev/null +++ b/src/engine/renderer/GLMemory.h @@ -0,0 +1,78 @@ +/* +=========================================================================== + +Daemon BSD Source Code +Copyright (c) 2025 Daemon Developers +All rights reserved. + +This file is part of the Daemon BSD Source Code (Daemon Source Code). + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Daemon developers nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL DAEMON DEVELOPERS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=========================================================================== +*/ +// GLMemory.h + +#ifndef GLMEMORY_H +#define GLMEMORY_H + +#include "gl_shader.h" + +void GLBufferCopy( GLBuffer* src, GLBuffer* dst, GLintptr srcOffset, GLintptr dstOffset, GLsizeiptr size ); + +struct GLStagingCopy { + GLBuffer* dst; + GLsizeiptr stagingOffset; + GLsizeiptr dstOffset; + GLsizeiptr size; +}; + +class GLStagingBuffer { + public: + uint32_t* MapBuffer( const GLsizeiptr size ); + void FlushBuffer(); + void QueueStagingCopy( GLBuffer* dst, const GLsizeiptr dstOffset ); + void FlushStagingCopyQueue(); + void FlushAll(); + + void InitGLBuffer(); + void FreeGLBuffer(); + + private: + static const GLsizeiptr SIZE; + + GLsizeiptr pointer = 0; + GLsizeiptr current = 0; + GLsizeiptr last = 0; + + static const uint32_t MAX_COPIES = 16; + GLStagingCopy copyQueue[MAX_COPIES]; + uint32_t currentCopy = 0; + + GLBuffer buffer = GLBuffer( "staging", BufferBind::STAGING, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT, + GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_INVALIDATE_BUFFER_BIT ); +}; + +extern GLStagingBuffer stagingBuffer; + +#endif // GLMEMORY_H diff --git a/src/engine/renderer/Material.cpp b/src/engine/renderer/Material.cpp index c27ac58f0..c88d94f89 100644 --- a/src/engine/renderer/Material.cpp +++ b/src/engine/renderer/Material.cpp @@ -38,16 +38,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "BufferBind.h" #include "ShadeCommon.h" #include "GeometryCache.h" +#include "GLMemory.h" -GLUBO materialsUBO( "materials", BufferBind::MATERIALS, GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_RANGE_BIT ); -GLBuffer texDataBuffer( "texData", BufferBind::TEX_DATA, GL_MAP_WRITE_BIT, GL_MAP_FLUSH_EXPLICIT_BIT ); -GLUBO lightMapDataUBO( "lightMapData", BufferBind::LIGHTMAP_DATA, GL_MAP_WRITE_BIT, GL_MAP_FLUSH_EXPLICIT_BIT ); +GLUBO materialsUBO( "materials", BufferBind::MATERIALS, 0, 0 ); +GLBuffer texDataBuffer( "texData", BufferBind::TEX_DATA, 0, 0 ); +GLUBO lightMapDataUBO( "lightMapData", BufferBind::LIGHTMAP_DATA, 0, 0 ); -GLSSBO surfaceDescriptorsSSBO( "surfaceDescriptors", BufferBind::SURFACE_DESCRIPTORS, GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_RANGE_BIT ); -GLSSBO surfaceCommandsSSBO( "surfaceCommands", BufferBind::SURFACE_COMMANDS, GL_MAP_WRITE_BIT, GL_MAP_FLUSH_EXPLICIT_BIT ); -GLBuffer culledCommandsBuffer( "culledCommands", BufferBind::CULLED_COMMANDS, GL_MAP_WRITE_BIT, GL_MAP_FLUSH_EXPLICIT_BIT ); -GLUBO surfaceBatchesUBO( "surfaceBatches", BufferBind::SURFACE_BATCHES, GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_RANGE_BIT ); -GLBuffer atomicCommandCountersBuffer( "atomicCommandCounters", BufferBind::COMMAND_COUNTERS_ATOMIC, GL_MAP_WRITE_BIT, GL_MAP_FLUSH_EXPLICIT_BIT ); +GLSSBO surfaceDescriptorsSSBO( "surfaceDescriptors", BufferBind::SURFACE_DESCRIPTORS, 0, 0 ); +GLSSBO surfaceCommandsSSBO( "surfaceCommands", BufferBind::SURFACE_COMMANDS, 0, 0 ); +GLBuffer culledCommandsBuffer( "culledCommands", BufferBind::CULLED_COMMANDS, 0, 0 ); +GLUBO surfaceBatchesUBO( "surfaceBatches", BufferBind::SURFACE_BATCHES, 0, 0 ); +GLBuffer atomicCommandCountersBuffer( "atomicCommandCounters", BufferBind::COMMAND_COUNTERS_ATOMIC, 0, 0 ); GLSSBO portalSurfacesSSBO( "portalSurfaces", BufferBind::PORTAL_SURFACES, GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT, 0 ); GLSSBO debugSSBO( "debug", BufferBind::DEBUG, GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_RANGE_BIT ); @@ -426,10 +427,13 @@ void MaterialSystem::GenerateWorldMaterialsBuffer() { totalStageSize = offset; // 4 bytes per component - materialsUBO.BufferData( offset, nullptr, GL_DYNAMIC_DRAW ); - uint32_t* materialsData = materialsUBO.MapBufferRange( offset ); + materialsUBO.BufferStorage( totalStageSize, 1, nullptr ); - GenerateMaterialsBuffer( materialStages, offset, materialsData ); + uint32_t* materialsData = stagingBuffer.MapBuffer( totalStageSize ); + + GenerateMaterialsBuffer( materialStages, totalStageSize, materialsData ); + + stagingBuffer.QueueStagingCopy( &materialsUBO, 0 ); for ( shaderStage_t* pStage : materialStages ) { if ( pStage->dynamic ) { @@ -437,7 +441,7 @@ void MaterialSystem::GenerateWorldMaterialsBuffer() { } } - materialsUBO.UnmapBuffer(); + GL_CheckErrors(); } void MaterialSystem::GenerateMaterialsBuffer( std::vector& stages, const uint32_t size, uint32_t* materialsData ) { @@ -537,11 +541,6 @@ void MaterialSystem::GenerateWorldCommandBuffer( std::vector& s totalDrawSurfs = surfaces.size(); - surfaceDescriptorsCount = totalDrawSurfs; - descriptorSize = BOUNDING_SPHERE_SIZE + maxStages; - surfaceDescriptorsSSBO.BufferData( surfaceDescriptorsCount * descriptorSize, nullptr, GL_STATIC_DRAW ); - uint32_t* surfaceDescriptors = surfaceDescriptorsSSBO.MapBufferRange( surfaceDescriptorsCount * descriptorSize ); - if ( glConfig2.maxUniformBlockSize >= MIN_MATERIAL_UBO_SIZE ) { texDataBufferType = GL_UNIFORM_BUFFER; texDataBindingPoint = BufferBind::TEX_DATA; @@ -550,10 +549,11 @@ void MaterialSystem::GenerateWorldCommandBuffer( std::vector& s texDataBindingPoint = BufferBind::TEX_DATA_STORAGE; } - texDataBuffer.BufferStorage( ( texData.size() + dynamicTexData.size() ) * TEX_BUNDLE_SIZE, 1, nullptr ); - texDataBuffer.MapAll(); - TexBundle* textureBundles = ( TexBundle* ) texDataBuffer.GetData(); - memset( textureBundles, 0, ( texData.size() + dynamicTexData.size() ) * TEX_BUNDLE_SIZE * sizeof( uint32_t ) ); + const uint32_t texDataSize = ( texData.size() + dynamicTexData.size() ) * TEX_BUNDLE_SIZE; + texDataBuffer.BufferStorage( texDataSize, 1, nullptr ); + + TexBundle* textureBundles = ( TexBundle* ) stagingBuffer.MapBuffer( texDataSize ); + memset( textureBundles, 0, texDataSize * sizeof( uint32_t ) ); GenerateTexturesBuffer( texData, textureBundles ); @@ -561,15 +561,14 @@ void MaterialSystem::GenerateWorldCommandBuffer( std::vector& s GenerateTexturesBuffer( dynamicTexData, textureBundles ); + stagingBuffer.QueueStagingCopy( &texDataBuffer, 0 ); + dynamicTexDataOffset = texData.size() * TEX_BUNDLE_SIZE; dynamicTexDataSize = dynamicTexData.size() * TEX_BUNDLE_SIZE; - texDataBuffer.FlushAll(); - texDataBuffer.UnmapBuffer(); - lightMapDataUBO.BufferStorage( MAX_LIGHTMAPS * LIGHTMAP_SIZE, 1, nullptr ); - lightMapDataUBO.MapAll(); - uint64_t* lightMapData = ( uint64_t* ) lightMapDataUBO.GetData(); + + uint64_t* lightMapData = ( uint64_t* ) stagingBuffer.MapBuffer( MAX_LIGHTMAPS * LIGHTMAP_SIZE ); memset( lightMapData, 0, MAX_LIGHTMAPS * LIGHTMAP_SIZE * sizeof( uint32_t ) ); for ( uint32_t i = 0; i < tr.lightmaps.size(); i++ ) { @@ -604,25 +603,20 @@ void MaterialSystem::GenerateWorldCommandBuffer( std::vector& s lightMapData[255 * 2 + 1] = tr.blackImage->texture->bindlessTextureHandle; } - lightMapDataUBO.FlushAll(); - lightMapDataUBO.UnmapBuffer(); + stagingBuffer.QueueStagingCopy( &lightMapDataUBO, 0 ); surfaceCommandsCount = totalBatchCount * SURFACE_COMMANDS_PER_BATCH; - surfaceCommandsSSBO.BufferStorage( surfaceCommandsCount * SURFACE_COMMAND_SIZE * MAX_VIEWFRAMES, 1, nullptr ); - surfaceCommandsSSBO.MapAll(); - SurfaceCommand* surfaceCommands = ( SurfaceCommand* ) surfaceCommandsSSBO.GetData(); - memset( surfaceCommands, 0, surfaceCommandsCount * sizeof( SurfaceCommand ) * MAX_VIEWFRAMES ); - culledCommandsBuffer.BufferStorage( surfaceCommandsCount * INDIRECT_COMMAND_SIZE * MAX_VIEWFRAMES, 1, nullptr ); - culledCommandsBuffer.MapAll(); - GLIndirectCommand* culledCommands = ( GLIndirectCommand* ) culledCommandsBuffer.GetData(); + GLIndirectCommand* culledCommands = + ( GLIndirectCommand* ) stagingBuffer.MapBuffer( surfaceCommandsCount * INDIRECT_COMMAND_SIZE * MAX_VIEWFRAMES ); memset( culledCommands, 0, surfaceCommandsCount * sizeof( GLIndirectCommand ) * MAX_VIEWFRAMES ); - culledCommandsBuffer.FlushAll(); - surfaceBatchesUBO.BufferData( MAX_SURFACE_COMMAND_BATCHES * SURFACE_COMMAND_BATCH_SIZE, nullptr, GL_STATIC_DRAW ); + stagingBuffer.QueueStagingCopy( &culledCommandsBuffer, 0 ); + + surfaceBatchesUBO.BufferStorage( MAX_SURFACE_COMMAND_BATCHES * SURFACE_COMMAND_BATCH_SIZE, 1, nullptr ); SurfaceCommandBatch* surfaceCommandBatches = - ( SurfaceCommandBatch* ) surfaceBatchesUBO.MapBufferRange( MAX_SURFACE_COMMAND_BATCHES * SURFACE_COMMAND_BATCH_SIZE ); + ( SurfaceCommandBatch* ) stagingBuffer.MapBuffer( MAX_SURFACE_COMMAND_BATCHES * SURFACE_COMMAND_BATCH_SIZE ); // memset( (void*) surfaceCommandBatches, 0, MAX_SURFACE_COMMAND_BATCHES * SURFACE_COMMAND_BATCH_SIZE ); // Fuck off gcc @@ -643,11 +637,14 @@ void MaterialSystem::GenerateWorldCommandBuffer( std::vector& s } } + stagingBuffer.QueueStagingCopy( &surfaceBatchesUBO, 0 ); + atomicCommandCountersBuffer.BufferStorage( MAX_COMMAND_COUNTERS * MAX_VIEWS, MAX_FRAMES, nullptr ); - atomicCommandCountersBuffer.MapAll(); - uint32_t* atomicCommandCounters = ( uint32_t* ) atomicCommandCountersBuffer.GetData(); + uint32_t* atomicCommandCounters = stagingBuffer.MapBuffer( MAX_COMMAND_COUNTERS * MAX_VIEWS ); memset( atomicCommandCounters, 0, MAX_COMMAND_COUNTERS * MAX_VIEWFRAMES * sizeof( uint32_t ) ); + stagingBuffer.QueueStagingCopy( &atomicCommandCountersBuffer, 0 ); + /* For use in debugging compute shaders Intended for use with Nsight Graphics to format the output */ if ( r_materialDebug.Get() ) { @@ -659,6 +656,22 @@ void MaterialSystem::GenerateWorldCommandBuffer( std::vector& s debugSSBO.UnmapBuffer(); } + stagingBuffer.FlushAll(); + + surfaceDescriptorsCount = totalDrawSurfs; + descriptorSize = BOUNDING_SPHERE_SIZE + maxStages; + surfaceDescriptorsSSBO.BufferStorage( surfaceDescriptorsCount* descriptorSize, 1, nullptr ); + uint32_t* surfaceDescriptors = stagingBuffer.MapBuffer( surfaceDescriptorsCount * descriptorSize ); + + stagingBuffer.QueueStagingCopy( &surfaceDescriptorsSSBO, 0 ); + + surfaceCommandsSSBO.BufferStorage( surfaceCommandsCount * SURFACE_COMMAND_SIZE * MAX_VIEWFRAMES, 1, nullptr ); + SurfaceCommand* surfaceCommands = + ( SurfaceCommand* ) stagingBuffer.MapBuffer( surfaceCommandsCount * SURFACE_COMMAND_SIZE * MAX_VIEWFRAMES ); + memset( surfaceCommands, 0, surfaceCommandsCount * sizeof( SurfaceCommand ) * MAX_VIEWFRAMES ); + + stagingBuffer.QueueStagingCopy( &surfaceCommandsSSBO, 0 ); + for ( MaterialSurface& surface : surfaces ) { if ( surface.skyBrush ) { continue; @@ -702,6 +715,8 @@ void MaterialSystem::GenerateWorldCommandBuffer( std::vector& s for ( int i = 0; i < MAX_VIEWFRAMES; i++ ) { memcpy( surfaceCommands + surfaceCommandsCount * i, surfaceCommands, surfaceCommandsCount * sizeof( SurfaceCommand ) ); } + + stagingBuffer.FlushAll(); uint32_t totalCount = 0; for ( MaterialPack& pack : materialPacks ) { @@ -712,16 +727,6 @@ void MaterialSystem::GenerateWorldCommandBuffer( std::vector& s totalStageSize * 4 / 1024.0f, dynamicStagesSize * 4 / 1024.0f, ( texData.size() + dynamicTexData.size() ) * TEX_BUNDLE_SIZE * 4 / 1024.0f ); - surfaceDescriptorsSSBO.UnmapBuffer(); - - surfaceCommandsSSBO.UnmapBuffer(); - - culledCommandsBuffer.UnmapBuffer(); - - atomicCommandCountersBuffer.UnmapBuffer(); - - surfaceBatchesUBO.UnmapBuffer(); - GL_CheckErrors(); } @@ -1471,25 +1476,27 @@ void MaterialSystem::AddStageTextures( MaterialSurface* surface, shader_t* shade } } -// Dynamic surfaces are those whose values in the SSBO can be updated +// Dynamic surfaces are those whose values in the UBOs/SSBO might require updating void MaterialSystem::UpdateDynamicSurfaces() { if ( dynamicStagesSize > 0 ) { - uint32_t* materialsData = materialsUBO.MapBufferRange( dynamicStagesOffset, dynamicStagesSize ); + uint32_t* materialsData = stagingBuffer.MapBuffer( dynamicStagesSize ); GenerateMaterialsBuffer( dynamicStages, dynamicStagesSize, materialsData ); - materialsUBO.UnmapBuffer(); + stagingBuffer.QueueStagingCopy( &materialsUBO, dynamicStagesOffset ); } if ( dynamicTexDataSize > 0 ) { TexBundle* textureBundles = - ( TexBundle* ) texDataBuffer.MapBufferRange( dynamicTexDataOffset, dynamicTexDataSize ); + ( TexBundle* ) stagingBuffer.MapBuffer( dynamicTexDataSize ); GenerateTexturesBuffer( dynamicTexData, textureBundles ); - texDataBuffer.UnmapBuffer(); + stagingBuffer.QueueStagingCopy( &texDataBuffer, dynamicTexDataOffset ); } + stagingBuffer.FlushAll(); + GL_CheckErrors(); } diff --git a/src/engine/renderer/gl_shader.h b/src/engine/renderer/gl_shader.h index 0499697c7..93369af69 100644 --- a/src/engine/renderer/gl_shader.h +++ b/src/engine/renderer/gl_shader.h @@ -1284,6 +1284,8 @@ class GLBuffer { std::string name; const GLuint64 SYNC_TIMEOUT = 10000000000; // 10 seconds + GLuint id; + GLBuffer( const char* newName, const GLuint newBindingPoint, const GLbitfield newFlags, const GLbitfield newMapFlags ) : name( newName ), internalTarget( 0 ), @@ -1332,6 +1334,8 @@ class GLBuffer { maxAreas = areaCount; glNamedBufferStorage( id, areaSize * areaCount * sizeof( uint32_t ), data, flags ); syncs.resize( areaCount ); + + GL_CheckErrors(); } void AreaIncr() { @@ -1372,6 +1376,10 @@ class GLBuffer { glFlushMappedNamedBufferRange( id, 0, maxAreas * areaSize * sizeof( uint32_t ) ); } + void FlushRange( const GLsizeiptr offset, const GLsizeiptr size ) { + glFlushMappedNamedBufferRange( id, offset * sizeof( uint32_t ), size * sizeof( uint32_t ) ); + } + uint32_t* MapBufferRange( const GLuint count ) { return MapBufferRange( 0, count ); } @@ -1400,14 +1408,13 @@ class GLBuffer { void DelBuffer() { glDeleteBuffers( 1, &id ); + mapped = false; } private: const GLenum internalTarget; const GLuint internalBindingPoint; - GLuint id; - bool mapped = false; const GLbitfield flags; const GLbitfield mapFlags; diff --git a/src/engine/renderer/shaders.cpp b/src/engine/renderer/shaders.cpp index d3cb0e622..a2252be13 100644 --- a/src/engine/renderer/shaders.cpp +++ b/src/engine/renderer/shaders.cpp @@ -72,7 +72,7 @@ std::unordered_map shadermap({ { "depthReduction_cp.glsl", std::string( reinterpret_cast< const char* >( depthReduction_cp_glsl ), sizeof( depthReduction_cp_glsl ) ) }, { "processSurfaces_cp.glsl", std::string( reinterpret_cast< const char* >( processSurfaces_cp_glsl ), sizeof( processSurfaces_cp_glsl ) ) }, - // Screen-space shaders + // Screen-space shaders { "screenSpace_vp.glsl", std::string( reinterpret_cast< const char* >( screenSpace_vp_glsl ), sizeof( screenSpace_vp_glsl ) ) }, { "blur_fp.glsl", std::string( reinterpret_cast< const char* >( blur_fp_glsl ), sizeof( blur_fp_glsl ) ) }, { "cameraEffects_fp.glsl", std::string( reinterpret_cast< const char* >( cameraEffects_fp_glsl ), sizeof( cameraEffects_fp_glsl ) ) }, diff --git a/src/engine/renderer/tr_vbo.cpp b/src/engine/renderer/tr_vbo.cpp index 5868845d2..a452b1a78 100644 --- a/src/engine/renderer/tr_vbo.cpp +++ b/src/engine/renderer/tr_vbo.cpp @@ -23,6 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "tr_local.h" #include "Material.h" #include "GeometryCache.h" +#include "GLMemory.h" // interleaved data: position, colour, qtangent, texcoord // -> struct shaderVertex_t in tr_local.h @@ -761,6 +762,10 @@ void R_InitVBOs() geometryCache.InitGLBuffers(); } + if ( glConfig2.directStateAccessAvailable && glConfig2.uniformBufferObjectAvailable ) { + stagingBuffer.InitGLBuffer(); + } + GL_CheckErrors(); } @@ -833,6 +838,10 @@ void R_ShutdownVBOs() geometryCache.FreeGLBuffers(); } + if ( glConfig2.directStateAccessAvailable && glConfig2.uniformBufferObjectAvailable ) { + stagingBuffer.FreeGLBuffer(); + } + tess.verts = tess.vertsBuffer = nullptr; tess.indexes = tess.indexesBuffer = nullptr; } From 3b0674e28bd170ee513a17d5ab3dc0c8c9a2eedc Mon Sep 17 00:00:00 2001 From: VReaperV Date: Sun, 8 Jun 2025 12:03:23 +0300 Subject: [PATCH 39/41] Use staging buffer for the geometry cache --- src/engine/renderer/GeometryCache.cpp | 24 +++++++++--------------- src/engine/renderer/GeometryCache.h | 5 ++--- 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/src/engine/renderer/GeometryCache.cpp b/src/engine/renderer/GeometryCache.cpp index 8845df99f..085011a33 100644 --- a/src/engine/renderer/GeometryCache.cpp +++ b/src/engine/renderer/GeometryCache.cpp @@ -36,7 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "common/Common.h" #include "GeometryCache.h" - +#include "GLMemory.h" #include "tr_local.h" GeometryCache geometryCache; @@ -61,12 +61,6 @@ void GeometryCache::FreeGLBuffers() { VAO.DelVAO(); } -void GeometryCache::AllocBuffers() { - VBO.BufferData( mapVerticesNumber * 8, nullptr, GL_STATIC_DRAW ); - - IBO.BufferData( mapIndicesNumber, nullptr, GL_STATIC_DRAW ); -} - void GeometryCache::AddMapGeometry( const uint32_t verticesNumber, const uint32_t indicesNumber, const vertexAttributeSpec_t* attrBegin, const vertexAttributeSpec_t* attrEnd, const glIndex_t* indices ) { @@ -75,28 +69,28 @@ void GeometryCache::AddMapGeometry( const uint32_t verticesNumber, const uint32_ VAO.Bind(); - AllocBuffers(); - VAO.SetAttrs( attrBegin, attrEnd ); VAO.SetVertexBuffer( VBO, 0 ); VAO.SetIndexBuffer( IBO ); VBO.BufferStorage( mapVerticesNumber * 8, 1, nullptr ); - VBO.MapAll(); - uint32_t* VBOVerts = VBO.GetData(); + uint32_t* VBOVerts = stagingBuffer.MapBuffer( mapVerticesNumber * 8 ); for ( const vertexAttributeSpec_t* spec = attrBegin; spec < attrEnd; spec++ ) { vboAttributeLayout_t& attr = VAO.attrs[spec->attrIndex]; R_CopyVertexAttribute( attr, *spec, mapVerticesNumber, ( byte* ) VBOVerts ); } - VBO.UnmapBuffer(); + + stagingBuffer.QueueStagingCopy( &VBO, 0 ); IBO.BufferStorage( mapIndicesNumber, 1, nullptr ); - IBO.MapAll(); - uint32_t* IBOIndices = IBO.GetData(); + uint32_t* IBOIndices = stagingBuffer.MapBuffer( mapIndicesNumber ); memcpy( IBOIndices, indices, mapIndicesNumber * sizeof( uint32_t ) ); - IBO.UnmapBuffer(); + + stagingBuffer.QueueStagingCopy( &IBO, 0 ); + + stagingBuffer.FlushAll(); glBindVertexArray( backEnd.currentVAO ); } diff --git a/src/engine/renderer/GeometryCache.h b/src/engine/renderer/GeometryCache.h index 7709540e2..ad01502ff 100644 --- a/src/engine/renderer/GeometryCache.h +++ b/src/engine/renderer/GeometryCache.h @@ -46,7 +46,6 @@ class GeometryCache { void InitGLBuffers(); void FreeGLBuffers(); - void AllocBuffers(); void AddMapGeometry( const uint32_t verticesNumber, const uint32_t indicesNumber, const vertexAttributeSpec_t* attrBegin, const vertexAttributeSpec_t* attrEnd, @@ -59,8 +58,8 @@ class GeometryCache { GLVAO VAO = GLVAO( 0 ); GLBuffer inputVBO = GLBuffer( "geometryCacheInputVBO", BufferBind::GEOMETRY_CACHE_INPUT_VBO, GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_RANGE_BIT ); - GLBuffer VBO = GLBuffer( "geometryCacheVBO", BufferBind::GEOMETRY_CACHE_VBO, GL_MAP_WRITE_BIT, GL_MAP_FLUSH_EXPLICIT_BIT ); - GLBuffer IBO = GLBuffer( "geometryCacheIBO", BufferBind::GEOMETRY_CACHE_IBO, GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_RANGE_BIT ); + GLBuffer VBO = GLBuffer( "geometryCacheVBO", BufferBind::GEOMETRY_CACHE_VBO, 0, 0 ); + GLBuffer IBO = GLBuffer( "geometryCacheIBO", BufferBind::GEOMETRY_CACHE_IBO, 0, 0 ); }; extern GeometryCache geometryCache; From ec4ba6a678ee737faf159dd9fc8ef9bfa5582352 Mon Sep 17 00:00:00 2001 From: VReaperV Date: Sun, 8 Jun 2025 11:41:52 +0300 Subject: [PATCH 40/41] Fix missing static --- src/engine/renderer/tr_bsp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/renderer/tr_bsp.cpp b/src/engine/renderer/tr_bsp.cpp index 23b85e2cd..3cd0c9b9b 100644 --- a/src/engine/renderer/tr_bsp.cpp +++ b/src/engine/renderer/tr_bsp.cpp @@ -919,7 +919,7 @@ static void ParseTriangleSurface( dsurface_t* ds, drawVert_t* verts, bspSurface_ // We may have a nodraw surface, because they might still need to be around for movement clipping if ( s_worldData.shaders[LittleLong( ds->shaderNum )].surfaceFlags & SURF_NODRAW ) { - surfaceType_t skipData = surfaceType_t::SF_SKIP; + static surfaceType_t skipData = surfaceType_t::SF_SKIP; surf->data = &skipData; return; } From c2afb67b1ee710e28f608d41688e62de4da43c45 Mon Sep 17 00:00:00 2001 From: VReaperV Date: Tue, 10 Jun 2025 21:16:55 +0300 Subject: [PATCH 41/41] Material system clean-up --- src/engine/renderer/Material.cpp | 123 +++++++++---------- src/engine/renderer/Material.h | 4 +- src/engine/renderer/gl_shader.cpp | 2 +- src/engine/renderer/gl_shader.h | 12 +- src/engine/renderer/glsl_source/cull_cp.glsl | 4 +- 5 files changed, 69 insertions(+), 76 deletions(-) diff --git a/src/engine/renderer/Material.cpp b/src/engine/renderer/Material.cpp index c88d94f89..e665bff88 100644 --- a/src/engine/renderer/Material.cpp +++ b/src/engine/renderer/Material.cpp @@ -501,46 +501,7 @@ void MaterialSystem::GenerateTexturesBuffer( std::vector& textures, void MaterialSystem::GenerateWorldCommandBuffer( std::vector& surfaces ) { Log::Debug( "Generating world command buffer" ); - totalBatchCount = 0; - - for ( MaterialSurface& surface : surfaces ) { - if ( surface.skyBrush ) { - continue; - } - - for ( uint8_t stage = 0; stage < surface.stages; stage++ ) { - Material* material = &materialPacks[surface.materialPackIDs[stage]].materials[surface.materialIDs[stage]]; - material->drawCommandCount++; - } - } - - uint32_t batchOffset = 0; - uint32_t globalID = 0; - for ( MaterialPack& pack : materialPacks ) { - for ( Material& material : pack.materials ) { - material.surfaceCommandBatchOffset = batchOffset; - - const uint32_t cmdCount = material.drawCommandCount; - const uint32_t batchCount = cmdCount % SURFACE_COMMANDS_PER_BATCH == 0 ? cmdCount / SURFACE_COMMANDS_PER_BATCH - : cmdCount / SURFACE_COMMANDS_PER_BATCH + 1; - - material.surfaceCommandBatchOffset = batchOffset; - material.surfaceCommandBatchCount = batchCount; - - batchOffset += batchCount; - material.globalID = globalID; - - material.drawCommandCount = 0; - - totalBatchCount += batchCount; - globalID++; - } - } - - Log::Debug( "Total batch count: %u", totalBatchCount ); - - totalDrawSurfs = surfaces.size(); - + // TexBundles if ( glConfig2.maxUniformBlockSize >= MIN_MATERIAL_UBO_SIZE ) { texDataBufferType = GL_UNIFORM_BUFFER; texDataBindingPoint = BufferBind::TEX_DATA; @@ -566,6 +527,7 @@ void MaterialSystem::GenerateWorldCommandBuffer( std::vector& s dynamicTexDataOffset = texData.size() * TEX_BUNDLE_SIZE; dynamicTexDataSize = dynamicTexData.size() * TEX_BUNDLE_SIZE; + // Lightmaps/Deluxemaps lightMapDataUBO.BufferStorage( MAX_LIGHTMAPS * LIGHTMAP_SIZE, 1, nullptr ); uint64_t* lightMapData = ( uint64_t* ) stagingBuffer.MapBuffer( MAX_LIGHTMAPS * LIGHTMAP_SIZE ); @@ -605,14 +567,43 @@ void MaterialSystem::GenerateWorldCommandBuffer( std::vector& s stagingBuffer.QueueStagingCopy( &lightMapDataUBO, 0 ); - surfaceCommandsCount = totalBatchCount * SURFACE_COMMANDS_PER_BATCH; + // Surface batches + for ( MaterialSurface& surface : surfaces ) { + if ( surface.skyBrush ) { + continue; + } - culledCommandsBuffer.BufferStorage( surfaceCommandsCount * INDIRECT_COMMAND_SIZE * MAX_VIEWFRAMES, 1, nullptr ); - GLIndirectCommand* culledCommands = - ( GLIndirectCommand* ) stagingBuffer.MapBuffer( surfaceCommandsCount * INDIRECT_COMMAND_SIZE * MAX_VIEWFRAMES ); - memset( culledCommands, 0, surfaceCommandsCount * sizeof( GLIndirectCommand ) * MAX_VIEWFRAMES ); + for ( uint8_t stage = 0; stage < surface.stages; stage++ ) { + Material* material = &materialPacks[surface.materialPackIDs[stage]].materials[surface.materialIDs[stage]]; + material->drawCommandCount++; + } + } + + totalBatchCount = 0; + uint32_t batchOffset = 0; + uint32_t globalID = 0; + for ( MaterialPack& pack : materialPacks ) { + for ( Material& material : pack.materials ) { + material.surfaceCommandBatchOffset = batchOffset; + + const uint32_t cmdCount = material.drawCommandCount; + const uint32_t batchCount = cmdCount % SURFACE_COMMANDS_PER_BATCH == 0 ? cmdCount / SURFACE_COMMANDS_PER_BATCH + : cmdCount / SURFACE_COMMANDS_PER_BATCH + 1; + + material.surfaceCommandBatchOffset = batchOffset; + material.surfaceCommandBatchCount = batchCount; + + batchOffset += batchCount; + material.globalID = globalID; + + material.drawCommandCount = 0; + + totalBatchCount += batchCount; + globalID++; + } + } - stagingBuffer.QueueStagingCopy( &culledCommandsBuffer, 0 ); + Log::Debug( "Total batch count: %u", totalBatchCount ); surfaceBatchesUBO.BufferStorage( MAX_SURFACE_COMMAND_BATCHES * SURFACE_COMMAND_BATCH_SIZE, 1, nullptr ); SurfaceCommandBatch* surfaceCommandBatches = @@ -639,12 +630,6 @@ void MaterialSystem::GenerateWorldCommandBuffer( std::vector& s stagingBuffer.QueueStagingCopy( &surfaceBatchesUBO, 0 ); - atomicCommandCountersBuffer.BufferStorage( MAX_COMMAND_COUNTERS * MAX_VIEWS, MAX_FRAMES, nullptr ); - uint32_t* atomicCommandCounters = stagingBuffer.MapBuffer( MAX_COMMAND_COUNTERS * MAX_VIEWS ); - memset( atomicCommandCounters, 0, MAX_COMMAND_COUNTERS * MAX_VIEWFRAMES * sizeof( uint32_t ) ); - - stagingBuffer.QueueStagingCopy( &atomicCommandCountersBuffer, 0 ); - /* For use in debugging compute shaders Intended for use with Nsight Graphics to format the output */ if ( r_materialDebug.Get() ) { @@ -656,21 +641,31 @@ void MaterialSystem::GenerateWorldCommandBuffer( std::vector& s debugSSBO.UnmapBuffer(); } + // Surfaces + surfaceCommandsCount = totalBatchCount * SURFACE_COMMANDS_PER_BATCH; + + culledCommandsBuffer.BufferStorage( surfaceCommandsCount * INDIRECT_COMMAND_SIZE * MAX_VIEWFRAMES, 1, nullptr ); + + atomicCommandCountersBuffer.BufferStorage( MAX_COMMAND_COUNTERS * MAX_VIEWS, MAX_FRAMES, nullptr ); + uint32_t* atomicCommandCounters = stagingBuffer.MapBuffer( MAX_COMMAND_COUNTERS * MAX_VIEWS ); + memset( atomicCommandCounters, 0, MAX_COMMAND_COUNTERS * MAX_VIEWFRAMES * sizeof( uint32_t ) ); + + stagingBuffer.QueueStagingCopy( &atomicCommandCountersBuffer, 0 ); + stagingBuffer.FlushAll(); - surfaceDescriptorsCount = totalDrawSurfs; + surfaceDescriptorsCount = surfaces.size(); + descriptorSize = BOUNDING_SPHERE_SIZE + maxStages; - surfaceDescriptorsSSBO.BufferStorage( surfaceDescriptorsCount* descriptorSize, 1, nullptr ); + surfaceDescriptorsSSBO.BufferStorage( surfaceDescriptorsCount * descriptorSize, 1, nullptr ); uint32_t* surfaceDescriptors = stagingBuffer.MapBuffer( surfaceDescriptorsCount * descriptorSize ); stagingBuffer.QueueStagingCopy( &surfaceDescriptorsSSBO, 0 ); surfaceCommandsSSBO.BufferStorage( surfaceCommandsCount * SURFACE_COMMAND_SIZE * MAX_VIEWFRAMES, 1, nullptr ); SurfaceCommand* surfaceCommands = - ( SurfaceCommand* ) stagingBuffer.MapBuffer( surfaceCommandsCount * SURFACE_COMMAND_SIZE * MAX_VIEWFRAMES ); - memset( surfaceCommands, 0, surfaceCommandsCount * sizeof( SurfaceCommand ) * MAX_VIEWFRAMES ); - - stagingBuffer.QueueStagingCopy( &surfaceCommandsSSBO, 0 ); + ( SurfaceCommand* ) stagingBuffer.MapBuffer( surfaceCommandsCount * SURFACE_COMMAND_SIZE ); + memset( surfaceCommands, 0, surfaceCommandsCount * sizeof( SurfaceCommand ) ); for ( MaterialSurface& surface : surfaces ) { if ( surface.skyBrush ) { @@ -713,7 +708,7 @@ void MaterialSystem::GenerateWorldCommandBuffer( std::vector& s } for ( int i = 0; i < MAX_VIEWFRAMES; i++ ) { - memcpy( surfaceCommands + surfaceCommandsCount * i, surfaceCommands, surfaceCommandsCount * sizeof( SurfaceCommand ) ); + stagingBuffer.QueueStagingCopy( &surfaceCommandsSSBO, i * surfaceCommandsCount * SURFACE_COMMAND_SIZE ); } stagingBuffer.FlushAll(); @@ -722,7 +717,7 @@ void MaterialSystem::GenerateWorldCommandBuffer( std::vector& s for ( MaterialPack& pack : materialPacks ) { totalCount += pack.materials.size(); } - Log::Notice( "Generated %u BSP materials from %u BSP surfaces", totalCount, totalDrawSurfs ); + Log::Notice( "Generated %u BSP materials from %u BSP surfaces", totalCount, surfaceDescriptorsCount ); Log::Notice( "Materials UBO: total: %.2f kb, dynamic: %.2f kb, texData: %.2f kb", totalStageSize * 4 / 1024.0f, dynamicStagesSize * 4 / 1024.0f, ( texData.size() + dynamicTexData.size() ) * TEX_BUNDLE_SIZE * 4 / 1024.0f ); @@ -1584,12 +1579,12 @@ void MaterialSystem::CullSurfaces() { } gl_cullShader->BindProgram( 0 ); - uint32_t globalWorkGroupX = totalDrawSurfs % MAX_COMMAND_COUNTERS == 0 ? - totalDrawSurfs / MAX_COMMAND_COUNTERS : totalDrawSurfs / MAX_COMMAND_COUNTERS + 1; + uint32_t globalWorkGroupX = surfaceDescriptorsCount % MAX_COMMAND_COUNTERS == 0 ? + surfaceDescriptorsCount / MAX_COMMAND_COUNTERS : surfaceDescriptorsCount / MAX_COMMAND_COUNTERS + 1; GL_Bind( depthImage ); gl_cullShader->SetUniform_Frame( nextFrame ); gl_cullShader->SetUniform_ViewID( view ); - gl_cullShader->SetUniform_TotalDrawSurfs( totalDrawSurfs ); + gl_cullShader->SetUniform_SurfaceDescriptorsCount( surfaceDescriptorsCount ); gl_cullShader->SetUniform_UseFrustumCulling( r_gpuFrustumCulling.Get() ); gl_cullShader->SetUniform_UseOcclusionCulling( r_gpuOcclusionCulling.Get() ); gl_cullShader->SetUniform_CameraPosition( origin ); @@ -1753,7 +1748,7 @@ void MaterialSystem::Free() { buildOneShader = true; - totalDrawSurfs = 0; + surfaceDescriptorsCount = 0; currentFrame = 0; nextFrame = 1; diff --git a/src/engine/renderer/Material.h b/src/engine/renderer/Material.h index 2ab9d2fad..8ce90cbb1 100644 --- a/src/engine/renderer/Material.h +++ b/src/engine/renderer/Material.h @@ -401,11 +401,9 @@ class MaterialSystem { image_t* depthImage; int depthImageLevels; - uint32_t totalDrawSurfs; - uint32_t totalBatchCount = 0; - uint32_t surfaceCommandsCount = 0; uint32_t surfaceDescriptorsCount = 0; + uint32_t totalBatchCount = 0; uint32_t packIDs[3] = { 0, 0, 0 }; diff --git a/src/engine/renderer/gl_shader.cpp b/src/engine/renderer/gl_shader.cpp index 498aaff20..3c9dd7b68 100644 --- a/src/engine/renderer/gl_shader.cpp +++ b/src/engine/renderer/gl_shader.cpp @@ -3028,7 +3028,7 @@ GLShader_cull::GLShader_cull() : false, "cull" ), u_Frame( this ), u_ViewID( this ), - u_TotalDrawSurfs( this ), + u_SurfaceDescriptorsCount( this ), u_SurfaceCommandsOffset( this ), u_Frustum( this ), u_UseFrustumCulling( this ), diff --git a/src/engine/renderer/gl_shader.h b/src/engine/renderer/gl_shader.h index 93369af69..60c44bf2e 100644 --- a/src/engine/renderer/gl_shader.h +++ b/src/engine/renderer/gl_shader.h @@ -2764,15 +2764,15 @@ class u_P11 : } }; -class u_TotalDrawSurfs : +class u_SurfaceDescriptorsCount : GLUniform1ui { public: - u_TotalDrawSurfs( GLShader* shader ) : - GLUniform1ui( shader, "u_TotalDrawSurfs", true ) { + u_SurfaceDescriptorsCount( GLShader* shader ) : + GLUniform1ui( shader, "u_SurfaceDescriptorsCount", true ) { } - void SetUniform_TotalDrawSurfs( const uint totalDrawSurfs ) { - this->SetValue( totalDrawSurfs ); + void SetUniform_SurfaceDescriptorsCount( const uint SurfaceDescriptorsCount ) { + this->SetValue( SurfaceDescriptorsCount ); } }; @@ -4153,7 +4153,7 @@ class GLShader_cull : public GLShader, public u_Frame, public u_ViewID, - public u_TotalDrawSurfs, + public u_SurfaceDescriptorsCount, public u_SurfaceCommandsOffset, public u_Frustum, public u_UseFrustumCulling, diff --git a/src/engine/renderer/glsl_source/cull_cp.glsl b/src/engine/renderer/glsl_source/cull_cp.glsl index 201cdc284..7333e3ffd 100644 --- a/src/engine/renderer/glsl_source/cull_cp.glsl +++ b/src/engine/renderer/glsl_source/cull_cp.glsl @@ -70,7 +70,7 @@ layout(std430, binding = BIND_PORTAL_SURFACES) restrict buffer portalSurfacesSSB uniform uint u_Frame; uniform uint u_ViewID; -uniform uint u_TotalDrawSurfs; +uniform uint u_SurfaceDescriptorsCount; uniform uint u_SurfaceCommandsOffset; uniform vec4 u_Frustum[6]; // xyz - normal, w - distance uniform bool u_UseFrustumCulling; @@ -198,7 +198,7 @@ void main() { } // Regular surfaces - if( globalInvocationID >= u_TotalDrawSurfs ) { + if( globalInvocationID >= u_SurfaceDescriptorsCount ) { return; } SurfaceDescriptor surface = surfaces[globalInvocationID];