WIP VkLightmap integration

This commit is contained in:
RaveYard 2023-08-31 19:15:15 +02:00 committed by Christoph Oelckers
parent 22dbbec4cc
commit 52220a5004
12 changed files with 262 additions and 41 deletions

View file

@ -4,8 +4,27 @@
#include "tarray.h"
#include "vectors.h"
#include "hw_collision.h"
#include "bounds.h"
#include <memory>
#include <dp_rect_pack.h>
typedef dp::rect_pack::RectPacker<int> 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<FVector3> verts;
TArray<FVector3> uvs;
//Plane plane;
FVector3 boundsMin, boundsMax;
@ -80,6 +100,68 @@ struct SmoothingGroup
std::vector<Surface*> 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<uint32_t> MeshElements;
TArray<int> MeshSurfaces;
TArray<SurfaceInfo> surfaceInfo;
TArray<PortalInfo> portalInfo;
std::unique_ptr<TriangleMeshShape> Collision;
// To do: these are currently not filled
TArray<std::unique_ptr<Surface>> surfaces;
TArray<SmoothingGroup> smoothingGroups;
std::vector<std::unique_ptr<Surface>> surfaces;
TArray<SmoothingGroup> smoothingGroups; // TODO fill
TArray<Portal> 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

View file

@ -220,7 +220,7 @@ public:
virtual int GetClientHeight() = 0;
virtual void BlurScene(float amount) {}
virtual void InitLightmap(int LMTextureSize, int LMTextureCount, TArray<uint16_t>& LMTextureData) {}
virtual void InitLightmap(int LMTextureSize, int LMTextureCount, TArray<uint16_t>& LMTextureData, hwrenderer::LevelMesh& mesh) {}
// Interface to hardware rendering resources
virtual IBuffer* CreateVertexBuffer(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute* attrs) { return nullptr; }

View file

@ -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());

View file

@ -17,7 +17,7 @@ struct Uniforms
float SunIntensity;
};
struct PushConstants
struct LightmapPushConstants
{
uint32_t LightStart;
uint32_t LightEnd;

View file

@ -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()

View file

@ -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<VulkanBuffer> indexBuffer;
std::unique_ptr<VulkanBuffer> transferBuffer;
std::unique_ptr<VulkanBuffer> nodesBuffer;
std::unique_ptr<VulkanBuffer> surfaceIndexBuffer;
std::unique_ptr<VulkanBuffer> surfaceBuffer;
std::unique_ptr<VulkanBuffer> portalBuffer;
std::unique_ptr<VulkanBuffer> blScratchBuffer;
std::unique_ptr<VulkanBuffer> blAccelStructBuffer;

View file

@ -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 <zvulkan/vulkancompatibledevice.h>
#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<uint16_t>& LMTextureData)
void VulkanRenderDevice::InitLightmap(int LMTextureSize, int LMTextureCount, TArray<uint16_t>& 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);

View file

@ -56,7 +56,7 @@ public:
void SetTextureFilterMode() override;
void StartPrecaching() override;
void BeginFrame() override;
void InitLightmap(int LMTextureSize, int LMTextureCount, TArray<uint16_t>& LMTextureData) override;
void InitLightmap(int LMTextureSize, int LMTextureCount, TArray<uint16_t>& LMTextureData, hwrenderer::LevelMesh& mesh) override;
void BlurScene(float amount) override;
void PostProcessScene(bool swscene, int fixedcm, float flash, const std::function<void()> &afterBloomDrawEndScene2D) override;
void AmbientOccludeScene(float m5) override;

View file

@ -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;

View file

@ -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<hwrenderer::Surface>();
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)
{

View file

@ -24,7 +24,7 @@ struct Surface
//
// Required for internal lightmapper:
BBox bounds;
int sampleDimension = 0;
// Lightmap world coordinates for the texture

View file

@ -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);