diff --git a/src/engine/renderer/GeometryOptimiser.cpp b/src/engine/renderer/GeometryOptimiser.cpp index 0f79ee8cb8..731af91bb0 100644 --- a/src/engine/renderer/GeometryOptimiser.cpp +++ b/src/engine/renderer/GeometryOptimiser.cpp @@ -315,13 +315,13 @@ void MergeDuplicateVertices( bspSurface_t** rendererSurfaces, int numSurfaces, s srfVert_t& vert = face->verts[triangle->indexes[j]]; uint32_t index = verts[vert]; - ASSERT_LT( idx, numIndicesIn ); + ASSERT_LT( idx, ( uint32_t ) numIndicesIn ); if ( !index ) { verts[vert] = vertIdx + 1; vertices[vertIdx] = vert; indices[idx] = vertIdx; - ASSERT_LT( vertIdx, numVerticesIn ); + ASSERT_LT( vertIdx, ( uint32_t ) numVerticesIn ); vertIdx++; } else { @@ -356,7 +356,7 @@ void MergeDuplicateVertices( bspSurface_t** rendererSurfaces, int numSurfaces, s } } */ -std::vector OptimiseMapGeometryMaterial( world_t* world, int numSurfaces ) { +std::vector OptimiseMapGeometryMaterial(bspSurface_t** rendererSurfaces, int numSurfaces ) { std::vector materialSurfaces; materialSurfaces.reserve( numSurfaces ); @@ -365,24 +365,43 @@ std::vector OptimiseMapGeometryMaterial( world_t* world, int nu // std::unordered_map triEdges; - int surfaceIndex = 0; - for ( int k = 0; k < world->numSurfaces; k++ ) { - bspSurface_t* surface = &world->surfaces[k]; + vec3_t worldBounds[2] = {}; + for ( int i = 0; i < numSurfaces; i++ ) { + bspSurface_t* surface = rendererSurfaces[i]; + + if ( surface->BSPModel ) { + // Not implemented yet + continue; + } MaterialSurface srf {}; srf.shader = surface->shader; srf.bspSurface = true; + srf.lightMapNum = surface->lightmapNum; srf.fog = surface->fogIndex; + srf.portalNum = surface->portalNum; srf.firstIndex = ( ( srfGeneric_t* ) surface->data )->firstIndex; - srf.count = ( ( srfGeneric_t* ) surface->data )->numTriangles; + srf.count = ( ( srfGeneric_t* ) surface->data )->numTriangles * 3; srf.verts = ( ( srfGeneric_t* ) surface->data )->verts; srf.tris = ( ( srfGeneric_t* ) surface->data )->triangles; + 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 ); - surfaceIndex++; } + materialSystem.GenerateWorldMaterialsBuffer(); + materialSystem.GeneratePortalBoundingSpheres(); + materialSystem.SetWorldBounds( worldBounds ); + materialSystem.GenerateWorldCommandBuffer( materialSurfaces ); + return materialSurfaces; } diff --git a/src/engine/renderer/GeometryOptimiser.h b/src/engine/renderer/GeometryOptimiser.h index b2f2b43796..2ce0b066c1 100644 --- a/src/engine/renderer/GeometryOptimiser.h +++ b/src/engine/renderer/GeometryOptimiser.h @@ -106,6 +106,6 @@ 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( world_t* world, int numSurfaces ); +std::vector OptimiseMapGeometryMaterial( bspSurface_t** rendererSurfaces, int numSurfaces ); #endif // GEOMETRY_OPTIMISER_H diff --git a/src/engine/renderer/Material.cpp b/src/engine/renderer/Material.cpp index d43f34aadd..06d3073032 100644 --- a/src/engine/renderer/Material.cpp +++ b/src/engine/renderer/Material.cpp @@ -430,40 +430,6 @@ void MaterialSystem::GenerateWorldMaterialsBuffer() { GenerateMaterialsBuffer( materialStages, offset, materialsData ); - for ( uint32_t materialPackID = 0; materialPackID < 3; materialPackID++ ) { - for ( Material& material : materialPacks[materialPackID].materials ) { - for ( drawSurf_t* drawSurf : material.drawSurfs ) { - uint32_t stage = 0; - for ( shaderStage_t* pStage = drawSurf->shader->stages; pStage < drawSurf->shader->lastStage; pStage++ ) { - if ( drawSurf->materialIDs[stage] != material.id || drawSurf->materialPackIDs[stage] != materialPackID ) { - stage++; - continue; - } - - // We need some of the values from the remapped stage, but material/materialPack ID has to come from pStage - shaderStage_t* remappedStage = pStage->materialRemappedStage ? pStage->materialRemappedStage : pStage; - const uint32_t SSBOOffset = - remappedStage->materialOffset + remappedStage->variantOffsets[drawSurf->shaderVariant[stage]]; - - tess.currentDrawSurf = drawSurf; - - tess.currentSSBOOffset = SSBOOffset; - tess.materialID = drawSurf->materialIDs[stage]; - tess.materialPackID = drawSurf->materialPackIDs[stage]; - - Tess_Begin( Tess_StageIteratorDummy, nullptr, nullptr, false, -1, 0 ); - rb_surfaceTable[Util::ordinal( *drawSurf->surface )]( drawSurf->surface ); - Tess_DrawElements(); - Tess_Clear(); - - drawSurf->drawCommandIDs[stage] = lastCommandID; - - stage++; - } - } - } - } - for ( shaderStage_t* pStage : materialStages ) { if ( pStage->dynamic ) { pStage->bufferOffset -= dynamicStagesOffset; @@ -508,11 +474,7 @@ void MaterialSystem::GenerateTexturesBuffer( std::vector& textures, const textureBundle_t* bundle = textureData.texBundles[i]; if ( bundle && bundle->image[0] ) { - if ( generatingWorldCommandBuffer ) { - textureBundles->textures[i] = bundle->image[0]->texture->bindlessTextureHandle; - } else { - textureBundles->textures[i] = BindAnimatedImage( 0, bundle ); - } + textureBundles->textures[i] = BindAnimatedImage( 0, bundle ); } } @@ -531,7 +493,7 @@ void MaterialSystem::GenerateTexturesBuffer( std::vector& textures, } // This generates the buffers with indirect rendering commands etc. -void MaterialSystem::GenerateWorldCommandBuffer() { +void MaterialSystem::GenerateWorldCommandBuffer( std::vector& surfaces ) { Log::Debug( "Generating world command buffer" ); totalBatchCount = 0; @@ -542,7 +504,7 @@ void MaterialSystem::GenerateWorldCommandBuffer() { for ( Material& material : pack.materials ) { material.surfaceCommandBatchOffset = batchOffset; - const uint32_t cmdCount = material.drawCommands.size(); + 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; @@ -675,97 +637,54 @@ void MaterialSystem::GenerateWorldCommandBuffer() { debugSSBO.UnmapBuffer(); } - for ( int i = 0; i < tr.refdef.numDrawSurfs; i++ ) { - const drawSurf_t* drawSurf = &tr.refdef.drawSurfs[i]; - - if ( drawSurf->entity != &tr.worldEntity ) { - continue; - } - - shader_t* shader = drawSurf->shader; - if ( !shader ) { - continue; - } - - shader = shader->remappedShader ? shader->remappedShader : shader; - if ( shader->isSky || shader->isPortal || shader->autoSpriteMode ) { - continue; - } - - // Don't add SF_SKIP surfaces - if ( *drawSurf->surface == surfaceType_t::SF_SKIP ) { - continue; - } - - // Depth prepass surfaces are added as stages to the main surface instead - if ( drawSurf->materialSystemSkip ) { - continue; - } - - SurfaceDescriptor surface; - VectorCopy( ( ( srfGeneric_t* ) drawSurf->surface )->origin, surface.boundingSphere.origin ); - surface.boundingSphere.radius = ( ( srfGeneric_t* ) drawSurf->surface )->radius; + for ( MaterialSurface& surface : surfaces ) { + SurfaceDescriptor surfaceDescriptor; + VectorCopy( surface.origin, surfaceDescriptor.boundingSphere.origin ); + surfaceDescriptor.boundingSphere.radius = surface.radius; - const bool depthPrePass = drawSurf->depthSurface != nullptr; + IndirectCompactCommand drawCmd { surface.count, surface.firstIndex }; - if ( depthPrePass ) { - const drawSurf_t* depthDrawSurf = drawSurf->depthSurface; - const Material* material = &materialPacks[depthDrawSurf->materialPackIDs[0]] - .materials[depthDrawSurf->materialIDs[0]]; - uint cmdID = material->surfaceCommandBatchOffset * SURFACE_COMMANDS_PER_BATCH + depthDrawSurf->drawCommandIDs[0]; + 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; // Add 1 because cmd 0 == no-command - surface.surfaceCommandIDs[0] = cmdID + 1; + surfaceDescriptor.surfaceCommandIDs[stage] = cmdID + 1; SurfaceCommand surfaceCommand; surfaceCommand.enabled = 0; - surfaceCommand.drawCommand = material->drawCommands[depthDrawSurf->drawCommandIDs[0]].cmd; - // We still need the textures for alpha-tested depth pre-pass surface commands - surfaceCommand.drawCommand.baseInstance |= depthDrawSurf->texDataDynamic[0] - ? ( depthDrawSurf->texDataIDs[0] + texData.size() ) << TEX_BUNDLE_BITS - : depthDrawSurf->texDataIDs[0] << TEX_BUNDLE_BITS; - surfaceCommands[cmdID] = surfaceCommand; - } - - uint32_t stage = 0; - for ( shaderStage_t* pStage = drawSurf->shader->stages; pStage < drawSurf->shader->lastStage; pStage++ ) { - const Material* material = &materialPacks[drawSurf->materialPackIDs[stage]].materials[drawSurf->materialIDs[stage]]; - uint32_t cmdID = material->surfaceCommandBatchOffset * SURFACE_COMMANDS_PER_BATCH + drawSurf->drawCommandIDs[stage]; - // Add 1 because cmd 0 == no-command - surface.surfaceCommandIDs[stage + ( depthPrePass ? 1 : 0 )] = cmdID + 1; - SurfaceCommand surfaceCommand; - surfaceCommand.enabled = 0; - surfaceCommand.drawCommand = material->drawCommands[drawSurf->drawCommandIDs[stage]].cmd; - surfaceCommand.drawCommand.baseInstance |= drawSurf->texDataDynamic[stage] - ? ( drawSurf->texDataIDs[stage] + texData.size() ) << TEX_BUNDLE_BITS - : drawSurf->texDataIDs[stage] << TEX_BUNDLE_BITS; - surfaceCommand.drawCommand.baseInstance |= ( HasLightMap( drawSurf ) ? GetLightMapNum( drawSurf ) : 255 ) << LIGHTMAP_BITS; + shaderStage_t* pStage = surface.shaderStages[stage]; + pStage = pStage->materialRemappedStage ? pStage->materialRemappedStage : pStage; + const uint32_t surfaceMaterialID = + pStage->materialOffset + pStage->variantOffsets[surface.shaderVariant[stage]]; + + surfaceCommand.drawCommand = drawCmd; + surfaceCommand.drawCommand.baseInstance = surfaceMaterialID; + surfaceCommand.drawCommand.baseInstance |= surface.texDataDynamic[stage] + ? ( surface.texDataIDs[stage] + texData.size() ) << TEX_BUNDLE_BITS + : surface.texDataIDs[stage] << TEX_BUNDLE_BITS; + surfaceCommand.drawCommand.baseInstance |= ( HasLightMap( &surface ) ? GetLightMapNum( &surface ) : 255 ) << LIGHTMAP_BITS; surfaceCommands[cmdID] = surfaceCommand; - stage++; - } - - if ( drawSurf->fogSurface ) { - const drawSurf_t* fogDrawSurf = drawSurf->fogSurface; - const Material* material = &materialPacks[fogDrawSurf->materialPackIDs[0]] - .materials[fogDrawSurf->materialIDs[0]]; - uint cmdID = material->surfaceCommandBatchOffset * SURFACE_COMMANDS_PER_BATCH + fogDrawSurf->drawCommandIDs[0]; - // Add 1 because cmd 0 == no-command - surface.surfaceCommandIDs[stage + ( depthPrePass ? 1 : 0 )] = cmdID + 1; - - SurfaceCommand surfaceCommand; - surfaceCommand.enabled = 0; - surfaceCommand.drawCommand = material->drawCommands[fogDrawSurf->drawCommandIDs[0]].cmd; - surfaceCommands[cmdID] = surfaceCommand; + material->drawCommandCount2++; } - memcpy( surfaceDescriptors, &surface, descriptorSize * sizeof( uint32_t ) ); + memcpy( surfaceDescriptors, &surfaceDescriptor, descriptorSize * sizeof( uint32_t ) ); surfaceDescriptors += descriptorSize; } for ( int i = 0; i < MAX_VIEWFRAMES; i++ ) { memcpy( surfaceCommands + surfaceCommandsCount * i, surfaceCommands, surfaceCommandsCount * sizeof( SurfaceCommand ) ); } + + uint32_t totalCount = 0; + for ( MaterialPack& pack : materialPacks ) { + totalCount += pack.materials.size(); + } + Log::Notice( "Generated %u BSP materials from %u BSP surfaces", totalCount, surfaces.size() ); + 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 ); surfaceDescriptorsSSBO.UnmapBuffer(); @@ -1011,7 +930,7 @@ void BindShaderFog( Material* material ) { gl_fogQuake3ShaderMaterial->BindProgram( 0 ); // Set shader uniforms. - const fog_t* fog = material->fog; + const fog_t* fog = tr.world->fogs + material->fog; // all fogging distance is based on world Z units vec4_t fogDistanceVector; @@ -1065,16 +984,16 @@ void BindShaderFog( Material* material ) { ); } -void ProcessMaterialNONE( Material*, shaderStage_t*, drawSurf_t* ) { +void ProcessMaterialNONE( Material*, shaderStage_t*, MaterialSurface* ) { ASSERT_UNREACHABLE(); } -void ProcessMaterialNOP( Material*, shaderStage_t*, drawSurf_t* ) { +void ProcessMaterialNOP( Material*, shaderStage_t*, MaterialSurface* ) { } // ProcessMaterial*() are essentially same as BindShader*(), but only set the GL program id to the material, // without actually binding it -void ProcessMaterialGeneric3D( Material* material, shaderStage_t* pStage, drawSurf_t* ) { +void ProcessMaterialGeneric3D( Material* material, shaderStage_t* pStage, MaterialSurface* ) { material->shader = gl_genericShaderMaterial; material->tcGenEnvironment = pStage->tcGen_Environment; @@ -1091,14 +1010,14 @@ void ProcessMaterialGeneric3D( Material* material, shaderStage_t* pStage, drawSu material->program = gl_genericShaderMaterial->GetProgram( pStage->deformIndex ); } -void ProcessMaterialLightMapping( Material* material, shaderStage_t* pStage, drawSurf_t* drawSurf ) { +void ProcessMaterialLightMapping( Material* material, shaderStage_t* pStage, MaterialSurface* surface ) { material->shader = gl_lightMappingShaderMaterial; - gl_lightMappingShaderMaterial->SetBspSurface( drawSurf->bspSurface ); + gl_lightMappingShaderMaterial->SetBspSurface( surface->bspSurface ); lightMode_t lightMode; deluxeMode_t deluxeMode; - SetLightDeluxeMode( drawSurf, pStage->type, lightMode, deluxeMode ); + SetLightDeluxeMode( surface, pStage->shader, pStage->type, lightMode, deluxeMode ); bool enableDeluxeMapping = ( deluxeMode == deluxeMode_t::MAP ); bool enableGridLighting = ( lightMode == lightMode_t::GRID ); @@ -1133,7 +1052,7 @@ void ProcessMaterialLightMapping( Material* material, shaderStage_t* pStage, dra material->program = gl_lightMappingShaderMaterial->GetProgram( pStage->deformIndex ); } -void ProcessMaterialReflection( Material* material, shaderStage_t* pStage, drawSurf_t* /* drawSurf */ ) { +void ProcessMaterialReflection( Material* material, shaderStage_t* pStage, MaterialSurface* /* surface */ ) { material->shader = gl_reflectionShaderMaterial; material->hasHeightMapInNormalMap = pStage->hasHeightMapInNormalMap; @@ -1147,7 +1066,7 @@ void ProcessMaterialReflection( Material* material, shaderStage_t* pStage, drawS material->program = gl_reflectionShaderMaterial->GetProgram( pStage->deformIndex ); } -void ProcessMaterialSkybox( Material* material, shaderStage_t* pStage, drawSurf_t* /* drawSurf */ ) { +void ProcessMaterialSkybox( Material* material, shaderStage_t* pStage, MaterialSurface* /* surface */ ) { material->shader = gl_skyboxShaderMaterial; material->deformIndex = pStage->deformIndex; @@ -1155,7 +1074,7 @@ void ProcessMaterialSkybox( Material* material, shaderStage_t* pStage, drawSurf_ material->program = gl_skyboxShaderMaterial->GetProgram( pStage->deformIndex ); } -void ProcessMaterialScreen( Material* material, shaderStage_t* pStage, drawSurf_t* /* drawSurf */ ) { +void ProcessMaterialScreen( Material* material, shaderStage_t* pStage, MaterialSurface* /* surface */ ) { material->shader = gl_screenShaderMaterial; material->deformIndex = pStage->deformIndex; @@ -1163,7 +1082,7 @@ void ProcessMaterialScreen( Material* material, shaderStage_t* pStage, drawSurf_ material->program = gl_screenShaderMaterial->GetProgram( pStage->deformIndex ); } -void ProcessMaterialHeatHaze( Material* material, shaderStage_t* pStage, drawSurf_t* ) { +void ProcessMaterialHeatHaze( Material* material, shaderStage_t* pStage, MaterialSurface* ) { material->shader = gl_heatHazeShaderMaterial; material->deformIndex = pStage->deformIndex; @@ -1171,12 +1090,12 @@ void ProcessMaterialHeatHaze( Material* material, shaderStage_t* pStage, drawSur material->program = gl_heatHazeShaderMaterial->GetProgram( pStage->deformIndex ); } -void ProcessMaterialLiquid( Material* material, shaderStage_t* pStage, drawSurf_t* drawSurf ) { +void ProcessMaterialLiquid( Material* material, shaderStage_t* pStage, MaterialSurface* surface ) { material->shader = gl_liquidShaderMaterial; lightMode_t lightMode; deluxeMode_t deluxeMode; - SetLightDeluxeMode( drawSurf, pStage->type, lightMode, deluxeMode ); + SetLightDeluxeMode( surface, pStage->shader, pStage->type, lightMode, deluxeMode ); material->hasHeightMapInNormalMap = pStage->hasHeightMapInNormalMap; material->enableReliefMapping = pStage->enableReliefMapping; @@ -1195,14 +1114,14 @@ void ProcessMaterialLiquid( Material* material, shaderStage_t* pStage, drawSurf_ material->program = gl_liquidShaderMaterial->GetProgram( pStage->deformIndex ); } -void ProcessMaterialFog( Material* material, shaderStage_t* pStage, drawSurf_t* drawSurf ) { +void ProcessMaterialFog( Material* material, shaderStage_t* pStage, MaterialSurface* surface ) { material->shader = gl_fogQuake3ShaderMaterial; - material->fog = tr.world->fogs + drawSurf->fog; + material->fog = surface->fog; material->program = gl_fogQuake3ShaderMaterial->GetProgram( pStage->deformIndex ); } -void MaterialSystem::AddStage( drawSurf_t* drawSurf, shaderStage_t* pStage, uint32_t stage, +void MaterialSystem::AddStage( MaterialSurface* surface, shaderStage_t* pStage, uint32_t stage, const bool mayUseVertexOverbright, const bool vertexLit, const bool fullbright ) { const int variant = ( mayUseVertexOverbright ? ShaderStageVariant::VERTEX_OVERBRIGHT : 0 ) | ( vertexLit ? ShaderStageVariant::VERTEX_LIT : 0 ) @@ -1213,7 +1132,7 @@ void MaterialSystem::AddStage( drawSurf_t* drawSurf, shaderStage_t* pStage, uint pStage->variantOffset++; } - drawSurf->shaderVariant[stage] = variant; + surface->shaderVariant[stage] = variant; // Look for a stage that will have the same data layout and data + data changes themselves for ( shaderStage_t* pStage2 : materialStages ) { @@ -1307,12 +1226,13 @@ void MaterialSystem::AddStage( drawSurf_t* drawSurf, shaderStage_t* pStage, uint } } -void MaterialSystem::ProcessStage( drawSurf_t* drawSurf, shaderStage_t* pStage, shader_t* shader, uint32_t* packIDs, uint32_t& stage, - uint32_t& previousMaterialID ) { +void MaterialSystem::ProcessStage( MaterialSurface* surface, shaderStage_t* pStage, shader_t* shader, uint32_t* packIDs, uint32_t& stage, + uint32_t& previousMaterialID, bool skipStageSync ) { lightMode_t lightMode; deluxeMode_t deluxeMode; - SetLightDeluxeMode( drawSurf, pStage->type, lightMode, deluxeMode ); - const bool mayUseVertexOverbright = pStage->type == stageType_t::ST_COLORMAP && drawSurf->bspSurface && pStage->shaderBinder == BindShaderGeneric3D; + SetLightDeluxeMode( surface, shader, pStage->type, lightMode, deluxeMode ); + const bool mayUseVertexOverbright = pStage->type == stageType_t::ST_COLORMAP + && surface->bspSurface && pStage->shaderBinder == BindShaderGeneric3D; const bool vertexLit = lightMode == lightMode_t::VERTEX && pStage->shaderBinder == BindShaderLightMapping; const bool fullbright = lightMode == lightMode_t::FULLBRIGHT && pStage->shaderBinder == BindShaderLightMapping; @@ -1334,7 +1254,7 @@ void MaterialSystem::ProcessStage( drawSurf_t* drawSurf, shaderStage_t* pStage, // In surfaces with multiple stages each consecutive stage must be drawn after the previous stage, // except if an opaque stage follows a transparent stage etc. - if ( stage > 0 ) { + if ( !skipStageSync && stage > 0 ) { material.useSync = true; material.syncMaterial = previousMaterialID; } @@ -1347,16 +1267,15 @@ void MaterialSystem::ProcessStage( drawSurf_t* drawSurf, shaderStage_t* pStage, material.cullType = shader->cullType; material.usePolygonOffset = shader->polygonOffset; - material.bspSurface = drawSurf->bspSurface; - pStage->materialProcessor( &material, pStage, drawSurf ); + material.bspSurface = surface->bspSurface; + pStage->materialProcessor( &material, pStage, surface ); pStage->paddedSize = material.shader->GetPaddedSize(); - // HACK: Copy the shaderStage_t and drawSurf_t that we need into the material, so we can use it with glsl_restart + // HACK: Copy the shaderStage_t and MaterialSurface that we need into the material, so we can use it with glsl_restart material.refStage = pStage; - material.refDrawSurf = *drawSurf; - material.refDrawSurf.entity = nullptr; - material.refDrawSurf.depthSurface = nullptr; - material.refDrawSurf.fogSurface = nullptr; + material.refDrawSurf = *surface; + material.refDrawSurf.verts = nullptr; + material.refDrawSurf.tris = nullptr; std::vector& materials = materialPacks[materialPack].materials; std::vector::iterator currentSearchIt = materials.begin(); @@ -1387,117 +1306,55 @@ void MaterialSystem::ProcessStage( drawSurf_t* drawSurf, shaderStage_t* pStage, pStage->useMaterialSystem = true; pStage->initialized = true; - AddStage( drawSurf, pStage, stage, mayUseVertexOverbright, vertexLit, fullbright ); - AddStageTextures( drawSurf, stage, &materials[previousMaterialID] ); + AddStage( surface, pStage, stage, mayUseVertexOverbright, vertexLit, fullbright ); + AddStageTextures( surface, shader, pStage, stage, &materials[previousMaterialID] ); - if ( std::find( materials[previousMaterialID].drawSurfs.begin(), materials[previousMaterialID].drawSurfs.end(), drawSurf ) - == materials[previousMaterialID].drawSurfs.end() ) { - materials[previousMaterialID].drawSurfs.emplace_back( drawSurf ); - } - - drawSurf->materialIDs[stage] = previousMaterialID; - drawSurf->materialPackIDs[stage] = materialPack; + surface->materialIDs[stage] = previousMaterialID; + surface->materialPackIDs[stage] = materialPack; + surface->shaderStages[stage] = pStage; packIDs[materialPack] = id; + materials[previousMaterialID].drawCommandCount++; + stage++; } -/* This will only generate the materials themselves -* 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::GenerateWorldMaterials() { - R_SyncRenderThread(); - - const int current_r_nocull = r_nocull->integer; - const int current_r_drawworld = r_drawworld->integer; - r_nocull->integer = 1; - r_drawworld->integer = 1; - generatingWorldCommandBuffer = true; - - Log::Debug( "Generating world materials" ); - - ++tr.viewCountNoReset; - R_AddWorldSurfaces(); +/* This will only generate a material itself +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++; - Log::Notice( "World bounds: min: %f %f %f max: %f %f %f", tr.viewParms.visBounds[0][0], tr.viewParms.visBounds[0][1], - tr.viewParms.visBounds[0][2], tr.viewParms.visBounds[1][0], tr.viewParms.visBounds[1][1], tr.viewParms.visBounds[1][2] ); - VectorCopy( tr.viewParms.visBounds[0], worldViewBounds[0] ); - VectorCopy( tr.viewParms.visBounds[1], worldViewBounds[1] ); - - backEnd.currentEntity = &tr.worldEntity; - - totalDrawSurfs = 0; - - uint32_t packIDs[3] = { 0, 0, 0 }; - - for ( int i = 0; i < tr.refdef.numDrawSurfs; i++ ) { - drawSurf_t* drawSurf = &tr.refdef.drawSurfs[i]; - if ( drawSurf->entity != &tr.worldEntity ) { - continue; - } - - shader_t* shader = drawSurf->shader; - if ( !shader ) { - continue; - } - - shader = shader->remappedShader ? shader->remappedShader : shader; - if ( shader->isSky || shader->isPortal || shader->autoSpriteMode ) { - continue; - } - - // Don't add SF_SKIP surfaces - if ( *drawSurf->surface == surfaceType_t::SF_SKIP ) { - continue; - } - - // Only add the main surface for surfaces with depth pre-pass or fog to the total count - if ( !drawSurf->materialSystemSkip ) { - totalDrawSurfs++; - } + uint32_t stage = 0; + uint32_t previousMaterialID = 0; + + if ( surface->shader->depthShader ) { + uint32_t unused; + ProcessStage( surface, surface->shader->depthShader->stages, surface->shader->depthShader, packIDs, stage, unused, true ); - uint32_t stage = 0; - uint32_t previousMaterialID = 0; - for ( shaderStage_t* pStage = drawSurf->shader->stages; pStage < drawSurf->shader->lastStage; pStage++ ) { - ProcessStage( drawSurf, pStage, shader, packIDs, stage, previousMaterialID ); - } + surface->stages++; } - GenerateWorldMaterialsBuffer(); + for ( shaderStage_t* pStage = surface->shader->stages; pStage < surface->shader->lastStage; pStage++ ) { + ProcessStage( surface, pStage, surface->shader, packIDs, stage, previousMaterialID ); - uint32_t totalCount = 0; - for ( MaterialPack& pack : materialPacks ) { - totalCount += pack.materials.size(); + surface->stages++; } - Log::Notice( "Generated %u materials from %u surfaces", totalCount, tr.refdef.numDrawSurfs ); - 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 ); - - /* for ( const MaterialPack& materialPack : materialPacks ) { - Log::Notice( "materialPack sort: %i %i", Util::ordinal( materialPack.fromSort ), Util::ordinal( materialPack.toSort ) ); - for ( const Material& material : materialPack.materials ) { - Log::Notice( "id: %u, useSync: %b, sync: %u, program: %i, stateBits: %u, total drawSurfs: %u, shader: %s, vbo: %s, ibo: %s" - ", culling: %i", - material.id, material.useSync, material.syncMaterial, material.program, material.stateBits, material.drawSurfs.size(), - material.shader->GetName(), material.vbo->name, material.ibo->name, material.cullType ); - } - } */ - - r_nocull->integer = current_r_nocull; - r_drawworld->integer = current_r_drawworld; - AddAllWorldSurfaces(); - GeneratePortalBoundingSpheres(); + if ( !surface->shader->noFog && surface->fog >= 1 ) { + uint32_t unused; + ProcessStage( surface, surface->shader->fogShader->stages, surface->shader->fogShader, packIDs, stage, unused, true ); - generatedWorldCommandBuffer = true; + surface->stages++; + } } -void MaterialSystem::AddAllWorldSurfaces() { - GenerateWorldCommandBuffer(); - - generatingWorldCommandBuffer = false; +void MaterialSystem::SetWorldBounds( vec3_t bounds[2] ) { + Log::Notice( "World bounds: min: %f %f %f max: %f %f %f", bounds[0][0], bounds[0][1], + bounds[0][2], bounds[1][0], bounds[1][1], bounds[1][2] ); + VectorCopy( bounds[0], worldViewBounds[0] ); + VectorCopy( bounds[1], worldViewBounds[1] ); } void MaterialSystem::GLSLRestart() { @@ -1510,9 +1367,8 @@ void MaterialSystem::GLSLRestart() { } } -void MaterialSystem::AddStageTextures( drawSurf_t* drawSurf, const uint32_t stage, Material* material ) { +void MaterialSystem::AddStageTextures( MaterialSurface* surface, shader_t* shader, shaderStage_t* pStage, const uint32_t stage, Material* material ) { TextureData textureData; - const shaderStage_t* pStage = &drawSurf->shader->stages[stage]; int bundleNum = 0; bool dynamic = false; @@ -1542,11 +1398,11 @@ void MaterialSystem::AddStageTextures( drawSurf_t* drawSurf, const uint32_t stag // Add lightmap and deluxemap for this surface to the material as well lightMode_t lightMode; deluxeMode_t deluxeMode; - SetLightDeluxeMode( drawSurf, pStage->type, lightMode, deluxeMode ); + SetLightDeluxeMode( surface, shader, pStage->type, lightMode, deluxeMode ); // u_Map, u_DeluxeMap - image_t* lightmap = SetLightMap( drawSurf, lightMode ); - image_t* deluxemap = SetDeluxeMap( drawSurf, deluxeMode ); + image_t* lightmap = SetLightMap( surface, lightMode ); + image_t* deluxemap = SetDeluxeMap( surface, deluxeMode ); material->AddTexture( lightmap->texture ); material->AddTexture( deluxemap->texture ); @@ -1559,12 +1415,12 @@ void MaterialSystem::AddStageTextures( drawSurf_t* drawSurf, const uint32_t stag std::vector::iterator it = std::find( textures.begin(), textures.end(), textureData ); if ( it == textures.end() ) { - drawSurf->texDataIDs[stage] = textures.size(); + surface->texDataIDs[stage] = textures.size(); textures.emplace_back( textureData ); } else { - drawSurf->texDataIDs[stage] = it - textures.begin(); + surface->texDataIDs[stage] = it - textures.begin(); } - drawSurf->texDataDynamic[stage] = dynamic; + surface->texDataDynamic[stage] = dynamic; if ( glConfig2.realtimeLighting ) { if ( r_realtimeLightingRenderer.Get() == Util::ordinal( realtimeLightingRenderer_t::TILED ) ) { @@ -1766,18 +1622,10 @@ void MaterialSystem::CullSurfaces() { } void MaterialSystem::StartFrame() { - if ( !generatedWorldCommandBuffer ) { - return; - } - frames[nextFrame].viewCount = 0; } void MaterialSystem::EndFrame() { - if ( !generatedWorldCommandBuffer ) { - return; - } - currentFrame = nextFrame; nextFrame++; if ( nextFrame >= MAX_FRAMES ) { @@ -1788,7 +1636,7 @@ void MaterialSystem::EndFrame() { void MaterialSystem::GeneratePortalBoundingSpheres() { Log::Debug( "Generating portal bounding spheres" ); - totalPortals = portalSurfacesTmp.size(); + totalPortals = portalSurfaces.size(); if ( totalPortals == 0 ) { return; @@ -1796,33 +1644,15 @@ void MaterialSystem::GeneratePortalBoundingSpheres() { // FIXME: This only requires distance, origin and radius can be moved to surfaceDescriptors SSBO, // drawSurfID is not needed as it's the same as the index in portalSurfacesSSBO - PortalSurface* portalSurfs = new PortalSurface[totalPortals * sizeof( PortalSurface ) * MAX_VIEWFRAMES]; + PortalSurface* portalSurfs = + ( PortalSurface* ) ri.Hunk_AllocateTempMemory( totalPortals * MAX_VIEWFRAMES * sizeof( PortalSurface ) ); uint32_t index = 0; - for ( drawSurf_t* drawSurf : portalSurfacesTmp ) { - Tess_MapVBOs( /*forceCPU=*/ true ); - Tess_Begin( Tess_StageIteratorDummy, nullptr, nullptr, true, -1, 0 ); - rb_surfaceTable[Util::ordinal( *( drawSurf->surface ) )]( drawSurf->surface ); - const int numVerts = tess.numVertexes; - vec3_t portalCenter{ 0.0, 0.0, 0.0 }; - for ( int vertIndex = 0; vertIndex < numVerts; vertIndex++ ) { - VectorAdd( portalCenter, tess.verts[vertIndex].xyz, portalCenter ); - } - VectorScale( portalCenter, 1.0 / numVerts, portalCenter ); - - float furthestDistance = 0.0; - for ( int vertIndex = 0; vertIndex < numVerts; vertIndex++ ) { - const float distance = Distance( portalCenter, tess.verts[vertIndex].xyz ); - furthestDistance = distance > furthestDistance ? distance : furthestDistance; - } - - Tess_Clear(); - - portalSurfaces.emplace_back( *drawSurf ); + for ( MaterialSurface& surface : portalSurfaces ) { PortalSurface sphere; - VectorCopy( portalCenter, sphere.origin ); - sphere.radius = furthestDistance; - sphere.drawSurfID = portalSurfaces.size() - 1; + VectorCopy( surface.origin, sphere.origin ); + sphere.radius = surface.radius; + sphere.drawSurfID = &surface - portalSurfaces.data(); sphere.distance = -1; portalBounds.emplace_back( sphere ); @@ -1837,7 +1667,7 @@ void MaterialSystem::GeneratePortalBoundingSpheres() { portalSurfacesSSBO.BufferStorage( totalPortals * PORTAL_SURFACE_SIZE * MAX_VIEWS, 2, portalSurfs ); portalSurfacesSSBO.MapAll(); - portalSurfacesTmp.clear(); + ri.Hunk_FreeTempMemory( portalSurfs ); } void MaterialSystem::InitGLBuffers() { @@ -1877,13 +1707,10 @@ void MaterialSystem::FreeGLBuffers() { } void MaterialSystem::Free() { - generatedWorldCommandBuffer = false; - materialStages.clear(); dynamicStages.clear(); autospriteSurfaces.clear(); portalSurfaces.clear(); - portalSurfacesTmp.clear(); portalBounds.clear(); skyShaders.clear(); renderedMaterials.clear(); @@ -1902,46 +1729,23 @@ void MaterialSystem::Free() { portalSurfacesSSBO.UnmapBuffer(); for ( PortalView& portalView : portalStack ) { - portalView.drawSurf = nullptr; memset( portalView.views, 0, MAX_VIEWS * sizeof( uint32_t ) ); portalView.count = 0; } } + totalDrawSurfs = 0; + currentFrame = 0; nextFrame = 1; maxStages = 0; + memset( packIDs, 0, sizeof( packIDs ) ); for ( MaterialPack& pack : materialPacks ) { - for ( Material& material : pack.materials ) { - material.drawCommands.clear(); - material.drawSurfs.clear(); - } pack.materials.clear(); } } -// This gets the information for the surface vertex/index data through Tess -void MaterialSystem::AddDrawCommand( const uint32_t materialID, const uint32_t materialPackID, const uint32_t materialsSSBOOffset, - const GLuint count, const GLuint firstIndex ) { - cmd.cmd.count = count; - cmd.cmd.firstIndex = firstIndex; - cmd.cmd.baseInstance = materialsSSBOOffset; - cmd.materialsSSBOOffset = materialsSSBOOffset; - - materialPacks[materialPackID].materials[materialID].drawCommands.emplace_back( cmd ); - lastCommandID = materialPacks[materialPackID].materials[materialID].drawCommands.size() - 1; - cmd.textureCount = 0; -} - -void MaterialSystem::AddTexture( Texture* texture ) { - if ( cmd.textureCount >= MAX_DRAWCOMMAND_TEXTURES ) { - Sys::Drop( "Exceeded max DrawCommand textures" ); - } - cmd.textures[cmd.textureCount] = texture; - cmd.textureCount++; -} - bool MaterialSystem::AddPortalSurface( uint32_t viewID, PortalSurface* portalSurfs ) { uint32_t portalViews[MAX_VIEWS] {}; uint32_t count = 0; @@ -1949,7 +1753,7 @@ bool MaterialSystem::AddPortalSurface( uint32_t viewID, PortalSurface* portalSur frames[nextFrame].viewFrames[viewID].viewCount = 0; portalStack[viewID].count = 0; - PortalSurface* tmpSurfs = new PortalSurface[totalPortals]; + PortalSurface* tmpSurfs = ( PortalSurface* ) ri.Hunk_AllocateTempMemory( totalPortals * sizeof( PortalSurface ) );; memcpy( tmpSurfs, portalSurfs + viewID * totalPortals, totalPortals * sizeof( PortalSurface ) ); std::sort( tmpSurfs, tmpSurfs + totalPortals, []( const PortalSurface& lhs, const PortalSurface& rhs ) { @@ -1965,8 +1769,17 @@ bool MaterialSystem::AddPortalSurface( uint32_t viewID, PortalSurface* portalSur uint32_t portalViewID = viewCount + 1; // This check has to be done first so we can correctly determine when we get to MAX_VIEWS - 1 amount of views screenRect_t surfRect; + drawSurf_t drawSurf; + { + drawSurf.bspSurface = portalSurfaces[portalSurface->drawSurfID].bspSurface; + drawSurf.entity = &tr.worldEntity; + drawSurf.fog = portalSurfaces[portalSurface->drawSurfID].fog; + drawSurf.portalNum = portalSurfaces[portalSurface->drawSurfID].portalNum; + drawSurf.shader = portalSurfaces[portalSurface->drawSurfID].shader; + drawSurf.surface = portalSurfaces[portalSurface->drawSurfID].surface; + } bool offScreenOrOutOfRange = 0 != PortalOffScreenOrOutOfRange( - &portalSurfaces[ portalSurface->drawSurfID ], surfRect ); + &drawSurf, surfRect ); Tess_Clear(); if ( offScreenOrOutOfRange ) { continue; @@ -1981,13 +1794,14 @@ bool MaterialSystem::AddPortalSurface( uint32_t viewID, PortalSurface* portalSur frames[nextFrame].viewFrames[viewID].viewCount++; portalStack[viewID].views[count] = portalViewID; - portalStack[portalViewID].drawSurf = &portalSurfaces[portalSurface->drawSurfID]; + portalStack[portalViewID].drawSurf = drawSurf; portalStack[viewID].count++; count++; viewCount++; if ( count == MAX_VIEWS || viewCount == MAX_VIEWS ) { + ri.Hunk_FreeTempMemory( tmpSurfs ); return false; } @@ -1995,6 +1809,7 @@ bool MaterialSystem::AddPortalSurface( uint32_t viewID, PortalSurface* portalSur uint32_t subView = frames[currentFrame].viewFrames[viewID].portalViews[j]; if ( subView != 0 && portalSurface->drawSurfID == frames[currentFrame].viewFrames[subView].portalSurfaceID ) { if ( !AddPortalSurface( subView, portalSurfs ) ) { + ri.Hunk_FreeTempMemory( tmpSurfs ); return false; } @@ -2006,6 +1821,7 @@ bool MaterialSystem::AddPortalSurface( uint32_t viewID, PortalSurface* portalSur memcpy( frames[nextFrame].viewFrames[viewID].portalViews, portalViews, MAX_VIEWS * sizeof( uint32_t ) ); + ri.Hunk_FreeTempMemory( tmpSurfs ); return true; } @@ -2031,10 +1847,10 @@ void MaterialSystem::AddPortalSurfaces() { void MaterialSystem::AddAutospriteSurfaces() { tr.currentEntity = &tr.worldEntity; - for ( const drawSurf_t &drawSurf : autospriteSurfaces ) + for ( const bspSurface_t* surface : autospriteSurfaces ) { - R_AddDrawSurf( drawSurf.surface, drawSurf.shader, - drawSurf.lightmapNum(), drawSurf.fog, drawSurf.bspSurface ); + R_AddDrawSurf( surface->data, surface->shader, + surface->lightmapNum, surface->fogIndex, true ); } } @@ -2096,7 +1912,7 @@ void MaterialSystem::RenderIndirect( const Material& material, const uint32_t vi * sizeof( GLIndirectCommand ) ) ), material.globalID * sizeof( uint32_t ) + ( MAX_COMMAND_COUNTERS * ( MAX_VIEWS * currentFrame + viewID ) ) * sizeof( uint32_t ), - material.drawCommands.size(), 0 ); + material.drawCommandCount, 0 ); } void MaterialSystem::RenderMaterial( Material& material, const uint32_t viewID ) { diff --git a/src/engine/renderer/Material.h b/src/engine/renderer/Material.h index 0a32e9fa4b..903f5a6628 100644 --- a/src/engine/renderer/Material.h +++ b/src/engine/renderer/Material.h @@ -63,7 +63,6 @@ struct DrawCommand { IndirectCompactCommand cmd; uint32_t materialsSSBOOffset = 0; uint32_t textureCount = 0; - Texture* textures[MAX_DRAWCOMMAND_TEXTURES]; DrawCommand() { } @@ -72,29 +71,35 @@ struct DrawCommand { cmd = other.cmd; materialsSSBOOffset = other.materialsSSBOOffset; textureCount = other.textureCount; - memcpy( textures, other.textures, textureCount * sizeof( Texture* ) ); } }; struct MaterialSurface { shader_t* shader; + surfaceType_t* surface; bool bspSurface; + int16_t lightMapNum; int fog; int portalNum = -1; GLuint firstIndex; GLuint count; + vec3_t origin; + float radius; + srfVert_t* verts; srfTriangle_t* tris; uint32_t materialPackIDs[MAX_SHADER_STAGES]; uint32_t materialIDs[MAX_SHADER_STAGES]; - uint32_t drawCommandIDs[MAX_SHADER_STAGES]; uint32_t texDataIDs[MAX_SHADER_STAGES]; bool texDataDynamic[MAX_SHADER_STAGES]; uint32_t shaderVariant[MAX_SHADER_STAGES]; + + uint8_t stages = 0; + shaderStage_t* shaderStages[MAX_SHADER_STAGES]; }; struct Material { @@ -116,7 +121,7 @@ struct Material { // Used only for glsl_restart shaderStage_t* refStage; - drawSurf_t refDrawSurf; + MaterialSurface refDrawSurf; int deformIndex; bool tcGenEnvironment; @@ -139,10 +144,10 @@ struct Material { bool usePolygonOffset = false; - fog_t* fog = nullptr; + int fog = 0; - std::vector drawSurfs; - std::vector drawCommands; + uint32_t drawCommandCount = 0; + uint32_t drawCommandCount2 = 0; bool texturesResident = false; std::vector textures; @@ -233,7 +238,7 @@ struct PortalSurface { struct PortalView { uint32_t count; - drawSurf_t* drawSurf; + drawSurf_t drawSurf; uint32_t views[MAX_VIEWS]; }; @@ -318,18 +323,15 @@ enum class BufferBind { class MaterialSystem { public: - bool generatedWorldCommandBuffer = false; - bool generatingWorldCommandBuffer = false; - vec3_t worldViewBounds[2] = {}; + vec3_t worldViewBounds[2]; uint8_t maxStages = 0; uint32_t descriptorSize; std::vector drawCommands; - std::vector portalSurfacesTmp; - std::vector portalSurfaces; - std::vector autospriteSurfaces; + std::vector portalSurfaces; + std::vector autospriteSurfaces; std::vector portalBounds; uint32_t totalPortals; std::vector skyShaders; @@ -358,10 +360,6 @@ class MaterialSystem { bool frameStart = false; - void AddTexture( Texture* texture ); - void AddDrawCommand( const uint32_t materialID, const uint32_t materialPackID, const uint32_t materialsSSBOOffset, - const GLuint count, const GLuint firstIndex ); - void AddPortalSurfaces(); void AddAutospriteSurfaces(); void RenderMaterials( const shaderSort_t fromSort, const shaderSort_t toSort, const uint32_t viewID ); @@ -379,21 +377,21 @@ class MaterialSystem { void InitGLBuffers(); void FreeGLBuffers(); - void AddStageTextures( drawSurf_t* drawSurf, const uint32_t stage, Material* material ); - void AddStage( drawSurf_t* drawSurf, shaderStage_t* pStage, uint32_t stage, + 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 ); - void ProcessStage( drawSurf_t* drawSurf, shaderStage_t* pStage, shader_t* shader, uint32_t* packIDs, uint32_t& stage, - uint32_t& previousMaterialID ); - void GenerateWorldMaterials(); + void ProcessStage( MaterialSurface* surface, shaderStage_t* pStage, shader_t* shader, uint32_t* packIDs, uint32_t& stage, + uint32_t& previousMaterialID, bool skipStageSync = false ); + void GenerateMaterial( MaterialSurface* surface ); void GenerateWorldMaterialsBuffer(); - void GenerateWorldCommandBuffer(); + void GenerateWorldCommandBuffer( std::vector& surfaces ); void GeneratePortalBoundingSpheres(); + void SetWorldBounds( vec3_t bounds[2] ); + void GenerateMaterialsBuffer( std::vector& stages, const uint32_t size, uint32_t* materialsData ); void GenerateTexturesBuffer( std::vector& textures, TexBundle* textureBundles ); - void AddAllWorldSurfaces(); - void GLSLRestart(); void Free(); @@ -410,14 +408,14 @@ class MaterialSystem { image_t* depthImage; int depthImageLevels; - DrawCommand cmd; - uint32_t lastCommandID; uint32_t totalDrawSurfs; uint32_t totalBatchCount = 0; uint32_t surfaceCommandsCount = 0; uint32_t surfaceDescriptorsCount = 0; + uint32_t packIDs[3] = { 0, 0, 0 }; + std::vector materialStages; std::vector dynamicStages; @@ -468,8 +466,6 @@ void UpdateSurfaceDataHeatHaze( uint32_t* materials, shaderStage_t* pStage, bool void UpdateSurfaceDataLiquid( uint32_t* materials, shaderStage_t* pStage, bool, bool, bool ); void UpdateSurfaceDataFog( uint32_t* materials, shaderStage_t* pStage, bool, bool, bool ); -// void UpdateSurf( uint32) - void BindShaderNONE( Material* ); void BindShaderNOP( Material* ); void BindShaderGeneric3D( Material* material ); @@ -481,15 +477,15 @@ void BindShaderHeatHaze( Material* material ); void BindShaderLiquid( Material* material ); void BindShaderFog( Material* material ); -void ProcessMaterialNONE( Material*, shaderStage_t*, drawSurf_t* ); -void ProcessMaterialNOP( Material*, shaderStage_t*, drawSurf_t* ); -void ProcessMaterialGeneric3D( Material* material, shaderStage_t* pStage, drawSurf_t* /* drawSurf */ ); -void ProcessMaterialLightMapping( Material* material, shaderStage_t* pStage, drawSurf_t* drawSurf ); -void ProcessMaterialReflection( Material* material, shaderStage_t* pStage, drawSurf_t* /* drawSurf */ ); -void ProcessMaterialSkybox( Material* material, shaderStage_t* pStage, drawSurf_t* /* drawSurf */ ); -void ProcessMaterialScreen( Material* material, shaderStage_t* pStage, drawSurf_t* /* drawSurf */ ); -void ProcessMaterialHeatHaze( Material* material, shaderStage_t* pStage, drawSurf_t* drawSurf ); -void ProcessMaterialLiquid( Material* material, shaderStage_t* pStage, drawSurf_t* /* drawSurf */ ); -void ProcessMaterialFog( Material* material, shaderStage_t* pStage, drawSurf_t* drawSurf ); +void ProcessMaterialNONE( Material*, shaderStage_t*, MaterialSurface* ); +void ProcessMaterialNOP( Material*, shaderStage_t*, MaterialSurface* ); +void ProcessMaterialGeneric3D( Material* material, shaderStage_t* pStage, MaterialSurface* /* surface */ ); +void ProcessMaterialLightMapping( Material* material, shaderStage_t* pStage, MaterialSurface* surface ); +void ProcessMaterialReflection( Material* material, shaderStage_t* pStage, MaterialSurface* /* surface */ ); +void ProcessMaterialSkybox( Material* material, shaderStage_t* pStage, MaterialSurface* /* surface */ ); +void ProcessMaterialScreen( Material* material, shaderStage_t* pStage, MaterialSurface* /* surface */ ); +void ProcessMaterialHeatHaze( Material* material, shaderStage_t* pStage, MaterialSurface* surface ); +void ProcessMaterialLiquid( Material* material, shaderStage_t* pStage, MaterialSurface* /* surface */ ); +void ProcessMaterialFog( Material* material, shaderStage_t* pStage, MaterialSurface* surface ); #endif // MATERIAL_H diff --git a/src/engine/renderer/ShadeCommon.h b/src/engine/renderer/ShadeCommon.h index bae521f9c8..7d8f107439 100644 --- a/src/engine/renderer/ShadeCommon.h +++ b/src/engine/renderer/ShadeCommon.h @@ -37,9 +37,9 @@ inline size_t GetLightMapNum( const shaderCommands_t* tess ) return tess->lightmapNum; } -inline size_t GetLightMapNum( const drawSurf_t* drawSurf ) +inline size_t GetLightMapNum( const MaterialSurface* surface ) { - return drawSurf->lightmapNum(); + return surface->lightMapNum; } template bool HasLightMap( Obj* obj ) @@ -77,9 +77,9 @@ inline shader_t* GetSurfaceShader( shaderCommands_t* tess ) return tess->surfaceShader; } -inline shader_t* GetSurfaceShader( drawSurf_t* drawSurf ) +inline shader_t* GetSurfaceShader( shader_t* shader ) { - return drawSurf->shader; + return shader; } template static bool hasExplicitelyDisabledLightMap( Obj* obj ) @@ -92,9 +92,9 @@ inline shaderStage_t* GetSurfaceLastStage( shaderCommands_t* tess ) return tess->surfaceLastStage; } -inline shaderStage_t* GetSurfaceLastStage( drawSurf_t* drawSurf ) +inline shaderStage_t* GetSurfaceLastStage( shader_t* shader ) { - return drawSurf->shader->lastStage; + return shader->lastStage; } inline shaderStage_t* GetSurfaceStages( shaderCommands_t* tess ) @@ -102,9 +102,9 @@ inline shaderStage_t* GetSurfaceStages( shaderCommands_t* tess ) return tess->surfaceStages; } -inline shaderStage_t* GetSurfaceStages( drawSurf_t* drawSurf ) +inline shaderStage_t* GetSurfaceStages( shader_t* shader ) { - return drawSurf->shader->stages; + return shader->stages; } template bool isExplicitelyVertexLitSurface( Obj* obj ) @@ -114,14 +114,14 @@ template bool isExplicitelyVertexLitSurface( Obj* obj ) return lastStage != stages && stages[0].rgbGen == colorGen_t::CGEN_VERTEX; } -template void SetLightDeluxeMode( Obj* obj, +template void SetLightDeluxeMode( Obj* obj, shader_t* shader, stageType_t stageType, lightMode_t& lightMode, deluxeMode_t& deluxeMode ) { lightMode = lightMode_t::FULLBRIGHT; deluxeMode = deluxeMode_t::NONE; - if ( hasExplicitelyDisabledLightMap( obj ) && !isExplicitelyVertexLitSurface( obj ) ) + if ( hasExplicitelyDisabledLightMap( shader ) && !isExplicitelyVertexLitSurface( shader ) ) { // Use fullbright on “surfaceparm nolightmap” materials. } diff --git a/src/engine/renderer/gl_shader.cpp b/src/engine/renderer/gl_shader.cpp index f43d773dd7..02dc4c0015 100644 --- a/src/engine/renderer/gl_shader.cpp +++ b/src/engine/renderer/gl_shader.cpp @@ -943,6 +943,8 @@ int GLShaderManager::GetDeformShaderIndex( deformStage_t *deforms, int numDeform deformShaderCount++; _deformShaderLookup[steps] = deformShaderCount; + } else { + index--; } return index; diff --git a/src/engine/renderer/tr_backend.cpp b/src/engine/renderer/tr_backend.cpp index 9199584ca0..d0b282ee27 100644 --- a/src/engine/renderer/tr_backend.cpp +++ b/src/engine/renderer/tr_backend.cpp @@ -170,11 +170,6 @@ GLuint64 GL_BindToTMU( int unit, image_t *image ) } if ( glConfig2.usingBindlessTextures ) { - if ( materialSystem.generatingWorldCommandBuffer ) { - materialSystem.AddTexture( image->texture ); - return image->texture->bindlessTextureHandle; - } - return tr.textureManager.BindTexture( 0, image->texture ); } @@ -858,7 +853,6 @@ static void RB_RenderDrawSurfaces( shaderSort_t fromSort, shaderSort_t toSort, for ( i = backEnd.viewParms.firstDrawSurf[ Util::ordinal(fromSort) ]; i < lastSurf; i++ ) { drawSurf = &backEnd.viewParms.drawSurfs[ i ]; - tess.currentDrawSurf = drawSurf; // FIXME: investigate why this happens. if( drawSurf->surface == nullptr ) diff --git a/src/engine/renderer/tr_bsp.cpp b/src/engine/renderer/tr_bsp.cpp index ec0f0aeefb..305604f8fd 100644 --- a/src/engine/renderer/tr_bsp.cpp +++ b/src/engine/renderer/tr_bsp.cpp @@ -2538,12 +2538,22 @@ static void R_CreateWorldVBO() { // HACK: portals: don't use VBO because when adding a portal we have to read back the verts CPU-side // Autosprite: don't use VBO because verts are rewritten each time based on view origin if ( surface->shader->isPortal || surface->shader->autoSpriteMode != 0 ) { + if( glConfig2.usingMaterialSystem && surface->shader->autoSpriteMode ) { + materialSystem.autospriteSurfaces.push_back( surface ); + } + if ( surface->shader->isPortal ) { numPortals++; } continue; } + if ( glConfig2.usingMaterialSystem && surface->shader->isSky + && std::find( materialSystem.skyShaders.begin(), materialSystem.skyShaders.end(), surface->shader ) + == materialSystem.skyShaders.end() ) { + materialSystem.skyShaders.emplace_back( surface->shader ); + } + if ( *surface->data == surfaceType_t::SF_FACE || *surface->data == surfaceType_t::SF_GRID || *surface->data == surfaceType_t::SF_TRIANGLES ) { srfGeneric_t* srf = ( srfGeneric_t* ) surface->data; @@ -2555,6 +2565,11 @@ static void R_CreateWorldVBO() { } surface->renderable = true; + + if ( i >= ( int ) s_worldData.models[0].numSurfaces ) { + surface->BSPModel = true; + } + numSurfaces++; } @@ -2562,33 +2577,6 @@ static void R_CreateWorldVBO() { return; } - bspSurface_t** rendererSurfaces = ( bspSurface_t** ) ri.Hunk_AllocateTempMemory( sizeof( bspSurface_t* ) * numSurfaces ); - numSurfaces = 0; - for ( int i = 0; i < s_worldData.numSurfaces; i++ ) { - bspSurface_t* surface = &s_worldData.surfaces[i]; - - if ( surface->renderable ) { - rendererSurfaces[numSurfaces++] = surface; - } - } - - OptimiseMapGeometryCore( &s_worldData, rendererSurfaces, numSurfaces ); - - Log::Debug( "...calculating world VBO ( %i verts %i tris )", numVertsInitial, numTriangles ); - - // Use srfVert_t for the temporary array used to feed R_CreateStaticVBO, despite containing - // extraneous data, so that verts can be conveniently be bulk copied from the surface. - srfVert_t* vboVerts = ( srfVert_t* ) ri.Hunk_AllocateTempMemory( numVertsInitial * sizeof( srfVert_t ) ); - glIndex_t* vboIdxs = ( glIndex_t* ) ri.Hunk_AllocateTempMemory( 3 * numTriangles * sizeof( glIndex_t ) ); - - int numVerts; - int numIndices; - MergeDuplicateVertices( rendererSurfaces, numSurfaces, vboVerts, numVertsInitial, vboIdxs, 3 * numTriangles, numVerts, numIndices ); - - if ( glConfig2.usingMaterialSystem ) { - OptimiseMapGeometryMaterial( &s_worldData, numSurfaces ); - } - s_worldData.numPortals = numPortals; s_worldData.portals = ( AABB* ) ri.Hunk_Alloc( numPortals * sizeof( AABB ), ha_pref::h_low ); int portal = 0; @@ -2622,11 +2610,59 @@ static void R_CreateWorldVBO() { break; } portal++; + + if( glConfig2.usingMaterialSystem ) { + MaterialSurface srf{}; + + srf.shader = surface->shader; + srf.surface = surface->data; + srf.bspSurface = true; + srf.lightMapNum = surface->lightmapNum; + srf.fog = surface->fogIndex; + srf.portalNum = surface->portalNum; + + srf.firstIndex = ( ( srfGeneric_t* ) surface->data )->firstIndex; + srf.count = ( ( srfGeneric_t* ) surface->data )->numTriangles * 3; + srf.verts = ( ( srfGeneric_t* ) surface->data )->verts; + srf.tris = ( ( srfGeneric_t* ) surface->data )->triangles; + + VectorCopy( ( ( srfGeneric_t* ) surface->data )->origin, srf.origin ); + srf.radius = ( ( srfGeneric_t* ) surface->data )->radius; + + materialSystem.portalSurfaces.emplace_back( srf ); + } } else { surface->portalNum = -1; } } + bspSurface_t** rendererSurfaces = ( bspSurface_t** ) ri.Hunk_AllocateTempMemory( sizeof( bspSurface_t* ) * numSurfaces ); + numSurfaces = 0; + for ( int i = 0; i < s_worldData.numSurfaces; i++ ) { + bspSurface_t* surface = &s_worldData.surfaces[i]; + + if ( surface->renderable ) { + rendererSurfaces[numSurfaces++] = surface; + } + } + + OptimiseMapGeometryCore( &s_worldData, rendererSurfaces, numSurfaces ); + + Log::Debug( "...calculating world VBO ( %i verts %i tris )", numVertsInitial, numTriangles ); + + // Use srfVert_t for the temporary array used to feed R_CreateStaticVBO, despite containing + // extraneous data, so that verts can be conveniently be bulk copied from the surface. + srfVert_t* vboVerts = ( srfVert_t* ) ri.Hunk_AllocateTempMemory( numVertsInitial * sizeof( srfVert_t ) ); + glIndex_t* vboIdxs = ( glIndex_t* ) ri.Hunk_AllocateTempMemory( 3 * numTriangles * sizeof( glIndex_t ) ); + + int numVerts; + int numIndices; + MergeDuplicateVertices( rendererSurfaces, numSurfaces, vboVerts, numVertsInitial, vboIdxs, 3 * numTriangles, numVerts, numIndices ); + + if ( glConfig2.usingMaterialSystem ) { + OptimiseMapGeometryMaterial( rendererSurfaces, numSurfaces ); + } + vertexAttributeSpec_t attrs[]{ { ATTR_INDEX_POSITION, GL_FLOAT, GL_FLOAT, &vboVerts[0].xyz, 3, sizeof( *vboVerts ), 0 }, { ATTR_INDEX_COLOR, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE, &vboVerts[0].lightColor, 4, sizeof( *vboVerts ), ATTR_OPTION_NORMALIZE }, @@ -4302,6 +4338,82 @@ static Cmd::LambdaCmd buildCubeMapsCmd( "buildcubemaps", Cmd::RENDERER, "generate cube probes for reflection mapping", []( const Cmd::Args & ) { R_BuildCubeMaps(); }); +static void SetWorldLight() { + tr.worldLight = tr.lightMode; + tr.modelLight = lightMode_t::FULLBRIGHT; + tr.modelDeluxe = deluxeMode_t::NONE; + + // Use fullbright lighting for everything if the world is fullbright. + if ( tr.worldLight != lightMode_t::FULLBRIGHT ) { + if ( tr.worldLight == lightMode_t::MAP ) { + // World surfaces use light mapping. + + if ( !tr.worldLightMapping ) { + /* Use vertex light as a fallback on world surfaces missing a light map, + q3map2 has an option to produce less lightmap files by skipping them when + they are very similar to the vertex color. The vertex color is expected + to match the color of the nearby lightmaps. We better not want to use + the grid light as a fallback as it would be close but not close enough. */ + + tr.worldLight = lightMode_t::VERTEX; + } + } else if ( tr.worldLight == lightMode_t::GRID ) { + if ( !tr.lightGrid1Image ) { + // Use vertex light on world surface if light color grid is missing. + tr.worldLight = lightMode_t::VERTEX; + } + } + + if ( tr.worldDeluxeMapping ) { + if ( tr.worldLight == lightMode_t::MAP ) { + tr.worldDeluxe = deluxeMode_t::MAP; + } + + /* The combination of grid light and deluxe map is + technically doable, but rendering the world with a + light grid while a light map is available is not + the experience we want to provide, so we don't + allow this combination to not compile the related + shaders. */ + } + + /* We can technically use emulated deluxe map from light direction dir + on surfaces with light map but no deluxe map, but this is ugly. + Also, enabling it would require to make some macro not conflicting and + then would increase the amount of GLSL shader variants to be compiled, + this to render legacy maps in a way legacy renderers never rendered them. + It could still be cool as an optional feature, if we use a better + algorithm for emulating the deluxe map from light direction grid. + See https://github.com/DaemonEngine/Daemon/issues/32 */ + + if ( tr.lightGrid1Image ) { + // Game model surfaces use grid lighting, they don't have vertex light colors. + tr.modelLight = lightMode_t::GRID; + } + + if ( glConfig2.deluxeMapping ) { + // Enable deluxe mapping emulation if light direction grid is there. + if ( tr.lightGrid2Image ) { + // Game model surfaces use grid lighting, they don't have vertex light colors. + tr.modelDeluxe = deluxeMode_t::GRID; + + // Only game models use emulated deluxe map from light direction grid. + } + } + } + + /* Set GLSL overbright parameters if the lighting mode is not fullbright. */ + if ( tr.lightMode != lightMode_t::FULLBRIGHT ) { + if ( r_overbrightQ3.Get() ) { + // light factor is applied to entire color buffer; identityLight can be used to cancel it + tr.identityLight = 1.0f / float( 1 << tr.overbrightBits ); + } else { + // light factor is applied wherever a precomputed light is sampled + tr.mapLightFactor = float( 1 << tr.overbrightBits ); + } + } +} + /* ================= RE_LoadWorldMap @@ -4427,6 +4539,9 @@ void RE_LoadWorldMap( const char *name ) R_LoadLightGrid( &header->lumps[ LUMP_LIGHTGRID ] ); // create a static vbo for the world + // Do SetWorldLight() before R_CreateWorldVBO(), because the latter will use the world light values to generate materials + SetWorldLight(); + R_CreateWorldVBO(); R_CreateClusters(); @@ -4435,99 +4550,9 @@ void RE_LoadWorldMap( const char *name ) } s_worldData.dataSize = ( byte * ) ri.Hunk_Alloc( 0, ha_pref::h_low ) - startMarker; - // only set tr.world now that we know the entire level has loaded properly tr.world = &s_worldData; - tr.worldLight = tr.lightMode; - tr.modelLight = lightMode_t::FULLBRIGHT; - tr.modelDeluxe = deluxeMode_t::NONE; - - // Use fullbright lighting for everything if the world is fullbright. - if ( tr.worldLight != lightMode_t::FULLBRIGHT ) - { - if ( tr.worldLight == lightMode_t::MAP ) - { - // World surfaces use light mapping. - - if ( !tr.worldLightMapping ) - { - /* Use vertex light as a fallback on world surfaces missing a light map, - q3map2 has an option to produce less lightmap files by skipping them when - they are very similar to the vertex color. The vertex color is expected - to match the color of the nearby lightmaps. We better not want to use - the grid light as a fallback as it would be close but not close enough. */ - - tr.worldLight = lightMode_t::VERTEX; - } - } - else if ( tr.worldLight == lightMode_t::GRID ) - { - if ( !tr.lightGrid1Image ) - { - // Use vertex light on world surface if light color grid is missing. - tr.worldLight = lightMode_t::VERTEX; - } - } - - if ( tr.worldDeluxeMapping ) - { - if ( tr.worldLight == lightMode_t::MAP ) - { - tr.worldDeluxe = deluxeMode_t::MAP; - } - - /* The combination of grid light and deluxe map is - technically doable, but rendering the world with a - light grid while a light map is available is not - the experience we want to provide, so we don't - allow this combination to not compile the related - shaders. */ - } - - /* We can technically use emulated deluxe map from light direction dir - on surfaces with light map but no deluxe map, but this is ugly. - Also, enabling it would require to make some macro not conflicting and - then would increase the amount of GLSL shader variants to be compiled, - this to render legacy maps in a way legacy renderers never rendered them. - It could still be cool as an optional feature, if we use a better - algorithm for emulating the deluxe map from light direction grid. - See https://github.com/DaemonEngine/Daemon/issues/32 */ - - if ( tr.lightGrid1Image ) - { - // Game model surfaces use grid lighting, they don't have vertex light colors. - tr.modelLight = lightMode_t::GRID; - } - - if ( glConfig2.deluxeMapping ) - { - // Enable deluxe mapping emulation if light direction grid is there. - if ( tr.lightGrid2Image ) - { - // Game model surfaces use grid lighting, they don't have vertex light colors. - tr.modelDeluxe = deluxeMode_t::GRID; - - // Only game models use emulated deluxe map from light direction grid. - } - } - } - - /* Set GLSL overbright parameters if the lighting mode is not fullbright. */ - if ( tr.lightMode != lightMode_t::FULLBRIGHT ) - { - if ( r_overbrightQ3.Get() ) - { - // light factor is applied to entire color buffer; identityLight can be used to cancel it - tr.identityLight = 1.0f / float( 1 << tr.overbrightBits ); - } - else - { - // light factor is applied wherever a precomputed light is sampled - tr.mapLightFactor = float( 1 << tr.overbrightBits ); - } - } - tr.worldLoaded = true; tr.loadingMap = ""; GLSL_InitWorldShaders(); diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index d74eca1cc1..ae01b561db 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -1093,12 +1093,12 @@ enum class ssaoMode { struct shaderStage_t; struct Material; - struct drawSurf_t; + struct MaterialSurface; using stageRenderer_t = void(*)(shaderStage_t *); using surfaceDataUpdater_t = void(*)(uint32_t*, shaderStage_t*, bool, bool, bool); using stageShaderBinder_t = void(*)(Material*); - using stageMaterialProcessor_t = void(*)(Material*, shaderStage_t*, drawSurf_t*); + using stageMaterialProcessor_t = void(*)(Material*, shaderStage_t*, MaterialSurface*); enum ShaderStageVariant { VERTEX_OVERBRIGHT = 1, @@ -1637,18 +1637,6 @@ enum class ssaoMode { int fog; int portalNum = -1; - uint32_t materialPackIDs[MAX_SHADER_STAGES]; - uint32_t materialIDs[MAX_SHADER_STAGES]; - - uint32_t drawCommandIDs[MAX_SHADER_STAGES]; - uint32_t texDataIDs[MAX_SHADER_STAGES]; - bool texDataDynamic[MAX_SHADER_STAGES]; - uint32_t shaderVariant[MAX_SHADER_STAGES]; - - drawSurf_t* depthSurface; - drawSurf_t* fogSurface; - bool materialSystemSkip = false; - inline int index() const { return int( ( sort & SORT_INDEX_MASK ) ); } @@ -1841,6 +1829,7 @@ enum class ssaoMode { int portalNum; bool renderable = false; + bool BSPModel = false; surfaceType_t *data; // any of srf*_t }; @@ -3089,7 +3078,7 @@ inline bool checkGLErrors() void R_AddPolygonSurfaces(); - int R_AddDrawSurf( surfaceType_t *surface, shader_t *shader, int lightmapNum, int fogNum, bool bspSurface = false, int portalNum = -1 ); + void R_AddDrawSurf( surfaceType_t *surface, shader_t *shader, int lightmapNum, int fogNum, bool bspSurface = false, int portalNum = -1 ); void R_LocalNormalToWorld( const vec3_t local, vec3_t world ); void R_LocalPointToWorld( const vec3_t local, vec3_t world ); @@ -3380,12 +3369,6 @@ void GLimp_LogComment_( std::string comment ); uint32_t numIndexes; uint32_t numVertexes; - // Material system stuff for setting up correct SSBO offsets - uint materialPackID = 0; - uint materialID = 0; - uint currentSSBOOffset = 0; - drawSurf_t* currentDrawSurf; - // Must be set by the stage iterator function if needed. These are *not* // automatically cleared by the likes of Tess_End. stageVars_t svars; diff --git a/src/engine/renderer/tr_main.cpp b/src/engine/renderer/tr_main.cpp index 47e938794f..e6befc7ce5 100644 --- a/src/engine/renderer/tr_main.cpp +++ b/src/engine/renderer/tr_main.cpp @@ -1840,7 +1840,7 @@ int R_SpriteFogNum( trRefEntity_t *ent ) R_AddDrawSurf ================= */ -int R_AddDrawSurf( surfaceType_t *surface, shader_t *shader, int lightmapNum, int fogNum, bool bspSurface, int portalNum ) +void R_AddDrawSurf( surfaceType_t *surface, shader_t *shader, int lightmapNum, int fogNum, bool bspSurface, int portalNum ) { // instead of checking for overflow, we just mask the index // so it wraps around @@ -1878,42 +1878,13 @@ int R_AddDrawSurf( surfaceType_t *surface, shader_t *shader, int lightmapNum, in tr.refdef.numDrawSurfs++; - // Portal and sky surfaces are not handled by the material system at all - if ( materialSystem.generatingWorldCommandBuffer && ( shader->isPortal || shader->isSky || shader->autoSpriteMode ) ) { - if ( shader->isSky && std::find( materialSystem.skyShaders.begin(), materialSystem.skyShaders.end(), shader ) - == materialSystem.skyShaders.end() ) { - materialSystem.skyShaders.emplace_back( shader ); - } - - if ( shader->isPortal ) - { - // R_AddWorldSurfaces guarantees not to add surfaces more than once - ASSERT_EQ( - std::find( materialSystem.portalSurfacesTmp.begin(), materialSystem.portalSurfacesTmp.end(), drawSurf ), - materialSystem.portalSurfacesTmp.end() ); - materialSystem.portalSurfacesTmp.emplace_back( drawSurf ); - } - - if ( shader->autoSpriteMode ) { - materialSystem.autospriteSurfaces.push_back( *drawSurf ); - } - - return baseIndex; - } - if ( shader->depthShader != nullptr ) { - const int depthSurfIndex = R_AddDrawSurf( surface, shader->depthShader, 0, 0, bspSurface ); - drawSurf->depthSurface = &tr.refdef.drawSurfs[depthSurfIndex]; - drawSurf->depthSurface->materialSystemSkip = true; + R_AddDrawSurf( surface, shader->depthShader, 0, 0, bspSurface ); } if( !shader->noFog && fogNum >= 1 ) { - const int fogSurfIndex = R_AddDrawSurf( surface, shader->fogShader, 0, fogNum, bspSurface ); - drawSurf->fogSurface = &tr.refdef.drawSurfs[fogSurfIndex]; - drawSurf->fogSurface->materialSystemSkip = true; + R_AddDrawSurf( surface, shader->fogShader, 0, fogNum, bspSurface ); } - - return baseIndex; } static uint32_t currentView = 0; @@ -2005,7 +1976,7 @@ static void R_SortDrawSurfs() break; } - R_MirrorViewBySurface( portalStack[portalStack[currentView].views[i]].drawSurf ); + R_MirrorViewBySurface( &portalStack[portalStack[currentView].views[i]].drawSurf ); } currentView--; } else { diff --git a/src/engine/renderer/tr_scene.cpp b/src/engine/renderer/tr_scene.cpp index 207b7b93b1..4626d9dae0 100644 --- a/src/engine/renderer/tr_scene.cpp +++ b/src/engine/renderer/tr_scene.cpp @@ -652,10 +652,6 @@ void RE_RenderScene( const refdef_t *fd ) R_AddClearBufferCmd(); R_AddSetupLightsCmd(); - if ( glConfig2.usingMaterialSystem && !materialSystem.generatedWorldCommandBuffer ) { - materialSystem.GenerateWorldMaterials(); - } - if ( glConfig2.usingMaterialSystem ) { materialSystem.StartFrame(); } diff --git a/src/engine/renderer/tr_shade.cpp b/src/engine/renderer/tr_shade.cpp index 9ceaef65c6..eb281927c0 100644 --- a/src/engine/renderer/tr_shade.cpp +++ b/src/engine/renderer/tr_shade.cpp @@ -529,8 +529,6 @@ Tess_DrawElements */ void Tess_DrawElements() { - int i; - if ( ( tess.numIndexes == 0 || tess.numVertexes == 0 ) && tess.multiDrawPrimitives == 0 ) { return; @@ -541,24 +539,12 @@ void Tess_DrawElements() { if ( tess.multiDrawPrimitives ) { - if ( !materialSystem.generatingWorldCommandBuffer ) { - glMultiDrawElements( GL_TRIANGLES, tess.multiDrawCounts, GL_INDEX_TYPE, ( const GLvoid** ) tess.multiDrawIndexes, tess.multiDrawPrimitives ); - } + glMultiDrawElements( GL_TRIANGLES, tess.multiDrawCounts, GL_INDEX_TYPE, ( const GLvoid** ) tess.multiDrawIndexes, tess.multiDrawPrimitives ); backEnd.pc.c_multiDrawElements++; backEnd.pc.c_multiDrawPrimitives += tess.multiDrawPrimitives; backEnd.pc.c_vboVertexes += tess.numVertexes; - - for ( i = 0; i < tess.multiDrawPrimitives; i++ ) - { - backEnd.pc.c_multiVboIndexes += tess.multiDrawCounts[ i ]; - backEnd.pc.c_indexes += tess.multiDrawCounts[ i ]; - if ( materialSystem.generatingWorldCommandBuffer ) { - materialSystem.AddDrawCommand( tess.materialID, tess.materialPackID, tess.currentSSBOOffset, - ( GLuint ) tess.multiDrawCounts[i], tess.multiDrawOffsets[i] ); - } - } } else { @@ -568,11 +554,7 @@ void Tess_DrawElements() base = tess.indexBase * sizeof( glIndex_t ); } - if ( materialSystem.generatingWorldCommandBuffer ) { - materialSystem.AddDrawCommand( tess.materialID, tess.materialPackID, tess.currentSSBOOffset, tess.numIndexes, tess.indexBase ); - } else { - glDrawRangeElements( GL_TRIANGLES, 0, tess.numVertexes, tess.numIndexes, GL_INDEX_TYPE, BUFFER_OFFSET( base ) ); - } + glDrawRangeElements( GL_TRIANGLES, 0, tess.numVertexes, tess.numIndexes, GL_INDEX_TYPE, BUFFER_OFFSET( base ) ); backEnd.pc.c_drawElements++; @@ -585,11 +567,7 @@ void Tess_DrawElements() } else { - if ( materialSystem.generatingWorldCommandBuffer ) { - materialSystem.AddDrawCommand( tess.materialID, tess.materialPackID, tess.currentSSBOOffset, tess.numIndexes, tess.indexBase ); - } else { - glDrawElements( GL_TRIANGLES, tess.numIndexes, GL_INDEX_TYPE, tess.indexes ); - } + glDrawElements( GL_TRIANGLES, tess.numIndexes, GL_INDEX_TYPE, tess.indexes ); backEnd.pc.c_drawElements++; @@ -948,7 +926,7 @@ void Render_lightMapping( shaderStage_t *pStage ) lightMode_t lightMode; deluxeMode_t deluxeMode; - SetLightDeluxeMode( &tess, pStage->type, lightMode, deluxeMode ); + SetLightDeluxeMode( &tess, tess.surfaceShader, pStage->type, lightMode, deluxeMode ); // u_Map, u_DeluxeMap image_t *lightmap = SetLightMap( &tess, lightMode ); @@ -2121,7 +2099,7 @@ void Render_liquid( shaderStage_t *pStage ) lightMode_t lightMode; deluxeMode_t deluxeMode; - SetLightDeluxeMode( &tess, pStage->type, lightMode, deluxeMode ); + SetLightDeluxeMode( &tess, tess.surfaceShader, pStage->type, lightMode, deluxeMode ); // choose right shader program gl_liquidShader->SetHeightMapInNormalMap( pStage->hasHeightMapInNormalMap ); @@ -2619,7 +2597,7 @@ void Tess_StageIteratorColor() int stage = 0; for ( shaderStage_t *pStage = tess.surfaceStages; pStage < tess.surfaceLastStage; pStage++ ) { - if ( !RB_EvalExpression( &pStage->ifExp, 1.0 ) && !( materialSystem.generatingWorldCommandBuffer && pStage->useMaterialSystem ) ) + if ( !RB_EvalExpression( &pStage->ifExp, 1.0 ) ) { continue; } @@ -2635,12 +2613,6 @@ void Tess_StageIteratorColor() Tess_ComputeColor( pStage ); Tess_ComputeTexMatrices( pStage ); - if ( materialSystem.generatingWorldCommandBuffer && pStage->useMaterialSystem ) { - tess.currentSSBOOffset = pStage->materialOffset; - tess.materialID = tess.currentDrawSurf->materialIDs[stage]; - tess.materialPackID = tess.currentDrawSurf->materialPackIDs[stage]; - } - pStage->colorRenderer( pStage ); stage++; diff --git a/src/engine/renderer/tr_world.cpp b/src/engine/renderer/tr_world.cpp index 8d3fd19172..43b746845d 100644 --- a/src/engine/renderer/tr_world.cpp +++ b/src/engine/renderer/tr_world.cpp @@ -405,7 +405,7 @@ static void R_RecursiveWorldNode( bspNode_t *node, int planeBits ) do { // if the node wasn't marked as potentially visible, exit - if ( node->visCounts[ tr.visIndex ] != tr.visCounts[ tr.visIndex ] && !materialSystem.generatingWorldCommandBuffer ) + if ( node->visCounts[ tr.visIndex ] != tr.visCounts[ tr.visIndex ] ) { return; }