Add support for drawing flats into the mesh cache

This commit is contained in:
Magnus Norddahl 2022-12-28 22:25:54 +01:00 committed by Christoph Oelckers
parent 0ee22ccd80
commit 43cef43e9b
8 changed files with 120 additions and 12 deletions

View file

@ -45,6 +45,24 @@ void Mesh::Draw(FRenderState& renderstate)
renderstate.Draw(cmd.DrawType, pair.second + cmd.Start, cmd.Count, apply);
}
for (const MeshDrawCommand& cmd : mIndexedDraws)
{
bool apply = applyIndex != cmd.ApplyIndex;
if (apply)
{
int newDepthFunc = mApplys[cmd.ApplyIndex].DepthFunc;
if (depthFunc != newDepthFunc)
{
depthFunc = newDepthFunc;
renderstate.SetDepthFunc(depthFunc);
}
applyIndex = cmd.ApplyIndex;
Apply(renderstate, mApplys[cmd.ApplyIndex]);
}
renderstate.DrawIndexed(cmd.DrawType, cmd.Start, cmd.Count, apply);
}
Apply(renderstate, origState);
}

View file

@ -12,6 +12,7 @@ private:
TArray<MeshApplyState> mApplys;
TArray<MeshDrawCommand> mDraws;
TArray<MeshDrawCommand> mIndexedDraws;
TArray<FFlatVertex> mVertices;
friend class MeshBuilder;

View file

@ -31,6 +31,19 @@ void MeshBuilder::Draw(int dt, int index, int count, bool apply)
mDraws.Push(command);
}
void MeshBuilder::DrawIndexed(int dt, int index, int count, bool apply)
{
if (apply)
Apply();
MeshDrawCommand command;
command.DrawType = dt;
command.Start = index;
command.Count = count;
command.ApplyIndex = mApplys.Size() - 1;
mIndexedDraws.Push(command);
}
void MeshBuilder::SetDepthFunc(int func)
{
mDepthFunc = func;
@ -67,16 +80,18 @@ void MeshBuilder::Apply()
std::unique_ptr<Mesh> MeshBuilder::Create()
{
if (mDraws.Size() == 0)
if (mDraws.Size() == 0 && mIndexedDraws.Size() == 0)
return {};
auto mesh = std::make_unique<Mesh>();
mesh->mApplys = std::move(mApplys);
mesh->mDraws = std::move(mDraws);
mesh->mIndexedDraws = std::move(mIndexedDraws);
mesh->mVertices = std::move(mVertices);
mApplys.Clear();
mDraws.Clear();
mIndexedDraws.Clear();
mVertices.Clear();
return mesh;

View file

@ -51,7 +51,7 @@ public:
// Draw commands
void Draw(int dt, int index, int count, bool apply = true) override;
void DrawIndexed(int dt, int index, int count, bool apply = true) override { } // TBD: this is only used for the sector flat rendering.
void DrawIndexed(int dt, int index, int count, bool apply = true) override;
// Immediate render state change commands. These only change infrequently and should not clutter the render state.
void SetDepthFunc(int func) override;
@ -81,6 +81,7 @@ private:
TArray<MeshApplyState> mApplys;
TArray<MeshDrawCommand> mDraws;
TArray<MeshDrawCommand> mIndexedDraws;
TArray<FFlatVertex> mVertices;
int mDepthFunc = 0;
};

View file

@ -83,6 +83,7 @@
#include "vm.h"
#include "texturemanager.h"
#include "hw_vertexbuilder.h"
#include "scene/hw_meshcache.h"
#include "version.h"
enum
@ -3243,6 +3244,7 @@ void MapLoader::LoadLevel(MapData *map, const char *lumpname, int position)
InitRenderInfo(); // create hardware independent renderer resources for the level. This must be done BEFORE the PolyObj Spawn!!!
Level->ClearDynamic3DFloorData(); // CreateVBO must be run on the plain 3D floor data.
CreateVBO(screen->mVertexData, Level->sectors);
meshcache.Clear();
screen->InitLightmap(Level->LMTextureSize, Level->LMTextureCount, Level->LMTextureData);

View file

@ -515,7 +515,7 @@ void HWFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector, int which)
//
//
//
if ((which & SSRF_RENDERFLOOR) && frontsector->floorplane.ZatPoint(vp.Pos) <= vp.Pos.Z && (!section || !(section->flags & FSection::DONTRENDERFLOOR)))
if ((which & SSRF_RENDERFLOOR) && (di->MeshBuilding || frontsector->floorplane.ZatPoint(vp.Pos) <= vp.Pos.Z) && (!section || !(section->flags & FSection::DONTRENDERFLOOR)))
{
// process the original floor first.
@ -573,7 +573,7 @@ void HWFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector, int which)
//
//
//
if ((which & SSRF_RENDERCEILING) && frontsector->ceilingplane.ZatPoint(vp.Pos) >= vp.Pos.Z && (!section || !(section->flags & FSection::DONTRENDERCEILING)))
if ((which & SSRF_RENDERCEILING) && (di->MeshBuilding || frontsector->ceilingplane.ZatPoint(vp.Pos) >= vp.Pos.Z) && (!section || !(section->flags & FSection::DONTRENDERCEILING)))
{
// process the original ceiling first.
@ -658,7 +658,7 @@ void HWFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector, int which)
double ff_top = rover->top.plane->ZatPoint(sector->centerspot);
if (ff_top < lastceilingheight)
{
if (vp.Pos.Z <= rover->top.plane->ZatPoint(vp.Pos))
if (di->MeshBuilding || vp.Pos.Z <= rover->top.plane->ZatPoint(vp.Pos))
{
SetFrom3DFloor(rover, true, !!(rover->flags&FF_FOG));
Colormap.FadeColor = frontsector->Colormap.FadeColor;
@ -672,7 +672,7 @@ void HWFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector, int which)
double ff_bottom = rover->bottom.plane->ZatPoint(sector->centerspot);
if (ff_bottom < lastceilingheight)
{
if (vp.Pos.Z <= rover->bottom.plane->ZatPoint(vp.Pos))
if (di->MeshBuilding || vp.Pos.Z <= rover->bottom.plane->ZatPoint(vp.Pos))
{
SetFrom3DFloor(rover, false, !(rover->flags&FF_FOG));
Colormap.FadeColor = frontsector->Colormap.FadeColor;
@ -698,7 +698,7 @@ void HWFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector, int which)
double ff_bottom = rover->bottom.plane->ZatPoint(sector->centerspot);
if (ff_bottom > lastfloorheight || (rover->flags&FF_FIX))
{
if (vp.Pos.Z >= rover->bottom.plane->ZatPoint(vp.Pos))
if (di->MeshBuilding || vp.Pos.Z >= rover->bottom.plane->ZatPoint(vp.Pos))
{
SetFrom3DFloor(rover, false, !(rover->flags&FF_FOG));
Colormap.FadeColor = frontsector->Colormap.FadeColor;
@ -719,7 +719,7 @@ void HWFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector, int which)
double ff_top = rover->top.plane->ZatPoint(sector->centerspot);
if (ff_top > lastfloorheight)
{
if (vp.Pos.Z >= rover->top.plane->ZatPoint(vp.Pos))
if (di->MeshBuilding || vp.Pos.Z >= rover->top.plane->ZatPoint(vp.Pos))
{
SetFrom3DFloor(rover, true, !!(rover->flags&FF_FOG));
Colormap.FadeColor = frontsector->Colormap.FadeColor;

View file

@ -3,35 +3,100 @@
#include "hw_drawinfo.h"
#include "hw_drawstructs.h"
#include "hw_mesh.h"
#include "hw_fakeflat.h"
#include "hw_vertexbuilder.h"
#include "g_levellocals.h"
#include <unordered_set>
EXTERN_CVAR(Bool, gl_texture)
EXTERN_CVAR(Float, gl_mask_threshold)
HWMeshCache meshcache;
void HWMeshCache::Clear()
{
Sectors.Reset();
nextRefresh = 0;
}
void HWMeshCache::Update(FRenderViewpoint& vp)
{
auto level = vp.ViewLevel;
unsigned int count = level->sectors.Size();
Sectors.Resize(count);
// Look for changes
for (unsigned int i = 0; i < count; i++)
{
auto sector = &level->sectors[i];
if (Sectors[i].Sector != sector) // Note: this is just a stupid way to detect we changed map. What is the proper way?
auto cacheitem = &Sectors[i];
if (cacheitem->Floorplane != sector->floorplane || cacheitem->Ceilingplane != sector->ceilingplane) // Sector height changes
{
Sectors[i].Sector = sector;
Sectors[i].Update(vp);
cacheitem->NeedsUpdate = true;
for (line_t* line : sector->Lines)
{
sector_t* backsector = (line->frontsector == sector) ? line->backsector : line->frontsector;
if (backsector)
{
Sectors[backsector->Index()].NeedsUpdate = true;
}
}
}
}
// Refresh 10 sectors per frame. Shouldn't be needed but for some reason some initial flats are black!!
for (int i = 0; i < 10; i++)
{
if (nextRefresh < count)
{
Sectors[nextRefresh].NeedsUpdate = true;
}
if (count > 0)
nextRefresh = (nextRefresh + 1) % count;
}
// Update changed sectors
for (unsigned int i = 0; i < count; i++)
{
auto sector = &level->sectors[i];
auto cacheitem = &Sectors[i];
if (cacheitem->NeedsUpdate)
{
cacheitem->NeedsUpdate = false;
cacheitem->Sector = sector;
cacheitem->Floorplane = sector->floorplane;
cacheitem->Ceilingplane = sector->ceilingplane;
cacheitem->Update(vp);
}
}
}
void HWCachedSector::Update(FRenderViewpoint& vp)
{
Opaque.reset();
Translucent.reset();
TranslucentDepthBiased.reset();
HWDrawInfo* di = HWDrawInfo::StartDrawInfo(vp.ViewLevel, nullptr, vp, nullptr);
di->MeshBuilding = true;
// Add all the walls to the draw lists
// Add to the draw lists
CheckUpdate(screen->mVertexData, Sector);
std::unordered_set<FSection*> seenSections;
for (int i = 0, count = Sector->subsectorcount; i < count; i++)
{
subsector_t* subsector = Sector->subsectors[i];
if (seenSections.find(subsector->section) == seenSections.end())
{
seenSections.insert(subsector->section);
HWFlat flat;
flat.section = subsector->section;
sector_t* front = hw_FakeFlat(subsector->render_sector, area_default, false);
flat.ProcessSector(di, front);
}
}
for (line_t* line : Sector->Lines)
{

View file

@ -8,7 +8,11 @@ struct FRenderViewpoint;
class HWCachedSector
{
public:
bool NeedsUpdate = true;
sector_t* Sector = nullptr;
secplane_t Floorplane;
secplane_t Ceilingplane;
std::unique_ptr<Mesh> Opaque;
std::unique_ptr<Mesh> Translucent;
@ -20,11 +24,13 @@ public:
class HWMeshCache
{
public:
void Clear();
void Update(FRenderViewpoint& vp);
TArray<HWCachedSector> Sectors;
private:
unsigned int nextRefresh = 0;
};
extern HWMeshCache meshcache;