diff --git a/src/common/rendering/hwrenderer/data/hw_levelmesh.h b/src/common/rendering/hwrenderer/data/hw_levelmesh.h index c230f4a515..21f6cb52d2 100644 --- a/src/common/rendering/hwrenderer/data/hw_levelmesh.h +++ b/src/common/rendering/hwrenderer/data/hw_levelmesh.h @@ -4,8 +4,27 @@ #include "tarray.h" #include "vectors.h" #include "hw_collision.h" +#include "bounds.h" #include +#include + +typedef dp::rect_pack::RectPacker RectPacker; + +struct SurfaceInfo // This is the structure of the buffer inside the shader +{ + FVector3 Normal; + float Sky; + float SamplingDistance; + uint32_t PortalIndex; + float Padding1, Padding2; +}; + +struct PortalInfo // This is the structure of the buffer inside the shader +{ + float transformation[16]; // mat4 +}; + namespace hwrenderer { @@ -43,6 +62,7 @@ public: // Surface geometry SurfaceType type = ST_UNKNOWN; TArray verts; + TArray uvs; //Plane plane; FVector3 boundsMin, boundsMax; @@ -80,6 +100,68 @@ struct SmoothingGroup std::vector surfaces; }; +struct Portal +{ + float transformation[4][4] = { + {1, 0, 0, 0}, + {0, 1, 0, 0}, + {0, 0, 1, 0}, + {0, 0, 0, 1} + }; + + int sourceSectorGroup = 0; + int targetSectorGroup = 0; + + inline FVector4 Mat4Vec4Mul(const FVector4& vec) const + { + FVector4 result(0.0f, 0.0f, 0.0f, 0.0f); + for (int i = 0; i < 4; ++i) { + for (int j = 0; j < 4; ++j) { + result[i] += transformation[i][j] * vec[j]; + } + } + return result; + } + + inline FVector3 TransformPosition(const FVector3& pos) const + { + auto v = Mat4Vec4Mul(FVector4(pos, 1.0)); + return FVector3(v.X, v.Y, v.Z); + } + + inline FVector3 TransformRotation(const FVector3& dir) const + { + auto v = Mat4Vec4Mul(FVector4(dir, 0.0)); + return FVector3(v.X, v.Y, v.Z); + } + + // Checks only transformation + inline bool IsInverseTransformationPortal(const Portal& portal) const + { + auto diff = portal.TransformPosition(TransformPosition(FVector3(0, 0, 0))); + return abs(diff.X) < 0.001 && abs(diff.Y) < 0.001 && abs(diff.Z) < 0.001; + } + + // Checks only transformation + inline bool IsEqualTransformationPortal(const Portal& portal) const + { + auto diff = portal.TransformPosition(FVector3(0, 0, 0)) - TransformPosition(FVector3(0, 0, 0)); + return (abs(diff.X) < 0.001 && abs(diff.Y) < 0.001 && abs(diff.Z) < 0.001); + } + + // Checks transformation, source and destiantion sector groups + inline bool IsEqualPortal(const Portal& portal) const + { + return sourceSectorGroup == portal.sourceSectorGroup && targetSectorGroup == portal.targetSectorGroup && IsEqualTransformationPortal(portal); + } + + // Checks transformation, source and destiantion sector groups + inline bool IsInversePortal(const Portal& portal) const + { + return sourceSectorGroup == portal.targetSectorGroup && targetSectorGroup == portal.sourceSectorGroup && IsInverseTransformationPortal(portal); + } +}; + class LevelMesh { public: @@ -90,11 +172,15 @@ public: TArray MeshElements; TArray MeshSurfaces; + TArray surfaceInfo; + TArray portalInfo; + std::unique_ptr Collision; - // To do: these are currently not filled - TArray> surfaces; - TArray smoothingGroups; + std::vector> surfaces; + TArray smoothingGroups; // TODO fill + TArray portals; // TODO fill + FVector3 SunDirection; FVector3 SunColor; @@ -103,6 +189,29 @@ public: FVector3 end = start + direction * std::max(maxDist - 10.0f, 0.0f); return !TriangleMeshShape::find_any_hit(Collision.get(), start, end); } + + inline void FinishSurface(int lightmapTextureWidth, int lightmapTextureHeight, RectPacker& packer, Surface& surface) + { + int sampleWidth = surface.texWidth; + int sampleHeight = surface.texHeight; + + auto result = packer.insert(sampleWidth, sampleHeight); + int x = result.pos.x, y = result.pos.y; + surface.atlasPageIndex = (int)result.pageIndex; + + // calculate final texture coordinates + for (unsigned i = 0; i < surface.uvs.Size(); i++) + { + auto& u = surface.uvs[i].X; + auto& v = surface.uvs[i].Y; + u = (u + x) / (float)lightmapTextureWidth; + v = (v + y) / (float)lightmapTextureHeight; + } + + surface.atlasX = x; + surface.atlasY = y; + + } }; } // namespace diff --git a/src/common/rendering/v_video.h b/src/common/rendering/v_video.h index df12a82a3c..cae60a38a6 100644 --- a/src/common/rendering/v_video.h +++ b/src/common/rendering/v_video.h @@ -220,7 +220,7 @@ public: virtual int GetClientHeight() = 0; virtual void BlurScene(float amount) {} - virtual void InitLightmap(int LMTextureSize, int LMTextureCount, TArray& LMTextureData) {} + virtual void InitLightmap(int LMTextureSize, int LMTextureCount, TArray& LMTextureData, hwrenderer::LevelMesh& mesh) {} // Interface to hardware rendering resources virtual IBuffer* CreateVertexBuffer(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute* attrs) { return nullptr; } diff --git a/src/common/rendering/vulkan/accelstructs/vk_lightmap.cpp b/src/common/rendering/vulkan/accelstructs/vk_lightmap.cpp index 0471dd014b..b05a2d7938 100644 --- a/src/common/rendering/vulkan/accelstructs/vk_lightmap.cpp +++ b/src/common/rendering/vulkan/accelstructs/vk_lightmap.cpp @@ -1,11 +1,13 @@ #include "vk_lightmap.h" #include "vulkan/vk_renderdevice.h" +#include "vk_raytrace.h" #include "zvulkan/vulkanbuilders.h" #include "halffloat.h" #include "filesystem.h" #include "cmdlib.h" + VkLightmap::VkLightmap(VulkanRenderDevice* fb) : fb(fb) { useRayQuery = fb->GetDevice()->PhysicalDevice.Features.RayQuery.rayQuery; @@ -90,7 +92,7 @@ void VkLightmap::RenderAtlasImage(size_t pageIndex) }; beginPass(); - for (size_t i = 0; i < mesh->surfaces.Size(); i++) + for (size_t i = 0; i < mesh->surfaces.size(); i++) { hwrenderer::Surface* targetSurface = mesh->surfaces[i].get(); if (targetSurface->atlasPageIndex != pageIndex) @@ -157,14 +159,14 @@ void VkLightmap::RenderAtlasImage(size_t pageIndex) lightinfo++; } - PushConstants pc; + LightmapPushConstants pc; pc.LightStart = firstLight; pc.LightEnd = firstLight + lightCount; pc.SurfaceIndex = (int32_t)i; pc.LightmapOrigin = targetSurface->worldOrigin - targetSurface->worldStepX - targetSurface->worldStepY; pc.LightmapStepX = targetSurface->worldStepX * viewport.width; pc.LightmapStepY = targetSurface->worldStepY * viewport.height; - cmdbuffer->pushConstants(raytrace.pipelineLayout.get(), VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushConstants), &pc); + cmdbuffer->pushConstants(raytrace.pipelineLayout.get(), VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(LightmapPushConstants), &pc); SceneVertex* vertex = &vertices.Vertices[firstVertex]; @@ -195,7 +197,7 @@ void VkLightmap::CreateAtlasImages() const int spacing = 3; // Note: the spacing is here to avoid that the resolve sampler finds data from other surface tiles RectPacker packer(atlasImageSize, atlasImageSize, RectPacker::Spacing(spacing)); - for (size_t i = 0; i < mesh->surfaces.Size(); i++) + for (size_t i = 0; i < mesh->surfaces.size(); i++) { hwrenderer::Surface* surface = mesh->surfaces[i].get(); @@ -260,14 +262,14 @@ void VkLightmap::ResolveAtlasImage(size_t i) viewport.height = (float)atlasImageSize; cmdbuffer->setViewport(0, 1, &viewport); - PushConstants pc; + LightmapPushConstants pc; pc.LightStart = 0; pc.LightEnd = 0; pc.SurfaceIndex = 0; pc.LightmapOrigin = FVector3(0.0f, 0.0f, 0.0f); pc.LightmapStepX = FVector3(0.0f, 0.0f, 0.0f); pc.LightmapStepY = FVector3(0.0f, 0.0f, 0.0f); - cmdbuffer->pushConstants(resolve.pipelineLayout.get(), VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(PushConstants), &pc); + cmdbuffer->pushConstants(resolve.pipelineLayout.get(), VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(LightmapPushConstants), &pc); int firstVertex = vertices.Pos; int vertexCount = 4; @@ -304,7 +306,7 @@ void VkLightmap::DownloadAtlasImage(size_t pageIndex) hvec4* pixels = (hvec4*)atlasImages[pageIndex].Transfer->Map(0, atlasImageSize * atlasImageSize * sizeof(hvec4)); - for (size_t i = 0; i < mesh->surfaces.Size(); i++) + for (size_t i = 0; i < mesh->surfaces.size(); i++) { hwrenderer::Surface* surface = mesh->surfaces[i].get(); if (surface->atlasPageIndex != pageIndex) @@ -406,7 +408,7 @@ void VkLightmap::CreateRaytracePipeline() raytrace.pipelineLayout = PipelineLayoutBuilder() .AddSetLayout(raytrace.descriptorSetLayout0.get()) .AddSetLayout(raytrace.descriptorSetLayout1.get()) - .AddPushConstantRange(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushConstants)) + .AddPushConstantRange(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(LightmapPushConstants)) .DebugName("raytrace.pipelineLayout") .Create(fb->GetDevice()); @@ -476,32 +478,37 @@ void VkLightmap::CreateRaytracePipeline() void VkLightmap::UpdateAccelStructDescriptors() { - // To do: fetch this from VkDescriptorSetManager - perhaps manage it all over there? + auto nodesBuffer = fb->GetRaytrace()->GetNodeBuffer(); + auto tlAccelStruct = fb->GetRaytrace()->GetAccelStruct(); + auto vertexBuffer = fb->GetRaytrace()->GetVertexBuffer(); + auto indexBuffer = fb->GetRaytrace()->GetIndexBuffer(); + auto surfaceIndexBuffer = fb->GetRaytrace()->GetSurfaceIndexBuffer(); + auto surfaceBuffer = fb->GetRaytrace()->GetSurfaceIndexBuffer(); + auto portalBuffer = fb->GetRaytrace()->GetPortalBuffer(); -#if 0 if (useRayQuery) { WriteDescriptors() - .AddAccelerationStructure(raytrace.descriptorSet1.get(), 0, tlAccelStruct.get()) + .AddAccelerationStructure(raytrace.descriptorSet1.get(), 0, tlAccelStruct) .Execute(fb->GetDevice()); } else { WriteDescriptors() - .AddBuffer(raytrace.descriptorSet1.get(), 0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, nodesBuffer.get()) - .AddBuffer(raytrace.descriptorSet1.get(), 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vertexBuffer.get()) - .AddBuffer(raytrace.descriptorSet1.get(), 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, indexBuffer.get()) + .AddBuffer(raytrace.descriptorSet1.get(), 0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, nodesBuffer) + .AddBuffer(raytrace.descriptorSet1.get(), 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vertexBuffer) + .AddBuffer(raytrace.descriptorSet1.get(), 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, indexBuffer) .Execute(fb->GetDevice()); } WriteDescriptors() - .AddBuffer(raytrace.descriptorSet0.get(), 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, uniformBuffer.get(), 0, sizeof(Uniforms)) - .AddBuffer(raytrace.descriptorSet0.get(), 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, surfaceIndexBuffer.get()) - .AddBuffer(raytrace.descriptorSet0.get(), 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, surfaceBuffer.get()) - .AddBuffer(raytrace.descriptorSet0.get(), 3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, sceneLightBuffer.get()) - .AddBuffer(raytrace.descriptorSet0.get(), 4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, portalBuffer.get()) + .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, surfaceIndexBuffer) + .AddBuffer(raytrace.descriptorSet0.get(), 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, surfaceBuffer) + //.AddBuffer(raytrace.descriptorSet0.get(), 3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, sceneLightBuffer.get()) // TODO !!!!!!!!! + .AddBuffer(raytrace.descriptorSet0.get(), 4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, portalBuffer) .Execute(fb->GetDevice()); -#endif + } void VkLightmap::CreateResolvePipeline() @@ -513,7 +520,7 @@ void VkLightmap::CreateResolvePipeline() resolve.pipelineLayout = PipelineLayoutBuilder() .AddSetLayout(resolve.descriptorSetLayout.get()) - .AddPushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(PushConstants)) + .AddPushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(LightmapPushConstants)) .DebugName("resolve.pipelineLayout") .Create(fb->GetDevice()); diff --git a/src/common/rendering/vulkan/accelstructs/vk_lightmap.h b/src/common/rendering/vulkan/accelstructs/vk_lightmap.h index aaacba6d9f..c07784483e 100644 --- a/src/common/rendering/vulkan/accelstructs/vk_lightmap.h +++ b/src/common/rendering/vulkan/accelstructs/vk_lightmap.h @@ -17,7 +17,7 @@ struct Uniforms float SunIntensity; }; -struct PushConstants +struct LightmapPushConstants { uint32_t LightStart; uint32_t LightEnd; diff --git a/src/common/rendering/vulkan/accelstructs/vk_raytrace.cpp b/src/common/rendering/vulkan/accelstructs/vk_raytrace.cpp index 06fa0e2a8a..03b0221297 100644 --- a/src/common/rendering/vulkan/accelstructs/vk_raytrace.cpp +++ b/src/common/rendering/vulkan/accelstructs/vk_raytrace.cpp @@ -70,6 +70,8 @@ void VkRaytrace::Reset() deletelist->Add(std::move(indexBuffer)); deletelist->Add(std::move(transferBuffer)); deletelist->Add(std::move(nodesBuffer)); + deletelist->Add(std::move(surfaceBuffer)); + deletelist->Add(std::move(portalBuffer)); deletelist->Add(std::move(blScratchBuffer)); deletelist->Add(std::move(blAccelStructBuffer)); deletelist->Add(std::move(blAccelStruct)); @@ -133,10 +135,32 @@ void VkRaytrace::CreateVertexAndIndexBuffers() .DebugName("nodesBuffer") .Create(fb->GetDevice()); + surfaceIndexBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT) + .Size(Mesh->MeshSurfaces.Size() * sizeof(int)) + .DebugName("surfaceBuffer") + .Create(fb->GetDevice()); + + surfaceBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT) + .Size(Mesh->surfaces.size() * sizeof(SurfaceInfo)) + .DebugName("surfaceBuffer") + .Create(fb->GetDevice()); + + portalBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT) + .Size(Mesh->portals.Size() * sizeof(SurfaceInfo)) + .DebugName("portalBuffer") + .Create(fb->GetDevice()); + + transferBuffer = BufferTransfer() .AddBuffer(vertexBuffer.get(), vertices.data(), vertices.size() * sizeof(FVector4)) .AddBuffer(indexBuffer.get(), Mesh->MeshElements.Data(), (size_t)Mesh->MeshElements.Size() * sizeof(uint32_t)) .AddBuffer(nodesBuffer.get(), &nodesHeader, sizeof(CollisionNodeBufferHeader), nodes.data(), nodes.size() * sizeof(CollisionNode)) + .AddBuffer(surfaceIndexBuffer.get(), &nodesHeader, sizeof(int), Mesh->MeshSurfaces.Data(), Mesh->MeshSurfaces.Size() * sizeof(int)) + .AddBuffer(surfaceBuffer.get(), Mesh->surfaceInfo.Data(), Mesh->surfaceInfo.Size() * sizeof(SurfaceInfo)) + .AddBuffer(portalBuffer.get(), Mesh->portalInfo.Data(), Mesh->portalInfo.Size() * sizeof(PortalInfo)) .Execute(fb->GetDevice(), fb->GetCommands()->GetTransferCommands()); PipelineBarrier() diff --git a/src/common/rendering/vulkan/accelstructs/vk_raytrace.h b/src/common/rendering/vulkan/accelstructs/vk_raytrace.h index d914f6efeb..8ca43891ee 100644 --- a/src/common/rendering/vulkan/accelstructs/vk_raytrace.h +++ b/src/common/rendering/vulkan/accelstructs/vk_raytrace.h @@ -37,6 +37,9 @@ public: VulkanBuffer* GetVertexBuffer() { return vertexBuffer.get(); } VulkanBuffer* GetIndexBuffer() { return indexBuffer.get(); } VulkanBuffer* GetNodeBuffer() { return nodesBuffer.get(); } + VulkanBuffer* GetSurfaceIndexBuffer() { return surfaceIndexBuffer.get(); } + VulkanBuffer* GetSurfaceBuffer() { return surfaceBuffer.get(); } + VulkanBuffer* GetPortalBuffer() { return portalBuffer.get(); } private: void Reset(); @@ -58,6 +61,9 @@ private: std::unique_ptr indexBuffer; std::unique_ptr transferBuffer; std::unique_ptr nodesBuffer; + std::unique_ptr surfaceIndexBuffer; + std::unique_ptr surfaceBuffer; + std::unique_ptr portalBuffer; std::unique_ptr blScratchBuffer; std::unique_ptr blAccelStructBuffer; diff --git a/src/common/rendering/vulkan/vk_renderdevice.cpp b/src/common/rendering/vulkan/vk_renderdevice.cpp index bcf1b916b6..bc477e7ec1 100644 --- a/src/common/rendering/vulkan/vk_renderdevice.cpp +++ b/src/common/rendering/vulkan/vk_renderdevice.cpp @@ -43,6 +43,7 @@ #include "vulkan/vk_renderstate.h" #include "vulkan/vk_postprocess.h" #include "vulkan/accelstructs/vk_raytrace.h" +#include "vulkan/accelstructs/vk_lightmap.h" #include "vulkan/pipelines/vk_renderpass.h" #include "vulkan/descriptorsets/vk_descriptorset.h" #include "vulkan/shaders/vk_shader.h" @@ -61,6 +62,7 @@ #include #include "engineerrors.h" #include "c_dispatch.h" +#include "accelstructs/halffloat.h" FString JitCaptureStackTrace(int framesToSkip, bool includeNativeFrames, int maxFrames = -1); @@ -474,8 +476,47 @@ void VulkanRenderDevice::BeginFrame() mDescriptorSetManager->BeginFrame(); } -void VulkanRenderDevice::InitLightmap(int LMTextureSize, int LMTextureCount, TArray& LMTextureData) +void VulkanRenderDevice::InitLightmap(int LMTextureSize, int LMTextureCount, TArray& LMTextureData, hwrenderer::LevelMesh& mesh) { + if(mesh.surfaces.size() > 0) + { + Printf("Running VkLightmap.\n"); + + VkLightmap lightmap(this); + lightmap.Raytrace(&mesh); + + Printf("Copying data.\n"); + + // TODO refactor + + auto clamp = [](float a, float min, float max) -> float { return a < min ? min : a > max ? max : a; }; + + RectPacker packer(LMTextureSize, LMTextureSize); + + for (auto& surface : mesh.surfaces) + { + mesh.FinishSurface(LMTextureSize, LMTextureSize, packer, *surface.get()); + + uint16_t* currentTexture = LMTextureData.Data() + (LMTextureSize * LMTextureSize * 3) * surface->atlasPageIndex; + + FVector3* colorSamples = surface->texPixels.data(); + // store results to lightmap texture + for (int i = 0; i < surface->texHeight; i++) + { + for (int j = 0; j < surface->texWidth; j++) + { + // get texture offset + int offs = ((surface->texWidth * (i + surface->atlasY)) + surface->atlasX) * 3; + + // convert RGB to bytes + currentTexture[offs + j * 3 + 0] = floatToHalf(clamp(colorSamples[i * surface->texWidth + j].X, 0.0f, 65000.0f)); + currentTexture[offs + j * 3 + 1] = floatToHalf(clamp(colorSamples[i * surface->texWidth + j].Y, 0.0f, 65000.0f)); + currentTexture[offs + j * 3 + 2] = floatToHalf(clamp(colorSamples[i * surface->texWidth + j].Z, 0.0f, 65000.0f)); + } + } + } + } + if (LMTextureData.Size() > 0) { GetTextureManager()->SetLightmap(LMTextureSize, LMTextureCount, LMTextureData); diff --git a/src/common/rendering/vulkan/vk_renderdevice.h b/src/common/rendering/vulkan/vk_renderdevice.h index 58d1733590..d147e3ab62 100644 --- a/src/common/rendering/vulkan/vk_renderdevice.h +++ b/src/common/rendering/vulkan/vk_renderdevice.h @@ -56,7 +56,7 @@ public: void SetTextureFilterMode() override; void StartPrecaching() override; void BeginFrame() override; - void InitLightmap(int LMTextureSize, int LMTextureCount, TArray& LMTextureData) override; + void InitLightmap(int LMTextureSize, int LMTextureCount, TArray& LMTextureData, hwrenderer::LevelMesh& mesh) override; void BlurScene(float amount) override; void PostProcessScene(bool swscene, int fixedcm, float flash, const std::function &afterBloomDrawEndScene2D) override; void AmbientOccludeScene(float m5) override; diff --git a/src/maploader/maploader.cpp b/src/maploader/maploader.cpp index f482fdeaca..5a4b468b39 100644 --- a/src/maploader/maploader.cpp +++ b/src/maploader/maploader.cpp @@ -3214,7 +3214,7 @@ void MapLoader::LoadLevel(MapData *map, const char *lumpname, int position) Level->levelMesh = new DoomLevelMesh(*Level); InitLightmap(map); - screen->InitLightmap(Level->LMTextureSize, Level->LMTextureCount, Level->LMTextureData); + screen->InitLightmap(Level->LMTextureSize, Level->LMTextureCount, Level->LMTextureData, *Level->levelMesh); for (int i = 0; i < MAXPLAYERS; ++i) { @@ -3327,7 +3327,7 @@ void MapLoader::SetSideLightmap(const LightmapSurface &surface) } } -#include "halffloat.h" +#include "vulkan/accelstructs/halffloat.h" void MapLoader::InitLightmap(MapData* map) { @@ -3342,6 +3342,10 @@ void MapLoader::InitLightmap(MapData* map) Level->SunColor = FVector3(1.f, 1.f, 1.f); Level->SunDirection = FVector3(0.45f, 0.3f, 0.9f); + // TODO keep only one copy? + Level->levelMesh->SunColor = Level->SunColor; + Level->levelMesh->SunDirection = Level->SunDirection; + Level->LMTextureCount = Level->levelMesh->SetupLightmapUvs(Level->LMTextureSize); @@ -3386,7 +3390,7 @@ void MapLoader::InitLightmap(MapData* map) return buffer.Data() + ((y * width) + x + (height * width * page)) * 3; }; - +#if 0 srand(1337); for (auto& surface : Level->levelMesh->Surfaces) { @@ -3394,9 +3398,9 @@ void MapLoader::InitLightmap(MapData* map) float g; float b; - r = rand() % 32 / 32.0; - g = rand() % 32 / 32.0; - b = rand() % 32 / 32.0; + r = rand() % 32 / 32.0f; + g = rand() % 32 / 32.0f; + b = rand() % 32 / 32.0f; for (int y = 0; y <= surface.texHeight; ++y) { @@ -3430,6 +3434,7 @@ void MapLoader::InitLightmap(MapData* map) } } } +#endif }; int size = Level->LMTextureSize; diff --git a/src/rendering/hwrenderer/doom_levelmesh.cpp b/src/rendering/hwrenderer/doom_levelmesh.cpp index 0015789ff7..eb02f62687 100644 --- a/src/rendering/hwrenderer/doom_levelmesh.cpp +++ b/src/rendering/hwrenderer/doom_levelmesh.cpp @@ -9,6 +9,7 @@ #include "c_dispatch.h" #include "g_levellocals.h" +#include "common/rendering/vulkan/accelstructs/vk_lightmap.h" CCMD(dumplevelmesh) { @@ -450,7 +451,7 @@ void DoomLevelMesh::DumpMesh(const FString& filename) const fprintf(f, "# DoomLevelMesh debug export\n"); fprintf(f, "# MeshVertices: %d, MeshElements: %d\n", MeshVertices.Size(), MeshElements.Size()); - double scale = 1 / 100.0; + double scale = 1 / 10.0; for (const auto& v : MeshVertices) { @@ -459,14 +460,14 @@ void DoomLevelMesh::DumpMesh(const FString& filename) const { const auto s = LightmapUvs.Size(); - for (int i = 0; i + 1 < s; i += 2) + for (unsigned i = 0; i + 1 < s; i += 2) { fprintf(f, "vt %f %f\n", LightmapUvs[i], LightmapUvs[i + 1]); } } const auto s = MeshElements.Size(); - for (auto i = 0; i + 2 < s; i += 3) + for (unsigned i = 0; i + 2 < s; i += 3) { // fprintf(f, "f %d %d %d\n", MeshElements[i] + 1, MeshElements[i + 1] + 1, MeshElements[i + 2] + 1); fprintf(f, "f %d/%d %d/%d %d/%d\n", @@ -490,6 +491,34 @@ int DoomLevelMesh::SetupLightmapUvs(int lightmapSize) sortedSurfaces.push_back(&surface); } + for (const auto& surface : Surfaces) + { + auto hwSurface = std::make_unique(); + + hwSurface->boundsMax = surface.bounds.max; + hwSurface->boundsMin = surface.bounds.min; + + // hwSurface->LightList = // TODO + hwSurface->projLocalToU = surface.projLocalToU; + hwSurface->projLocalToV = surface.projLocalToV; + hwSurface->smoothingGroupIndex = -1; + hwSurface->texHeight = surface.texHeight; + hwSurface->texWidth = surface.texWidth; + + hwSurface->translateWorldToLocal = surface.translateWorldToLocal; + hwSurface->type = hwrenderer::SurfaceType(surface.type); + + hwSurface->texPixels.resize(surface.texWidth * surface.texHeight); + + for (int i = 0; i < surface.numVerts; ++i) + { + hwSurface->verts.Push(MeshVertices[surface.startVertIndex + i]); + } + + // TODO push + surfaces.push_back(std::move(hwSurface)); + } + std::sort(sortedSurfaces.begin(), sortedSurfaces.end(), [](Surface* a, Surface* b) { return a->texHeight != b->texHeight ? a->texHeight > b->texHeight : a->texWidth > b->texWidth; }); RectPacker packer(lightmapSize, lightmapSize, RectPacker::Spacing(0)); @@ -536,7 +565,7 @@ void DoomLevelMesh::FinishSurface(int lightmapTextureWidth, int lightmapTextureH auto result = packer.insert(sampleWidth, sampleHeight); int x = result.pos.x, y = result.pos.y; - surface.atlasPageIndex = result.pageIndex; + surface.atlasPageIndex = (int)result.pageIndex; // calculate final texture coordinates auto uvIndex = surface.startUvIndex; @@ -637,7 +666,7 @@ void DoomLevelMesh::BuildSurfaceParams(int lightMapTextureWidth, int lightMapTex plane = &surface.plane; bounds = GetBoundsFromSurface(surface); - //surface->bounds = bounds; + surface.bounds = bounds; if (surface.sampleDimension <= 0) { diff --git a/src/rendering/hwrenderer/doom_levelmesh.h b/src/rendering/hwrenderer/doom_levelmesh.h index 7b26da1712..0dd70fd58b 100644 --- a/src/rendering/hwrenderer/doom_levelmesh.h +++ b/src/rendering/hwrenderer/doom_levelmesh.h @@ -24,7 +24,7 @@ struct Surface // // Required for internal lightmapper: - + BBox bounds; int sampleDimension = 0; // Lightmap world coordinates for the texture diff --git a/wadsrc/static/shaders/lightmap/frag.glsl b/wadsrc/static/shaders/lightmap/frag.glsl index d3eccd8fee..056781db6f 100644 --- a/wadsrc/static/shaders/lightmap/frag.glsl +++ b/wadsrc/static/shaders/lightmap/frag.glsl @@ -170,7 +170,7 @@ float TraceAmbientOcclusion(vec3 origin, vec3 normal) { const float minDistance = 0.05; const float aoDistance = 100; - const int SampleCount = 2048; + const int SampleCount = 128; vec3 N = normal; vec3 up = abs(N.x) < abs(N.y) ? vec3(1.0, 0.0, 0.0) : vec3(0.0, 1.0, 0.0);