Generate mesh data flats with a sky

This commit is contained in:
Magnus Norddahl 2023-12-13 00:25:44 +01:00
commit b93df82ac7
4 changed files with 175 additions and 149 deletions

View file

@ -88,7 +88,7 @@ void DoomLevelSubmesh::CreateStaticSurfaces(FLevelLocals& doomMap)
MeshBuilder state;
// Create surface objects for all visible side parts
// Create surface objects for all sides
for (unsigned int i = 0; i < doomMap.sides.Size(); i++)
{
side_t* side = &doomMap.sides[i];
@ -115,70 +115,15 @@ void DoomLevelSubmesh::CreateStaticSurfaces(FLevelLocals& doomMap)
state.ClearDepthBias();
state.EnableTexture(gl_texture);
state.EnableBrightmap(true);
state.AlphaFunc(Alpha_GEqual, 0.f);
CreateWallSurface(side, disp, state, result.list);
for (HWWall& wallpart : result.list)
{
if (wallpart.texture && wallpart.texture->isMasked())
{
state.AlphaFunc(Alpha_GEqual, gl_mask_threshold);
}
else
{
state.AlphaFunc(Alpha_GEqual, 0.f);
}
wallpart.DrawWall(&disp, state, false);
int pipelineID = 0;
int startVertIndex = Mesh.Vertices.Size();
for (auto& it : state.mSortedLists)
{
const MeshApplyState& applyState = it.first;
pipelineID = screen->GetLevelMeshPipelineID(applyState.applyData, applyState.surfaceUniforms, applyState.material);
int uniformsIndex = Mesh.Uniforms.Size();
Mesh.Uniforms.Push(applyState.surfaceUniforms);
Mesh.Materials.Push(applyState.material);
for (MeshDrawCommand& command : it.second.mDraws)
{
for (int i = command.Start, end = command.Start + command.Count; i < end; i++)
{
Mesh.Vertices.Push(state.mVertices[i]);
Mesh.UniformIndexes.Push(uniformsIndex);
}
}
for (MeshDrawCommand& command : it.second.mIndexedDraws)
{
for (int i = command.Start, end = command.Start + command.Count; i < end; i++)
{
Mesh.Vertices.Push(state.mVertices[state.mIndexes[i]]);
Mesh.UniformIndexes.Push(uniformsIndex);
}
}
}
state.mSortedLists.clear();
state.mVertices.Clear();
state.mIndexes.Clear();
DoomLevelMeshSurface surf;
surf.Submesh = this;
surf.Type = wallpart.LevelMeshInfo.Type;
surf.ControlSector = wallpart.LevelMeshInfo.ControlSector;
surf.TypeIndex = side->Index();
surf.Side = side;
surf.AlwaysUpdate = !!(front->Flags & SECF_LM_DYNAMIC);
surf.SectorGroup = LevelMesh->sectorGroup[front->Index()];
surf.Alpha = float(side->linedef->alpha);
surf.MeshLocation.StartVertIndex = startVertIndex;
surf.MeshLocation.NumVerts = Mesh.Vertices.Size() - startVertIndex;
surf.Plane = ToPlane(Mesh.Vertices[startVertIndex + 3].fPos(), Mesh.Vertices[startVertIndex + 2].fPos(), Mesh.Vertices[startVertIndex + 1].fPos(), Mesh.Vertices[startVertIndex].fPos());
surf.Texture = wallpart.texture;
surf.PipelineID = pipelineID;
surf.PortalIndex = (surf.Type == ST_MIDDLESIDE) ? LevelMesh->linePortals[side->linedef->Index()] : 0;
Surfaces.Push(surf);
}
// final pass: translucent stuff
state.AlphaFunc(Alpha_GEqual, gl_mask_sprite_threshold);
state.SetRenderStyle(STYLE_Translucent);
CreateWallSurface(side, disp, state, result.translucent);
state.AlphaFunc(Alpha_GEqual, 0.f);
state.SetRenderStyle(STYLE_Normal);
for (const HWWall& portal : result.portals)
{
@ -206,88 +151,172 @@ void DoomLevelSubmesh::CreateStaticSurfaces(FLevelLocals& doomMap)
state.ClearDepthBias();
state.EnableTexture(gl_texture);
state.EnableBrightmap(true);
CreateFlatSurface(disp, state, result.list);
for (HWFlat& flatpart : result.list)
CreateFlatSurface(disp, state, result.portals, true);
// final pass: translucent stuff
state.AlphaFunc(Alpha_GEqual, gl_mask_sprite_threshold);
state.SetRenderStyle(STYLE_Translucent);
CreateFlatSurface(disp, state, result.translucentborder);
state.SetDepthMask(false);
CreateFlatSurface(disp, state, result.translucent);
state.AlphaFunc(Alpha_GEqual, 0.f);
state.SetDepthMask(true);
state.SetRenderStyle(STYLE_Normal);
}
}
}
void DoomLevelSubmesh::CreateWallSurface(side_t* side, HWWallDispatcher& disp, MeshBuilder& state, TArray<HWWall>& list)
{
for (HWWall& wallpart : list)
{
if (wallpart.texture && wallpart.texture->isMasked())
{
state.AlphaFunc(Alpha_GEqual, gl_mask_threshold);
}
else
{
state.AlphaFunc(Alpha_GEqual, 0.f);
}
wallpart.DrawWall(&disp, state, false);
int pipelineID = 0;
int startVertIndex = Mesh.Vertices.Size();
for (auto& it : state.mSortedLists)
{
const MeshApplyState& applyState = it.first;
pipelineID = screen->GetLevelMeshPipelineID(applyState.applyData, applyState.surfaceUniforms, applyState.material);
int uniformsIndex = Mesh.Uniforms.Size();
Mesh.Uniforms.Push(applyState.surfaceUniforms);
Mesh.Materials.Push(applyState.material);
for (MeshDrawCommand& command : it.second.mDraws)
{
if (flatpart.texture && flatpart.texture->isMasked())
for (int i = command.Start, end = command.Start + command.Count; i < end; i++)
{
state.AlphaFunc(Alpha_GEqual, gl_mask_threshold);
}
else
{
state.AlphaFunc(Alpha_GEqual, 0.f);
}
flatpart.DrawFlat(&disp, state, false);
int pipelineID = 0;
int uniformsIndex = 0;
bool foundDraw = false;
for (auto& it : state.mSortedLists)
{
const MeshApplyState& applyState = it.first;
pipelineID = screen->GetLevelMeshPipelineID(applyState.applyData, applyState.surfaceUniforms, applyState.material);
uniformsIndex = Mesh.Uniforms.Size();
Mesh.Uniforms.Push(applyState.surfaceUniforms);
Mesh.Materials.Push(applyState.material);
foundDraw = true;
break;
}
state.mSortedLists.clear();
state.mVertices.Clear();
state.mIndexes.Clear();
if (!foundDraw)
continue;
DoomLevelMeshSurface surf;
surf.Submesh = this;
surf.Type = flatpart.ceiling ? ST_CEILING : ST_FLOOR;
surf.ControlSector = flatpart.controlsector ? flatpart.controlsector->model : nullptr;
surf.AlwaysUpdate = !!(sector->Flags & SECF_LM_DYNAMIC);
surf.SectorGroup = LevelMesh->sectorGroup[sector->Index()];
surf.Alpha = flatpart.alpha;
surf.Texture = flatpart.texture;
surf.PipelineID = pipelineID;
surf.PortalIndex = LevelMesh->sectorPortals[flatpart.ceiling][i];
auto plane = surf.ControlSector ? surf.ControlSector->GetSecPlane(!flatpart.ceiling) : sector->GetSecPlane(flatpart.ceiling);
surf.Plane = FVector4((float)plane.Normal().X, (float)plane.Normal().Y, (float)plane.Normal().Z, -(float)plane.D);
if (surf.ControlSector)
surf.Plane = -surf.Plane;
for (subsector_t* sub : section.subsectors)
{
int startVertIndex = Mesh.Vertices.Size();
for (int i = 0, end = sub->numlines; i < end; i++)
{
auto& vt = sub->firstline[end - 1 - i].v1;
FFlatVertex ffv;
ffv.x = (float)vt->fX();
ffv.y = (float)vt->fY();
ffv.z = (float)plane.ZatPoint(vt);
ffv.u = (float)vt->fX() / 64.f;
ffv.v = -(float)vt->fY() / 64.f;
ffv.lu = 0.0f;
ffv.lv = 0.0f;
ffv.lindex = -1.0f;
Mesh.Vertices.Push(ffv);
Mesh.UniformIndexes.Push(uniformsIndex);
}
surf.TypeIndex = sub->Index();
surf.Subsector = sub;
surf.MeshLocation.StartVertIndex = startVertIndex;
surf.MeshLocation.NumVerts = sub->numlines;
Surfaces.Push(surf);
Mesh.Vertices.Push(state.mVertices[i]);
Mesh.UniformIndexes.Push(uniformsIndex);
}
}
for (MeshDrawCommand& command : it.second.mIndexedDraws)
{
for (int i = command.Start, end = command.Start + command.Count; i < end; i++)
{
Mesh.Vertices.Push(state.mVertices[state.mIndexes[i]]);
Mesh.UniformIndexes.Push(uniformsIndex);
}
}
}
state.mSortedLists.clear();
state.mVertices.Clear();
state.mIndexes.Clear();
DoomLevelMeshSurface surf;
surf.Submesh = this;
surf.Type = wallpart.LevelMeshInfo.Type;
surf.ControlSector = wallpart.LevelMeshInfo.ControlSector;
surf.TypeIndex = side->Index();
surf.Side = side;
surf.AlwaysUpdate = !!(side->sector->Flags & SECF_LM_DYNAMIC);
surf.SectorGroup = LevelMesh->sectorGroup[side->sector->Index()];
surf.Alpha = float(side->linedef->alpha);
surf.MeshLocation.StartVertIndex = startVertIndex;
surf.MeshLocation.NumVerts = Mesh.Vertices.Size() - startVertIndex;
surf.Plane = ToPlane(Mesh.Vertices[startVertIndex + 3].fPos(), Mesh.Vertices[startVertIndex + 2].fPos(), Mesh.Vertices[startVertIndex + 1].fPos(), Mesh.Vertices[startVertIndex].fPos());
surf.Texture = wallpart.texture;
surf.PipelineID = pipelineID;
surf.PortalIndex = (surf.Type == ST_MIDDLESIDE) ? LevelMesh->linePortals[side->linedef->Index()] : 0;
Surfaces.Push(surf);
}
}
void DoomLevelSubmesh::CreateFlatSurface(HWFlatDispatcher& disp, MeshBuilder& state, TArray<HWFlat>& list, bool isSky)
{
for (HWFlat& flatpart : list)
{
if (flatpart.texture && flatpart.texture->isMasked())
{
state.AlphaFunc(Alpha_GEqual, gl_mask_threshold);
}
else
{
state.AlphaFunc(Alpha_GEqual, 0.f);
}
flatpart.DrawFlat(&disp, state, false);
int pipelineID = 0;
int uniformsIndex = 0;
bool foundDraw = false;
for (auto& it : state.mSortedLists)
{
const MeshApplyState& applyState = it.first;
pipelineID = screen->GetLevelMeshPipelineID(applyState.applyData, applyState.surfaceUniforms, applyState.material);
uniformsIndex = Mesh.Uniforms.Size();
Mesh.Uniforms.Push(applyState.surfaceUniforms);
Mesh.Materials.Push(applyState.material);
foundDraw = true;
break;
}
state.mSortedLists.clear();
state.mVertices.Clear();
state.mIndexes.Clear();
if (!foundDraw)
continue;
DoomLevelMeshSurface surf;
surf.Submesh = this;
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 = LevelMesh->sectorGroup[flatpart.sector->Index()];
surf.Alpha = flatpart.alpha;
surf.Texture = flatpart.texture;
surf.PipelineID = pipelineID;
surf.PortalIndex = LevelMesh->sectorPortals[flatpart.ceiling][flatpart.sector->Index()];
surf.IsSky = isSky;
auto plane = surf.ControlSector ? surf.ControlSector->GetSecPlane(!flatpart.ceiling) : flatpart.sector->GetSecPlane(flatpart.ceiling);
surf.Plane = FVector4((float)plane.Normal().X, (float)plane.Normal().Y, (float)plane.Normal().Z, -(float)plane.D);
if (surf.ControlSector)
surf.Plane = -surf.Plane;
for (subsector_t* sub : flatpart.section->subsectors)
{
int startVertIndex = Mesh.Vertices.Size();
for (int i = 0, end = sub->numlines; i < end; i++)
{
auto& vt = sub->firstline[end - 1 - i].v1;
FFlatVertex ffv;
ffv.x = (float)vt->fX();
ffv.y = (float)vt->fY();
ffv.z = (float)plane.ZatPoint(vt);
ffv.u = (float)vt->fX() / 64.f;
ffv.v = -(float)vt->fY() / 64.f;
ffv.lu = 0.0f;
ffv.lv = 0.0f;
ffv.lindex = -1.0f;
Mesh.Vertices.Push(ffv);
Mesh.UniformIndexes.Push(uniformsIndex);
}
surf.TypeIndex = sub->Index();
surf.Subsector = sub;
surf.MeshLocation.StartVertIndex = startVertIndex;
surf.MeshLocation.NumVerts = sub->numlines;
Surfaces.Push(surf);
}
}
}
@ -712,18 +741,6 @@ void DoomLevelSubmesh::SetupTileTransform(int lightMapTextureWidth, int lightMap
Mesh.Vertices[surface.MeshLocation.StartVertIndex + i].lv = (tDelta | surface.TileTransform.ProjLocalToV);
}
#if 0
// project tCoords so they lie on the plane
const FVector4& plane = surface.plane;
float d = ((bounds.min | FVector3(plane.X, plane.Y, plane.Z)) - plane.W) / plane[axis]; //d = (plane->PointToDist(bounds.min)) / plane->Normal()[axis];
for (int i = 0; i < 2; i++)
{
tCoords[i].MakeUnit();
d = (tCoords[i] | FVector3(plane.X, plane.Y, plane.Z)) / plane[axis]; //d = dot(tCoords[i], plane->Normal()) / plane->Normal()[axis];
tCoords[i][axis] -= d;
}
#endif
surface.AtlasTile.Width = width;
surface.AtlasTile.Height = height;
}

View file

@ -14,7 +14,9 @@ typedef dp::rect_pack::RectPacker<int> RectPacker;
struct FLevelLocals;
struct FPolyObj;
struct HWWallDispatcher;
class DoomLevelMesh;
class MeshBuilder;
struct DoomLevelMeshSurface : public LevelMeshSurface
{
@ -62,6 +64,9 @@ private:
void CreateIndexes();
void CreateWallSurface(side_t* side, HWWallDispatcher& disp, MeshBuilder& state, TArray<HWWall>& list);
void CreateFlatSurface(HWFlatDispatcher& disp, MeshBuilder& state, TArray<HWFlat>& list, bool isSky = false);
static FVector4 ToPlane(const FVector3& pt1, const FVector3& pt2, const FVector3& pt3)
{
FVector3 n = ((pt2 - pt1) ^ (pt3 - pt2)).Unit();

View file

@ -44,6 +44,10 @@ struct HWFlatDispatcher
{
di->AddFlat(flat, fog);
}
else if (flat->plane.texture == skyflatnum || flat->stack)
{
mh->portals.Push(*flat);
}
else
{
if (flat->renderstyle != STYLE_Translucent || flat->alpha < 1.f - FLT_EPSILON || fog || flat->texture == nullptr)

View file

@ -551,7 +551,7 @@ void HWFlat::ProcessSector(HWFlatDispatcher *di, FRenderState& state, sector_t *
//
//
//
if ((which & SSRF_RENDERFLOOR) && (!di->di || frontsector->floorplane.ZatPoint(vp->Pos) <= vp->Pos.Z) && (!section || !(section->flags & FSection::DONTRENDERFLOOR)))
if ((which & SSRF_RENDERFLOOR) && (!di->di || (frontsector->floorplane.ZatPoint(vp->Pos) <= vp->Pos.Z && (!section || !(section->flags & FSection::DONTRENDERFLOOR)))))
{
// process the original floor first.
@ -579,7 +579,7 @@ void HWFlat::ProcessSector(HWFlatDispatcher *di, FRenderState& state, sector_t *
alpha = 1.0f - frontsector->GetReflect(sector_t::floor);
}
if (alpha != 0.f && frontsector->GetTexture(sector_t::floor) != skyflatnum)
if ((di->di && alpha != 0.f && frontsector->GetTexture(sector_t::floor) != skyflatnum) || (!di->di && (alpha != 0.f || stack)))
{
iboindex = frontsector->iboindex[sector_t::floor];
@ -609,7 +609,7 @@ void HWFlat::ProcessSector(HWFlatDispatcher *di, FRenderState& state, sector_t *
//
//
//
if ((which & SSRF_RENDERCEILING) && (!di->di || frontsector->ceilingplane.ZatPoint(vp->Pos) >= vp->Pos.Z) && (!section || !(section->flags & FSection::DONTRENDERCEILING)))
if ((which & SSRF_RENDERCEILING) && ((!di->di || frontsector->ceilingplane.ZatPoint(vp->Pos) >= vp->Pos.Z && (!section || !(section->flags & FSection::DONTRENDERCEILING)))))
{
// process the original ceiling first.
@ -636,7 +636,7 @@ void HWFlat::ProcessSector(HWFlatDispatcher *di, FRenderState& state, sector_t *
alpha = 1.0f - frontsector->GetReflect(sector_t::ceiling);
}
if (alpha != 0.f && frontsector->GetTexture(sector_t::ceiling) != skyflatnum)
if ((di->di && alpha != 0.f && frontsector->GetTexture(sector_t::ceiling) != skyflatnum) || (!di->di && (alpha != 0.f || stack)))
{
iboindex = frontsector->iboindex[sector_t::ceiling];
ceiling = true;