mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-04-22 02:40:57 +00:00
WIP partial lightmapping
This commit is contained in:
parent
5fc7a4dc41
commit
d19a73641a
10 changed files with 84 additions and 7 deletions
|
@ -52,6 +52,8 @@ struct LevelMeshSurface
|
|||
int texWidth = 0;
|
||||
int texHeight = 0;
|
||||
|
||||
bool needsUpdate = true;
|
||||
|
||||
//
|
||||
// Required for internal lightmapper:
|
||||
//
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "vectors.h"
|
||||
#include "matrix.h"
|
||||
#include "hw_material.h"
|
||||
#include "hw_levelmesh.h"
|
||||
#include "texmanip.h"
|
||||
#include "version.h"
|
||||
#include "i_interface.h"
|
||||
|
@ -257,6 +258,7 @@ protected:
|
|||
|
||||
EPassType mPassType = NORMAL_PASS;
|
||||
|
||||
TArray<LevelMeshSurface*> mActiveLightmapSurfaces;
|
||||
public:
|
||||
|
||||
uint64_t firstFrame = 0;
|
||||
|
@ -729,6 +731,22 @@ public:
|
|||
return SetViewpoint(matrices);
|
||||
}
|
||||
|
||||
inline void PushVisibleSurface(LevelMeshSurface* surface)
|
||||
{
|
||||
if(surface && surface->needsUpdate && mActiveLightmapSurfaces.Find(surface) >= mActiveLightmapSurfaces.Size()) // yikes, how awful
|
||||
mActiveLightmapSurfaces.Push(surface);
|
||||
}
|
||||
|
||||
inline const auto& GetVisibleSurfaceList() const
|
||||
{
|
||||
return mActiveLightmapSurfaces;
|
||||
}
|
||||
|
||||
inline void ClearVisibleSurfaceList()
|
||||
{
|
||||
mActiveLightmapSurfaces.Clear();
|
||||
}
|
||||
|
||||
// API-dependent render interface
|
||||
|
||||
// Worker threads
|
||||
|
|
|
@ -156,6 +156,7 @@ public:
|
|||
virtual bool IsPoly() { return false; }
|
||||
virtual bool CompileNextShader() { return true; }
|
||||
virtual void SetLevelMesh(LevelMesh *mesh) { }
|
||||
virtual void UpdateLightmaps(const TArray<LevelMeshSurface*>& surfaces) {}
|
||||
bool allowSSBO() const
|
||||
{
|
||||
#ifndef HW_BLOCK_SSBO
|
||||
|
|
|
@ -31,6 +31,17 @@ VkLightmap::~VkLightmap()
|
|||
lights.Buffer->Unmap();
|
||||
}
|
||||
|
||||
static int lastSurfaceCount;
|
||||
|
||||
ADD_STAT(lightmapper)
|
||||
{
|
||||
FString out;
|
||||
|
||||
out.Format("Last batch surface count: %d", lastSurfaceCount);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
void VkLightmap::Raytrace(LevelMesh* level, const TArray<LevelMeshSurface*>& surfaces)
|
||||
{
|
||||
bool newLevel = (mesh != level);
|
||||
|
@ -42,8 +53,15 @@ void VkLightmap::Raytrace(LevelMesh* level, const TArray<LevelMeshSurface*>& sur
|
|||
CreateAtlasImages();
|
||||
}
|
||||
|
||||
for (auto surface : surfaces)
|
||||
{
|
||||
surface->needsUpdate = false;
|
||||
}
|
||||
|
||||
UploadUniforms();
|
||||
|
||||
lastSurfaceCount = surfaces.Size();
|
||||
|
||||
for (size_t pageIndex = 0; pageIndex < atlasImages.size(); pageIndex++)
|
||||
{
|
||||
RenderAtlasImage(pageIndex, surfaces);
|
||||
|
@ -53,7 +71,7 @@ void VkLightmap::Raytrace(LevelMesh* level, const TArray<LevelMeshSurface*>& sur
|
|||
{
|
||||
ResolveAtlasImage(pageIndex);
|
||||
BlurAtlasImage(pageIndex);
|
||||
CopyAtlasImageResult(pageIndex);
|
||||
CopyAtlasImageResult(pageIndex, surfaces);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -375,14 +393,14 @@ void VkLightmap::BlurAtlasImage(size_t pageIndex)
|
|||
}
|
||||
}
|
||||
|
||||
void VkLightmap::CopyAtlasImageResult(size_t pageIndex)
|
||||
void VkLightmap::CopyAtlasImageResult(size_t pageIndex, const TArray<LevelMeshSurface*>& surfaces)
|
||||
{
|
||||
LightmapImage& img = atlasImages[pageIndex];
|
||||
|
||||
std::vector<VkImageCopy> regions;
|
||||
for (int i = 0, count = mesh->GetSurfaceCount(); i < count; i++)
|
||||
for (int i = 0, count = surfaces.Size(); i < count; i++)
|
||||
{
|
||||
LevelMeshSurface* surface = mesh->GetSurface(i);
|
||||
LevelMeshSurface* surface = surfaces[i];
|
||||
if (surface->lightmapperAtlasPage != pageIndex)
|
||||
continue;
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ private:
|
|||
void RenderAtlasImage(size_t pageIndex, const TArray<LevelMeshSurface*>& surfaces);
|
||||
void ResolveAtlasImage(size_t pageIndex);
|
||||
void BlurAtlasImage(size_t pageIndex);
|
||||
void CopyAtlasImageResult(size_t pageIndex);
|
||||
void CopyAtlasImageResult(size_t pageIndex, const TArray<LevelMeshSurface*>& surfaces);
|
||||
|
||||
LightmapImage CreateImage(int width, int height);
|
||||
|
||||
|
|
|
@ -531,17 +531,20 @@ void VulkanRenderDevice::PrintStartupLog()
|
|||
Printf("Min. uniform buffer offset alignment: %" PRIu64 "\n", limits.minUniformBufferOffsetAlignment);
|
||||
}
|
||||
|
||||
LevelMesh* lastMesh = nullptr; // Temp hack; Since this function is called every frame we only want to do this once
|
||||
|
||||
void VulkanRenderDevice::SetLevelMesh(LevelMesh* mesh)
|
||||
{
|
||||
mRaytrace->SetLevelMesh(mesh);
|
||||
|
||||
static LevelMesh* lastMesh = nullptr; // Temp hack; Since this function is called every frame we only want to do this once
|
||||
if (lastMesh != mesh && mesh->GetSurfaceCount() > 0)
|
||||
{
|
||||
lastMesh = mesh;
|
||||
|
||||
mesh->UpdateLightLists();
|
||||
GetTextureManager()->CreateLightmap(mesh->LMTextureSize, mesh->LMTextureCount);
|
||||
|
||||
#if 0 // full lightmap generation
|
||||
TArray<LevelMeshSurface*> surfaces;
|
||||
surfaces.Reserve(mesh->GetSurfaceCount());
|
||||
for (unsigned i = 0, count = mesh->GetSurfaceCount(); i < count; ++i)
|
||||
|
@ -549,8 +552,23 @@ void VulkanRenderDevice::SetLevelMesh(LevelMesh* mesh)
|
|||
surfaces[i] = mesh->GetSurface(i);
|
||||
}
|
||||
|
||||
GetTextureManager()->CreateLightmap(mesh->LMTextureSize, mesh->LMTextureCount);
|
||||
GetLightmap()->Raytrace(mesh, surfaces);
|
||||
#else
|
||||
GetLightmap()->Raytrace(mesh, {});
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanRenderDevice::UpdateLightmaps(const TArray<LevelMeshSurface*>& surfaces)
|
||||
{
|
||||
if (surfaces.Size() > 0)
|
||||
{
|
||||
auto levelMesh = lastMesh; // There's nothing more permanent than a temporary solution
|
||||
|
||||
if (levelMesh)
|
||||
{
|
||||
GetLightmap()->Raytrace(levelMesh, surfaces);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -63,6 +63,7 @@ public:
|
|||
void AmbientOccludeScene(float m5) override;
|
||||
void SetSceneRenderTarget(bool useSSAO) override;
|
||||
void SetLevelMesh(LevelMesh* mesh) override;
|
||||
void UpdateLightmaps(const TArray<LevelMeshSurface*>& surfaces) override;
|
||||
void SetShadowMaps(const TArray<float>& lights, hwrenderer::LevelAABBTree* tree, bool newTree) override;
|
||||
void SetSaveBuffers(bool yes) override;
|
||||
void ImageTransitionScene(bool unknown) override;
|
||||
|
|
|
@ -23,6 +23,18 @@ CCMD(dumplevelmesh)
|
|||
}
|
||||
}
|
||||
|
||||
CCMD(invalidatelightmap)
|
||||
{
|
||||
int count = 0;
|
||||
for (auto& surface : level.levelMesh->Surfaces)
|
||||
{
|
||||
if (!surface.needsUpdate)
|
||||
++count;
|
||||
surface.needsUpdate = true;
|
||||
}
|
||||
Printf("Marked %d out of %d surfaces for update.\n", count, level.levelMesh->Surfaces.Size());
|
||||
}
|
||||
|
||||
DoomLevelMesh::DoomLevelMesh(FLevelLocals &doomMap)
|
||||
{
|
||||
SunColor = doomMap.SunColor; // TODO keep only one copy?
|
||||
|
|
|
@ -124,6 +124,7 @@ sector_t* RenderViewpoint(FRenderViewpoint& mainvp, AActor* camera, IntRect* bou
|
|||
screen->mShadowMap->SetCollectLights(nullptr);
|
||||
}
|
||||
|
||||
RenderState.ClearVisibleSurfaceList();
|
||||
screen->SetLevelMesh(camera->Level->levelMesh);
|
||||
|
||||
static HWDrawContext mainthread_drawctx;
|
||||
|
@ -197,6 +198,8 @@ sector_t* RenderViewpoint(FRenderViewpoint& mainvp, AActor* camera, IntRect* bou
|
|||
screen->NextEye(eyeCount);
|
||||
}
|
||||
|
||||
screen->UpdateLightmaps(RenderState.GetVisibleSurfaceList());
|
||||
|
||||
return mainvp.sector;
|
||||
}
|
||||
|
||||
|
|
|
@ -192,6 +192,10 @@ void HWFlat::DrawSubsectors(HWDrawInfo *di, FRenderState &state)
|
|||
}
|
||||
state.SetLightIndex(dynlightindex);
|
||||
|
||||
for (auto& subsector : section->subsectors)
|
||||
{
|
||||
state.PushVisibleSurface(subsector->lightmap[ceiling ? 1 : 0][0]);
|
||||
}
|
||||
|
||||
state.DrawIndexed(DT_Triangles, iboindex + section->vertexindex, section->vertexcount);
|
||||
flatvertices += section->vertexcount;
|
||||
|
|
Loading…
Reference in a new issue