mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-22 20:21:26 +00:00
Initialize lightmap texture in SetLevelMesh
Create VkLightmap class on VulkanRenderDevice
This commit is contained in:
parent
6de6ae28e9
commit
db5c659fab
15 changed files with 125 additions and 200 deletions
|
@ -207,10 +207,14 @@ public:
|
||||||
|
|
||||||
std::unique_ptr<TriangleMeshShape> Collision;
|
std::unique_ptr<TriangleMeshShape> Collision;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<Surface>> surfaces;
|
TArray<hwrenderer::Surface> Surfaces;
|
||||||
|
|
||||||
TArray<SmoothingGroup> smoothingGroups; // TODO fill
|
TArray<SmoothingGroup> smoothingGroups; // TODO fill
|
||||||
TArray<Portal> portals; // TODO fill
|
TArray<Portal> portals; // TODO fill
|
||||||
|
|
||||||
|
int LMTextureCount = 0;
|
||||||
|
int LMTextureSize = 0;
|
||||||
|
|
||||||
FVector3 SunDirection;
|
FVector3 SunDirection;
|
||||||
FVector3 SunColor;
|
FVector3 SunColor;
|
||||||
|
|
||||||
|
|
|
@ -220,9 +220,6 @@ public:
|
||||||
virtual int GetClientHeight() = 0;
|
virtual int GetClientHeight() = 0;
|
||||||
virtual void BlurScene(float amount) {}
|
virtual void BlurScene(float amount) {}
|
||||||
|
|
||||||
virtual void GenerateLightmap(TArray<uint16_t>& LMTextureData, int LMTextureSize, hwrenderer::LevelMesh& mesh) {}
|
|
||||||
virtual void InitLightmap(int LMTextureSize, int LMTextureCount, TArray<uint16_t>& LMTextureData) {}
|
|
||||||
|
|
||||||
// Interface to hardware rendering resources
|
// Interface to hardware rendering resources
|
||||||
virtual IBuffer* CreateVertexBuffer(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute* attrs) { return nullptr; }
|
virtual IBuffer* CreateVertexBuffer(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute* attrs) { return nullptr; }
|
||||||
virtual IBuffer* CreateIndexBuffer() { return nullptr; }
|
virtual IBuffer* CreateIndexBuffer() { return nullptr; }
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
#include "filesystem.h"
|
#include "filesystem.h"
|
||||||
#include "cmdlib.h"
|
#include "cmdlib.h"
|
||||||
|
|
||||||
|
|
||||||
VkLightmap::VkLightmap(VulkanRenderDevice* fb) : fb(fb)
|
VkLightmap::VkLightmap(VulkanRenderDevice* fb) : fb(fb)
|
||||||
{
|
{
|
||||||
useRayQuery = fb->GetDevice()->PhysicalDevice.Features.RayQuery.rayQuery;
|
useRayQuery = fb->GetDevice()->PhysicalDevice.Features.RayQuery.rayQuery;
|
||||||
|
@ -95,9 +94,9 @@ void VkLightmap::RenderAtlasImage(size_t pageIndex)
|
||||||
};
|
};
|
||||||
beginPass();
|
beginPass();
|
||||||
|
|
||||||
for (size_t i = 0; i < mesh->surfaces.size(); i++)
|
for (unsigned int i = 0; i < mesh->Surfaces.Size(); i++)
|
||||||
{
|
{
|
||||||
hwrenderer::Surface* targetSurface = mesh->surfaces[i].get();
|
hwrenderer::Surface* targetSurface = &mesh->Surfaces[i];
|
||||||
if (targetSurface->atlasPageIndex != pageIndex)
|
if (targetSurface->atlasPageIndex != pageIndex)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -123,8 +122,6 @@ void VkLightmap::RenderAtlasImage(size_t pageIndex)
|
||||||
int vertexCount = (int)surface->verts.Size();
|
int vertexCount = (int)surface->verts.Size();
|
||||||
if (lights.Pos + lightCount > lights.BufferSize || vertices.Pos + vertexCount > vertices.BufferSize)
|
if (lights.Pos + lightCount > lights.BufferSize || vertices.Pos + vertexCount > vertices.BufferSize)
|
||||||
{
|
{
|
||||||
printf(".");
|
|
||||||
|
|
||||||
// Flush scene buffers
|
// Flush scene buffers
|
||||||
FinishCommands();
|
FinishCommands();
|
||||||
lights.Pos = 0;
|
lights.Pos = 0;
|
||||||
|
@ -134,8 +131,6 @@ void VkLightmap::RenderAtlasImage(size_t pageIndex)
|
||||||
BeginCommands();
|
BeginCommands();
|
||||||
beginPass();
|
beginPass();
|
||||||
|
|
||||||
printf(".");
|
|
||||||
|
|
||||||
if (lights.Pos + lightCount > lights.BufferSize)
|
if (lights.Pos + lightCount > lights.BufferSize)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("SceneLightBuffer is too small!");
|
throw std::runtime_error("SceneLightBuffer is too small!");
|
||||||
|
@ -200,9 +195,9 @@ void VkLightmap::CreateAtlasImages()
|
||||||
const int spacing = 3; // Note: the spacing is here to avoid that the resolve sampler finds data from other surface tiles
|
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));
|
RectPacker packer(atlasImageSize, atlasImageSize, RectPacker::Spacing(spacing));
|
||||||
|
|
||||||
for (size_t i = 0; i < mesh->surfaces.size(); i++)
|
for (unsigned int i = 0; i < mesh->Surfaces.Size(); i++)
|
||||||
{
|
{
|
||||||
hwrenderer::Surface* surface = mesh->surfaces[i].get();
|
hwrenderer::Surface* surface = &mesh->Surfaces[i];
|
||||||
|
|
||||||
auto result = packer.insert(surface->texWidth + 2, surface->texHeight + 2);
|
auto result = packer.insert(surface->texWidth + 2, surface->texHeight + 2);
|
||||||
surface->atlasX = result.pos.x + 1;
|
surface->atlasX = result.pos.x + 1;
|
||||||
|
@ -309,9 +304,9 @@ void VkLightmap::DownloadAtlasImage(size_t pageIndex)
|
||||||
|
|
||||||
hvec4* pixels = (hvec4*)atlasImages[pageIndex].Transfer->Map(0, atlasImageSize * atlasImageSize * sizeof(hvec4));
|
hvec4* pixels = (hvec4*)atlasImages[pageIndex].Transfer->Map(0, atlasImageSize * atlasImageSize * sizeof(hvec4));
|
||||||
|
|
||||||
for (size_t i = 0; i < mesh->surfaces.size(); i++)
|
for (unsigned int i = 0; i < mesh->Surfaces.Size(); i++)
|
||||||
{
|
{
|
||||||
hwrenderer::Surface* surface = mesh->surfaces[i].get();
|
hwrenderer::Surface* surface = &mesh->Surfaces[i];
|
||||||
if (surface->atlasPageIndex != pageIndex)
|
if (surface->atlasPageIndex != pageIndex)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
@ -144,7 +144,7 @@ void VkRaytrace::CreateVertexAndIndexBuffers()
|
||||||
|
|
||||||
surfaceBuffer = BufferBuilder()
|
surfaceBuffer = BufferBuilder()
|
||||||
.Usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)
|
.Usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)
|
||||||
.Size(Mesh->surfaces.size() * sizeof(SurfaceInfo))
|
.Size(Mesh->Surfaces.Size() * sizeof(SurfaceInfo))
|
||||||
.DebugName("surfaceBuffer")
|
.DebugName("surfaceBuffer")
|
||||||
.Create(fb->GetDevice());
|
.Create(fb->GetDevice());
|
||||||
|
|
||||||
|
|
|
@ -189,6 +189,35 @@ void VkTextureManager::CreateLightmap()
|
||||||
SetLightmap(1, 1, data);
|
SetLightmap(1, 1, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VkTextureManager::CreateLightmap(int LMTextureSize, int LMTextureCount)
|
||||||
|
{
|
||||||
|
int w = LMTextureSize;
|
||||||
|
int h = LMTextureSize;
|
||||||
|
int count = LMTextureCount;
|
||||||
|
int pixelsize = 8;
|
||||||
|
|
||||||
|
Lightmap.Reset(fb);
|
||||||
|
|
||||||
|
Lightmap.Image = ImageBuilder()
|
||||||
|
.Size(w, h, 1, count)
|
||||||
|
.Format(VK_FORMAT_R16G16B16A16_SFLOAT)
|
||||||
|
.Usage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT)
|
||||||
|
.DebugName("VkRenderBuffers.Lightmap")
|
||||||
|
.Create(fb->GetDevice());
|
||||||
|
|
||||||
|
Lightmap.View = ImageViewBuilder()
|
||||||
|
.Type(VK_IMAGE_VIEW_TYPE_2D_ARRAY)
|
||||||
|
.Image(Lightmap.Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT)
|
||||||
|
.DebugName("VkRenderBuffers.LightmapView")
|
||||||
|
.Create(fb->GetDevice());
|
||||||
|
|
||||||
|
auto cmdbuffer = fb->GetCommands()->GetTransferCommands();
|
||||||
|
|
||||||
|
VkImageTransition()
|
||||||
|
.AddImage(&Lightmap, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false, 0, count)
|
||||||
|
.Execute(cmdbuffer);
|
||||||
|
}
|
||||||
|
|
||||||
void VkTextureManager::SetLightmap(int LMTextureSize, int LMTextureCount, const TArray<uint16_t>& LMTextureData)
|
void VkTextureManager::SetLightmap(int LMTextureSize, int LMTextureCount, const TArray<uint16_t>& LMTextureData)
|
||||||
{
|
{
|
||||||
int w = LMTextureSize;
|
int w = LMTextureSize;
|
||||||
|
|
|
@ -23,6 +23,7 @@ public:
|
||||||
|
|
||||||
void BeginFrame();
|
void BeginFrame();
|
||||||
|
|
||||||
|
void CreateLightmap(int LMTextureSize, int LMTextureCount);
|
||||||
void SetLightmap(int LMTextureSize, int LMTextureCount, const TArray<uint16_t>& LMTextureData);
|
void SetLightmap(int LMTextureSize, int LMTextureCount, const TArray<uint16_t>& LMTextureData);
|
||||||
|
|
||||||
VkTextureImage* GetTexture(const PPTextureType& type, PPTexture* tex);
|
VkTextureImage* GetTexture(const PPTextureType& type, PPTexture* tex);
|
||||||
|
|
|
@ -184,6 +184,7 @@ void VulkanRenderDevice::InitializeState()
|
||||||
mDescriptorSetManager.reset(new VkDescriptorSetManager(this));
|
mDescriptorSetManager.reset(new VkDescriptorSetManager(this));
|
||||||
mRenderPassManager.reset(new VkRenderPassManager(this));
|
mRenderPassManager.reset(new VkRenderPassManager(this));
|
||||||
mRaytrace.reset(new VkRaytrace(this));
|
mRaytrace.reset(new VkRaytrace(this));
|
||||||
|
mLightmap.reset(new VkLightmap(this));
|
||||||
|
|
||||||
mBufferManager->Init();
|
mBufferManager->Init();
|
||||||
|
|
||||||
|
@ -476,61 +477,6 @@ void VulkanRenderDevice::BeginFrame()
|
||||||
mDescriptorSetManager->BeginFrame();
|
mDescriptorSetManager->BeginFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanRenderDevice::GenerateLightmap(TArray<uint16_t>& LMTextureData, int LMTextureSize, hwrenderer::LevelMesh& mesh)
|
|
||||||
{
|
|
||||||
if (false && 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; };
|
|
||||||
|
|
||||||
|
|
||||||
std::sort(mesh.surfaces.begin(), mesh.surfaces.end(), [](const std::unique_ptr<hwrenderer::Surface>& a, const std::unique_ptr<hwrenderer::Surface>& b) { return a->texHeight != b->texHeight ? a->texHeight > b->texHeight : a->texWidth > b->texWidth; });
|
|
||||||
|
|
||||||
|
|
||||||
RectPacker packer(LMTextureSize, LMTextureSize, RectPacker::Spacing(0));
|
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VulkanRenderDevice::InitLightmap(int LMTextureSize, int LMTextureCount, TArray<uint16_t>& LMTextureData)
|
|
||||||
{
|
|
||||||
if (LMTextureData.Size() > 0)
|
|
||||||
{
|
|
||||||
GetTextureManager()->SetLightmap(LMTextureSize, LMTextureCount, LMTextureData);
|
|
||||||
LMTextureData.Reset(); // We no longer need this, release the memory
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VulkanRenderDevice::Draw2D()
|
void VulkanRenderDevice::Draw2D()
|
||||||
{
|
{
|
||||||
::Draw2D(twod, *RenderState(0));
|
::Draw2D(twod, *RenderState(0));
|
||||||
|
@ -589,6 +535,61 @@ void VulkanRenderDevice::PrintStartupLog()
|
||||||
void VulkanRenderDevice::SetLevelMesh(hwrenderer::LevelMesh* mesh)
|
void VulkanRenderDevice::SetLevelMesh(hwrenderer::LevelMesh* mesh)
|
||||||
{
|
{
|
||||||
mRaytrace->SetLevelMesh(mesh);
|
mRaytrace->SetLevelMesh(mesh);
|
||||||
|
|
||||||
|
if (mesh->Surfaces.Size() > 0)
|
||||||
|
{
|
||||||
|
#if 0 // To do: GetLightmap()->Raytrace should output directly to the lightmap texture instead of forcing us to download it to the CPU first
|
||||||
|
|
||||||
|
GetTextureManager()->CreateLightmap(mesh->LMTextureSize, mesh->LMTextureCount);
|
||||||
|
GetCommands()->WaitForCommands(false);
|
||||||
|
GetLightmap()->Raytrace(mesh);
|
||||||
|
|
||||||
|
#else // Temporary version using the old zdray Raytracer code as-is
|
||||||
|
|
||||||
|
Printf("Running VkLightmap.\n");
|
||||||
|
|
||||||
|
GetLightmap()->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; };
|
||||||
|
|
||||||
|
// BUG: This is a destructive action as it reorders the surfaces array that is indexed by MeshSurfaces
|
||||||
|
std::sort(mesh->Surfaces.begin(), mesh->Surfaces.end(), [](const hwrenderer::Surface& a, const hwrenderer::Surface& b) { return a.texHeight != b.texHeight ? a.texHeight > b.texHeight : a.texWidth > b.texWidth; });
|
||||||
|
|
||||||
|
RectPacker packer(mesh->LMTextureSize, mesh->LMTextureSize, RectPacker::Spacing(0));
|
||||||
|
|
||||||
|
TArray<uint16_t> LMTextureData;
|
||||||
|
LMTextureData.Resize(mesh->LMTextureSize * mesh->LMTextureSize * mesh->LMTextureCount * 3);
|
||||||
|
|
||||||
|
for (auto& surface : mesh->Surfaces)
|
||||||
|
{
|
||||||
|
mesh->FinishSurface(mesh->LMTextureSize, mesh->LMTextureSize, packer, surface);
|
||||||
|
|
||||||
|
uint16_t* currentTexture = LMTextureData.Data() + (mesh->LMTextureSize * mesh->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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GetTextureManager()->SetLightmap(mesh->LMTextureSize, mesh->LMTextureCount, LMTextureData);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanRenderDevice::SetShadowMaps(const TArray<float>& lights, hwrenderer::LevelAABBTree* tree, bool newTree)
|
void VulkanRenderDevice::SetShadowMaps(const TArray<float>& lights, hwrenderer::LevelAABBTree* tree, bool newTree)
|
||||||
|
|
|
@ -15,6 +15,7 @@ class VkDescriptorSetManager;
|
||||||
class VkRenderPassManager;
|
class VkRenderPassManager;
|
||||||
class VkFramebufferManager;
|
class VkFramebufferManager;
|
||||||
class VkRaytrace;
|
class VkRaytrace;
|
||||||
|
class VkLightmap;
|
||||||
class VkRenderState;
|
class VkRenderState;
|
||||||
class VkStreamBuffer;
|
class VkStreamBuffer;
|
||||||
class VkHardwareDataBuffer;
|
class VkHardwareDataBuffer;
|
||||||
|
@ -38,6 +39,7 @@ public:
|
||||||
VkDescriptorSetManager* GetDescriptorSetManager() { return mDescriptorSetManager.get(); }
|
VkDescriptorSetManager* GetDescriptorSetManager() { return mDescriptorSetManager.get(); }
|
||||||
VkRenderPassManager *GetRenderPassManager() { return mRenderPassManager.get(); }
|
VkRenderPassManager *GetRenderPassManager() { return mRenderPassManager.get(); }
|
||||||
VkRaytrace* GetRaytrace() { return mRaytrace.get(); }
|
VkRaytrace* GetRaytrace() { return mRaytrace.get(); }
|
||||||
|
VkLightmap* GetLightmap() { return mLightmap.get(); }
|
||||||
VkRenderState *GetRenderState(int threadIndex) { return mRenderState[threadIndex].get(); }
|
VkRenderState *GetRenderState(int threadIndex) { return mRenderState[threadIndex].get(); }
|
||||||
VkPostprocess *GetPostprocess() { return mPostprocess.get(); }
|
VkPostprocess *GetPostprocess() { return mPostprocess.get(); }
|
||||||
VkRenderBuffers *GetBuffers() { return mActiveRenderBuffers; }
|
VkRenderBuffers *GetBuffers() { return mActiveRenderBuffers; }
|
||||||
|
@ -56,8 +58,6 @@ public:
|
||||||
void SetTextureFilterMode() override;
|
void SetTextureFilterMode() override;
|
||||||
void StartPrecaching() override;
|
void StartPrecaching() override;
|
||||||
void BeginFrame() override;
|
void BeginFrame() override;
|
||||||
void GenerateLightmap(TArray<uint16_t>& LMTextureData, int LMTextureSize, hwrenderer::LevelMesh& mesh) override;
|
|
||||||
void InitLightmap(int LMTextureSize, int LMTextureCount, TArray<uint16_t>& LMTextureData) override;
|
|
||||||
void BlurScene(float amount) override;
|
void BlurScene(float amount) override;
|
||||||
void PostProcessScene(bool swscene, int fixedcm, float flash, const std::function<void()> &afterBloomDrawEndScene2D) override;
|
void PostProcessScene(bool swscene, int fixedcm, float flash, const std::function<void()> &afterBloomDrawEndScene2D) override;
|
||||||
void AmbientOccludeScene(float m5) override;
|
void AmbientOccludeScene(float m5) override;
|
||||||
|
@ -108,6 +108,7 @@ private:
|
||||||
std::unique_ptr<VkDescriptorSetManager> mDescriptorSetManager;
|
std::unique_ptr<VkDescriptorSetManager> mDescriptorSetManager;
|
||||||
std::unique_ptr<VkRenderPassManager> mRenderPassManager;
|
std::unique_ptr<VkRenderPassManager> mRenderPassManager;
|
||||||
std::unique_ptr<VkRaytrace> mRaytrace;
|
std::unique_ptr<VkRaytrace> mRaytrace;
|
||||||
|
std::unique_ptr<VkLightmap> mLightmap;
|
||||||
std::vector<std::unique_ptr<VkRenderState>> mRenderState;
|
std::vector<std::unique_ptr<VkRenderState>> mRenderState;
|
||||||
|
|
||||||
VkRenderBuffers *mActiveRenderBuffers = nullptr;
|
VkRenderBuffers *mActiveRenderBuffers = nullptr;
|
||||||
|
|
|
@ -396,9 +396,9 @@ void D_Render(std::function<void()> action, bool interpolate)
|
||||||
for (auto Level : AllLevels())
|
for (auto Level : AllLevels())
|
||||||
{
|
{
|
||||||
// Check for the presence of dynamic lights at the start of the frame once.
|
// Check for the presence of dynamic lights at the start of the frame once.
|
||||||
if ((gl_lights && vid_rendermode == 4) || (r_dynlights && vid_rendermode != 4) || Level->LMTextureCount > 0)
|
if ((gl_lights && vid_rendermode == 4) || (r_dynlights && vid_rendermode != 4) || Level->lightmaps)
|
||||||
{
|
{
|
||||||
Level->HasDynamicLights = Level->lights || Level->LMTextureCount > 0;
|
Level->HasDynamicLights = Level->lights || Level->lightmaps;
|
||||||
}
|
}
|
||||||
else Level->HasDynamicLights = false; // lights are off so effectively we have none.
|
else Level->HasDynamicLights = false; // lights are off so effectively we have none.
|
||||||
if (interpolate) Level->interpolator.DoInterpolations(I_GetTimeFrac());
|
if (interpolate) Level->interpolator.DoInterpolations(I_GetTimeFrac());
|
||||||
|
|
|
@ -454,11 +454,8 @@ public:
|
||||||
TArray<FLinePortal> linePortals;
|
TArray<FLinePortal> linePortals;
|
||||||
|
|
||||||
// Lightmaps
|
// Lightmaps
|
||||||
|
bool lightmaps = false;
|
||||||
TArray<LightmapSurface> LMSurfaces;
|
TArray<LightmapSurface> LMSurfaces;
|
||||||
TArray<float> LMTexCoords;
|
|
||||||
int LMTextureCount = 0;
|
|
||||||
int LMTextureSize = 0;
|
|
||||||
TArray<uint16_t> LMTextureData;
|
|
||||||
FVector3 SunDirection;
|
FVector3 SunDirection;
|
||||||
FVector3 SunColor;
|
FVector3 SunColor;
|
||||||
|
|
||||||
|
|
|
@ -3214,10 +3214,6 @@ void MapLoader::LoadLevel(MapData *map, const char *lumpname, int position)
|
||||||
Level->levelMesh = new DoomLevelMesh(*Level);
|
Level->levelMesh = new DoomLevelMesh(*Level);
|
||||||
InitLightmap(map);
|
InitLightmap(map);
|
||||||
|
|
||||||
screen->GenerateLightmap(Level->LMTextureData, Level->LMTextureSize, *Level->levelMesh);
|
|
||||||
|
|
||||||
screen->InitLightmap(Level->LMTextureSize, Level->LMTextureCount, Level->LMTextureData);
|
|
||||||
|
|
||||||
for (int i = 0; i < MAXPLAYERS; ++i)
|
for (int i = 0; i < MAXPLAYERS; ++i)
|
||||||
{
|
{
|
||||||
if (Level->PlayerInGame(i) && Level->Players[i]->mo != nullptr)
|
if (Level->PlayerInGame(i) && Level->Players[i]->mo != nullptr)
|
||||||
|
@ -3330,96 +3326,6 @@ void MapLoader::SetSideLightmap(const LightmapSurface &surface)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "vulkan/accelstructs/halffloat.h"
|
|
||||||
|
|
||||||
void MapLoader::GenerateLightmap(const DoomLevelMesh& mesh, int atlasPages, int atlasWidth, int atlasHeight)
|
|
||||||
{
|
|
||||||
Level->LMTextureData.Resize(atlasWidth * atlasHeight * 3 * atlasPages);
|
|
||||||
|
|
||||||
uint16_t* ptr = Level->LMTextureData.Data();
|
|
||||||
|
|
||||||
for (int i = 0; i < atlasPages; ++i)
|
|
||||||
{
|
|
||||||
for (int y = 0; y < atlasWidth; ++y)
|
|
||||||
{
|
|
||||||
for (int x = 0; x < atlasHeight; ++x)
|
|
||||||
{
|
|
||||||
/**(ptr++) = floatToHalf(float(x) / width);
|
|
||||||
*(ptr++) = floatToHalf(float(y) / height);
|
|
||||||
*(ptr++) = floatToHalf((x + y) % 2 == 0 ? 1.0f : 0.0f);*/
|
|
||||||
switch (i % 3)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
*(ptr++) = floatToHalf(1.0f);
|
|
||||||
*(ptr++) = floatToHalf(0.0f);
|
|
||||||
*(ptr++) = floatToHalf(0.0f);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
*(ptr++) = floatToHalf(0.0f);
|
|
||||||
*(ptr++) = floatToHalf(1.0f);
|
|
||||||
*(ptr++) = floatToHalf(0.0f);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
*(ptr++) = floatToHalf(0.0f);
|
|
||||||
*(ptr++) = floatToHalf(0.0f);
|
|
||||||
*(ptr++) = floatToHalf(1.0f);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto get_xy = [&](int page, int x, int y) -> uint16_t*
|
|
||||||
{
|
|
||||||
return Level->LMTextureData.Data() + ((y * atlasWidth) + x + (atlasHeight * atlasWidth * page)) * 3;
|
|
||||||
};
|
|
||||||
|
|
||||||
//#if 0
|
|
||||||
srand(1337);
|
|
||||||
for (auto& surface : mesh.Surfaces)
|
|
||||||
{
|
|
||||||
float r;
|
|
||||||
float g;
|
|
||||||
float b;
|
|
||||||
|
|
||||||
r = rand() % 32 / 32.0f;
|
|
||||||
g = rand() % 32 / 32.0f;
|
|
||||||
b = rand() % 32 / 32.0f;
|
|
||||||
|
|
||||||
for (int y = 0; y <= surface.texHeight; ++y)
|
|
||||||
{
|
|
||||||
for (int x = 0; x <= surface.texWidth; ++x)
|
|
||||||
{
|
|
||||||
auto ptr = get_xy(surface.atlasPageIndex, surface.atlasX + x, surface.atlasY + y);
|
|
||||||
|
|
||||||
ptr[0] = floatToHalf(r);
|
|
||||||
ptr[1] = floatToHalf(g);
|
|
||||||
ptr[2] = floatToHalf(b);
|
|
||||||
|
|
||||||
if (x % 4 == 0 || y % 4 == 0)
|
|
||||||
{
|
|
||||||
ptr[0] = floatToHalf(0.0f);
|
|
||||||
ptr[1] = floatToHalf(0.0f);
|
|
||||||
ptr[2] = floatToHalf(0.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*if (Level->levelMesh->TraceSky(surface.worldOrigin - surface.worldStepX * 0.5f - surface.worldStepY * 0.5f + surface.worldStepX * x + surface.worldStepY * y + FVector3(surface.plane.Normal()), Level->SunDirection, 32000.0f))
|
|
||||||
{
|
|
||||||
ptr[0] = floatToHalf(Level->SunColor.X);
|
|
||||||
ptr[1] = floatToHalf(Level->SunColor.Y);
|
|
||||||
ptr[2] = floatToHalf(Level->SunColor.Z);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ptr[0] = 0;
|
|
||||||
ptr[1] = 0;
|
|
||||||
ptr[2] = 0;
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MapLoader::BindLightmapSurfacesToGeometry()
|
void MapLoader::BindLightmapSurfacesToGeometry()
|
||||||
{
|
{
|
||||||
// Allocate room for all surfaces
|
// Allocate room for all surfaces
|
||||||
|
@ -3487,11 +3393,7 @@ void MapLoader::BindLightmapSurfacesToGeometry()
|
||||||
void MapLoader::InitLightmap(MapData* map)
|
void MapLoader::InitLightmap(MapData* map)
|
||||||
{
|
{
|
||||||
// We have to reset everything as FLevelLocals is recycled between maps
|
// We have to reset everything as FLevelLocals is recycled between maps
|
||||||
Level->LMTexCoords.Reset();
|
|
||||||
Level->LMSurfaces.Reset();
|
Level->LMSurfaces.Reset();
|
||||||
Level->LMTextureData.Reset();
|
|
||||||
|
|
||||||
Level->LMTextureSize = 1024; // TODO cvar
|
|
||||||
|
|
||||||
// TODO read from ZDRayInfoThing
|
// TODO read from ZDRayInfoThing
|
||||||
Level->SunColor = FVector3(1.f, 1.f, 1.f);
|
Level->SunColor = FVector3(1.f, 1.f, 1.f);
|
||||||
|
@ -3500,9 +3402,8 @@ void MapLoader::InitLightmap(MapData* map)
|
||||||
Level->levelMesh->SunColor = Level->SunColor; // TODO keep only one copy?
|
Level->levelMesh->SunColor = Level->SunColor; // TODO keep only one copy?
|
||||||
Level->levelMesh->SunDirection = Level->SunDirection;
|
Level->levelMesh->SunDirection = Level->SunDirection;
|
||||||
|
|
||||||
Level->LMTextureCount = Level->levelMesh->SetupLightmapUvs(Level->LMTextureSize);
|
Level->lightmaps = true;
|
||||||
|
|
||||||
GenerateLightmap(*Level->levelMesh, Level->LMTextureCount, Level->LMTextureSize, Level->LMTextureSize);
|
|
||||||
BindLightmapSurfacesToGeometry();
|
BindLightmapSurfacesToGeometry();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -312,7 +312,6 @@ public:
|
||||||
void LoadLightmap(MapData *map);
|
void LoadLightmap(MapData *map);
|
||||||
#endif
|
#endif
|
||||||
void InitLightmap(MapData* map);
|
void InitLightmap(MapData* map);
|
||||||
void GenerateLightmap(const DoomLevelMesh& mesh, int atlasPages, int atlasWidth, int atlasHeight);
|
|
||||||
void BindLightmapSurfacesToGeometry();
|
void BindLightmapSurfacesToGeometry();
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -337,7 +337,7 @@ void DoomLevelMesh::CreateFloorSurface(FLevelLocals &doomMap, subsector_t *sub,
|
||||||
surf.type = hwrenderer::ST_FLOOR;
|
surf.type = hwrenderer::ST_FLOOR;
|
||||||
surf.typeIndex = typeIndex;
|
surf.typeIndex = typeIndex;
|
||||||
surf.controlSector = is3DFloor ? sector : nullptr;
|
surf.controlSector = is3DFloor ? sector : nullptr;
|
||||||
surf.plane = FVector4(plane.Normal().X, plane.Normal().Y, plane.Normal().Z, plane.D);
|
surf.plane = FVector4((float)plane.Normal().X, (float)plane.Normal().Y, (float)plane.Normal().Z, (float)plane.D);
|
||||||
|
|
||||||
Surfaces.Push(surf);
|
Surfaces.Push(surf);
|
||||||
}
|
}
|
||||||
|
@ -376,7 +376,7 @@ void DoomLevelMesh::CreateCeilingSurface(FLevelLocals &doomMap, subsector_t *sub
|
||||||
surf.type = hwrenderer::ST_CEILING;
|
surf.type = hwrenderer::ST_CEILING;
|
||||||
surf.typeIndex = typeIndex;
|
surf.typeIndex = typeIndex;
|
||||||
surf.controlSector = is3DFloor ? sector : nullptr;
|
surf.controlSector = is3DFloor ? sector : nullptr;
|
||||||
surf.plane = FVector4(plane.Normal().X, plane.Normal().Y, plane.Normal().Z, plane.D);
|
surf.plane = FVector4((float)plane.Normal().X, (float)plane.Normal().Y, (float)plane.Normal().Z, (float)plane.D);
|
||||||
|
|
||||||
Surfaces.Push(surf);
|
Surfaces.Push(surf);
|
||||||
}
|
}
|
||||||
|
@ -487,21 +487,23 @@ void DoomLevelMesh::DumpMesh(const FString& filename) const
|
||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
int DoomLevelMesh::SetupLightmapUvs(int lightmapSize)
|
void DoomLevelMesh::SetupLightmapUvs()
|
||||||
{
|
{
|
||||||
|
LMTextureSize = 1024; // TODO cvar
|
||||||
|
|
||||||
std::vector<Surface*> sortedSurfaces;
|
std::vector<Surface*> sortedSurfaces;
|
||||||
sortedSurfaces.reserve(Surfaces.Size());
|
sortedSurfaces.reserve(Surfaces.Size());
|
||||||
|
|
||||||
for (auto& surface : Surfaces)
|
for (auto& surface : Surfaces)
|
||||||
{
|
{
|
||||||
BuildSurfaceParams(lightmapSize, lightmapSize, surface);
|
BuildSurfaceParams(LMTextureSize, LMTextureSize, surface);
|
||||||
sortedSurfaces.push_back(&surface);
|
sortedSurfaces.push_back(&surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
for (const auto& surface : Surfaces)
|
for (const auto& surface : Surfaces)
|
||||||
{
|
{
|
||||||
auto hwSurface = std::make_unique<hwrenderer::Surface>();
|
hwrenderer::Surface hwSurface;
|
||||||
|
|
||||||
for (int i = 0; i < surface.numVerts; ++i)
|
for (int i = 0; i < surface.numVerts; ++i)
|
||||||
{
|
{
|
||||||
|
@ -535,36 +537,37 @@ int DoomLevelMesh::SetupLightmapUvs(int lightmapSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO push
|
// TODO push
|
||||||
surfaces.push_back(std::move(hwSurface));
|
Surfaces.push_back(hwSurface);
|
||||||
|
|
||||||
SurfaceInfo info;
|
SurfaceInfo info;
|
||||||
info.Normal = surface.plane.XYZ();
|
info.Normal = surface.plane.XYZ();
|
||||||
info.PortalIndex = 0;
|
info.PortalIndex = 0;
|
||||||
info.SamplingDistance = surface.sampleDimension;
|
info.SamplingDistance = (float)surface.sampleDimension;
|
||||||
info.Sky = surface.bSky;
|
info.Sky = surface.bSky;
|
||||||
|
|
||||||
surfaceInfo.Push(info);
|
surfaceInfo.Push(info);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
{
|
{
|
||||||
hwrenderer::SmoothingGroup smoothing;
|
hwrenderer::SmoothingGroup smoothing;
|
||||||
|
|
||||||
for (auto& surface : surfaces)
|
for (auto& surface : Surfaces)
|
||||||
{
|
{
|
||||||
smoothing.surfaces.push_back(surface.get());
|
smoothing.surfaces.push_back(&surface);
|
||||||
}
|
}
|
||||||
smoothingGroups.Push(std::move(smoothing));
|
smoothingGroups.Push(std::move(smoothing));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::sort(sortedSurfaces.begin(), sortedSurfaces.end(), [](Surface* a, Surface* b) { return a->texHeight != b->texHeight ? a->texHeight > b->texHeight : a->texWidth > b->texWidth; });
|
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));
|
RectPacker packer(LMTextureSize, LMTextureSize, RectPacker::Spacing(0));
|
||||||
|
|
||||||
for (Surface* surf : sortedSurfaces)
|
for (Surface* surf : sortedSurfaces)
|
||||||
{
|
{
|
||||||
FinishSurface(lightmapSize, lightmapSize, packer, *surf);
|
FinishSurface(LMTextureSize, LMTextureSize, packer, *surf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// You have no idea how long this took me to figure out...
|
// You have no idea how long this took me to figure out...
|
||||||
|
@ -589,8 +592,7 @@ int DoomLevelMesh::SetupLightmapUvs(int lightmapSize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LMTextureCount = (int)packer.getNumPages();
|
||||||
return packer.getNumPages();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DoomLevelMesh::FinishSurface(int lightmapTextureWidth, int lightmapTextureHeight, RectPacker& packer, Surface& surface)
|
void DoomLevelMesh::FinishSurface(int lightmapTextureWidth, int lightmapTextureHeight, RectPacker& packer, Surface& surface)
|
||||||
|
@ -642,7 +644,7 @@ void DoomLevelMesh::FinishSurface(int lightmapTextureWidth, int lightmapTextureH
|
||||||
|
|
||||||
BBox DoomLevelMesh::GetBoundsFromSurface(const Surface& surface) const
|
BBox DoomLevelMesh::GetBoundsFromSurface(const Surface& surface) const
|
||||||
{
|
{
|
||||||
constexpr float M_INFINITY = 1e30; // TODO cleanup
|
constexpr float M_INFINITY = 1e30f; // TODO cleanup
|
||||||
|
|
||||||
FVector3 low(M_INFINITY, M_INFINITY, M_INFINITY);
|
FVector3 low(M_INFINITY, M_INFINITY, M_INFINITY);
|
||||||
FVector3 hi(-M_INFINITY, -M_INFINITY, -M_INFINITY);
|
FVector3 hi(-M_INFINITY, -M_INFINITY, -M_INFINITY);
|
||||||
|
|
|
@ -25,18 +25,16 @@ public:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
int surfaceIndex = MeshSurfaces[hit.triangle];
|
int surfaceIndex = MeshSurfaces[hit.triangle];
|
||||||
const hwrenderer::Surface& surface = Surfaces[surfaceIndex];
|
return Surfaces[surfaceIndex].bSky;
|
||||||
return surface.bSky;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TArray<hwrenderer::Surface> Surfaces;
|
|
||||||
TArray<FVector2> LightmapUvs;
|
TArray<FVector2> LightmapUvs;
|
||||||
|
|
||||||
static_assert(alignof(FVector2) == alignof(float[2]) && sizeof(FVector2) == sizeof(float) * 2);
|
static_assert(alignof(FVector2) == alignof(float[2]) && sizeof(FVector2) == sizeof(float) * 2);
|
||||||
|
|
||||||
void DumpMesh(const FString& filename) const;
|
void DumpMesh(const FString& filename) const;
|
||||||
|
|
||||||
int SetupLightmapUvs(int lightmapSize);
|
void SetupLightmapUvs();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void CreateSubsectorSurfaces(FLevelLocals &doomMap);
|
void CreateSubsectorSurfaces(FLevelLocals &doomMap);
|
||||||
|
|
|
@ -83,7 +83,7 @@ public:
|
||||||
|
|
||||||
bool TraceSunVisibility(float x, float y, float z)
|
bool TraceSunVisibility(float x, float y, float z)
|
||||||
{
|
{
|
||||||
if (level.LMTextureCount == 0 || !Actor)
|
if (!level.lightmaps || !Actor)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!ActorMoved && CurrentBit < 64)
|
if (!ActorMoved && CurrentBit < 64)
|
||||||
|
|
Loading…
Reference in a new issue