mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 23:02:08 +00:00
Upload acceleration structures for the level mesh
This commit is contained in:
parent
bf1732904f
commit
97073410c4
12 changed files with 802 additions and 0 deletions
|
@ -803,6 +803,7 @@ set (VULKAN_SOURCES
|
|||
common/rendering/vulkan/renderer/vk_streambuffer.cpp
|
||||
common/rendering/vulkan/renderer/vk_postprocess.cpp
|
||||
common/rendering/vulkan/renderer/vk_renderbuffers.cpp
|
||||
common/rendering/vulkan/renderer/vk_raytrace.cpp
|
||||
common/rendering/vulkan/shaders/vk_shader.cpp
|
||||
common/rendering/vulkan/textures/vk_samplers.cpp
|
||||
common/rendering/vulkan/textures/vk_hwtexture.cpp
|
||||
|
@ -961,6 +962,7 @@ set (PCH_SOURCES
|
|||
rendering/hwrenderer/hw_entrypoint.cpp
|
||||
rendering/hwrenderer/hw_vertexbuilder.cpp
|
||||
rendering/hwrenderer/doom_aabbtree.cpp
|
||||
rendering/hwrenderer/doom_levelmesh.cpp
|
||||
rendering/hwrenderer/hw_models.cpp
|
||||
rendering/hwrenderer/hw_precache.cpp
|
||||
rendering/hwrenderer/scene/hw_lighting.cpp
|
||||
|
|
21
src/common/rendering/hwrenderer/data/hw_levelmesh.h
Normal file
21
src/common/rendering/hwrenderer/data/hw_levelmesh.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "tarray.h"
|
||||
#include "vectors.h"
|
||||
|
||||
namespace hwrenderer
|
||||
{
|
||||
|
||||
class LevelMesh
|
||||
{
|
||||
public:
|
||||
virtual ~LevelMesh() = default;
|
||||
|
||||
TArray<FVector3> MeshVertices;
|
||||
TArray<int> MeshUVIndex;
|
||||
TArray<unsigned int> MeshElements;
|
||||
TArray<int> MeshSurfaces;
|
||||
};
|
||||
|
||||
} // namespace
|
|
@ -43,6 +43,7 @@
|
|||
#include "v_2ddrawer.h"
|
||||
#include "intrect.h"
|
||||
#include "hw_shadowmap.h"
|
||||
#include "hw_levelmesh.h"
|
||||
#include "buffers.h"
|
||||
|
||||
|
||||
|
@ -164,6 +165,7 @@ public:
|
|||
{
|
||||
mShadowMap.SetAABBTree(tree);
|
||||
}
|
||||
virtual void SetLevelMesh(hwrenderer::LevelMesh *mesh) { }
|
||||
bool allowSSBO()
|
||||
{
|
||||
#ifndef HW_BLOCK_SSBO
|
||||
|
|
285
src/common/rendering/vulkan/renderer/vk_raytrace.cpp
Normal file
285
src/common/rendering/vulkan/renderer/vk_raytrace.cpp
Normal file
|
@ -0,0 +1,285 @@
|
|||
/*
|
||||
** Vulkan backend
|
||||
** Copyright (c) 2016-2020 Magnus Norddahl
|
||||
**
|
||||
** This software is provided 'as-is', without any express or implied
|
||||
** warranty. In no event will the authors be held liable for any damages
|
||||
** arising from the use of this software.
|
||||
**
|
||||
** Permission is granted to anyone to use this software for any purpose,
|
||||
** including commercial applications, and to alter it and redistribute it
|
||||
** freely, subject to the following restrictions:
|
||||
**
|
||||
** 1. The origin of this software must not be misrepresented; you must not
|
||||
** claim that you wrote the original software. If you use this software
|
||||
** in a product, an acknowledgment in the product documentation would be
|
||||
** appreciated but is not required.
|
||||
** 2. Altered source versions must be plainly marked as such, and must not be
|
||||
** misrepresented as being the original software.
|
||||
** 3. This notice may not be removed or altered from any source distribution.
|
||||
**
|
||||
*/
|
||||
|
||||
#include "vk_raytrace.h"
|
||||
#include "vulkan/system/vk_builders.h"
|
||||
#include "vulkan/system/vk_framebuffer.h"
|
||||
#include "doom_levelmesh.h"
|
||||
|
||||
void VkRaytrace::SetLevelMesh(hwrenderer::LevelMesh* mesh)
|
||||
{
|
||||
if (mesh != Mesh)
|
||||
{
|
||||
Reset();
|
||||
Mesh = mesh;
|
||||
if (Mesh)
|
||||
{
|
||||
if (GetVulkanFrameBuffer()->device->SupportsDeviceExtension(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME) && GetVulkanFrameBuffer()->device->SupportsDeviceExtension(VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME))
|
||||
{
|
||||
CreateVulkanObjects();
|
||||
}
|
||||
else
|
||||
{
|
||||
Printf("This vulkan device does not support ray tracing.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VkRaytrace::Reset()
|
||||
{
|
||||
vertexBuffer.reset();
|
||||
indexBuffer.reset();
|
||||
transferBuffer.reset();
|
||||
|
||||
blScratchBuffer.reset();
|
||||
blAccelStructBuffer.reset();
|
||||
blAccelStruct.reset();
|
||||
|
||||
tlTransferBuffer.reset();
|
||||
tlScratchBuffer.reset();
|
||||
tlInstanceBuffer.reset();
|
||||
tlAccelStructBuffer.reset();
|
||||
tlAccelStruct.reset();
|
||||
}
|
||||
|
||||
void VkRaytrace::CreateVulkanObjects()
|
||||
{
|
||||
CreateVertexAndIndexBuffers();
|
||||
CreateBottomLevelAccelerationStructure();
|
||||
CreateTopLevelAccelerationStructure();
|
||||
|
||||
//CreateShaders();
|
||||
//CreatePipeline();
|
||||
//CreateDescriptorSet();
|
||||
|
||||
PipelineBarrier finishbuildbarrier;
|
||||
finishbuildbarrier.addMemory(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR);
|
||||
finishbuildbarrier.execute(GetVulkanFrameBuffer()->GetTransferCommands(), VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR);
|
||||
}
|
||||
|
||||
void VkRaytrace::CreateVertexAndIndexBuffers()
|
||||
{
|
||||
size_t vertexbuffersize = (size_t)Mesh->MeshVertices.Size() * sizeof(FVector3);
|
||||
size_t indexbuffersize = (size_t)Mesh->MeshElements.Size() * sizeof(uint32_t);
|
||||
size_t transferbuffersize = vertexbuffersize + indexbuffersize;
|
||||
size_t vertexoffset = 0;
|
||||
size_t indexoffset = vertexoffset + vertexbuffersize;
|
||||
|
||||
BufferBuilder vbuilder;
|
||||
vbuilder.setUsage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
vbuilder.setSize(vertexbuffersize);
|
||||
vertexBuffer = vbuilder.create(GetVulkanFrameBuffer()->device);
|
||||
vertexBuffer->SetDebugName("vertexBuffer");
|
||||
|
||||
BufferBuilder ibuilder;
|
||||
ibuilder.setUsage(VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
ibuilder.setSize(indexbuffersize);
|
||||
indexBuffer = ibuilder.create(GetVulkanFrameBuffer()->device);
|
||||
indexBuffer->SetDebugName("indexBuffer");
|
||||
|
||||
BufferBuilder tbuilder;
|
||||
tbuilder.setUsage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
|
||||
tbuilder.setSize(transferbuffersize);
|
||||
transferBuffer = tbuilder.create(GetVulkanFrameBuffer()->device);
|
||||
transferBuffer->SetDebugName("transferBuffer");
|
||||
uint8_t* data = (uint8_t*)transferBuffer->Map(0, transferbuffersize);
|
||||
memcpy(data + vertexoffset, Mesh->MeshVertices.Data(), vertexbuffersize);
|
||||
memcpy(data + indexoffset, Mesh->MeshElements.Data(), indexbuffersize);
|
||||
transferBuffer->Unmap();
|
||||
|
||||
GetVulkanFrameBuffer()->GetTransferCommands()->copyBuffer(transferBuffer.get(), vertexBuffer.get(), vertexoffset);
|
||||
GetVulkanFrameBuffer()->GetTransferCommands()->copyBuffer(transferBuffer.get(), indexBuffer.get(), indexoffset);
|
||||
|
||||
VkMemoryBarrier barrier = { VK_STRUCTURE_TYPE_MEMORY_BARRIER };
|
||||
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR;
|
||||
GetVulkanFrameBuffer()->GetTransferCommands()->pipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, 0, 1, &barrier, 0, nullptr, 0, nullptr);
|
||||
}
|
||||
|
||||
void VkRaytrace::CreateBottomLevelAccelerationStructure()
|
||||
{
|
||||
VkBufferDeviceAddressInfo info = { VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO };
|
||||
info.buffer = vertexBuffer->buffer;
|
||||
VkDeviceAddress vertexAddress = vkGetBufferDeviceAddress(GetVulkanFrameBuffer()->device->device, &info);
|
||||
|
||||
info = { VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO };
|
||||
info.buffer = indexBuffer->buffer;
|
||||
VkDeviceAddress indexAddress = vkGetBufferDeviceAddress(GetVulkanFrameBuffer()->device->device, &info);
|
||||
|
||||
VkAccelerationStructureGeometryTrianglesDataKHR triangles = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR };
|
||||
triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT;
|
||||
triangles.vertexData.deviceAddress = vertexAddress;
|
||||
triangles.vertexStride = sizeof(FVector3);
|
||||
triangles.indexType = VK_INDEX_TYPE_UINT32;
|
||||
triangles.indexData.deviceAddress = indexAddress;
|
||||
triangles.maxVertex = Mesh->MeshVertices.Size();
|
||||
|
||||
VkAccelerationStructureGeometryKHR accelStructBLDesc = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR };
|
||||
accelStructBLDesc.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR;
|
||||
accelStructBLDesc.flags = VK_GEOMETRY_OPAQUE_BIT_KHR;
|
||||
accelStructBLDesc.geometry.triangles = triangles;
|
||||
|
||||
VkAccelerationStructureBuildRangeInfoKHR rangeInfo = {};
|
||||
rangeInfo.primitiveCount = Mesh->MeshElements.Size() / 3;
|
||||
|
||||
VkAccelerationStructureBuildGeometryInfoKHR buildInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR };
|
||||
buildInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
|
||||
buildInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR;
|
||||
buildInfo.flags = accelStructBLDesc.flags | VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
|
||||
buildInfo.geometryCount = 1;
|
||||
buildInfo.pGeometries = &accelStructBLDesc;
|
||||
|
||||
uint32_t maxPrimitiveCount = rangeInfo.primitiveCount;
|
||||
|
||||
VkAccelerationStructureBuildSizesInfoKHR sizeInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR };
|
||||
vkGetAccelerationStructureBuildSizesKHR(GetVulkanFrameBuffer()->device->device, VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &buildInfo, &maxPrimitiveCount, &sizeInfo);
|
||||
|
||||
BufferBuilder blbufbuilder;
|
||||
blbufbuilder.setUsage(VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
|
||||
blbufbuilder.setSize(sizeInfo.accelerationStructureSize);
|
||||
blAccelStructBuffer = blbufbuilder.create(GetVulkanFrameBuffer()->device);
|
||||
blAccelStructBuffer->SetDebugName("blAccelStructBuffer");
|
||||
|
||||
VkAccelerationStructureKHR blAccelStructHandle = {};
|
||||
VkAccelerationStructureCreateInfoKHR createInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR };
|
||||
createInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
|
||||
createInfo.buffer = blAccelStructBuffer->buffer;
|
||||
createInfo.size = sizeInfo.accelerationStructureSize;
|
||||
VkResult result = vkCreateAccelerationStructureKHR(GetVulkanFrameBuffer()->device->device, &createInfo, nullptr, &blAccelStructHandle);
|
||||
if (result != VK_SUCCESS)
|
||||
throw std::runtime_error("vkCreateAccelerationStructureKHR failed");
|
||||
blAccelStruct = std::make_unique<VulkanAccelerationStructure>(GetVulkanFrameBuffer()->device, blAccelStructHandle);
|
||||
|
||||
BufferBuilder sbuilder;
|
||||
sbuilder.setUsage(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
sbuilder.setSize(sizeInfo.buildScratchSize);
|
||||
blScratchBuffer = sbuilder.create(GetVulkanFrameBuffer()->device);
|
||||
blScratchBuffer->SetDebugName("blScratchBuffer");
|
||||
|
||||
info = { VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO };
|
||||
info.buffer = blScratchBuffer->buffer;
|
||||
VkDeviceAddress scratchAddress = vkGetBufferDeviceAddress(GetVulkanFrameBuffer()->device->device, &info);
|
||||
|
||||
buildInfo.dstAccelerationStructure = blAccelStruct->accelstruct;
|
||||
buildInfo.scratchData.deviceAddress = scratchAddress;
|
||||
VkAccelerationStructureBuildRangeInfoKHR* rangeInfos[] = { &rangeInfo };
|
||||
GetVulkanFrameBuffer()->GetTransferCommands()->buildAccelerationStructures(1, &buildInfo, rangeInfos);
|
||||
}
|
||||
|
||||
void VkRaytrace::CreateTopLevelAccelerationStructure()
|
||||
{
|
||||
VkAccelerationStructureDeviceAddressInfoKHR addressInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR };
|
||||
addressInfo.accelerationStructure = blAccelStruct->accelstruct;
|
||||
VkDeviceAddress blAccelStructAddress = vkGetAccelerationStructureDeviceAddressKHR(GetVulkanFrameBuffer()->device->device, &addressInfo);
|
||||
|
||||
VkAccelerationStructureInstanceKHR instance = {};
|
||||
instance.transform.matrix[0][0] = 1.0f;
|
||||
instance.transform.matrix[1][1] = 1.0f;
|
||||
instance.transform.matrix[2][2] = 1.0f;
|
||||
instance.instanceCustomIndex = 0;
|
||||
instance.accelerationStructureReference = blAccelStructAddress;
|
||||
instance.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
|
||||
instance.mask = 0xff;
|
||||
instance.instanceShaderBindingTableRecordOffset = 0;
|
||||
|
||||
BufferBuilder tbuilder;
|
||||
tbuilder.setUsage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
|
||||
tbuilder.setSize(sizeof(VkAccelerationStructureInstanceKHR));
|
||||
tlTransferBuffer = tbuilder.create(GetVulkanFrameBuffer()->device);
|
||||
tlTransferBuffer->SetDebugName("tlTransferBuffer");
|
||||
auto data = (uint8_t*)tlTransferBuffer->Map(0, sizeof(VkAccelerationStructureInstanceKHR));
|
||||
memcpy(data, &instance, sizeof(VkAccelerationStructureInstanceKHR));
|
||||
tlTransferBuffer->Unmap();
|
||||
|
||||
BufferBuilder instbufbuilder;
|
||||
instbufbuilder.setUsage(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
|
||||
instbufbuilder.setSize(sizeof(VkAccelerationStructureInstanceKHR));
|
||||
tlInstanceBuffer = instbufbuilder.create(GetVulkanFrameBuffer()->device);
|
||||
tlInstanceBuffer->SetDebugName("tlInstanceBuffer");
|
||||
|
||||
GetVulkanFrameBuffer()->GetTransferCommands()->copyBuffer(tlTransferBuffer.get(), tlInstanceBuffer.get());
|
||||
|
||||
VkMemoryBarrier barrier = { VK_STRUCTURE_TYPE_MEMORY_BARRIER };
|
||||
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR;
|
||||
GetVulkanFrameBuffer()->GetTransferCommands()->pipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, 0, 1, &barrier, 0, nullptr, 0, nullptr);
|
||||
|
||||
VkBufferDeviceAddressInfo info = { VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO };
|
||||
info.buffer = tlInstanceBuffer->buffer;
|
||||
VkDeviceAddress instanceBufferAddress = vkGetBufferDeviceAddress(GetVulkanFrameBuffer()->device->device, &info);
|
||||
|
||||
VkAccelerationStructureGeometryInstancesDataKHR instances = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR };
|
||||
instances.data.deviceAddress = instanceBufferAddress;
|
||||
|
||||
VkAccelerationStructureGeometryKHR accelStructTLDesc = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR };
|
||||
accelStructTLDesc.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR;
|
||||
accelStructTLDesc.geometry.instances = instances;
|
||||
|
||||
VkAccelerationStructureBuildRangeInfoKHR rangeInfo = {};
|
||||
rangeInfo.primitiveCount = 1;
|
||||
|
||||
VkAccelerationStructureBuildGeometryInfoKHR buildInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR };
|
||||
buildInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
|
||||
buildInfo.geometryCount = 1;
|
||||
buildInfo.pGeometries = &accelStructTLDesc;
|
||||
buildInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR;
|
||||
buildInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
|
||||
buildInfo.srcAccelerationStructure = VK_NULL_HANDLE;
|
||||
|
||||
uint32_t maxInstanceCount = 1;
|
||||
|
||||
VkAccelerationStructureBuildSizesInfoKHR sizeInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR };
|
||||
vkGetAccelerationStructureBuildSizesKHR(GetVulkanFrameBuffer()->device->device, VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &buildInfo, &maxInstanceCount, &sizeInfo);
|
||||
|
||||
BufferBuilder tlbufbuilder;
|
||||
tlbufbuilder.setUsage(VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
|
||||
tlbufbuilder.setSize(sizeInfo.accelerationStructureSize);
|
||||
tlAccelStructBuffer = tlbufbuilder.create(GetVulkanFrameBuffer()->device);
|
||||
tlAccelStructBuffer->SetDebugName("tlAccelStructBuffer");
|
||||
|
||||
VkAccelerationStructureKHR tlAccelStructHandle = {};
|
||||
VkAccelerationStructureCreateInfoKHR createInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR };
|
||||
createInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
|
||||
createInfo.buffer = tlAccelStructBuffer->buffer;
|
||||
createInfo.size = sizeInfo.accelerationStructureSize;
|
||||
VkResult result = vkCreateAccelerationStructureKHR(GetVulkanFrameBuffer()->device->device, &createInfo, nullptr, &tlAccelStructHandle);
|
||||
if (result != VK_SUCCESS)
|
||||
throw std::runtime_error("vkCreateAccelerationStructureKHR failed");
|
||||
tlAccelStruct = std::make_unique<VulkanAccelerationStructure>(GetVulkanFrameBuffer()->device, tlAccelStructHandle);
|
||||
|
||||
BufferBuilder sbuilder;
|
||||
sbuilder.setUsage(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
sbuilder.setSize(sizeInfo.buildScratchSize);
|
||||
tlScratchBuffer = sbuilder.create(GetVulkanFrameBuffer()->device);
|
||||
tlScratchBuffer->SetDebugName("tlScratchBuffer");
|
||||
|
||||
info = { VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO };
|
||||
info.buffer = tlScratchBuffer->buffer;
|
||||
VkDeviceAddress scratchAddress = vkGetBufferDeviceAddress(GetVulkanFrameBuffer()->device->device, &info);
|
||||
|
||||
buildInfo.dstAccelerationStructure = tlAccelStruct->accelstruct;
|
||||
buildInfo.scratchData.deviceAddress = scratchAddress;
|
||||
|
||||
VkAccelerationStructureBuildRangeInfoKHR* rangeInfos[] = { &rangeInfo };
|
||||
GetVulkanFrameBuffer()->GetTransferCommands()->buildAccelerationStructures(1, &buildInfo, rangeInfos);
|
||||
}
|
34
src/common/rendering/vulkan/renderer/vk_raytrace.h
Normal file
34
src/common/rendering/vulkan/renderer/vk_raytrace.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "vulkan/system/vk_objects.h"
|
||||
#include "hw_levelmesh.h"
|
||||
|
||||
class VkRaytrace
|
||||
{
|
||||
public:
|
||||
void SetLevelMesh(hwrenderer::LevelMesh* mesh);
|
||||
|
||||
private:
|
||||
void Reset();
|
||||
void CreateVulkanObjects();
|
||||
void CreateVertexAndIndexBuffers();
|
||||
void CreateBottomLevelAccelerationStructure();
|
||||
void CreateTopLevelAccelerationStructure();
|
||||
|
||||
hwrenderer::LevelMesh* Mesh = nullptr;
|
||||
|
||||
std::unique_ptr<VulkanBuffer> vertexBuffer;
|
||||
std::unique_ptr<VulkanBuffer> indexBuffer;
|
||||
std::unique_ptr<VulkanBuffer> transferBuffer;
|
||||
|
||||
std::unique_ptr<VulkanBuffer> blScratchBuffer;
|
||||
std::unique_ptr<VulkanBuffer> blAccelStructBuffer;
|
||||
std::unique_ptr<VulkanAccelerationStructure> blAccelStruct;
|
||||
|
||||
std::unique_ptr<VulkanBuffer> tlTransferBuffer;
|
||||
std::unique_ptr<VulkanBuffer> tlScratchBuffer;
|
||||
std::unique_ptr<VulkanBuffer> tlInstanceBuffer;
|
||||
std::unique_ptr<VulkanBuffer> tlAccelStructBuffer;
|
||||
std::unique_ptr<VulkanAccelerationStructure> tlAccelStruct;
|
||||
};
|
|
@ -49,6 +49,7 @@
|
|||
#include "vulkan/renderer/vk_streambuffer.h"
|
||||
#include "vulkan/renderer/vk_postprocess.h"
|
||||
#include "vulkan/renderer/vk_renderbuffers.h"
|
||||
#include "vulkan/renderer/vk_raytrace.h"
|
||||
#include "vulkan/shaders/vk_shader.h"
|
||||
#include "vulkan/textures/vk_samplers.h"
|
||||
#include "vulkan/textures/vk_hwtexture.h"
|
||||
|
@ -153,6 +154,7 @@ void VulkanFrameBuffer::InitializeState()
|
|||
|
||||
mPostprocess.reset(new VkPostprocess());
|
||||
mRenderPassManager.reset(new VkRenderPassManager());
|
||||
mRaytrace.reset(new VkRaytrace());
|
||||
|
||||
mVertexData = new FFlatVertexBuffer(GetWidth(), GetHeight());
|
||||
mSkyData = new FSkyVertexBuffer;
|
||||
|
@ -801,6 +803,11 @@ void VulkanFrameBuffer::CreateFanToTrisIndexBuffer()
|
|||
FanToTrisIndexBuffer->SetData(sizeof(uint32_t) * data.Size(), data.Data(), BufferUsageType::Static);
|
||||
}
|
||||
|
||||
void VulkanFrameBuffer::SetLevelMesh(hwrenderer::LevelMesh* mesh)
|
||||
{
|
||||
mRaytrace->SetLevelMesh(mesh);
|
||||
}
|
||||
|
||||
void VulkanFrameBuffer::UpdateShadowMap()
|
||||
{
|
||||
mPostprocess->UpdateShadowMap();
|
||||
|
|
|
@ -8,6 +8,7 @@ struct FRenderViewpoint;
|
|||
class VkSamplerManager;
|
||||
class VkShaderManager;
|
||||
class VkRenderPassManager;
|
||||
class VkRaytrace;
|
||||
class VkRenderState;
|
||||
class VkStreamBuffer;
|
||||
class VKDataBuffer;
|
||||
|
@ -32,6 +33,7 @@ public:
|
|||
VkShaderManager *GetShaderManager() { return mShaderManager.get(); }
|
||||
VkSamplerManager *GetSamplerManager() { return mSamplerManager.get(); }
|
||||
VkRenderPassManager *GetRenderPassManager() { return mRenderPassManager.get(); }
|
||||
VkRaytrace* GetRaytrace() { return mRaytrace.get(); }
|
||||
VkRenderState *GetRenderState() { return mRenderState.get(); }
|
||||
VkPostprocess *GetPostprocess() { return mPostprocess.get(); }
|
||||
VkRenderBuffers *GetBuffers() { return mActiveRenderBuffers; }
|
||||
|
@ -90,6 +92,7 @@ public:
|
|||
void PostProcessScene(bool swscene, int fixedcm, float flash, const std::function<void()> &afterBloomDrawEndScene2D) override;
|
||||
void AmbientOccludeScene(float m5) override;
|
||||
void SetSceneRenderTarget(bool useSSAO) override;
|
||||
void SetLevelMesh(hwrenderer::LevelMesh* mesh) override;
|
||||
void UpdateShadowMap() override;
|
||||
void SetSaveBuffers(bool yes) override;
|
||||
void ImageTransitionScene(bool unknown) override;
|
||||
|
@ -133,6 +136,7 @@ private:
|
|||
std::unique_ptr<VkRenderBuffers> mSaveBuffers;
|
||||
std::unique_ptr<VkPostprocess> mPostprocess;
|
||||
std::unique_ptr<VkRenderPassManager> mRenderPassManager;
|
||||
std::unique_ptr<VkRaytrace> mRaytrace;
|
||||
std::unique_ptr<VulkanCommandPool> mCommandPool;
|
||||
std::unique_ptr<VulkanCommandBuffer> mTransferCommands;
|
||||
std::unique_ptr<VkRenderState> mRenderState;
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
#include "r_data/r_canvastexture.h"
|
||||
#include "r_data/r_interpolate.h"
|
||||
#include "doom_aabbtree.h"
|
||||
#include "doom_levelmesh.h"
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
|
@ -476,6 +477,7 @@ public:
|
|||
FCanvasTextureInfo canvasTextureInfo;
|
||||
EventManager *localEventManager = nullptr;
|
||||
DoomLevelAABBTree* aabbTree = nullptr;
|
||||
DoomLevelMesh* levelMesh = nullptr;
|
||||
|
||||
// [ZZ] Destructible geometry information
|
||||
TMap<int, FHealthGroup> healthGroups;
|
||||
|
|
|
@ -3266,6 +3266,7 @@ void MapLoader::LoadLevel(MapData *map, const char *lumpname, int position)
|
|||
Level->FinalizePortals(); // finalize line portals after polyobjects have been initialized. This info is needed for properly flagging them.
|
||||
|
||||
Level->aabbTree = new DoomLevelAABBTree(Level);
|
||||
Level->levelMesh = new DoomLevelMesh(*Level);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
387
src/rendering/hwrenderer/doom_levelmesh.cpp
Normal file
387
src/rendering/hwrenderer/doom_levelmesh.cpp
Normal file
|
@ -0,0 +1,387 @@
|
|||
|
||||
#include "templates.h"
|
||||
#include "doom_levelmesh.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "texturemanager.h"
|
||||
|
||||
DoomLevelMesh::DoomLevelMesh(FLevelLocals &doomMap)
|
||||
{
|
||||
for (unsigned int i = 0; i < doomMap.sides.Size(); i++)
|
||||
{
|
||||
CreateSideSurfaces(doomMap, &doomMap.sides[i]);
|
||||
}
|
||||
|
||||
CreateSubsectorSurfaces(doomMap);
|
||||
|
||||
for (size_t i = 0; i < Surfaces.Size(); i++)
|
||||
{
|
||||
const Surface &s = Surfaces[i];
|
||||
int numVerts = s.numVerts;
|
||||
unsigned int pos = s.startVertIndex;
|
||||
FVector3* verts = &MeshVertices[pos];
|
||||
|
||||
for (int j = 0; j < numVerts; j++)
|
||||
{
|
||||
MeshUVIndex.Push(j);
|
||||
}
|
||||
|
||||
if (s.type == ST_FLOOR || s.type == ST_CEILING)
|
||||
{
|
||||
for (int j = 2; j < numVerts; j++)
|
||||
{
|
||||
if (!IsDegenerate(verts[0], verts[j - 1], verts[j]))
|
||||
{
|
||||
MeshElements.Push(pos);
|
||||
MeshElements.Push(pos + j - 1);
|
||||
MeshElements.Push(pos + j);
|
||||
MeshSurfaces.Push((int)i);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (s.type == ST_MIDDLEWALL || s.type == ST_UPPERWALL || s.type == ST_LOWERWALL)
|
||||
{
|
||||
if (!IsDegenerate(verts[0], verts[1], verts[2]))
|
||||
{
|
||||
MeshElements.Push(pos + 0);
|
||||
MeshElements.Push(pos + 1);
|
||||
MeshElements.Push(pos + 2);
|
||||
MeshSurfaces.Push((int)i);
|
||||
}
|
||||
if (!IsDegenerate(verts[1], verts[2], verts[3]))
|
||||
{
|
||||
MeshElements.Push(pos + 3);
|
||||
MeshElements.Push(pos + 2);
|
||||
MeshElements.Push(pos + 1);
|
||||
MeshSurfaces.Push((int)i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DoomLevelMesh::CreateSideSurfaces(FLevelLocals &doomMap, side_t *side)
|
||||
{
|
||||
sector_t *front;
|
||||
sector_t *back;
|
||||
|
||||
front = side->sector;
|
||||
back = (side->linedef->frontsector == front) ? side->linedef->backsector : side->linedef->frontsector;
|
||||
|
||||
if (IsControlSector(front))
|
||||
return;
|
||||
|
||||
FVector2 v1 = ToFVector2(side->V1()->fPos());
|
||||
FVector2 v2 = ToFVector2(side->V2()->fPos());
|
||||
|
||||
float v1Top = (float)front->ceilingplane.ZatPoint(v1);
|
||||
float v1Bottom = (float)front->floorplane.ZatPoint(v1);
|
||||
float v2Top = (float)front->ceilingplane.ZatPoint(v2);
|
||||
float v2Bottom = (float)front->floorplane.ZatPoint(v2);
|
||||
|
||||
int typeIndex = side->Index();
|
||||
|
||||
FVector2 dx(v2.X - v1.X, v2.Y - v1.Y);
|
||||
float distance = dx.Length();
|
||||
|
||||
if (back)
|
||||
{
|
||||
for (unsigned int j = 0; j < front->e->XFloor.ffloors.Size(); j++)
|
||||
{
|
||||
F3DFloor *xfloor = front->e->XFloor.ffloors[j];
|
||||
|
||||
// Don't create a line when both sectors have the same 3d floor
|
||||
bool bothSides = false;
|
||||
for (unsigned int k = 0; k < back->e->XFloor.ffloors.Size(); k++)
|
||||
{
|
||||
if (back->e->XFloor.ffloors[k] == xfloor)
|
||||
{
|
||||
bothSides = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bothSides)
|
||||
continue;
|
||||
|
||||
Surface surf;
|
||||
surf.type = ST_MIDDLEWALL;
|
||||
surf.typeIndex = typeIndex;
|
||||
surf.controlSector = xfloor->model;
|
||||
|
||||
FVector3 verts[4];
|
||||
verts[0].X = verts[2].X = v2.X;
|
||||
verts[0].Y = verts[2].Y = v2.Y;
|
||||
verts[1].X = verts[3].X = v1.X;
|
||||
verts[1].Y = verts[3].Y = v1.Y;
|
||||
verts[0].Z = (float)xfloor->model->floorplane.ZatPoint(v2);
|
||||
verts[1].Z = (float)xfloor->model->floorplane.ZatPoint(v1);
|
||||
verts[2].Z = (float)xfloor->model->ceilingplane.ZatPoint(v2);
|
||||
verts[3].Z = (float)xfloor->model->ceilingplane.ZatPoint(v1);
|
||||
|
||||
surf.startVertIndex = MeshVertices.Size();
|
||||
surf.numVerts = 4;
|
||||
MeshVertices.Push(verts[0]);
|
||||
MeshVertices.Push(verts[1]);
|
||||
MeshVertices.Push(verts[2]);
|
||||
MeshVertices.Push(verts[3]);
|
||||
|
||||
surf.plane = ToPlane(verts[0], verts[1], verts[2]);
|
||||
Surfaces.Push(surf);
|
||||
}
|
||||
|
||||
float v1TopBack = (float)back->ceilingplane.ZatPoint(v1);
|
||||
float v1BottomBack = (float)back->floorplane.ZatPoint(v1);
|
||||
float v2TopBack = (float)back->ceilingplane.ZatPoint(v2);
|
||||
float v2BottomBack = (float)back->floorplane.ZatPoint(v2);
|
||||
|
||||
if (v1Top == v1TopBack && v1Bottom == v1BottomBack && v2Top == v2TopBack && v2Bottom == v2BottomBack)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// bottom seg
|
||||
if (v1Bottom < v1BottomBack || v2Bottom < v2BottomBack)
|
||||
{
|
||||
if (IsBottomSideVisible(side))
|
||||
{
|
||||
Surface surf;
|
||||
|
||||
FVector3 verts[4];
|
||||
verts[0].X = verts[2].X = v1.X;
|
||||
verts[0].Y = verts[2].Y = v1.Y;
|
||||
verts[1].X = verts[3].X = v2.X;
|
||||
verts[1].Y = verts[3].Y = v2.Y;
|
||||
verts[0].Z = v1Bottom;
|
||||
verts[1].Z = v2Bottom;
|
||||
verts[2].Z = v1BottomBack;
|
||||
verts[3].Z = v2BottomBack;
|
||||
|
||||
surf.startVertIndex = MeshVertices.Size();
|
||||
surf.numVerts = 4;
|
||||
MeshVertices.Push(verts[0]);
|
||||
MeshVertices.Push(verts[1]);
|
||||
MeshVertices.Push(verts[2]);
|
||||
MeshVertices.Push(verts[3]);
|
||||
|
||||
surf.plane = ToPlane(verts[0], verts[1], verts[2]);
|
||||
surf.type = ST_LOWERWALL;
|
||||
surf.typeIndex = typeIndex;
|
||||
surf.controlSector = nullptr;
|
||||
|
||||
Surfaces.Push(surf);
|
||||
}
|
||||
|
||||
v1Bottom = v1BottomBack;
|
||||
v2Bottom = v2BottomBack;
|
||||
}
|
||||
|
||||
// top seg
|
||||
if (v1Top > v1TopBack || v2Top > v2TopBack)
|
||||
{
|
||||
bool bSky = IsTopSideSky(front, back, side);
|
||||
if (bSky || IsTopSideVisible(side))
|
||||
{
|
||||
Surface surf;
|
||||
|
||||
FVector3 verts[4];
|
||||
verts[0].X = verts[2].X = v1.X;
|
||||
verts[0].Y = verts[2].Y = v1.Y;
|
||||
verts[1].X = verts[3].X = v2.X;
|
||||
verts[1].Y = verts[3].Y = v2.Y;
|
||||
verts[0].Z = v1TopBack;
|
||||
verts[1].Z = v2TopBack;
|
||||
verts[2].Z = v1Top;
|
||||
verts[3].Z = v2Top;
|
||||
|
||||
surf.startVertIndex = MeshVertices.Size();
|
||||
surf.numVerts = 4;
|
||||
MeshVertices.Push(verts[0]);
|
||||
MeshVertices.Push(verts[1]);
|
||||
MeshVertices.Push(verts[2]);
|
||||
MeshVertices.Push(verts[3]);
|
||||
|
||||
surf.plane = ToPlane(verts[0], verts[1], verts[2]);
|
||||
surf.type = ST_UPPERWALL;
|
||||
surf.typeIndex = typeIndex;
|
||||
surf.bSky = bSky;
|
||||
surf.controlSector = nullptr;
|
||||
|
||||
Surfaces.Push(surf);
|
||||
}
|
||||
|
||||
v1Top = v1TopBack;
|
||||
v2Top = v2TopBack;
|
||||
}
|
||||
}
|
||||
|
||||
// middle seg
|
||||
if (back == nullptr)
|
||||
{
|
||||
Surface surf;
|
||||
|
||||
FVector3 verts[4];
|
||||
verts[0].X = verts[2].X = v1.X;
|
||||
verts[0].Y = verts[2].Y = v1.Y;
|
||||
verts[1].X = verts[3].X = v2.X;
|
||||
verts[1].Y = verts[3].Y = v2.Y;
|
||||
verts[0].Z = v1Bottom;
|
||||
verts[1].Z = v2Bottom;
|
||||
verts[2].Z = v1Top;
|
||||
verts[3].Z = v2Top;
|
||||
|
||||
surf.startVertIndex = MeshVertices.Size();
|
||||
surf.numVerts = 4;
|
||||
MeshVertices.Push(verts[0]);
|
||||
MeshVertices.Push(verts[1]);
|
||||
MeshVertices.Push(verts[2]);
|
||||
MeshVertices.Push(verts[3]);
|
||||
|
||||
surf.plane = ToPlane(verts[0], verts[1], verts[2]);
|
||||
surf.type = ST_MIDDLEWALL;
|
||||
surf.typeIndex = typeIndex;
|
||||
surf.controlSector = nullptr;
|
||||
|
||||
Surfaces.Push(surf);
|
||||
}
|
||||
}
|
||||
|
||||
void DoomLevelMesh::CreateFloorSurface(FLevelLocals &doomMap, subsector_t *sub, sector_t *sector, int typeIndex, bool is3DFloor)
|
||||
{
|
||||
Surface surf;
|
||||
|
||||
if (!is3DFloor)
|
||||
{
|
||||
surf.plane = sector->floorplane;
|
||||
}
|
||||
else
|
||||
{
|
||||
surf.plane = sector->ceilingplane;
|
||||
surf.plane.FlipVert();
|
||||
}
|
||||
|
||||
surf.numVerts = sub->numlines;
|
||||
surf.startVertIndex = MeshVertices.Size();
|
||||
MeshVertices.Resize(surf.startVertIndex + surf.numVerts);
|
||||
FVector3* verts = &MeshVertices[surf.startVertIndex];
|
||||
|
||||
for (int j = 0; j < surf.numVerts; j++)
|
||||
{
|
||||
seg_t *seg = &sub->firstline[(surf.numVerts - 1) - j];
|
||||
FVector2 v1 = ToFVector2(seg->v1->fPos());
|
||||
|
||||
verts[j].X = v1.X;
|
||||
verts[j].Y = v1.Y;
|
||||
verts[j].Z = (float)surf.plane.ZatPoint(verts[j]);
|
||||
}
|
||||
|
||||
surf.type = ST_FLOOR;
|
||||
surf.typeIndex = typeIndex;
|
||||
surf.controlSector = is3DFloor ? sector : nullptr;
|
||||
|
||||
Surfaces.Push(surf);
|
||||
}
|
||||
|
||||
void DoomLevelMesh::CreateCeilingSurface(FLevelLocals &doomMap, subsector_t *sub, sector_t *sector, int typeIndex, bool is3DFloor)
|
||||
{
|
||||
Surface surf;
|
||||
surf.bSky = IsSkySector(sector);
|
||||
|
||||
if (!is3DFloor)
|
||||
{
|
||||
surf.plane = sector->ceilingplane;
|
||||
}
|
||||
else
|
||||
{
|
||||
surf.plane = sector->floorplane;
|
||||
surf.plane.FlipVert();
|
||||
}
|
||||
|
||||
surf.numVerts = sub->numlines;
|
||||
surf.startVertIndex = MeshVertices.Size();
|
||||
MeshVertices.Resize(surf.startVertIndex + surf.numVerts);
|
||||
FVector3* verts = &MeshVertices[surf.startVertIndex];
|
||||
|
||||
for (int j = 0; j < surf.numVerts; j++)
|
||||
{
|
||||
seg_t *seg = &sub->firstline[j];
|
||||
FVector2 v1 = ToFVector2(seg->v1->fPos());
|
||||
|
||||
verts[j].X = v1.X;
|
||||
verts[j].Y = v1.Y;
|
||||
verts[j].Z = (float)surf.plane.ZatPoint(verts[j]);
|
||||
}
|
||||
|
||||
surf.type = ST_CEILING;
|
||||
surf.typeIndex = typeIndex;
|
||||
surf.controlSector = is3DFloor ? sector : nullptr;
|
||||
|
||||
Surfaces.Push(surf);
|
||||
}
|
||||
|
||||
void DoomLevelMesh::CreateSubsectorSurfaces(FLevelLocals &doomMap)
|
||||
{
|
||||
for (unsigned int i = 0; i < doomMap.subsectors.Size(); i++)
|
||||
{
|
||||
subsector_t *sub = &doomMap.subsectors[i];
|
||||
|
||||
if (sub->numlines < 3)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
sector_t *sector = sub->sector;
|
||||
if (!sector || IsControlSector(sector))
|
||||
continue;
|
||||
|
||||
CreateFloorSurface(doomMap, sub, sector, i, false);
|
||||
CreateCeilingSurface(doomMap, sub, sector, i, false);
|
||||
|
||||
for (unsigned int j = 0; j < sector->e->XFloor.ffloors.Size(); j++)
|
||||
{
|
||||
CreateFloorSurface(doomMap, sub, sector->e->XFloor.ffloors[j]->model, i, true);
|
||||
CreateCeilingSurface(doomMap, sub, sector->e->XFloor.ffloors[j]->model, i, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool DoomLevelMesh::IsTopSideSky(sector_t* frontsector, sector_t* backsector, side_t* side)
|
||||
{
|
||||
return IsSkySector(frontsector) && IsSkySector(backsector);
|
||||
}
|
||||
|
||||
bool DoomLevelMesh::IsTopSideVisible(side_t* side)
|
||||
{
|
||||
auto tex = TexMan.GetGameTexture(side->GetTexture(side_t::top), true);
|
||||
return tex && tex->isValid();
|
||||
}
|
||||
|
||||
bool DoomLevelMesh::IsBottomSideVisible(side_t* side)
|
||||
{
|
||||
auto tex = TexMan.GetGameTexture(side->GetTexture(side_t::bottom), true);
|
||||
return tex && tex->isValid();
|
||||
}
|
||||
|
||||
bool DoomLevelMesh::IsSkySector(sector_t* sector)
|
||||
{
|
||||
return sector->GetTexture(sector_t::ceiling) == skyflatnum;
|
||||
}
|
||||
|
||||
bool DoomLevelMesh::IsControlSector(sector_t* sector)
|
||||
{
|
||||
//return sector->controlsector;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DoomLevelMesh::IsDegenerate(const FVector3 &v0, const FVector3 &v1, const FVector3 &v2)
|
||||
{
|
||||
// A degenerate triangle has a zero cross product for two of its sides.
|
||||
float ax = v1.X - v0.X;
|
||||
float ay = v1.Y - v0.Y;
|
||||
float az = v1.Z - v0.Z;
|
||||
float bx = v2.X - v0.X;
|
||||
float by = v2.Y - v0.Y;
|
||||
float bz = v2.Z - v0.Z;
|
||||
float crossx = ay * bz - az * by;
|
||||
float crossy = az * bx - ax * bz;
|
||||
float crossz = ax * by - ay * bx;
|
||||
float crosslengthsqr = crossx * crossx + crossy * crossy + crossz * crossz;
|
||||
return crosslengthsqr <= 1.e-6f;
|
||||
}
|
55
src/rendering/hwrenderer/doom_levelmesh.h
Normal file
55
src/rendering/hwrenderer/doom_levelmesh.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "hw_levelmesh.h"
|
||||
#include "tarray.h"
|
||||
#include "vectors.h"
|
||||
#include "r_defs.h"
|
||||
|
||||
struct FLevelLocals;
|
||||
|
||||
struct Surface
|
||||
{
|
||||
SurfaceType type;
|
||||
int typeIndex;
|
||||
int numVerts;
|
||||
unsigned int startVertIndex;
|
||||
secplane_t plane;
|
||||
sector_t *controlSector;
|
||||
bool bSky;
|
||||
};
|
||||
|
||||
class DoomLevelMesh : public hwrenderer::LevelMesh
|
||||
{
|
||||
public:
|
||||
DoomLevelMesh(FLevelLocals &doomMap);
|
||||
|
||||
TArray<Surface> Surfaces;
|
||||
|
||||
private:
|
||||
void CreateSubsectorSurfaces(FLevelLocals &doomMap);
|
||||
void CreateCeilingSurface(FLevelLocals &doomMap, subsector_t *sub, sector_t *sector, int typeIndex, bool is3DFloor);
|
||||
void CreateFloorSurface(FLevelLocals &doomMap, subsector_t *sub, sector_t *sector, int typeIndex, bool is3DFloor);
|
||||
void CreateSideSurfaces(FLevelLocals &doomMap, side_t *side);
|
||||
|
||||
static bool IsTopSideSky(sector_t* frontsector, sector_t* backsector, side_t* side);
|
||||
static bool IsTopSideVisible(side_t* side);
|
||||
static bool IsBottomSideVisible(side_t* side);
|
||||
static bool IsSkySector(sector_t* sector);
|
||||
static bool IsControlSector(sector_t* sector);
|
||||
|
||||
static secplane_t ToPlane(const FVector3& pt1, const FVector3& pt2, const FVector3& pt3)
|
||||
{
|
||||
FVector3 n = ((pt2 - pt1) ^ (pt3 - pt2)).Unit();
|
||||
float d = pt1 | n;
|
||||
secplane_t p;
|
||||
p.set(n.X, n.Y, n.Z, d);
|
||||
return p;
|
||||
}
|
||||
|
||||
static FVector2 ToFVector2(const DVector2& v) { return FVector2((float)v.X, (float)v.Y); }
|
||||
static FVector3 ToFVector3(const DVector3& v) { return FVector3((float)v.X, (float)v.Y, (float)v.Z); }
|
||||
static FVector4 ToFVector4(const DVector4& v) { return FVector4((float)v.X, (float)v.Y, (float)v.Z, (float)v.W); }
|
||||
|
||||
static bool IsDegenerate(const FVector3 &v0, const FVector3 &v1, const FVector3 &v2);
|
||||
};
|
|
@ -123,6 +123,8 @@ sector_t* RenderViewpoint(FRenderViewpoint& mainvp, AActor* camera, IntRect* bou
|
|||
screen->mShadowMap.SetCollectLights(nullptr);
|
||||
}
|
||||
|
||||
screen->SetLevelMesh(camera->Level->levelMesh);
|
||||
|
||||
// Update the attenuation flag of all light defaults for each viewpoint.
|
||||
// This function will only do something if the setting differs.
|
||||
FLightDefaults::SetAttenuationForLevel(!!(camera->Level->flags3 & LEVEL3_ATTENUATE));
|
||||
|
|
Loading…
Reference in a new issue