mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-03-09 11:03:12 +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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ private:
|
|||
|
||||
TArray<MeshApplyState> mApplys;
|
||||
TArray<MeshDrawCommand> mDraws;
|
||||
TArray<MeshDrawCommand> mIndexedDraws;
|
||||
TArray<FFlatVertex> mVertices;
|
||||
|
||||
friend class MeshBuilder;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue