Skip to content

Commit

Permalink
Add more dynamic update code to level mesh
Browse files Browse the repository at this point in the history
  • Loading branch information
dpjudas committed Aug 10, 2024
1 parent 8b78a15 commit f1b9e68
Show file tree
Hide file tree
Showing 15 changed files with 147 additions and 101 deletions.
13 changes: 12 additions & 1 deletion src/common/rendering/hwrenderer/data/hw_levelmesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ class LevelMesh
info.Vertices = &Mesh.Vertices[info.VertexStart];
info.UniformIndexes = &Mesh.UniformIndexes[info.VertexStart];
info.Indexes = &Mesh.Indexes[info.IndexStart];
// To do: mark range as dirty
return info;
}

Expand All @@ -89,17 +90,27 @@ class LevelMesh
Mesh.Materials.Resize(info.Start + count);
info.Uniforms = &Mesh.Uniforms[info.Start];
info.Materials = &Mesh.Materials[info.Start];
// To do: mark range as dirty
return info;
}

void FreeGeometry(int vertexStart, int vertexCount, int indexStart, int indexCount)
{
for (int i = 0; i < indexCount; i++)
Mesh.Indexes[indexStart + i] = 0;
// To do: add to a free list
// To do: mark range as dirty
}

void FreeUniforms(int start, int count)
{
// To do: add to a free list
}

void FreeSurface(unsigned int surfaceIndex)
{
// To do: remove the surface from the surface tile, if attached
// To do: add to a free list
}

struct
Expand All @@ -121,7 +132,7 @@ class LevelMesh
TArray<int> SurfaceIndexes;
int DynamicIndexStart = 0;

// Above data must not be resized beyond these limits as that's the size of the GPU buffers)
// Above data must not be resized beyond these limits as that's the size of the GPU buffers
int MaxVertices = 0;
int MaxIndexes = 0;
int MaxSurfaces = 0;
Expand Down
2 changes: 0 additions & 2 deletions src/common/rendering/hwrenderer/data/hw_levelmeshsurface.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ struct LevelMeshSurface
FVector4 Plane = FVector4(0.0f, 0.0f, 1.0f, 0.0f);
int LightmapTileIndex = -1;

bool AlwaysUpdate = false;

FGameTexture* Texture = nullptr;
float Alpha = 1.0;

Expand Down
2 changes: 2 additions & 0 deletions src/common/rendering/hwrenderer/data/hw_lightmaptile.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ struct LightmapTile
// True if the tile needs to be rendered into the lightmap texture before it can be used
bool NeedsUpdate = true;

bool AlwaysUpdate = false;

FVector2 ToUV(const FVector3& vert) const
{
FVector3 localPos = vert - Transform.TranslateWorldToLocal;
Expand Down
2 changes: 1 addition & 1 deletion src/g_levellocals.h
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ struct FLevelLocals

// Lightmaps
bool lightmaps = false;
TArray<DoomLevelMeshSurface*> Surfaces;
TArray<int> LightmapTiles;
FVector3 SunDirection;
FVector3 SunColor;
uint16_t LightmapSampleDistance;
Expand Down
4 changes: 2 additions & 2 deletions src/gamedata/r_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1257,7 +1257,7 @@ struct side_t
uint16_t Flags;
int UDMFIndex; // needed to access custom UDMF fields which are stored in loading order.
FLightNode * lighthead; // all dynamic lights that may affect this wall
TArrayView<DoomLevelMeshSurface*> surface; // all mesh surfaces belonging to this sidedef
TArrayView<int> LightmapTiles; // all lightmap tiles belonging to this sidedef
seg_t **segs; // all segs belonging to this sidedef in ascending order. Used for precise rendering
int numsegs;
int sidenum;
Expand Down Expand Up @@ -1674,7 +1674,7 @@ struct subsector_t
// 2: has one-sided walls
FPortalCoverage portalcoverage[2];
TArray<DVisualThinker *> sprites;
TArrayView<DoomLevelMeshSurface*> surface[2]; // all mesh surfaces belonging to this subsector
TArrayView<int> LightmapTiles[2]; // all lightmap tiles belonging to this subsector
};


Expand Down
11 changes: 6 additions & 5 deletions src/maploader/maploader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2989,23 +2989,24 @@ void MapLoader::InitLevelMesh(MapData* map)
for (unsigned int i = 0; i < Level->subsectors.Size(); i++)
allSurfaces += 2 + Level->subsectors[i].sector->e->XFloor.ffloors.Size() * 2;

Level->Surfaces.Resize(allSurfaces);
memset(Level->Surfaces.Data(), 0, sizeof(DoomLevelMeshSurface*) * allSurfaces);
Level->LightmapTiles.Resize(allSurfaces);
for (int& value : Level->LightmapTiles)
value = -1;

unsigned int offset = 0;
for (unsigned int i = 0; i < Level->sides.Size(); i++)
{
auto& side = Level->sides[i];
int count = 4 + side.sector->e->XFloor.ffloors.Size();
side.surface = TArrayView<DoomLevelMeshSurface*>(&Level->Surfaces[offset], count);
side.LightmapTiles = TArrayView<int>(&Level->LightmapTiles[offset], count);
offset += count;
}
for (unsigned int i = 0; i < Level->subsectors.Size(); i++)
{
auto& subsector = Level->subsectors[i];
unsigned int count = 1 + subsector.sector->e->XFloor.ffloors.Size();
subsector.surface[0] = TArrayView<DoomLevelMeshSurface*>(&Level->Surfaces[offset], count);
subsector.surface[1] = TArrayView<DoomLevelMeshSurface*>(&Level->Surfaces[offset + count], count);
subsector.LightmapTiles[0] = TArrayView<int>(&Level->LightmapTiles[offset], count);
subsector.LightmapTiles[1] = TArrayView<int>(&Level->LightmapTiles[offset + count], count);
offset += count * 2;
}

Expand Down
119 changes: 73 additions & 46 deletions src/rendering/hwrenderer/doom_levelmesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@ void PrintSurfaceInfo(const DoomLevelMeshSurface* surface)
Printf(" Pixels: %dx%d (area: %d)\n", tile->AtlasLocation.Width, tile->AtlasLocation.Height, tile->AtlasLocation.Area());
Printf(" Sample dimension: %d\n", tile->SampleDimension);
Printf(" Needs update?: %d\n", tile->NeedsUpdate);
Printf(" Always update?: %d\n", tile->AlwaysUpdate);
}
Printf(" Always update?: %d\n", surface->AlwaysUpdate);
Printf(" Sector group: %d\n", surface->SectorGroup);
Printf(" Texture: '%s'\n", gameTexture ? gameTexture->GetName().GetChars() : "<nullptr>");
Printf(" Alpha: %f\n", surface->Alpha);
Expand Down Expand Up @@ -345,8 +345,44 @@ void DoomLevelMesh::CreateSurfaces(FLevelLocals& doomMap)
}
}

void DoomLevelMesh::FreeSide(FLevelLocals& doomMap, unsigned int sideIndex)
{
if (sideIndex < 0 || sideIndex >= Sides.Size())
return;

int surf = Sides[sideIndex].FirstSurface;
while (surf != -1)
{
unsigned int next = Surfaces[surf].NextSurface;
FreeSurface(surf);
surf = next;
}
Sides[sideIndex].FirstSurface = -1;

// To do: call FreeGeometry and FreeUniforms
}

void DoomLevelMesh::FreeFlat(FLevelLocals& doomMap, unsigned int sectorIndex)
{
if (sectorIndex < 0 || sectorIndex >= Flats.Size())
return;

int surf = Flats[sectorIndex].FirstSurface;
while (surf != -1)
{
unsigned int next = Surfaces[surf].NextSurface;
FreeSurface(surf - 1);
surf = next;
}
Flats[sectorIndex].FirstSurface = -1;

// To do: call FreeGeometry and FreeUniforms
}

void DoomLevelMesh::UpdateSide(FLevelLocals& doomMap, unsigned int sideIndex)
{
FreeSide(doomMap, sideIndex);

side_t* side = &doomMap.sides[sideIndex];
seg_t* seg = side->segs[0];
if (!seg)
Expand All @@ -369,27 +405,29 @@ void DoomLevelMesh::UpdateSide(FLevelLocals& doomMap, unsigned int sideIndex)
state.EnableTexture(true);
state.EnableBrightmap(true);
state.AlphaFunc(Alpha_GEqual, 0.f);
CreateWallSurface(side, disp, state, result.list, false, true);
CreateWallSurface(side, disp, state, result.list, false, true, sideIndex);

for (HWWall& portal : result.portals)
{
WallPortals.Push(portal);
}

CreateWallSurface(side, disp, state, result.portals, true, false);
CreateWallSurface(side, disp, state, result.portals, true, false, sideIndex);

/*
// final pass: translucent stuff
state.AlphaFunc(Alpha_GEqual, gl_mask_sprite_threshold);
state.SetRenderStyle(STYLE_Translucent);
CreateWallSurface(side, disp, state, result.translucent, false, true);
CreateWallSurface(side, disp, state, result.translucent, false, true, sideIndex);
state.AlphaFunc(Alpha_GEqual, 0.f);
state.SetRenderStyle(STYLE_Normal);
*/
}

void DoomLevelMesh::UpdateFlat(FLevelLocals& doomMap, unsigned int sectorIndex)
{
FreeSide(doomMap, sectorIndex);

sector_t* sector = &doomMap.sectors[sectorIndex];
for (FSection& section : doomMap.sections.SectionsForSector(sectorIndex))
{
Expand All @@ -405,23 +443,23 @@ void DoomLevelMesh::UpdateFlat(FLevelLocals& doomMap, unsigned int sectorIndex)
state.ClearDepthBias();
state.EnableTexture(true);
state.EnableBrightmap(true);
CreateFlatSurface(disp, state, result.list, false, false);
CreateFlatSurface(disp, state, result.list, false, false, sectorIndex);

CreateFlatSurface(disp, state, result.portals, true, false);
CreateFlatSurface(disp, state, result.portals, true, false, sectorIndex);

// final pass: translucent stuff
state.AlphaFunc(Alpha_GEqual, gl_mask_sprite_threshold);
state.SetRenderStyle(STYLE_Translucent);
CreateFlatSurface(disp, state, result.translucentborder, false, true);
CreateFlatSurface(disp, state, result.translucentborder, false, true, sectorIndex);
state.SetDepthMask(false);
CreateFlatSurface(disp, state, result.translucent, false, true);
CreateFlatSurface(disp, state, result.translucent, false, true, sectorIndex);
state.AlphaFunc(Alpha_GEqual, 0.f);
state.SetDepthMask(true);
state.SetRenderStyle(STYLE_Normal);
}
}

void DoomLevelMesh::CreateWallSurface(side_t* side, HWWallDispatcher& disp, MeshBuilder& state, TArray<HWWall>& list, bool isPortal, bool translucent)
void DoomLevelMesh::CreateWallSurface(side_t* side, HWWallDispatcher& disp, MeshBuilder& state, TArray<HWWall>& list, bool isPortal, bool translucent, unsigned int sideIndex)
{
for (HWWall& wallpart : list)
{
Expand Down Expand Up @@ -534,7 +572,6 @@ void DoomLevelMesh::CreateWallSurface(side_t* side, HWWallDispatcher& disp, Mesh
surf.ControlSector = wallpart.LevelMeshInfo.ControlSector;
surf.TypeIndex = side->Index();
surf.Side = side;
surf.AlwaysUpdate = !!(side->sector->Flags & SECF_LM_DYNAMIC);
surf.SectorGroup = sectorGroup[side->sector->Index()];
surf.Alpha = float(side->linedef->alpha);
surf.MeshLocation.StartVertIndex = ginfo.VertexStart;
Expand All @@ -547,12 +584,19 @@ void DoomLevelMesh::CreateWallSurface(side_t* side, HWWallDispatcher& disp, Mesh
surf.PortalIndex = isPortal ? linePortals[side->linedef->Index()] : 0;
surf.IsSky = isPortal ? (wallpart.portaltype == PORTALTYPE_SKY || wallpart.portaltype == PORTALTYPE_SKYBOX || wallpart.portaltype == PORTALTYPE_HORIZON) : false;
surf.Bounds = GetBoundsFromSurface(surf);
surf.LightmapTileIndex = disp.Level->lightmaps ? AddSurfaceToTile(surf, sampleDimension) : -1;
surf.LightmapTileIndex = disp.Level->lightmaps ? AddSurfaceToTile(surf, sampleDimension, !!(side->sector->Flags & SECF_LM_DYNAMIC)) : -1;

if (sideIndex < Sides.Size())
{
surf.NextSurface = Sides[sideIndex].FirstSurface;
Sides[sideIndex].FirstSurface = Surfaces.Size();
}

Surfaces.Push(surf);
}
}

int DoomLevelMesh::AddSurfaceToTile(const DoomLevelMeshSurface& surf, uint16_t sampleDimension)
int DoomLevelMesh::AddSurfaceToTile(const DoomLevelMeshSurface& surf, uint16_t sampleDimension, bool alwaysUpdate)
{
if (surf.IsSky)
return -1;
Expand All @@ -574,6 +618,7 @@ int DoomLevelMesh::AddSurfaceToTile(const DoomLevelMeshSurface& surf, uint16_t s
tile.Bounds.max.X = std::max(tile.Bounds.max.X, surf.Bounds.max.X);
tile.Bounds.max.Y = std::max(tile.Bounds.max.Y, surf.Bounds.max.Y);
tile.Bounds.max.Z = std::max(tile.Bounds.max.Z, surf.Bounds.max.Z);
tile.AlwaysUpdate = tile.AlwaysUpdate || alwaysUpdate;

return index;
}
Expand All @@ -586,6 +631,7 @@ int DoomLevelMesh::AddSurfaceToTile(const DoomLevelMeshSurface& surf, uint16_t s
tile.Bounds = surf.Bounds;
tile.Plane = surf.Plane;
tile.SampleDimension = GetSampleDimension(surf, sampleDimension);
tile.AlwaysUpdate = alwaysUpdate;

LightmapTiles.Push(tile);
bindings[binding] = index;
Expand Down Expand Up @@ -614,7 +660,7 @@ int DoomLevelMesh::GetSampleDimension(const DoomLevelMeshSurface& surf, uint16_t
return sampleDimension;
}

void DoomLevelMesh::CreateFlatSurface(HWFlatDispatcher& disp, MeshBuilder& state, TArray<HWFlat>& list, bool isSky, bool translucent)
void DoomLevelMesh::CreateFlatSurface(HWFlatDispatcher& disp, MeshBuilder& state, TArray<HWFlat>& list, bool isSky, bool translucent, unsigned int sectorIndex)
{
for (HWFlat& flatpart : list)
{
Expand Down Expand Up @@ -702,7 +748,6 @@ void DoomLevelMesh::CreateFlatSurface(HWFlatDispatcher& disp, MeshBuilder& state
DoomLevelMeshSurface surf;
surf.Type = flatpart.ceiling ? ST_CEILING : ST_FLOOR;
surf.ControlSector = flatpart.controlsector ? flatpart.controlsector->model : nullptr;
surf.AlwaysUpdate = !!(flatpart.sector->Flags & SECF_LM_DYNAMIC);
surf.SectorGroup = sectorGroup[flatpart.sector->Index()];
surf.Alpha = flatpart.alpha;
surf.Texture = flatpart.texture;
Expand Down Expand Up @@ -775,36 +820,18 @@ void DoomLevelMesh::CreateFlatSurface(HWFlatDispatcher& disp, MeshBuilder& state
surf.MeshLocation.NumVerts = sub->numlines;
surf.MeshLocation.NumElements = (sub->numlines - 2) * 3;
surf.Bounds = GetBoundsFromSurface(surf);
surf.LightmapTileIndex = disp.Level->lightmaps ? AddSurfaceToTile(surf, sampleDimension) : -1;
Surfaces.Push(surf);
}
}
}
surf.LightmapTileIndex = disp.Level->lightmaps ? AddSurfaceToTile(surf, sampleDimension, !!(flatpart.sector->Flags & SECF_LM_DYNAMIC)) : -1;

#if 0
void DoomLevelMesh::CreateDynamicSurfaces(FLevelLocals& doomMap)
{
// Look for polyobjects
for (unsigned int i = 0; i < doomMap.lines.Size(); i++)
{
side_t* side = doomMap.lines[i].sidedef[0];
bool isPolyLine = !!(side->Flags & WALLF_POLYOBJ);
if (!isPolyLine)
continue;
if (sectorIndex < Flats.Size())
{
surf.NextSurface = Flats[sectorIndex].FirstSurface;
Flats[sectorIndex].FirstSurface = Surfaces.Size();
}

// Make sure we have a surface array on the polyobj sidedef
if (!side->surface)
{
auto array = std::make_unique<DoomLevelMeshSurface * []>(4);
memset(array.get(), 0, sizeof(DoomLevelMeshSurface*));
side->surface = array.get();
PolyLMSurfaces.Push(std::move(array));
Surfaces.Push(surf);
}

CreateSideSurfaces(doomMap, side);
}
}
#endif

void DoomLevelMesh::SortIndexes()
{
Expand Down Expand Up @@ -879,7 +906,7 @@ void DoomLevelMesh::SetSubsectorLightmap(DoomLevelMeshSurface* surface)
if (!surface->ControlSector)
{
int index = surface->Type == ST_CEILING ? 1 : 0;
surface->Subsector->surface[index][0] = surface;
surface->Subsector->LightmapTiles[index][0] = surface->LightmapTileIndex;
}
else
{
Expand All @@ -889,7 +916,7 @@ void DoomLevelMesh::SetSubsectorLightmap(DoomLevelMeshSurface* surface)
{
if (ffloors[i]->model == surface->ControlSector)
{
surface->Subsector->surface[index][i + 1] = surface;
surface->Subsector->LightmapTiles[index][i + 1] = surface->LightmapTileIndex;
}
}
}
Expand All @@ -901,16 +928,16 @@ void DoomLevelMesh::SetSideLightmap(DoomLevelMeshSurface* surface)
{
if (surface->Type == ST_UPPERSIDE)
{
surface->Side->surface[0] = surface;
surface->Side->LightmapTiles[0] = surface->LightmapTileIndex;
}
else if (surface->Type == ST_MIDDLESIDE)
{
surface->Side->surface[1] = surface;
surface->Side->surface[2] = surface;
surface->Side->LightmapTiles[1] = surface->LightmapTileIndex;
surface->Side->LightmapTiles[2] = surface->LightmapTileIndex;
}
else if (surface->Type == ST_LOWERSIDE)
{
surface->Side->surface[3] = surface;
surface->Side->LightmapTiles[3] = surface->LightmapTileIndex;
}
}
else
Expand All @@ -921,7 +948,7 @@ void DoomLevelMesh::SetSideLightmap(DoomLevelMeshSurface* surface)
{
if (ffloors[i]->model == surface->ControlSector)
{
backside->surface[4 + i] = surface;
backside->LightmapTiles[4 + i] = surface->LightmapTileIndex;
}
}
}
Expand Down
Loading

0 comments on commit f1b9e68

Please sign in to comment.