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); 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); Apply(renderstate, origState);
} }

View file

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

View file

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

View file

@ -51,7 +51,7 @@ public:
// Draw commands // Draw commands
void Draw(int dt, int index, int count, bool apply = true) override; 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. // Immediate render state change commands. These only change infrequently and should not clutter the render state.
void SetDepthFunc(int func) override; void SetDepthFunc(int func) override;
@ -81,6 +81,7 @@ private:
TArray<MeshApplyState> mApplys; TArray<MeshApplyState> mApplys;
TArray<MeshDrawCommand> mDraws; TArray<MeshDrawCommand> mDraws;
TArray<MeshDrawCommand> mIndexedDraws;
TArray<FFlatVertex> mVertices; TArray<FFlatVertex> mVertices;
int mDepthFunc = 0; int mDepthFunc = 0;
}; };

View file

@ -83,6 +83,7 @@
#include "vm.h" #include "vm.h"
#include "texturemanager.h" #include "texturemanager.h"
#include "hw_vertexbuilder.h" #include "hw_vertexbuilder.h"
#include "scene/hw_meshcache.h"
#include "version.h" #include "version.h"
enum 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!!! 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. Level->ClearDynamic3DFloorData(); // CreateVBO must be run on the plain 3D floor data.
CreateVBO(screen->mVertexData, Level->sectors); CreateVBO(screen->mVertexData, Level->sectors);
meshcache.Clear();
screen->InitLightmap(Level->LMTextureSize, Level->LMTextureCount, Level->LMTextureData); 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. // 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. // 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); double ff_top = rover->top.plane->ZatPoint(sector->centerspot);
if (ff_top < lastceilingheight) 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)); SetFrom3DFloor(rover, true, !!(rover->flags&FF_FOG));
Colormap.FadeColor = frontsector->Colormap.FadeColor; 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); double ff_bottom = rover->bottom.plane->ZatPoint(sector->centerspot);
if (ff_bottom < lastceilingheight) 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)); SetFrom3DFloor(rover, false, !(rover->flags&FF_FOG));
Colormap.FadeColor = frontsector->Colormap.FadeColor; 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); double ff_bottom = rover->bottom.plane->ZatPoint(sector->centerspot);
if (ff_bottom > lastfloorheight || (rover->flags&FF_FIX)) 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)); SetFrom3DFloor(rover, false, !(rover->flags&FF_FOG));
Colormap.FadeColor = frontsector->Colormap.FadeColor; 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); double ff_top = rover->top.plane->ZatPoint(sector->centerspot);
if (ff_top > lastfloorheight) 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)); SetFrom3DFloor(rover, true, !!(rover->flags&FF_FOG));
Colormap.FadeColor = frontsector->Colormap.FadeColor; Colormap.FadeColor = frontsector->Colormap.FadeColor;

View file

@ -3,35 +3,100 @@
#include "hw_drawinfo.h" #include "hw_drawinfo.h"
#include "hw_drawstructs.h" #include "hw_drawstructs.h"
#include "hw_mesh.h" #include "hw_mesh.h"
#include "hw_fakeflat.h"
#include "hw_vertexbuilder.h"
#include "g_levellocals.h" #include "g_levellocals.h"
#include <unordered_set>
EXTERN_CVAR(Bool, gl_texture) EXTERN_CVAR(Bool, gl_texture)
EXTERN_CVAR(Float, gl_mask_threshold) EXTERN_CVAR(Float, gl_mask_threshold)
HWMeshCache meshcache; HWMeshCache meshcache;
void HWMeshCache::Clear()
{
Sectors.Reset();
nextRefresh = 0;
}
void HWMeshCache::Update(FRenderViewpoint& vp) void HWMeshCache::Update(FRenderViewpoint& vp)
{ {
auto level = vp.ViewLevel; auto level = vp.ViewLevel;
unsigned int count = level->sectors.Size(); unsigned int count = level->sectors.Size();
Sectors.Resize(count); Sectors.Resize(count);
// Look for changes
for (unsigned int i = 0; i < count; i++) for (unsigned int i = 0; i < count; i++)
{ {
auto sector = &level->sectors[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; cacheitem->NeedsUpdate = true;
Sectors[i].Update(vp); 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) void HWCachedSector::Update(FRenderViewpoint& vp)
{ {
Opaque.reset();
Translucent.reset();
TranslucentDepthBiased.reset();
HWDrawInfo* di = HWDrawInfo::StartDrawInfo(vp.ViewLevel, nullptr, vp, nullptr); HWDrawInfo* di = HWDrawInfo::StartDrawInfo(vp.ViewLevel, nullptr, vp, nullptr);
di->MeshBuilding = true; 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) for (line_t* line : Sector->Lines)
{ {

View file

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