diff --git a/src/common/rendering/hwrenderer/data/hw_levelmesh.h b/src/common/rendering/hwrenderer/data/hw_levelmesh.h index 572f57443..8510f3f9c 100644 --- a/src/common/rendering/hwrenderer/data/hw_levelmesh.h +++ b/src/common/rendering/hwrenderer/data/hw_levelmesh.h @@ -238,6 +238,13 @@ struct FMaterialState } }; +struct LevelSubmeshDrawRange +{ + int PipelineID; + int Start; + int Count; +}; + class LevelSubmesh { public: @@ -260,6 +267,8 @@ public: std::unique_ptr Collision; + TArray DrawList; + // Lightmap atlas int LMTextureCount = 0; int LMTextureSize = 0; diff --git a/src/common/rendering/hwrenderer/data/hw_meshbuilder.cpp b/src/common/rendering/hwrenderer/data/hw_meshbuilder.cpp index 5c886fb9d..6df23029e 100644 --- a/src/common/rendering/hwrenderer/data/hw_meshbuilder.cpp +++ b/src/common/rendering/hwrenderer/data/hw_meshbuilder.cpp @@ -66,6 +66,7 @@ void MeshBuilder::Apply() state.applyData.AlphaThreshold = mSurfaceUniforms.uAlphaThreshold; state.applyData.DepthFunc = mDepthFunc; state.applyData.FogEnabled = mFogEnabled; + state.applyData.FogColor = (mFogColor & 0xffffff) == 0; state.applyData.BrightmapEnabled = mBrightmapEnabled; state.applyData.TextureClamp = mTextureClamp; state.applyData.TextureMode = mTextureMode; diff --git a/src/common/rendering/hwrenderer/data/hw_meshbuilder.h b/src/common/rendering/hwrenderer/data/hw_meshbuilder.h index 08944ec1f..dbe095e0f 100644 --- a/src/common/rendering/hwrenderer/data/hw_meshbuilder.h +++ b/src/common/rendering/hwrenderer/data/hw_meshbuilder.h @@ -7,24 +7,25 @@ class Mesh; +struct MeshApplyData +{ + FRenderStyle RenderStyle; + int SpecialEffect; + int TextureEnabled; + float AlphaThreshold; + int DepthFunc; + int FogEnabled; + int FogColor; + int BrightmapEnabled; + int TextureClamp; + int TextureMode; + int TextureModeFlags; +}; + class MeshApplyState { public: - struct ApplyData - { - FRenderStyle RenderStyle; - int SpecialEffect; - int TextureEnabled; - float AlphaThreshold; - int DepthFunc; - int FogEnabled; - int BrightmapEnabled; - int TextureClamp; - int TextureMode; - int TextureModeFlags; - }; - - ApplyData applyData; + MeshApplyData applyData; SurfaceUniforms surfaceUniforms; FMaterialState material; VSMatrix textureMatrix; @@ -40,7 +41,7 @@ public: if (material.mOverrideShader != other.material.mOverrideShader) return material.mOverrideShader < other.material.mOverrideShader; - int result = memcmp(&applyData, &other.applyData, sizeof(ApplyData)); + int result = memcmp(&applyData, &other.applyData, sizeof(MeshApplyData)); if (result != 0) return result < 0; diff --git a/src/common/rendering/v_video.h b/src/common/rendering/v_video.h index 98176ed8d..04c8e941e 100644 --- a/src/common/rendering/v_video.h +++ b/src/common/rendering/v_video.h @@ -74,6 +74,7 @@ class FModelRenderer; struct SamplerUniform; struct FVertexBufferAttribute; struct HWViewpointUniforms; +struct MeshApplyData; // // VIDEO @@ -226,6 +227,7 @@ public: virtual void PostProcessScene(bool swscene, int fixedcm, float flash, const std::function &afterBloomDrawEndScene2D) { if (afterBloomDrawEndScene2D) afterBloomDrawEndScene2D(); } + virtual int GetLevelMeshPipelineID(const MeshApplyData& applyData, const SurfaceUniforms& surfaceUniforms, const FMaterialState& material) { return 0; } virtual void DrawLevelMesh(const HWViewpointUniforms& viewpoint) { } void ScaleCoordsFromWindow(int16_t &x, int16_t &y); diff --git a/src/common/rendering/vulkan/accelstructs/vk_raytrace.cpp b/src/common/rendering/vulkan/accelstructs/vk_raytrace.cpp index d75440c2d..6c0578d73 100644 --- a/src/common/rendering/vulkan/accelstructs/vk_raytrace.cpp +++ b/src/common/rendering/vulkan/accelstructs/vk_raytrace.cpp @@ -91,11 +91,6 @@ void VkRaytrace::BeginFrame() } } -int VkRaytrace::GetIndexCount() -{ - return Mesh->StaticMesh->MeshElements.Size(); -} - void VkRaytrace::UploadMeshes(bool dynamicOnly) { TArray locations(2); diff --git a/src/common/rendering/vulkan/accelstructs/vk_raytrace.h b/src/common/rendering/vulkan/accelstructs/vk_raytrace.h index 89b1d0f25..b6be562c7 100644 --- a/src/common/rendering/vulkan/accelstructs/vk_raytrace.h +++ b/src/common/rendering/vulkan/accelstructs/vk_raytrace.h @@ -77,7 +77,7 @@ public: VulkanBuffer* GetSurfaceUniformsBuffer() { return SurfaceUniformsBuffer.get(); } VulkanBuffer* GetPortalBuffer() { return PortalBuffer.get(); } - int GetIndexCount(); + LevelMesh* GetMesh() { return Mesh; } private: struct BLAS diff --git a/src/common/rendering/vulkan/vk_renderdevice.cpp b/src/common/rendering/vulkan/vk_renderdevice.cpp index 3741944c0..431fa484d 100644 --- a/src/common/rendering/vulkan/vk_renderdevice.cpp +++ b/src/common/rendering/vulkan/vk_renderdevice.cpp @@ -38,6 +38,7 @@ #include "hw_cvars.h" #include "hw_skydome.h" #include "flatvertices.h" +#include "hw_meshbuilder.h" #include "vk_renderdevice.h" #include "vulkan/vk_renderstate.h" @@ -70,6 +71,7 @@ FString JitCaptureStackTrace(int framesToSkip, bool includeNativeFrames, int max EXTERN_CVAR(Int, gl_tonemap) EXTERN_CVAR(Int, screenblocks) EXTERN_CVAR(Bool, cl_capfps) +EXTERN_CVAR(Bool, r_skipmats) // Physical device info static std::vector SupportedDevices; @@ -611,6 +613,120 @@ int VulkanRenderDevice::GetBindlessTextureIndex(FMaterial* material, int clampmo return static_cast(material)->GetBindlessIndex(materialState); } +int VulkanRenderDevice::GetLevelMeshPipelineID(const MeshApplyData& applyData, const SurfaceUniforms& surfaceUniforms, const FMaterialState& material) +{ + if (levelVertexFormatIndex == -1) + { + static const std::vector format = + { + { 0, VATTR_VERTEX, VFmt_Float4, (int)myoffsetof(FFlatVertex, x) }, + { 0, VATTR_TEXCOORD, VFmt_Float2, (int)myoffsetof(FFlatVertex, u) }, + { 0, VATTR_LIGHTMAP, VFmt_Float2, (int)myoffsetof(FFlatVertex, lu) }, + { 1, VATTR_UNIFORM_INDEXES, VFmt_Int, 0 } + }; + levelVertexFormatIndex = GetRenderPassManager()->GetVertexFormat({ sizeof(FFlatVertex), sizeof(int32_t) }, format); + } + + VkPipelineKey pipelineKey; + pipelineKey.DrawType = DT_Triangles; + pipelineKey.VertexFormat = levelVertexFormatIndex; + pipelineKey.RenderStyle = applyData.RenderStyle; + pipelineKey.DepthTest = true; // mDepthTest; + pipelineKey.DepthWrite = true; // mDepthTest && mDepthWrite; + pipelineKey.DepthFunc = applyData.DepthFunc; + pipelineKey.DepthClamp = false; // mDepthClamp; + pipelineKey.DepthBias = false; // !(mBias.mFactor == 0 && mBias.mUnits == 0); + pipelineKey.StencilTest = false; // mStencilTest; + pipelineKey.StencilPassOp = 0; // mStencilOp; + pipelineKey.ColorMask = 15; // mColorMask; + pipelineKey.CullMode = 0; // mCullMode; + pipelineKey.NumTextureLayers = material.mMaterial ? material.mMaterial->NumLayers() : 0; + pipelineKey.NumTextureLayers = max(pipelineKey.NumTextureLayers, SHADER_MIN_REQUIRED_TEXTURE_LAYERS);// Always force minimum 8 textures as the shader requires it + if (applyData.SpecialEffect > EFF_NONE) + { + pipelineKey.ShaderKey.SpecialEffect = applyData.SpecialEffect; + pipelineKey.ShaderKey.EffectState = 0; + pipelineKey.ShaderKey.AlphaTest = false; + } + else + { + int effectState = material.mOverrideShader >= 0 ? material.mOverrideShader : (material.mMaterial ? material.mMaterial->GetShaderIndex() : 0); + pipelineKey.ShaderKey.SpecialEffect = EFF_NONE; + pipelineKey.ShaderKey.EffectState = applyData.TextureEnabled ? effectState : SHADER_NoTexture; + if (r_skipmats && pipelineKey.ShaderKey.EffectState >= 3 && pipelineKey.ShaderKey.EffectState <= 4) + pipelineKey.ShaderKey.EffectState = 0; + pipelineKey.ShaderKey.AlphaTest = surfaceUniforms.uAlphaThreshold >= 0.f; + } + + int tempTM = (material.mMaterial && material.mMaterial->Source()->isHardwareCanvas()) ? TM_OPAQUE : TM_NORMAL; + int f = applyData.TextureModeFlags; + if (!applyData.BrightmapEnabled) f &= ~(TEXF_Brightmap | TEXF_Glowmap); + if (applyData.TextureClamp) f |= TEXF_ClampY; + int uTextureMode = (applyData.TextureMode == TM_NORMAL && tempTM == TM_OPAQUE ? TM_OPAQUE : applyData.TextureMode) | f; + + pipelineKey.ShaderKey.TextureMode = uTextureMode & 0xffff; + pipelineKey.ShaderKey.ClampY = (uTextureMode & TEXF_ClampY) != 0; + pipelineKey.ShaderKey.Brightmap = (uTextureMode & TEXF_Brightmap) != 0; + pipelineKey.ShaderKey.Detailmap = (uTextureMode & TEXF_Detailmap) != 0; + pipelineKey.ShaderKey.Glowmap = (uTextureMode & TEXF_Glowmap) != 0; + + // The way GZDoom handles state is just plain insanity! + int fogset = 0; + if (applyData.FogEnabled) + { + if (applyData.FogEnabled == 2) + { + fogset = -3; // 2D rendering with 'foggy' overlay. + } + else if (applyData.FogColor) + { + fogset = gl_fogmode; + } + else + { + fogset = -gl_fogmode; + } + } + pipelineKey.ShaderKey.Simple2D = (fogset == -3); + pipelineKey.ShaderKey.FogBeforeLights = (fogset > 0); + pipelineKey.ShaderKey.FogAfterLights = (fogset < 0); + pipelineKey.ShaderKey.FogRadial = (fogset < -1 || fogset > 1); + pipelineKey.ShaderKey.SWLightRadial = (gl_fogmode == 2); + pipelineKey.ShaderKey.SWLightBanded = false; // gl_bandedswlight; + + float lightlevel = surfaceUniforms.uLightLevel; + if (lightlevel < 0.0) + { + pipelineKey.ShaderKey.LightMode = 0; // Default + } + else + { + /*if (mLightMode == 5) + pipelineKey.ShaderKey.LightMode = 3; // Build + else if (mLightMode == 16) + pipelineKey.ShaderKey.LightMode = 2; // Vanilla + else*/ + pipelineKey.ShaderKey.LightMode = 1; // Software + } + + pipelineKey.ShaderKey.UseShadowmap = gl_light_shadows == 1; + pipelineKey.ShaderKey.UseRaytrace = gl_light_shadows == 2; + + pipelineKey.ShaderKey.GBufferPass = false; + pipelineKey.ShaderKey.UseLevelMesh = true; + + for (unsigned int i = 0, count = levelMeshPipelineKeys.Size(); i < count; i++) + { + if (levelMeshPipelineKeys[i] == pipelineKey) + { + return i; + } + } + + levelMeshPipelineKeys.Push(pipelineKey); + return levelMeshPipelineKeys.Size() - 1; +} + void VulkanRenderDevice::DrawLevelMesh(const HWViewpointUniforms& viewpoint) { auto cmdbuffer = GetCommands()->GetDrawCommands(); @@ -658,48 +774,11 @@ void VulkanRenderDevice::DrawLevelMesh(const HWViewpointUniforms& viewpoint) cmdbuffer->setStencilReference(VK_STENCIL_FRONT_AND_BACK, 0); cmdbuffer->setDepthBias(0.0f, 0.0f, 0.0f); - static const std::vector format = - { - { 0, VATTR_VERTEX, VFmt_Float4, (int)myoffsetof(FFlatVertex, x) }, - { 0, VATTR_TEXCOORD, VFmt_Float2, (int)myoffsetof(FFlatVertex, u) }, - { 0, VATTR_LIGHTMAP, VFmt_Float2, (int)myoffsetof(FFlatVertex, lu) }, - { 1, VATTR_UNIFORM_INDEXES, VFmt_Int, 0 } - }; - int vertexFormatIndex = GetRenderPassManager()->GetVertexFormat({ sizeof(FFlatVertex), sizeof(int32_t) }, format); VkBuffer vertexBuffers[2] = { GetRaytrace()->GetVertexBuffer()->buffer, GetRaytrace()->GetUniformIndexBuffer()->buffer }; VkDeviceSize vertexBufferOffsets[] = { 0, 0 }; cmdbuffer->bindVertexBuffers(0, 2, vertexBuffers, vertexBufferOffsets); cmdbuffer->bindIndexBuffer(GetRaytrace()->GetIndexBuffer()->buffer, 0, VK_INDEX_TYPE_UINT32); - VkPipelineKey pipelineKey; - pipelineKey.DrawType = DT_Triangles; - pipelineKey.VertexFormat = vertexFormatIndex; - pipelineKey.RenderStyle = DefaultRenderStyle(); - pipelineKey.DepthTest = true; - pipelineKey.DepthWrite = true; - pipelineKey.DepthFunc = DF_Less; - pipelineKey.DepthClamp = false; - pipelineKey.DepthBias = false; - pipelineKey.StencilTest = false; - pipelineKey.StencilPassOp = 0; - pipelineKey.ColorMask = 15; - pipelineKey.CullMode = 0; - pipelineKey.NumTextureLayers = 0; - pipelineKey.NumTextureLayers = max(pipelineKey.NumTextureLayers, SHADER_MIN_REQUIRED_TEXTURE_LAYERS);// Always force minimum 8 textures as the shader requires it - pipelineKey.ShaderKey.SpecialEffect = EFF_NONE; - pipelineKey.ShaderKey.EffectState = SHADER_Default; - pipelineKey.ShaderKey.AlphaTest = false; - pipelineKey.ShaderKey.SWLightRadial = true; - pipelineKey.ShaderKey.LightMode = 1; // Software - pipelineKey.ShaderKey.UseShadowmap = gl_light_shadows == 1; - pipelineKey.ShaderKey.UseRaytrace = gl_light_shadows == 2; - pipelineKey.ShaderKey.GBufferPass = key.DrawBuffers > 1; - pipelineKey.ShaderKey.UseLevelMesh = true; - - VulkanPipelineLayout* layout = GetRenderPassManager()->GetPipelineLayout(pipelineKey.NumTextureLayers, pipelineKey.ShaderKey.UseLevelMesh); - - cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, passSetup->GetPipeline(pipelineKey)); - auto rsbuffers = GetBufferManager()->GetRSBuffers(); memcpy(((char*)rsbuffers->Viewpoint.Data) + rsbuffers->Viewpoint.UploadIndex * rsbuffers->Viewpoint.BlockAlign, &viewpoint, sizeof(HWViewpointUniforms)); int viewpointIndex = rsbuffers->Viewpoint.UploadIndex++; @@ -710,21 +789,29 @@ void VulkanRenderDevice::DrawLevelMesh(const HWViewpointUniforms& viewpoint) matrices.TextureMatrix.loadIdentity(); rsbuffers->MatrixBuffer->Write(matrices); - uint32_t viewpointOffset = viewpointIndex * rsbuffers->Viewpoint.BlockAlign; - uint32_t matrixOffset = rsbuffers->MatrixBuffer->Offset(); - uint32_t lightsOffset = 0; - uint32_t offsets[] = { viewpointOffset, matrixOffset, lightsOffset }; - cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptors->GetFixedSet()); - cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 1, descriptors->GetLevelMeshSet(), 3, offsets); - cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 2, descriptors->GetBindlessSet()); + auto submesh = GetRaytrace()->GetMesh()->StaticMesh.get(); + for (LevelSubmeshDrawRange& range : submesh->DrawList) + { + auto& pipelineKey = levelMeshPipelineKeys[range.PipelineID]; + VulkanPipelineLayout* layout = GetRenderPassManager()->GetPipelineLayout(pipelineKey.NumTextureLayers, pipelineKey.ShaderKey.UseLevelMesh); + cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, passSetup->GetPipeline(pipelineKey)); - PushConstants pushConstants = {}; - pushConstants.uDataIndex = 0; - pushConstants.uLightIndex = -1; - pushConstants.uBoneIndexBase = -1; - cmdbuffer->pushConstants(layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, (uint32_t)sizeof(PushConstants), &pushConstants); + uint32_t viewpointOffset = viewpointIndex * rsbuffers->Viewpoint.BlockAlign; + uint32_t matrixOffset = rsbuffers->MatrixBuffer->Offset(); + uint32_t lightsOffset = 0; + uint32_t offsets[] = { viewpointOffset, matrixOffset, lightsOffset }; + cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptors->GetFixedSet()); + cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 1, descriptors->GetLevelMeshSet(), 3, offsets); + cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 2, descriptors->GetBindlessSet()); - cmdbuffer->drawIndexed(GetRaytrace()->GetIndexCount(), 1, 0, 0, 0); + PushConstants pushConstants = {}; + pushConstants.uDataIndex = 0; + pushConstants.uLightIndex = -1; + pushConstants.uBoneIndexBase = -1; + cmdbuffer->pushConstants(layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, (uint32_t)sizeof(PushConstants), &pushConstants); + + cmdbuffer->drawIndexed(range.Count, 1, range.Start, 0, 0); + } cmdbuffer->endRenderPass(); } diff --git a/src/common/rendering/vulkan/vk_renderdevice.h b/src/common/rendering/vulkan/vk_renderdevice.h index ee8db667b..67414ec5c 100644 --- a/src/common/rendering/vulkan/vk_renderdevice.h +++ b/src/common/rendering/vulkan/vk_renderdevice.h @@ -22,6 +22,7 @@ class VkHardwareDataBuffer; class VkHardwareTexture; class VkRenderBuffers; class VkPostprocess; +class VkPipelineKey; class VulkanRenderDevice : public SystemBaseFrameBuffer { @@ -89,6 +90,7 @@ public: int GetBindlessTextureIndex(FMaterial* material, int clampmode, int translation) override; + int GetLevelMeshPipelineID(const MeshApplyData& applyData, const SurfaceUniforms& surfaceUniforms, const FMaterialState& material) override; void DrawLevelMesh(const HWViewpointUniforms& viewpoint) override; private: @@ -118,6 +120,9 @@ private: LevelMesh* levelMesh = nullptr; bool levelMeshChanged = true; + + int levelVertexFormatIndex = -1; + TArray levelMeshPipelineKeys; }; class CVulkanError : public CEngineError diff --git a/src/rendering/hwrenderer/doom_levelsubmesh.cpp b/src/rendering/hwrenderer/doom_levelsubmesh.cpp index d95b074e0..2734b3206 100644 --- a/src/rendering/hwrenderer/doom_levelsubmesh.cpp +++ b/src/rendering/hwrenderer/doom_levelsubmesh.cpp @@ -112,20 +112,31 @@ void DoomLevelSubmesh::CreateStaticSurfaces(FLevelLocals& doomMap) // Part 1: solid geometry. This is set up so that there are no transparent parts state.SetDepthFunc(DF_Less); - state.AlphaFunc(Alpha_GEqual, 0.f); state.ClearDepthBias(); state.EnableTexture(gl_texture); state.EnableBrightmap(true); for (HWWall& wallpart : result.list) { + if (wallpart.texture && wallpart.texture->isMasked()) + { + state.AlphaFunc(Alpha_GEqual, gl_mask_threshold); + } + else + { + state.AlphaFunc(Alpha_GEqual, 0.f); + } + wallpart.DrawWall(&disp, state, false); + int pipelineID = 0; int startVertIndex = MeshVertices.Size(); for (auto& it : state.mSortedLists) { const MeshApplyState& applyState = it.first; + pipelineID = screen->GetLevelMeshPipelineID(applyState.applyData, applyState.surfaceUniforms, applyState.material); + int uniformsIndex = MeshSurfaceUniforms.Size(); MeshSurfaceUniforms.Push(applyState.surfaceUniforms); MeshSurfaceMaterials.Push(applyState.material); @@ -154,6 +165,7 @@ void DoomLevelSubmesh::CreateStaticSurfaces(FLevelLocals& doomMap) surf.numVerts = MeshVertices.Size() - startVertIndex; surf.plane = ToPlane(MeshVertices[startVertIndex].fPos(), MeshVertices[startVertIndex + 1].fPos(), MeshVertices[startVertIndex + 2].fPos(), MeshVertices[startVertIndex + 3].fPos()); surf.texture = wallpart.texture; + surf.PipelineID = pipelineID; Surfaces.Push(surf); } } @@ -204,64 +216,80 @@ void DoomLevelSubmesh::CreateDynamicSurfaces(FLevelLocals& doomMap) void DoomLevelSubmesh::CreateIndexes() { + // Order indexes by pipeline + std::unordered_map> pipelineSurfaces; for (size_t i = 0; i < Surfaces.Size(); i++) { - DoomLevelMeshSurface& s = Surfaces[i]; - int numVerts = s.numVerts; - unsigned int pos = s.startVertIndex; - FFlatVertex* verts = &MeshVertices[pos]; + DoomLevelMeshSurface* s = &Surfaces[i]; + pipelineSurfaces[s->PipelineID].Push(i); + } - s.Vertices = verts; - s.startElementIndex = MeshElements.Size(); - s.numElements = 0; - - if (s.Type == ST_CEILING) + for (const auto& it : pipelineSurfaces) + { + LevelSubmeshDrawRange range; + range.PipelineID = it.first; + range.Start = MeshElements.Size(); + for (unsigned int i : it.second) { - for (int j = 2; j < numVerts; j++) + DoomLevelMeshSurface& s = Surfaces[i]; + int numVerts = s.numVerts; + unsigned int pos = s.startVertIndex; + FFlatVertex* verts = &MeshVertices[pos]; + + s.Vertices = verts; + s.startElementIndex = MeshElements.Size(); + s.numElements = 0; + + if (s.Type == ST_CEILING) { - if (!IsDegenerate(verts[0].fPos(), verts[j - 1].fPos(), verts[j].fPos())) + for (int j = 2; j < numVerts; j++) { - MeshElements.Push(pos); - MeshElements.Push(pos + j - 1); - MeshElements.Push(pos + j); + if (!IsDegenerate(verts[0].fPos(), verts[j - 1].fPos(), verts[j].fPos())) + { + MeshElements.Push(pos); + MeshElements.Push(pos + j - 1); + MeshElements.Push(pos + j); + MeshSurfaceIndexes.Push((int)i); + s.numElements += 3; + } + } + } + else if (s.Type == ST_FLOOR) + { + for (int j = 2; j < numVerts; j++) + { + if (!IsDegenerate(verts[0].fPos(), verts[j - 1].fPos(), verts[j].fPos())) + { + MeshElements.Push(pos + j); + MeshElements.Push(pos + j - 1); + MeshElements.Push(pos); + MeshSurfaceIndexes.Push((int)i); + s.numElements += 3; + } + } + } + else if (s.Type == ST_MIDDLESIDE || s.Type == ST_UPPERSIDE || s.Type == ST_LOWERSIDE) + { + if (!IsDegenerate(verts[0].fPos(), verts[2].fPos(), verts[1].fPos())) + { + MeshElements.Push(pos + 0); + MeshElements.Push(pos + 1); + MeshElements.Push(pos + 2); + MeshSurfaceIndexes.Push((int)i); + s.numElements += 3; + } + if (!IsDegenerate(verts[0].fPos(), verts[2].fPos(), verts[3].fPos())) + { + MeshElements.Push(pos + 0); + MeshElements.Push(pos + 2); + MeshElements.Push(pos + 3); MeshSurfaceIndexes.Push((int)i); s.numElements += 3; } } } - else if (s.Type == ST_FLOOR) - { - for (int j = 2; j < numVerts; j++) - { - if (!IsDegenerate(verts[0].fPos(), verts[j - 1].fPos(), verts[j].fPos())) - { - MeshElements.Push(pos + j); - MeshElements.Push(pos + j - 1); - MeshElements.Push(pos); - MeshSurfaceIndexes.Push((int)i); - s.numElements += 3; - } - } - } - else if (s.Type == ST_MIDDLESIDE || s.Type == ST_UPPERSIDE || s.Type == ST_LOWERSIDE) - { - if (!IsDegenerate(verts[0].fPos(), verts[2].fPos(), verts[1].fPos())) - { - MeshElements.Push(pos + 0); - MeshElements.Push(pos + 1); - MeshElements.Push(pos + 2); - MeshSurfaceIndexes.Push((int)i); - s.numElements += 3; - } - if (!IsDegenerate(verts[0].fPos(), verts[2].fPos(), verts[3].fPos())) - { - MeshElements.Push(pos + 0); - MeshElements.Push(pos + 2); - MeshElements.Push(pos + 3); - MeshSurfaceIndexes.Push((int)i); - s.numElements += 3; - } - } + range.Count = MeshElements.Size() - range.Start; + DrawList.Push(range); } } diff --git a/src/rendering/hwrenderer/doom_levelsubmesh.h b/src/rendering/hwrenderer/doom_levelsubmesh.h index ea840d057..93792b783 100644 --- a/src/rendering/hwrenderer/doom_levelsubmesh.h +++ b/src/rendering/hwrenderer/doom_levelsubmesh.h @@ -34,6 +34,7 @@ struct DoomLevelMeshSurface : public LevelMeshSurface sector_t* ControlSector = nullptr; FFlatVertex* Vertices = nullptr; + int PipelineID = 0; }; class DoomLevelSubmesh : public LevelSubmesh