Make the light list part of the level mesh
This commit is contained in:
parent
b436903a28
commit
68f9fee55b
11 changed files with 195 additions and 156 deletions
|
|
@ -34,7 +34,6 @@ public:
|
|||
virtual LevelMeshSurface* GetSurface(int index) { return nullptr; }
|
||||
virtual unsigned int GetSurfaceIndex(const LevelMeshSurface* surface) const { return 0xffffffff; }
|
||||
virtual int GetSurfaceCount() { return 0; }
|
||||
virtual int AddSurfaceLights(const LevelMeshSurface* surface, LevelMeshLight* list, int listMaxSize) { return 0; }
|
||||
|
||||
LevelMeshSurface* Trace(const FVector3& start, FVector3 direction, float maxDist);
|
||||
|
||||
|
|
@ -55,6 +54,10 @@ public:
|
|||
// Surface info
|
||||
TArray<SurfaceUniforms> Uniforms;
|
||||
TArray<FMaterialState> Materials;
|
||||
TArray<int32_t> LightIndexes;
|
||||
|
||||
// Lights
|
||||
TArray<LevelMeshLight> Lights;
|
||||
|
||||
// Index data
|
||||
TArray<uint32_t> Indexes;
|
||||
|
|
@ -68,6 +71,8 @@ public:
|
|||
int MaxUniforms = 0;
|
||||
int MaxSurfaceIndexes = 0;
|
||||
int MaxNodes = 0;
|
||||
int MaxLights = 0;
|
||||
int MaxLightIndexes = 0;
|
||||
} Mesh;
|
||||
|
||||
std::unique_ptr<TriangleMeshShape> Collision;
|
||||
|
|
|
|||
|
|
@ -36,8 +36,7 @@ struct LevelMeshSurface
|
|||
// Light list location in the lightmapper GPU buffers
|
||||
struct
|
||||
{
|
||||
int Pos = -1;
|
||||
int Pos = 0;
|
||||
int Count = 0;
|
||||
int ResetCounter = -1;
|
||||
} LightList;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -55,6 +55,8 @@ void VkLevelMesh::Reset()
|
|||
deletelist->Add(std::move(UniformsBuffer));
|
||||
deletelist->Add(std::move(SurfaceIndexBuffer));
|
||||
deletelist->Add(std::move(PortalBuffer));
|
||||
deletelist->Add(std::move(LightBuffer));
|
||||
deletelist->Add(std::move(LightIndexBuffer));
|
||||
deletelist->Add(std::move(StaticBLAS.ScratchBuffer));
|
||||
deletelist->Add(std::move(StaticBLAS.AccelStructBuffer));
|
||||
deletelist->Add(std::move(StaticBLAS.AccelStruct));
|
||||
|
|
@ -173,6 +175,8 @@ void VkLevelMesh::UploadMeshes(bool dynamicOnly)
|
|||
Locations.UniformIndexes.Push({ 0, (int)Mesh->Mesh.UniformIndexes.Size() });
|
||||
Locations.Uniforms.Push({ 0, (int)Mesh->Mesh.Uniforms.Size() });
|
||||
Locations.Portals.Push({ 0, (int)Mesh->Portals.Size() });
|
||||
Locations.Light.Push({ 0, (int)Mesh->Mesh.Lights.Size() });
|
||||
Locations.LightIndex.Push({ 0, (int)Mesh->Mesh.LightIndexes.Size() });
|
||||
}
|
||||
|
||||
VkLevelMeshUploader uploader(this);
|
||||
|
|
@ -242,6 +246,18 @@ void VkLevelMesh::CreateBuffers()
|
|||
.Size(Mesh->Portals.Size() * sizeof(PortalInfo))
|
||||
.DebugName("PortalBuffer")
|
||||
.Create(fb->GetDevice());
|
||||
|
||||
LightBuffer = BufferBuilder()
|
||||
.Usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)
|
||||
.Size(Mesh->Mesh.MaxLights * sizeof(LightInfo))
|
||||
.DebugName("LightBuffer")
|
||||
.Create(fb->GetDevice());
|
||||
|
||||
LightIndexBuffer = BufferBuilder()
|
||||
.Usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)
|
||||
.Size(Mesh->Mesh.MaxLightIndexes * sizeof(int32_t))
|
||||
.DebugName("LightIndexBuffer")
|
||||
.Create(fb->GetDevice());
|
||||
}
|
||||
|
||||
VkLevelMesh::BLAS VkLevelMesh::CreateBLAS(bool preferFastBuild, int indexOffset, int indexCount)
|
||||
|
|
@ -455,9 +471,11 @@ void VkLevelMeshUploader::Upload()
|
|||
UploadRanges(Mesh->Locations.UniformIndexes, Mesh->Mesh->Mesh.UniformIndexes.Data(), Mesh->UniformIndexBuffer.get());
|
||||
UploadRanges(Mesh->Locations.Index, Mesh->Mesh->Mesh.Indexes.Data(), Mesh->IndexBuffer.get());
|
||||
UploadRanges(Mesh->Locations.SurfaceIndex, Mesh->Mesh->Mesh.SurfaceIndexes.Data(), Mesh->SurfaceIndexBuffer.get());
|
||||
UploadRanges(Mesh->Locations.LightIndex, Mesh->Mesh->Mesh.LightIndexes.Data(), Mesh->LightIndexBuffer.get());
|
||||
UploadSurfaces();
|
||||
UploadUniforms();
|
||||
UploadPortals();
|
||||
UploadLights();
|
||||
|
||||
EndTransfer(transferBufferSize);
|
||||
ClearRanges();
|
||||
|
|
@ -473,6 +491,8 @@ void VkLevelMeshUploader::ClearRanges()
|
|||
Mesh->Locations.UniformIndexes.clear();
|
||||
Mesh->Locations.Uniforms.clear();
|
||||
Mesh->Locations.Portals.clear();
|
||||
Mesh->Locations.Light.clear();
|
||||
Mesh->Locations.LightIndex.clear();
|
||||
}
|
||||
|
||||
void VkLevelMeshUploader::BeginTransfer(size_t transferBufferSize)
|
||||
|
|
@ -635,6 +655,33 @@ void VkLevelMeshUploader::UploadPortals()
|
|||
}
|
||||
}
|
||||
|
||||
void VkLevelMeshUploader::UploadLights()
|
||||
{
|
||||
for (const MeshBufferRange& range : Mesh->Locations.Light)
|
||||
{
|
||||
LightInfo* lights = (LightInfo*)(data + datapos);
|
||||
for (int i = 0, count = range.Size; i < count; i++)
|
||||
{
|
||||
const auto& light = Mesh->Mesh->Mesh.Lights[range.Offset + i];
|
||||
LightInfo info;
|
||||
info.Origin = SwapYZ(light.Origin);
|
||||
info.RelativeOrigin = SwapYZ(light.RelativeOrigin);
|
||||
info.Radius = light.Radius;
|
||||
info.Intensity = light.Intensity;
|
||||
info.InnerAngleCos = light.InnerAngleCos;
|
||||
info.OuterAngleCos = light.OuterAngleCos;
|
||||
info.SpotDir = SwapYZ(light.SpotDir);
|
||||
info.Color = light.Color;
|
||||
*(lights++) = info;
|
||||
}
|
||||
|
||||
size_t copysize = range.Size * sizeof(LightInfo);
|
||||
if (copysize > 0)
|
||||
cmdbuffer->copyBuffer(transferBuffer.get(), Mesh->LightBuffer.get(), datapos, range.Offset * sizeof(LightInfo), copysize);
|
||||
datapos += copysize;
|
||||
}
|
||||
}
|
||||
|
||||
size_t VkLevelMeshUploader::GetTransferSize()
|
||||
{
|
||||
// Figure out how much memory we need to transfer it to the GPU
|
||||
|
|
@ -648,5 +695,7 @@ size_t VkLevelMeshUploader::GetTransferSize()
|
|||
for (const MeshBufferRange& range : Mesh->Locations.Surface) transferBufferSize += range.Size * sizeof(SurfaceInfo);
|
||||
for (const MeshBufferRange& range : Mesh->Locations.Uniforms) transferBufferSize += range.Size * sizeof(SurfaceUniforms);
|
||||
for (const MeshBufferRange& range : Mesh->Locations.Portals) transferBufferSize += range.Size * sizeof(PortalInfo);
|
||||
for (const MeshBufferRange& range : Mesh->Locations.LightIndex) transferBufferSize += range.Size * sizeof(int32_t);
|
||||
for (const MeshBufferRange& range : Mesh->Locations.Light) transferBufferSize += range.Size * sizeof(LightInfo);
|
||||
return transferBufferSize;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,24 @@ struct PortalInfo
|
|||
VSMatrix transformation;
|
||||
};
|
||||
|
||||
struct LightInfo
|
||||
{
|
||||
FVector3 Origin;
|
||||
float Padding0;
|
||||
FVector3 RelativeOrigin;
|
||||
float Padding1;
|
||||
float Radius;
|
||||
float Intensity;
|
||||
float InnerAngleCos;
|
||||
float OuterAngleCos;
|
||||
FVector3 SpotDir;
|
||||
float Padding2;
|
||||
FVector3 Color;
|
||||
float Padding3;
|
||||
};
|
||||
|
||||
static_assert(sizeof(LightInfo) == sizeof(float) * 20);
|
||||
|
||||
struct MeshBufferRange
|
||||
{
|
||||
int Offset = 0;
|
||||
|
|
@ -65,6 +83,8 @@ public:
|
|||
VulkanBuffer* GetSurfaceBuffer() { return SurfaceBuffer.get(); }
|
||||
VulkanBuffer* GetUniformsBuffer() { return UniformsBuffer.get(); }
|
||||
VulkanBuffer* GetPortalBuffer() { return PortalBuffer.get(); }
|
||||
VulkanBuffer* GetLightBuffer() { return LightBuffer.get(); }
|
||||
VulkanBuffer* GetLightIndexBuffer() { return LightIndexBuffer.get(); }
|
||||
|
||||
LevelMesh* GetMesh() { return Mesh; }
|
||||
|
||||
|
|
@ -107,6 +127,8 @@ private:
|
|||
TArray<MeshBufferRange> UniformIndexes;
|
||||
TArray<MeshBufferRange> Uniforms;
|
||||
TArray<MeshBufferRange> Portals;
|
||||
TArray<MeshBufferRange> Light;
|
||||
TArray<MeshBufferRange> LightIndex;
|
||||
} Locations;
|
||||
|
||||
std::unique_ptr<VulkanBuffer> VertexBuffer;
|
||||
|
|
@ -116,6 +138,8 @@ private:
|
|||
std::unique_ptr<VulkanBuffer> SurfaceBuffer;
|
||||
std::unique_ptr<VulkanBuffer> UniformsBuffer;
|
||||
std::unique_ptr<VulkanBuffer> PortalBuffer;
|
||||
std::unique_ptr<VulkanBuffer> LightBuffer;
|
||||
std::unique_ptr<VulkanBuffer> LightIndexBuffer;
|
||||
|
||||
std::unique_ptr<VulkanBuffer> NodeBuffer;
|
||||
|
||||
|
|
@ -151,6 +175,7 @@ private:
|
|||
void UploadSurfaces();
|
||||
void UploadUniforms();
|
||||
void UploadPortals();
|
||||
void UploadLights();
|
||||
|
||||
template<typename T>
|
||||
void UploadRanges(const TArray<MeshBufferRange>& ranges, const T* srcbuffer, VulkanBuffer* destbuffer);
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ VkLightmapper::VkLightmapper(VulkanRenderDevice* fb) : fb(fb)
|
|||
try
|
||||
{
|
||||
CreateUniformBuffer();
|
||||
CreateLightBuffer();
|
||||
CreateTileBuffer();
|
||||
CreateDrawIndexedBuffer();
|
||||
|
||||
|
|
@ -63,8 +62,6 @@ VkLightmapper::~VkLightmapper()
|
|||
|
||||
void VkLightmapper::ReleaseResources()
|
||||
{
|
||||
if (lights.Buffer)
|
||||
lights.Buffer->Unmap();
|
||||
if (copytiles.Buffer)
|
||||
copytiles.Buffer->Unmap();
|
||||
if (drawindexed.CommandsBuffer)
|
||||
|
|
@ -85,8 +82,6 @@ void VkLightmapper::SetLevelMesh(LevelMesh* level)
|
|||
|
||||
void VkLightmapper::BeginFrame()
|
||||
{
|
||||
lights.Pos = 0;
|
||||
lights.ResetCounter++;
|
||||
drawindexed.Pos = 0;
|
||||
}
|
||||
|
||||
|
|
@ -200,42 +195,8 @@ void VkLightmapper::Render()
|
|||
{
|
||||
LevelMeshSurface* surface = mesh->GetSurface(surfaceIndex);
|
||||
pc.SurfaceIndex = surfaceIndex;
|
||||
|
||||
if (surface->LightList.ResetCounter != lights.ResetCounter)
|
||||
{
|
||||
int lightCount = mesh->AddSurfaceLights(surface, templightlist.Data(), (int)templightlist.Size());
|
||||
|
||||
if (lights.Pos + lightCount > lights.BufferSize)
|
||||
{
|
||||
// Our light buffer is full. Postpone the rest.
|
||||
buffersFull = true;
|
||||
break;
|
||||
}
|
||||
|
||||
surface->LightList.Pos = lights.Pos;
|
||||
surface->LightList.Count = lightCount;
|
||||
surface->LightList.ResetCounter = lights.ResetCounter;
|
||||
|
||||
LightInfo* lightinfo = &lights.Lights[lights.Pos];
|
||||
for (int i = 0; i < lightCount; i++)
|
||||
{
|
||||
const LevelMeshLight* light = &templightlist[i];
|
||||
lightinfo->Origin = SwapYZ(light->Origin);
|
||||
lightinfo->RelativeOrigin = SwapYZ(light->RelativeOrigin);
|
||||
lightinfo->Radius = light->Radius;
|
||||
lightinfo->Intensity = light->Intensity;
|
||||
lightinfo->InnerAngleCos = light->InnerAngleCos;
|
||||
lightinfo->OuterAngleCos = light->OuterAngleCos;
|
||||
lightinfo->SpotDir = SwapYZ(light->SpotDir);
|
||||
lightinfo->Color = light->Color;
|
||||
lightinfo++;
|
||||
}
|
||||
|
||||
lights.Pos += lightCount;
|
||||
}
|
||||
|
||||
pc.LightStart = surface->LightList.Pos;
|
||||
pc.LightEnd = pc.LightStart + surface->LightList.Count;
|
||||
pc.LightEnd = surface->LightList.Pos + surface->LightList.Count;
|
||||
|
||||
VkDrawIndexedIndirectCommand cmd;
|
||||
cmd.indexCount = surface->MeshLocation.NumElements;
|
||||
|
|
@ -680,7 +641,8 @@ void VkLightmapper::CreateRaytracePipeline()
|
|||
.AddBinding(2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT)
|
||||
.AddBinding(3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT)
|
||||
.AddBinding(4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT)
|
||||
.AddBinding(5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)
|
||||
.AddBinding(5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT)
|
||||
.AddBinding(6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)
|
||||
.DebugName("raytrace.descriptorSetLayout0")
|
||||
.Create(fb->GetDevice());
|
||||
|
||||
|
|
@ -748,7 +710,7 @@ void VkLightmapper::CreateRaytracePipeline()
|
|||
|
||||
raytrace.descriptorPool0 = DescriptorPoolBuilder()
|
||||
.AddPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1)
|
||||
.AddPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 5)
|
||||
.AddPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 6)
|
||||
.MaxSets(1)
|
||||
.DebugName("raytrace.descriptorPool0")
|
||||
.Create(fb->GetDevice());
|
||||
|
|
@ -801,9 +763,10 @@ void VkLightmapper::UpdateAccelStructDescriptors()
|
|||
.AddBuffer(raytrace.descriptorSet0.get(), 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, uniforms.Buffer.get(), 0, sizeof(Uniforms))
|
||||
.AddBuffer(raytrace.descriptorSet0.get(), 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetSurfaceIndexBuffer())
|
||||
.AddBuffer(raytrace.descriptorSet0.get(), 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetSurfaceBuffer())
|
||||
.AddBuffer(raytrace.descriptorSet0.get(), 3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, lights.Buffer.get())
|
||||
.AddBuffer(raytrace.descriptorSet0.get(), 4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetPortalBuffer())
|
||||
.AddBuffer(raytrace.descriptorSet0.get(), 5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, drawindexed.ConstantsBuffer.get(), 0, drawindexed.BufferSize * sizeof(LightmapRaytracePC))
|
||||
.AddBuffer(raytrace.descriptorSet0.get(), 3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetLightBuffer())
|
||||
.AddBuffer(raytrace.descriptorSet0.get(), 4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetLightIndexBuffer())
|
||||
.AddBuffer(raytrace.descriptorSet0.get(), 5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetPortalBuffer())
|
||||
.AddBuffer(raytrace.descriptorSet0.get(), 6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, drawindexed.ConstantsBuffer.get(), 0, drawindexed.BufferSize * sizeof(LightmapRaytracePC))
|
||||
.Execute(fb->GetDevice());
|
||||
}
|
||||
|
||||
|
|
@ -1075,25 +1038,6 @@ void VkLightmapper::CreateUniformBuffer()
|
|||
.Create(fb->GetDevice());
|
||||
}
|
||||
|
||||
void VkLightmapper::CreateLightBuffer()
|
||||
{
|
||||
size_t size = sizeof(LightInfo) * lights.BufferSize;
|
||||
|
||||
lights.Buffer = BufferBuilder()
|
||||
.Usage(
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
|
||||
VMA_MEMORY_USAGE_UNKNOWN, VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT)
|
||||
.MemoryType(
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
|
||||
.Size(size)
|
||||
.DebugName("LightmapLightBuffer")
|
||||
.Create(fb->GetDevice());
|
||||
|
||||
lights.Lights = (LightInfo*)lights.Buffer->Map(0, size);
|
||||
lights.Pos = 0;
|
||||
}
|
||||
|
||||
void VkLightmapper::CreateTileBuffer()
|
||||
{
|
||||
size_t size = sizeof(CopyTileInfo) * copytiles.BufferSize;
|
||||
|
|
|
|||
|
|
@ -79,22 +79,6 @@ struct LightmapBakeImage
|
|||
uint16_t maxY = 0;
|
||||
};
|
||||
|
||||
struct LightInfo
|
||||
{
|
||||
FVector3 Origin;
|
||||
float Padding0;
|
||||
FVector3 RelativeOrigin;
|
||||
float Padding1;
|
||||
float Radius;
|
||||
float Intensity;
|
||||
float InnerAngleCos;
|
||||
float OuterAngleCos;
|
||||
FVector3 SpotDir;
|
||||
float Padding2;
|
||||
FVector3 Color;
|
||||
float Padding3;
|
||||
};
|
||||
|
||||
struct SelectedTile
|
||||
{
|
||||
LightmapTile* Tile = nullptr;
|
||||
|
|
@ -103,8 +87,6 @@ struct SelectedTile
|
|||
bool Rendered = false;
|
||||
};
|
||||
|
||||
static_assert(sizeof(LightInfo) == sizeof(float) * 20);
|
||||
|
||||
struct CopyTileInfo
|
||||
{
|
||||
int SrcPosX;
|
||||
|
|
@ -147,7 +129,6 @@ private:
|
|||
void CreateBlurPipeline();
|
||||
void CreateCopyPipeline();
|
||||
void CreateUniformBuffer();
|
||||
void CreateLightBuffer();
|
||||
void CreateTileBuffer();
|
||||
void CreateDrawIndexedBuffer();
|
||||
void CreateBakeImage();
|
||||
|
|
@ -180,15 +161,6 @@ private:
|
|||
VkDeviceSize StructStride = sizeof(Uniforms);
|
||||
} uniforms;
|
||||
|
||||
struct
|
||||
{
|
||||
const int BufferSize = 2 * 1024 * 1024;
|
||||
std::unique_ptr<VulkanBuffer> Buffer;
|
||||
LightInfo* Lights = nullptr;
|
||||
int Pos = 0;
|
||||
int ResetCounter = 0;
|
||||
} lights;
|
||||
|
||||
struct
|
||||
{
|
||||
const int BufferSize = 100'000;
|
||||
|
|
|
|||
|
|
@ -289,6 +289,13 @@ public:
|
|||
bool swapped;
|
||||
bool explicitpitch;
|
||||
|
||||
// Locations in the level mesh light list. Ends with index = 0 or all entries used
|
||||
enum { max_levelmesh_entries = 4 };
|
||||
struct
|
||||
{
|
||||
int index;
|
||||
int portalgroup;
|
||||
} levelmesh[max_levelmesh_entries];
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -175,10 +175,101 @@ DoomLevelMesh::DoomLevelMesh(FLevelLocals& doomMap)
|
|||
Mesh.MaxUniforms = std::max(Mesh.Uniforms.size() * 2, (size_t)10000);
|
||||
Mesh.MaxSurfaceIndexes = std::max(Mesh.SurfaceIndexes.size() * 2, (size_t)10000);
|
||||
Mesh.MaxNodes = std::max(Collision->get_nodes().size() * 2, (size_t)10000);
|
||||
Mesh.MaxLights = 100'000;
|
||||
Mesh.MaxLightIndexes = 4 * 1024 * 1024;
|
||||
}
|
||||
|
||||
void DoomLevelMesh::CreateLights(FLevelLocals& doomMap)
|
||||
{
|
||||
if (Mesh.Lights.Size() != 0)
|
||||
return;
|
||||
|
||||
for (DoomLevelMeshSurface& surface : Surfaces)
|
||||
{
|
||||
surface.LightList.Pos = Mesh.LightIndexes.Size();
|
||||
surface.LightList.Count = 0;
|
||||
|
||||
std::pair<FLightNode*, int> nodePortalGroup = GetSurfaceLightNode(&surface);
|
||||
FLightNode* node = nodePortalGroup.first;
|
||||
int portalgroup = nodePortalGroup.second;
|
||||
if (!node)
|
||||
continue;
|
||||
|
||||
int listpos = 0;
|
||||
while (node)
|
||||
{
|
||||
FDynamicLight* light = node->lightsource;
|
||||
if (light && light->Trace())
|
||||
{
|
||||
int lightindex = GetLightIndex(light, portalgroup);
|
||||
if (lightindex >= 0)
|
||||
{
|
||||
Mesh.LightIndexes.Push(lightindex);
|
||||
surface.LightList.Count++;
|
||||
}
|
||||
}
|
||||
node = node->nextLight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int DoomLevelMesh::GetLightIndex(FDynamicLight* light, int portalgroup)
|
||||
{
|
||||
int index;
|
||||
for (index = 0; index < FDynamicLight::max_levelmesh_entries && light->levelmesh[index].index != 0; index++)
|
||||
{
|
||||
if (light->levelmesh[index].portalgroup == portalgroup)
|
||||
return light->levelmesh[index].index - 1;
|
||||
}
|
||||
if (index == FDynamicLight::max_levelmesh_entries)
|
||||
return 0;
|
||||
|
||||
DVector3 pos = light->PosRelative(portalgroup);
|
||||
|
||||
LevelMeshLight meshlight;
|
||||
meshlight.Origin = { (float)pos.X, (float)pos.Y, (float)pos.Z };
|
||||
meshlight.RelativeOrigin = meshlight.Origin;
|
||||
meshlight.Radius = (float)light->GetRadius();
|
||||
meshlight.Intensity = (float)light->target->Alpha;
|
||||
if (light->IsSpot())
|
||||
{
|
||||
meshlight.InnerAngleCos = (float)light->pSpotInnerAngle->Cos();
|
||||
meshlight.OuterAngleCos = (float)light->pSpotOuterAngle->Cos();
|
||||
|
||||
DAngle negPitch = -*light->pPitch;
|
||||
DAngle Angle = light->target->Angles.Yaw;
|
||||
double xzLen = negPitch.Cos();
|
||||
meshlight.SpotDir.X = float(-Angle.Cos() * xzLen);
|
||||
meshlight.SpotDir.Y = float(-Angle.Sin() * xzLen);
|
||||
meshlight.SpotDir.Z = float(-negPitch.Sin());
|
||||
}
|
||||
else
|
||||
{
|
||||
meshlight.InnerAngleCos = -1.0f;
|
||||
meshlight.OuterAngleCos = -1.0f;
|
||||
meshlight.SpotDir.X = 0.0f;
|
||||
meshlight.SpotDir.Y = 0.0f;
|
||||
meshlight.SpotDir.Z = 0.0f;
|
||||
}
|
||||
meshlight.Color.X = light->GetRed() * (1.0f / 255.0f);
|
||||
meshlight.Color.Y = light->GetGreen() * (1.0f / 255.0f);
|
||||
meshlight.Color.Z = light->GetBlue() * (1.0f / 255.0f);
|
||||
|
||||
if (light->Sector)
|
||||
meshlight.SectorGroup = sectorGroup[light->Sector->Index()];
|
||||
else
|
||||
meshlight.SectorGroup = 0;
|
||||
|
||||
int lightindex = Mesh.Lights.Size();
|
||||
light->levelmesh[index].index = lightindex + 1;
|
||||
light->levelmesh[index].portalgroup = portalgroup;
|
||||
Mesh.Lights.Push(meshlight);
|
||||
return lightindex;
|
||||
}
|
||||
|
||||
void DoomLevelMesh::BeginFrame(FLevelLocals& doomMap)
|
||||
{
|
||||
CreateLights(doomMap);
|
||||
#if 0
|
||||
static_cast<DoomLevelSubmesh*>(DynamicMesh.get())->Update(doomMap);
|
||||
if (doomMap.lightmaps)
|
||||
|
|
@ -196,63 +287,6 @@ bool DoomLevelMesh::TraceSky(const FVector3& start, FVector3 direction, float di
|
|||
return surface && surface->IsSky;
|
||||
}
|
||||
|
||||
int DoomLevelMesh::AddSurfaceLights(const LevelMeshSurface* surface, LevelMeshLight* list, int listMaxSize)
|
||||
{
|
||||
std::pair<FLightNode*, int> nodePortalGroup = GetSurfaceLightNode(static_cast<const DoomLevelMeshSurface*>(surface));
|
||||
FLightNode* node = nodePortalGroup.first;
|
||||
int portalgroup = nodePortalGroup.second;
|
||||
if (!node)
|
||||
return 0;
|
||||
|
||||
int listpos = 0;
|
||||
while (node && listpos < listMaxSize)
|
||||
{
|
||||
FDynamicLight* light = node->lightsource;
|
||||
if (light && light->Trace())
|
||||
{
|
||||
DVector3 pos = light->PosRelative(portalgroup);
|
||||
|
||||
LevelMeshLight& meshlight = list[listpos++];
|
||||
meshlight.Origin = { (float)pos.X, (float)pos.Y, (float)pos.Z };
|
||||
meshlight.RelativeOrigin = meshlight.Origin;
|
||||
meshlight.Radius = (float)light->GetRadius();
|
||||
meshlight.Intensity = (float)light->target->Alpha;
|
||||
if (light->IsSpot())
|
||||
{
|
||||
meshlight.InnerAngleCos = (float)light->pSpotInnerAngle->Cos();
|
||||
meshlight.OuterAngleCos = (float)light->pSpotOuterAngle->Cos();
|
||||
|
||||
DAngle negPitch = -*light->pPitch;
|
||||
DAngle Angle = light->target->Angles.Yaw;
|
||||
double xzLen = negPitch.Cos();
|
||||
meshlight.SpotDir.X = float(-Angle.Cos() * xzLen);
|
||||
meshlight.SpotDir.Y = float(-Angle.Sin() * xzLen);
|
||||
meshlight.SpotDir.Z = float(-negPitch.Sin());
|
||||
}
|
||||
else
|
||||
{
|
||||
meshlight.InnerAngleCos = -1.0f;
|
||||
meshlight.OuterAngleCos = -1.0f;
|
||||
meshlight.SpotDir.X = 0.0f;
|
||||
meshlight.SpotDir.Y = 0.0f;
|
||||
meshlight.SpotDir.Z = 0.0f;
|
||||
}
|
||||
meshlight.Color.X = light->GetRed() * (1.0f / 255.0f);
|
||||
meshlight.Color.Y = light->GetGreen() * (1.0f / 255.0f);
|
||||
meshlight.Color.Z = light->GetBlue() * (1.0f / 255.0f);
|
||||
|
||||
if (light->Sector)
|
||||
meshlight.SectorGroup = sectorGroup[light->Sector->Index()];
|
||||
else
|
||||
meshlight.SectorGroup = 0;
|
||||
}
|
||||
|
||||
node = node->nextLight;
|
||||
}
|
||||
|
||||
return listpos;
|
||||
}
|
||||
|
||||
std::pair<FLightNode*, int> DoomLevelMesh::GetSurfaceLightNode(const DoomLevelMeshSurface* doomsurf)
|
||||
{
|
||||
FLightNode* node = nullptr;
|
||||
|
|
|
|||
|
|
@ -49,7 +49,6 @@ public:
|
|||
LevelMeshSurface* GetSurface(int index) override { return &Surfaces[index]; }
|
||||
unsigned int GetSurfaceIndex(const LevelMeshSurface* surface) const override { return (unsigned int)(ptrdiff_t)(static_cast<const DoomLevelMeshSurface*>(surface) - Surfaces.Data()); }
|
||||
int GetSurfaceCount() override { return Surfaces.Size(); }
|
||||
int AddSurfaceLights(const LevelMeshSurface* surface, LevelMeshLight* list, int listMaxSize) override;
|
||||
|
||||
void BeginFrame(FLevelLocals& doomMap);
|
||||
bool TraceSky(const FVector3& start, FVector3 direction, float dist);
|
||||
|
|
@ -65,6 +64,8 @@ public:
|
|||
TArray<int> sectorPortals[2]; // index is sector+plane, value is index into the portal list
|
||||
TArray<int> linePortals; // index is linedef, value is index into the portal list
|
||||
|
||||
void CreateLights(FLevelLocals& doomMap);
|
||||
|
||||
private:
|
||||
void CreateSurfaces(FLevelLocals& doomMap);
|
||||
|
||||
|
|
@ -89,6 +90,8 @@ private:
|
|||
void CreatePortals(FLevelLocals& doomMap);
|
||||
std::pair<FLightNode*, int> GetSurfaceLightNode(const DoomLevelMeshSurface* doomsurf);
|
||||
|
||||
int GetLightIndex(FDynamicLight* light, int portalgroup);
|
||||
|
||||
TArray<SideSurfaceRange> Sides;
|
||||
TArray<FlatSurfaceRange> Flats;
|
||||
std::map<LightmapTileBinding, int> bindings;
|
||||
|
|
|
|||
|
|
@ -41,7 +41,8 @@ struct LightInfo
|
|||
layout(set = 0, binding = 1) buffer SurfaceIndexBuffer { uint surfaceIndices[]; };
|
||||
layout(set = 0, binding = 2) buffer SurfaceBuffer { SurfaceInfo surfaces[]; };
|
||||
layout(set = 0, binding = 3) buffer LightBuffer { LightInfo lights[]; };
|
||||
layout(set = 0, binding = 4) buffer PortalBuffer { PortalInfo portals[]; };
|
||||
layout(set = 0, binding = 4) buffer LightIndexBuffer { int lightIndexes[]; };
|
||||
layout(set = 0, binding = 5) buffer PortalBuffer { PortalInfo portals[]; };
|
||||
|
||||
struct LightmapRaytracePC
|
||||
{
|
||||
|
|
@ -61,4 +62,4 @@ struct LightmapRaytracePC
|
|||
float TileHeight;
|
||||
};
|
||||
|
||||
layout(std430, set = 0, binding = 5) buffer ConstantsBuffer { LightmapRaytracePC constants[]; };
|
||||
layout(std430, set = 0, binding = 6) buffer ConstantsBuffer { LightmapRaytracePC constants[]; };
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ void main()
|
|||
|
||||
for (uint j = LightStart; j < LightEnd; j++)
|
||||
{
|
||||
incoming += TraceLight(origin, normal, lights[j], SurfaceIndex);
|
||||
incoming += TraceLight(origin, normal, lights[lightIndexes[j]], SurfaceIndex);
|
||||
}
|
||||
|
||||
#if defined(USE_AO)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue