Misc lightmapper adjustments

This commit is contained in:
Magnus Norddahl 2025-06-24 15:04:16 +02:00
commit d1c6fbe61f
5 changed files with 53 additions and 36 deletions

View file

@ -57,6 +57,9 @@ struct LightmapTile
uint16_t SampleDimension = 0;
FVector4 Plane = FVector4(0.0f, 0.0f, 1.0f, 0.0f);
// Flats must always use XY axis (slopes may change rapidly in a way that causes artifacts otherwise)
bool UseXYAxis = false;
// Initial tile for surfaces that can be baked in the background
bool NeedsInitialBake = false;
@ -69,20 +72,20 @@ struct LightmapTile
// Used to track if tile has already been added to the VisibleTiles list for this scene
int LastSeen = 0;
FVector2 ToUV(const FVector3& vert) const
/*FVector2 ToUV(const FVector3& vert) const
{
FVector3 localPos = vert - Transform.TranslateWorldToLocal;
float u = (localPos | Transform.ProjLocalToU) / AtlasLocation.Width;
float v = (localPos | Transform.ProjLocalToV) / AtlasLocation.Height;
return FVector2(u, v);
}
}*/
FVector2 ToUV(const FVector3& vert, float textureSize) const
{
// Clamp in case the wall moved outside the tile (happens if a lift moves with a static lightmap on it)
FVector3 localPos = vert - Transform.TranslateWorldToLocal;
float u = std::max(std::min(localPos | Transform.ProjLocalToU, (float)AtlasLocation.Width), 0.0f);
float v = std::max(std::min(localPos | Transform.ProjLocalToV, (float)AtlasLocation.Height), 0.0f);
float u = std::max(std::min(localPos | Transform.ProjLocalToU, (float)AtlasLocation.Width - 2.0f), 1.0f);
float v = std::max(std::min(localPos | Transform.ProjLocalToV, (float)AtlasLocation.Height - 2.0f), 1.0f);
u = (AtlasLocation.X + u) / textureSize;
v = (AtlasLocation.Y + v) / textureSize;
return FVector2(u, v);
@ -133,7 +136,8 @@ struct LightmapTile
FVector3 tCoords[2] = { FVector3(0.0f, 0.0f, 0.0f), FVector3(0.0f, 0.0f, 0.0f) };
int width, height;
switch (BestAxis(Plane))
PlaneAxis planeAxis = UseXYAxis ? AXIS_XY : BestAxis(Plane);
switch (planeAxis)
{
default:
case AXIS_YZ:

View file

@ -112,12 +112,13 @@ void VkLightmapper::Raytrace(const TArray<LightmapTile*>& tiles)
Blur();
CopyResult();
if (drawindexed.Pos == drawindexed.BufferSize || copytiles.Pos == drawindexed.BufferSize)
if (drawindexed.IsFull || copytiles.Pos == drawindexed.BufferSize)
{
fb->GetCommands()->PopGroup(fb->GetCommands()->GetTransferCommands());
fb->WaitForCommands(false);
fb->GetCommands()->PushGroup(fb->GetCommands()->GetTransferCommands(), "lightmap.total");
drawindexed.Pos = 0;
drawindexed.IsFull = false;
copytiles.Pos = 0;
}
}
@ -218,12 +219,23 @@ void VkLightmapper::Render()
pc.ProjLocalToU = SwapYZ(targetTile->Transform.ProjLocalToU);
pc.ProjLocalToV = SwapYZ(targetTile->Transform.ProjLocalToV);
bool buffersFull = false;
// Paint all surfaces visible in the tile
visibleSurfaces.Clear();
mesh->GetVisibleSurfaces(targetTile, visibleSurfaces);
if (drawindexed.Pos + (int)visibleSurfaces.Size() >= drawindexed.BufferSize)
{
// Our indirect draw buffer is full. Mark the remaining tiles as not rendered
while (i < count)
{
selectedTiles[i].Tile->ReceivedNewLight = true;
i++;
}
drawindexed.IsFull = true;
break;
}
for (int surfaceIndex : visibleSurfaces)
{
LevelMeshSurface* surface = &mesh->Mesh.Surfaces[surfaceIndex];
@ -238,29 +250,13 @@ void VkLightmapper::Render()
drawindexed.Constants[drawindexed.Pos] = pc;
drawindexed.Commands[drawindexed.Pos] = cmd;
drawindexed.Pos++;
if (drawindexed.Pos == drawindexed.BufferSize)
{
// Our indirect draw buffer is full. Postpone the rest.
buffersFull = true;
break;
}
}
if (buffersFull)
{
while (i < count)
{
selectedTiles[i].Tile->ReceivedNewLight = true;
i++;
}
break;
}
selectedTile.Rendered = true;
}
cmdbuffer->drawIndexedIndirect(drawindexed.CommandsBuffer->buffer, startPos * sizeof(VkDrawIndexedIndirectCommand), drawindexed.Pos - startPos, sizeof(VkDrawIndexedIndirectCommand));
if (drawindexed.Pos > startPos)
cmdbuffer->drawIndexedIndirect(drawindexed.CommandsBuffer->buffer, startPos * sizeof(VkDrawIndexedIndirectCommand), drawindexed.Pos - startPos, sizeof(VkDrawIndexedIndirectCommand));
cmdbuffer->endRenderPass();
@ -922,6 +918,9 @@ void VkLightmapper::CreateCopyPipeline()
.Create(fb->GetDevice());
copy.sampler = SamplerBuilder()
.MinFilter(VK_FILTER_NEAREST)
.MagFilter(VK_FILTER_NEAREST)
.MipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST)
.DebugName("copy.Sampler")
.Create(fb->GetDevice());
}
@ -1006,7 +1005,7 @@ void VkLightmapper::CreateBakeImage()
.AddCombinedImageSampler(bakeImage.resolve.DescriptorSet.get(), 0, bakeImage.raytrace.View.get(), resolve.sampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
.AddCombinedImageSampler(bakeImage.blur.DescriptorSet[0].get(), 0, bakeImage.resolve.View.get(), blur.sampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
.AddCombinedImageSampler(bakeImage.blur.DescriptorSet[1].get(), 0, bakeImage.blur.View.get(), blur.sampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
.AddCombinedImageSampler(bakeImage.copy.DescriptorSet.get(), 0, bakeImage.resolve.View.get(), blur.sampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
.AddCombinedImageSampler(bakeImage.copy.DescriptorSet.get(), 0, bakeImage.resolve.View.get(), copy.sampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
.AddBuffer(bakeImage.copy.DescriptorSet.get(), 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, copytiles.Buffer.get())
.Execute(fb->GetDevice());
}

View file

@ -175,6 +175,7 @@ private:
VkDrawIndexedIndirectCommand* Commands = nullptr;
LightmapRaytracePC* Constants = nullptr;
int Pos = 0;
bool IsFull = false;
} drawindexed;
struct

View file

@ -515,6 +515,7 @@ void DoomLevelMesh::BuildSubsectorVisibilityLists(FLevelLocals& doomMap)
// Always bake the subsector
VisibleSubsectors[i].Push(i);
sub->validcount = validcount;
stack.Push(sub);
@ -1465,6 +1466,10 @@ void DoomLevelMesh::CreateFlat(FLevelLocals& doomMap, unsigned int sectorIndex)
sinfo.NextSubsectorSurface = SubsectorSurfaces[subsectorIndex];
SubsectorSurfaces[subsectorIndex] = surf;
}
else
{
sinfo.NextSubsectorSurface = -1;
}
surf = sinfo.NextSurface;
}
}
@ -1749,6 +1754,7 @@ int DoomLevelMesh::AddSurfaceToTile(const DoomSurfaceInfo& info, const LevelMesh
tile.Plane = surf.Plane;
tile.SampleDimension = GetSampleDimension(sampleDimension);
tile.UseCount = 1;
tile.UseXYAxis = (info.Type == ST_CEILING || info.Type == ST_FLOOR);
int index = AllocTile(tile);
Lightmap.AddedTiles.Push(index);

View file

@ -8,7 +8,7 @@ vec4 centerFragColor;
vec4 clampedSample(vec4 f)
{
return f != vec4(0, 0, 0, 0) ? f : centerFragColor;
return f.a != 0.0 ? f : centerFragColor;
}
void main()
@ -18,15 +18,22 @@ void main()
centerFragColor = textureOffset(tex, texCoord, ivec2(0, 0));
if (centerFragColor.a != 0.0)
{
#if defined(BLUR_HORIZONTAL)
fragcolor =
centerFragColor * 0.5 +
clampedSample(textureOffset(tex, texCoord, ivec2( 1, 0))) * 0.25 +
clampedSample(textureOffset(tex, texCoord, ivec2(-1, 0))) * 0.25;
fragcolor =
centerFragColor * 0.5 +
clampedSample(textureOffset(tex, texCoord, ivec2( 1, 0))) * 0.25 +
clampedSample(textureOffset(tex, texCoord, ivec2(-1, 0))) * 0.25;
#else
fragcolor =
centerFragColor * 0.5 +
clampedSample(textureOffset(tex, texCoord, ivec2(0, 1))) * 0.25 +
clampedSample(textureOffset(tex, texCoord, ivec2(0,-1))) * 0.25;
fragcolor =
centerFragColor * 0.5 +
clampedSample(textureOffset(tex, texCoord, ivec2(0, 1))) * 0.25 +
clampedSample(textureOffset(tex, texCoord, ivec2(0,-1))) * 0.25;
#endif
}
else
{
fragcolor = centerFragColor;
}
}