mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-03-10 03:12:33 +00:00
Add support for drawing flats into the mesh cache
This commit is contained in:
parent
0ee22ccd80
commit
43cef43e9b
8 changed files with 120 additions and 12 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue