diff --git a/data/base/shaders/tcmask_instanced.frag b/data/base/shaders/tcmask_instanced.frag index 3e1cdfe6ed8..873941f5d96 100644 --- a/data/base/shaders/tcmask_instanced.frag +++ b/data/base/shaders/tcmask_instanced.frag @@ -376,7 +376,9 @@ void main() 0., 1., 0., 0., 0., 1. ); - light += iterateOverAllPointLights(clipSpaceCoord, fragPos, -N, normalize(halfVec - lightDir), diffuse, specularMapValue, identityMat); + // Normals are in view space, we need to get back to world space + vec3 worldSpaceNormal = -(inverse(ViewMatrix) * vec4(N, 0.f)).xyz; + light += iterateOverAllPointLights(clipSpaceCoord, fragPos, worldSpaceNormal, normalize(halfVec - lightDir), diffuse, specularMapValue, identityMat); #endif light.rgb *= visibility; diff --git a/data/base/shaders/vk/tcmask_instanced.frag b/data/base/shaders/vk/tcmask_instanced.frag index f7d0923b87a..d5258a8fe48 100644 --- a/data/base/shaders/vk/tcmask_instanced.frag +++ b/data/base/shaders/vk/tcmask_instanced.frag @@ -344,7 +344,9 @@ void main() 0., 1., 0., 0., 0., 1. ); - light += iterateOverAllPointLights(clipSpaceCoord, fragPos, -N, normalize(halfVec - lightDir), diffuse, specularMapValue, identityMat); + // Normals are in view space, we need to get back to world space + vec3 worldSpaceNormal = -(inverse(ViewMatrix) * vec4(N, 0.f)).xyz; + light += iterateOverAllPointLights(clipSpaceCoord, fragPos, worldSpaceNormal, normalize(halfVec - lightDir), diffuse, specularMapValue, identityMat); } light.rgb *= visibility; diff --git a/lib/ivis_opengl/piedraw.cpp b/lib/ivis_opengl/piedraw.cpp index aa33a00bf77..69813ae572f 100644 --- a/lib/ivis_opengl/piedraw.cpp +++ b/lib/ivis_opengl/piedraw.cpp @@ -957,9 +957,10 @@ class InstancedMeshRenderer { ShadowCastingShapes = 0x1, TranslucentShapes = 0x2, - OldShadows = 0x4 + AdditiveShapes = 0x4, + OldShadows = 0x8 }; - static constexpr int DrawParts_All = DrawParts::ShadowCastingShapes | DrawParts::TranslucentShapes; + static constexpr int DrawParts_All = DrawParts::ShadowCastingShapes | DrawParts::TranslucentShapes | DrawParts::AdditiveShapes; // Draws all queued meshes, given a projection + view matrix bool DrawAll(uint64_t currentGameFrame, const glm::mat4 &projectionMatrix, const glm::mat4 &viewMatrix, const ShadowCascadesInfo& shadowMVPMatrix, int drawParts = DrawParts_All, bool depthPass = false); @@ -983,8 +984,10 @@ class InstancedMeshRenderer typedef templatedState MeshInstanceKey; std::unordered_map> instanceMeshes; std::unordered_map> instanceTranslucentMeshes; + std::unordered_map> instanceAdditiveMeshes; size_t instancesCount = 0; size_t translucentInstancesCount = 0; + size_t additiveInstancesCount = 0; std::vector tshapes; std::vector shapes; @@ -1011,6 +1014,7 @@ class InstancedMeshRenderer }; std::vector finalizedDrawCalls; size_t startIdxTranslucentDrawCalls = 0; + size_t startIdxAdditiveDrawCalls = 0; }; bool InstancedMeshRenderer::initialize() @@ -1036,8 +1040,10 @@ void InstancedMeshRenderer::clear() { instanceMeshes.clear(); instanceTranslucentMeshes.clear(); + instanceAdditiveMeshes.clear(); instancesCount = 0; translucentInstancesCount = 0; + additiveInstancesCount = 0; tshapes.clear(); shapes.clear(); lightmapTexture = nullptr; @@ -1104,7 +1110,19 @@ bool InstancedMeshRenderer::Draw3DShape(iIMDShape *shape, int frame, PIELIGHT te tshape.modelMatrix = glm::translate(tshape.modelMatrix, glm::vec3(1.0f, (-shape->max.y * (pie_RAISE_SCALE - pieFlagData)) * (1.0f / pie_RAISE_SCALE), 1.0f)); } - if (pieFlag & (pie_ADDITIVE | pie_TRANSLUCENT | pie_PREMULTIPLIED)) + if (pieFlag & (pie_ADDITIVE | pie_PREMULTIPLIED)) + { + if (useInstancedRendering) + { + instanceAdditiveMeshes[currentState].push_back(tshape); + } + else + { + tshapes.push_back(tshape); + } + ++additiveInstancesCount; + } + else if (pieFlag & pie_TRANSLUCENT) { if (useInstancedRendering) { @@ -1328,12 +1346,12 @@ bool InstancedMeshRenderer::FinalizeInstances() instancesData.clear(); finalizedDrawCalls.clear(); - if (instancesCount + translucentInstancesCount == 0) + if (instancesCount + translucentInstancesCount + additiveInstancesCount == 0) { return true; } - instancesData.reserve(instancesCount + translucentInstancesCount); + instancesData.reserve(instancesCount + translucentInstancesCount + additiveInstancesCount); for (const auto& mesh : instanceMeshes) { @@ -1359,6 +1377,19 @@ bool InstancedMeshRenderer::FinalizeInstances() finalizedDrawCalls.emplace_back(mesh.first, meshInstances.size(), startingIdxInInstancesBuffer); } + startIdxAdditiveDrawCalls = finalizedDrawCalls.size(); + + for (const auto& mesh : instanceAdditiveMeshes) + { + const auto& meshInstances = mesh.second; + size_t startingIdxInInstancesBuffer = instancesData.size(); + for (const auto& instance : meshInstances) + { + instancesData.push_back(GenerateInstanceData(instance.frame, instance.colour, instance.teamcolour, instance.flag, instance.flag_data, instance.modelMatrix, instance.stretch)); + } + finalizedDrawCalls.emplace_back(mesh.first, meshInstances.size(), startingIdxInInstancesBuffer); + } + // Upload buffer ++currInstanceBufferIdx; if (currInstanceBufferIdx >= instanceDataBuffers.size()) @@ -1613,9 +1644,9 @@ void InstancedMeshRenderer::Draw3DShapes_Instanced(uint64_t currentGameFrame, Sh if ((drawParts & DrawParts::TranslucentShapes) == DrawParts::TranslucentShapes) { - // Draw translucent models last + // Draw translucent models next gfx_api::context::get().debugStringMarker("Remaining passes - translucent models"); - for (size_t i = startIdxTranslucentDrawCalls; i < finalizedDrawCalls.size(); ++i) + for (size_t i = startIdxTranslucentDrawCalls; i < startIdxAdditiveDrawCalls; ++i) { const auto& call = finalizedDrawCalls[i]; const iIMDShape * shape = call.state.shape; @@ -1629,6 +1660,24 @@ void InstancedMeshRenderer::Draw3DShapes_Instanced(uint64_t currentGameFrame, Sh } } + if ((drawParts & DrawParts::AdditiveShapes) == DrawParts::AdditiveShapes) + { + // Draw additive models last + gfx_api::context::get().debugStringMarker("Remaining passes - additive models"); + for (size_t i = startIdxAdditiveDrawCalls; i < finalizedDrawCalls.size(); ++i) + { + const auto& call = finalizedDrawCalls[i]; + const iIMDShape * shape = call.state.shape; + size_t instanceBufferOffset = static_cast(sizeof(gfx_api::Draw3DShapePerInstanceInterleavedData) * call.startingIdxInInstancesBuffer); + pie_Draw3DShape2_Instanced(perFrameUniformsShaderOnce, globalUniforms, shape, call.state.pieFlag, instanceDataBuffers[currInstanceBufferIdx], instanceBufferOffset, call.instance_count, depthPass, lightmapTexture); + } + if (startIdxAdditiveDrawCalls < finalizedDrawCalls.size()) + { + // unbind last index buffer bound inside pie_Draw3DShape2 + gfx_api::context::get().unbind_index_buffer(*((finalizedDrawCalls.back().state.shape)->buffers[VBO_INDEX])); + } + } + if (drawParts != 0) { gfx_api::context::get().disable_all_vertex_buffers();