Improve lightmap atlas and add some more error checks

This commit is contained in:
Magnus Norddahl 2021-11-13 04:52:13 +01:00
parent 5d0fe12221
commit 346f71e60a
3 changed files with 45 additions and 48 deletions

View file

@ -280,8 +280,12 @@ void GPURaytracer::SubmitCommands()
submit.addCommandBuffer(cmdbuffer.get());
submit.execute(device.get(), device->graphicsQueue, submitFence.get());
vkWaitForFences(device->device, 1, &submitFence->fence, VK_TRUE, std::numeric_limits<uint64_t>::max());
vkResetFences(device->device, 1, &submitFence->fence);
VkResult result = vkWaitForFences(device->device, 1, &submitFence->fence, VK_TRUE, std::numeric_limits<uint64_t>::max());
if (result != VK_SUCCESS)
throw std::runtime_error("vkWaitForFences failed");
result = vkResetFences(device->device, 1, &submitFence->fence);
if (result != VK_SUCCESS)
throw std::runtime_error("vkResetFences failed");
cmdbuffer.reset();
}

View file

@ -246,9 +246,15 @@ BBox LevelMesh::GetBoundsFromSurface(const Surface* surface)
void LevelMesh::CreateTextures()
{
std::vector<Surface*> sortedSurfaces;
sortedSurfaces.reserve(surfaces.size());
for (auto& surf : surfaces)
sortedSurfaces.push_back(surf.get());
std::sort(sortedSurfaces.begin(), sortedSurfaces.end(), [](Surface* a, Surface* b) { return a->lightmapDims[1] > b->lightmapDims[1]; });
for (Surface* surf : sortedSurfaces)
{
FinishSurface(surf.get());
FinishSurface(surf);
}
}
@ -328,12 +334,12 @@ void LevelMesh::FinishSurface(Surface* surface)
color *= 0.5f;
// get texture offset
int offs = (((textureWidth * (y + surface->lightmapOffs[1])) + surface->lightmapOffs[0]) * 3);
int offs = ((textureWidth * (y + surface->lightmapOffs[1])) + surface->lightmapOffs[0]) * 3;
// convert RGB to bytes
currentTexture[offs + x * 3 + 0] = floatToHalf(colorSamples[y * sampleWidth + x].x);
currentTexture[offs + x * 3 + 1] = floatToHalf(colorSamples[y * sampleWidth + x].y);
currentTexture[offs + x * 3 + 2] = floatToHalf(colorSamples[y * sampleWidth + x].z);
currentTexture[offs + x * 3 + 0] = floatToHalf(clamp(colorSamples[y * sampleWidth + x].x, -65000.0f, 65000.0f));
currentTexture[offs + x * 3 + 1] = floatToHalf(clamp(colorSamples[y * sampleWidth + x].y, -65000.0f, 65000.0f));
currentTexture[offs + x * 3 + 2] = floatToHalf(clamp(colorSamples[y * sampleWidth + x].z, -65000.0f, 65000.0f));
}
}
#else
@ -343,12 +349,12 @@ void LevelMesh::FinishSurface(Surface* surface)
for (int j = 0; j < sampleWidth; j++)
{
// get texture offset
int offs = (((textureWidth * (i + surface->lightmapOffs[1])) + surface->lightmapOffs[0]) * 3);
int offs = ((textureWidth * (i + surface->lightmapOffs[1])) + surface->lightmapOffs[0]) * 3;
// convert RGB to bytes
currentTexture[offs + j * 3 + 0] = floatToHalf(colorSamples[i * sampleWidth + j].x);
currentTexture[offs + j * 3 + 1] = floatToHalf(colorSamples[i * sampleWidth + j].y);
currentTexture[offs + j * 3 + 2] = floatToHalf(colorSamples[i * sampleWidth + j].z);
currentTexture[offs + j * 3 + 0] = floatToHalf(clamp(colorSamples[i * sampleWidth + j].x, -65000.0f, 65000.0f));
currentTexture[offs + j * 3 + 1] = floatToHalf(clamp(colorSamples[i * sampleWidth + j].y, -65000.0f, 65000.0f));
currentTexture[offs + j * 3 + 2] = floatToHalf(clamp(colorSamples[i * sampleWidth + j].z, -65000.0f, 65000.0f));
}
}
#endif

View file

@ -33,6 +33,7 @@
#include <cstring>
#include "framework/tarray.h"
#include "framework/halffloat.h"
#include "lightmap/collision.h"
struct MapSubsectorEx;
@ -79,53 +80,39 @@ class LightmapTexture
public:
LightmapTexture(int width, int height) : textureWidth(width), textureHeight(height)
{
mPixels.resize(width * height * 3);
allocBlocks.resize(width);
#ifdef _DEBUG
mPixels.resize(width * height * 3, floatToHalf(0.5f));
#else
mPixels.resize(width * height * 3, 0);
#endif
allocBlocks.resize(height);
}
bool MakeRoomForBlock(const int width, const int height, int* x, int* y)
{
int bestRow1 = textureHeight;
for (int i = 0; i <= textureWidth - width; i++)
int startY = 0;
int startX = 0;
for (int i = 0; i < textureHeight; i++)
{
int bestRow2 = 0;
int j;
for (j = 0; j < width; j++)
startX = std::max(startX, allocBlocks[i]);
int available = textureWidth - startX;
if (available < width)
{
if (allocBlocks[i + j] >= bestRow1)
{
break;
}
if (allocBlocks[i + j] > bestRow2)
{
bestRow2 = allocBlocks[i + j];
}
startY = i + 1;
startX = 0;
}
// found a free block
if (j == width)
else if (i - startY + 1 == height)
{
*x = i;
*y = bestRow1 = bestRow2;
for (int yy = 0; yy < height; yy++)
{
allocBlocks[startY + yy] = startX + width;
}
*x = startX;
*y = startY;
return true;
}
}
if (bestRow1 + height > textureHeight)
{
// no room
return false;
}
// store row offset
for (int i = 0; i < width; i++)
{
allocBlocks[*x + i] = bestRow1 + height;
}
return true;
return false;
}
int Width() const { return textureWidth; }