- rewrote render hacks to prepare their vertex data in the processing pass.

This eliminates 3 of the 5 remaining occurences of FQuadDrawer and gets a large section of code out of the GL backend into the common hardware rendering code.

# Conflicts:
#	src/gl/scene/gl_scene.cpp
This commit is contained in:
Christoph Oelckers 2018-08-15 20:20:27 +02:00
parent c5d1b884dd
commit e5ff500c5a
7 changed files with 401 additions and 394 deletions

View file

@ -237,248 +237,6 @@ FDrawInfo *FDrawInfo::EndDrawInfo()
return gl_drawinfo;
}
//==========================================================================
//
// Flood gaps with the back side's ceiling/floor texture
// This requires a stencil because the projected plane interferes with
// the depth buffer
//
//==========================================================================
void FDrawInfo::SetupFloodStencil(wallseg * ws)
{
int recursion = GLRenderer->mPortalState.GetRecursion();
// Create stencil
glStencilFunc(GL_EQUAL, recursion, ~0); // create stencil
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); // increment stencil of valid pixels
// Use revertible color mask, to avoid stomping on anaglyph 3D state
glColorMask(0, 0, 0, 0); // don't write to the graphics buffer
gl_RenderState.EnableTexture(false);
gl_RenderState.ResetColor();
glEnable(GL_DEPTH_TEST);
glDepthMask(true);
gl_RenderState.Apply();
FQuadDrawer qd;
qd.Set(0, ws->x1, ws->z1, ws->y1, 0, 0);
qd.Set(1, ws->x1, ws->z2, ws->y1, 0, 0);
qd.Set(2, ws->x2, ws->z2, ws->y2, 0, 0);
qd.Set(3, ws->x2, ws->z1, ws->y2, 0, 0);
qd.Render(GL_TRIANGLE_FAN);
glStencilFunc(GL_EQUAL, recursion + 1, ~0); // draw sky into stencil
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // this stage doesn't modify the stencil
glColorMask(1, 1, 1, 1); // don't write to the graphics buffer
gl_RenderState.EnableTexture(true);
glDisable(GL_DEPTH_TEST);
glDepthMask(false);
}
void FDrawInfo::ClearFloodStencil(wallseg * ws)
{
int recursion = GLRenderer->mPortalState.GetRecursion();
glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
gl_RenderState.EnableTexture(false);
// Use revertible color mask, to avoid stomping on anaglyph 3D state
glColorMask(0, 0, 0, 0); // don't write to the graphics buffer
gl_RenderState.ResetColor();
gl_RenderState.Apply();
FQuadDrawer qd;
qd.Set(0, ws->x1, ws->z1, ws->y1, 0, 0);
qd.Set(1, ws->x1, ws->z2, ws->y1, 0, 0);
qd.Set(2, ws->x2, ws->z2, ws->y2, 0, 0);
qd.Set(3, ws->x2, ws->z1, ws->y2, 0, 0);
qd.Render(GL_TRIANGLE_FAN);
// restore old stencil op.
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glStencilFunc(GL_EQUAL, recursion, ~0);
gl_RenderState.EnableTexture(true);
glColorMask(1, 1, 1, 1);
glEnable(GL_DEPTH_TEST);
glDepthMask(true);
}
//==========================================================================
//
// Draw the plane segment into the gap
//
//==========================================================================
void FDrawInfo::DrawFloodedPlane(wallseg * ws, float planez, sector_t * sec, bool ceiling)
{
GLSectorPlane plane;
int lightlevel;
FColormap Colormap;
FMaterial * gltexture;
plane.GetFromSector(sec, ceiling);
gltexture=FMaterial::ValidateTexture(plane.texture, false, true);
if (!gltexture) return;
if (isFullbrightScene())
{
Colormap.Clear();
lightlevel=255;
}
else
{
Colormap = sec->Colormap;
if (gltexture->tex->isFullbright())
{
Colormap.MakeWhite();
lightlevel=255;
}
else lightlevel=abs(ceiling? sec->GetCeilingLight() : sec->GetFloorLight());
}
int rel = getExtraLight();
SetColor(lightlevel, rel, Colormap, 1.0f);
SetFog(lightlevel, rel, &Colormap, false);
gl_RenderState.SetMaterial(gltexture, CLAMP_NONE, 0, -1, false);
float fviewx = Viewpoint.Pos.X;
float fviewy = Viewpoint.Pos.Y;
float fviewz = Viewpoint.Pos.Z;
gl_RenderState.SetPlaneTextureRotation(&plane, gltexture);
gl_RenderState.Apply();
float prj_fac1 = (planez-fviewz)/(ws->z1-fviewz);
float prj_fac2 = (planez-fviewz)/(ws->z2-fviewz);
float px1 = fviewx + prj_fac1 * (ws->x1-fviewx);
float py1 = fviewy + prj_fac1 * (ws->y1-fviewy);
float px2 = fviewx + prj_fac2 * (ws->x1-fviewx);
float py2 = fviewy + prj_fac2 * (ws->y1-fviewy);
float px3 = fviewx + prj_fac2 * (ws->x2-fviewx);
float py3 = fviewy + prj_fac2 * (ws->y2-fviewy);
float px4 = fviewx + prj_fac1 * (ws->x2-fviewx);
float py4 = fviewy + prj_fac1 * (ws->y2-fviewy);
FQuadDrawer qd;
qd.Set(0, px1, planez, py1, px1 / 64, -py1 / 64);
qd.Set(1, px2, planez, py2, px2 / 64, -py2 / 64);
qd.Set(2, px3, planez, py3, px3 / 64, -py3 / 64);
qd.Set(3, px4, planez, py4, px4 / 64, -py4 / 64);
qd.Render(GL_TRIANGLE_FAN);
gl_RenderState.EnableTextureMatrix(false);
}
//==========================================================================
//
//
//
//==========================================================================
void FDrawInfo::FloodUpperGap(seg_t * seg)
{
wallseg ws;
sector_t ffake, bfake;
sector_t * fakefsector = hw_FakeFlat(seg->frontsector, &ffake, in_area, true);
sector_t * fakebsector = hw_FakeFlat(seg->backsector, &bfake, in_area, false);
vertex_t * v1, * v2;
// Although the plane can be sloped this code will only be called
// when the edge itself is not.
double backz = fakebsector->ceilingplane.ZatPoint(seg->v1);
double frontz = fakefsector->ceilingplane.ZatPoint(seg->v1);
if (fakebsector->GetTexture(sector_t::ceiling)==skyflatnum) return;
if (backz < Viewpoint.Pos.Z) return;
if (seg->sidedef == seg->linedef->sidedef[0])
{
v1=seg->linedef->v1;
v2=seg->linedef->v2;
}
else
{
v1=seg->linedef->v2;
v2=seg->linedef->v1;
}
ws.x1 = v1->fX();
ws.y1 = v1->fY();
ws.x2 = v2->fX();
ws.y2 = v2->fY();
ws.z1= frontz;
ws.z2= backz;
// Step1: Draw a stencil into the gap
SetupFloodStencil(&ws);
// Step2: Project the ceiling plane into the gap
DrawFloodedPlane(&ws, ws.z2, fakebsector, true);
// Step3: Delete the stencil
ClearFloodStencil(&ws);
}
//==========================================================================
//
//
//
//==========================================================================
void FDrawInfo::FloodLowerGap(seg_t * seg)
{
wallseg ws;
sector_t ffake, bfake;
sector_t * fakefsector = hw_FakeFlat(seg->frontsector, &ffake, in_area, true);
sector_t * fakebsector = hw_FakeFlat(seg->backsector, &bfake, in_area, false);
vertex_t * v1, * v2;
// Although the plane can be sloped this code will only be called
// when the edge itself is not.
double backz = fakebsector->floorplane.ZatPoint(seg->v1);
double frontz = fakefsector->floorplane.ZatPoint(seg->v1);
if (fakebsector->GetTexture(sector_t::floor) == skyflatnum) return;
if (fakebsector->GetPlaneTexZ(sector_t::floor) > Viewpoint.Pos.Z) return;
if (seg->sidedef == seg->linedef->sidedef[0])
{
v1=seg->linedef->v1;
v2=seg->linedef->v2;
}
else
{
v1=seg->linedef->v2;
v2=seg->linedef->v1;
}
ws.x1 = v1->fX();
ws.y1 = v1->fY();
ws.x2 = v2->fX();
ws.y2 = v2->fY();
ws.z2= frontz;
ws.z1= backz;
// Step1: Draw a stencil into the gap
SetupFloodStencil(&ws);
// Step2: Project the ceiling plane into the gap
DrawFloodedPlane(&ws, ws.z1, fakebsector, false);
// Step3: Delete the stencil
ClearFloodStencil(&ws);
}
// Same here for the dependency on the portal.
void FDrawInfo::AddSubsectorToPortal(FSectorPortalGroup *ptg, subsector_t *sub)
{

View file

@ -57,11 +57,11 @@ struct FDrawInfo : public HWDrawInfo
void DrawDecalsForMirror(GLWall *wall);
void StartScene();
void SetupFloodStencil(wallseg * ws);
void ClearFloodStencil(wallseg * ws);
void SetupFloodStencil(int vindex);
void ClearFloodStencil(int vindex);
void DrawFloodedPlane(wallseg * ws, float planez, sector_t * sec, bool ceiling);
void FloodUpperGap(seg_t * seg) override;
void FloodLowerGap(seg_t * seg) override;
void FloodUpperGap(seg_t * seg);
void FloodLowerGap(seg_t * seg);
// Wall drawer
void RenderWall(GLWall *wall, int textured);
@ -75,7 +75,6 @@ struct FDrawInfo : public HWDrawInfo
void DrawFlat(GLFlat *flat, int pass, bool trans) override; // trans only has meaning for GLPASS_LIGHTSONLY
void DrawSkyboxSector(GLFlat *flat, int pass);
void DrawSubsectors(GLFlat *flat, int pass, bool istrans);
void DrawSubsector(GLFlat *flat, subsector_t * sub);
// Sprite drawer
void DrawSprite(GLSprite *sprite, int pass);
@ -100,18 +99,6 @@ struct FDrawInfo : public HWDrawInfo
static FDrawInfo *StartDrawInfo(FRenderViewpoint &parentvp, HWViewpointUniforms *uniforms);
FDrawInfo *EndDrawInfo();
gl_subsectorrendernode * GetOtherFloorPlanes(unsigned int sector)
{
if (sector<otherfloorplanes.Size()) return otherfloorplanes[sector];
else return NULL;
}
gl_subsectorrendernode * GetOtherCeilingPlanes(unsigned int sector)
{
if (sector<otherceilingplanes.Size()) return otherceilingplanes[sector];
else return NULL;
}
void SetColor(int light, int rellight, const FColormap &cm, float alpha, bool weapon = false)
{
gl_SetColor(light, rellight, isFullbrightScene(), cm, alpha, weapon);

View file

@ -47,55 +47,6 @@
#include "gl/scene/gl_drawinfo.h"
#include "gl/renderer/gl_quaddrawer.h"
//==========================================================================
//
//
//
//==========================================================================
void FDrawInfo::DrawSubsector(GLFlat *flat, subsector_t * sub)
{
if (gl.buffermethod != BM_DEFERRED)
{
FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer();
for (unsigned int k = 0; k < sub->numlines; k++)
{
vertex_t *vt = sub->firstline[k].v1;
ptr->x = vt->fX();
ptr->z = flat->plane.plane.ZatPoint(vt) + flat->dz;
ptr->y = vt->fY();
ptr->u = vt->fX() / 64.f;
ptr->v = -vt->fY() / 64.f;
ptr++;
}
GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_FAN);
}
else
{
// if we cannot access the buffer, use the quad drawer as fallback by splitting the subsector into quads.
// Trying to get this into the vertex buffer in the processing pass is too costly and this is only used for render hacks.
FQuadDrawer qd;
unsigned int vi[4];
vi[0] = 0;
for (unsigned int i = 0; i < sub->numlines - 2; i += 2)
{
for (unsigned int j = 1; j < 4; j++)
{
vi[j] = MIN(i + j, sub->numlines - 1);
}
for (unsigned int x = 0; x < 4; x++)
{
vertex_t *vt = sub->firstline[vi[x]].v1;
qd.Set(x, vt->fX(), flat->plane.plane.ZatPoint(vt) + flat->dz, vt->fY(), vt->fX() / 64.f, -vt->fY() / 64.f);
}
qd.Render(GL_TRIANGLE_FAN);
}
}
flatvertices += sub->numlines;
flatprimitives++;
}
//==========================================================================
@ -146,9 +97,9 @@ void FDrawInfo::DrawSubsectors(GLFlat *flat, int pass, bool istrans)
}
}
// Draw the subsectors assigned to it due to missing textures
if (!(flat->renderflags&SSRF_RENDER3DPLANES))
{
// Draw the subsectors assigned to it due to missing textures
gl_subsectorrendernode * node = (flat->renderflags&SSRF_RENDERFLOOR)?
GetOtherFloorPlanes(flat->sector->sectornum) :
GetOtherCeilingPlanes(flat->sector->sectornum);
@ -156,12 +107,99 @@ void FDrawInfo::DrawSubsectors(GLFlat *flat, int pass, bool istrans)
while (node)
{
gl_RenderState.ApplyLightIndex(node->lightindex);
DrawSubsector(flat, node->sub);
auto num = node->sub->numlines;
flatvertices += num;
flatprimitives++;
glDrawArrays(GL_TRIANGLE_FAN, node->vertexindex, num);
node = node->next;
}
// Flood gaps with the back side's ceiling/floor texture
// This requires a stencil because the projected plane interferes with
// the depth buffer
gl_floodrendernode * fnode = (flat->renderflags&SSRF_RENDERFLOOR) ?
GetFloodFloorSegs(flat->sector->sectornum) :
GetFloodCeilingSegs(flat->sector->sectornum);
gl_RenderState.ApplyLightIndex(flat->dynlightindex);
while (fnode)
{
flatvertices += 12;
flatprimitives+=3;
// Push bleeding floor/ceiling textures back a little in the z-buffer
// so they don't interfere with overlapping mid textures.
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(1.0f, 128.0f);
SetupFloodStencil(fnode->vertexindex);
glDrawArrays(GL_TRIANGLE_FAN, fnode->vertexindex + 4, 4);
ClearFloodStencil(fnode->vertexindex);
glPolygonOffset(0.0f, 0.0f);
glDisable(GL_POLYGON_OFFSET_FILL);
fnode = fnode->next;
}
}
}
//==========================================================================
//
//
//==========================================================================
void FDrawInfo::SetupFloodStencil(int vindex)
{
int recursion = GLRenderer->mPortalState.GetRecursion();
// Create stencil
gl_RenderState.SetEffect(EFF_STENCIL);
gl_RenderState.EnableTexture(false);
gl_RenderState.Apply();
glStencilFunc(GL_EQUAL, recursion, ~0); // create stencil
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); // increment stencil of valid pixels
glColorMask(0, 0, 0, 0); // don't write to the graphics buffer
glEnable(GL_DEPTH_TEST);
glDepthMask(true);
glDrawArrays(GL_TRIANGLE_FAN, vindex, 4);
glStencilFunc(GL_EQUAL, recursion + 1, ~0); // draw sky into stencil
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // this stage doesn't modify the stencil
glColorMask(1, 1, 1, 1); // don't write to the graphics buffer
glDisable(GL_DEPTH_TEST);
glDepthMask(false);
gl_RenderState.EnableTexture(true);
gl_RenderState.SetEffect(EFF_NONE);
gl_RenderState.Apply();
}
void FDrawInfo::ClearFloodStencil(int vindex)
{
int recursion = GLRenderer->mPortalState.GetRecursion();
gl_RenderState.SetEffect(EFF_STENCIL);
gl_RenderState.EnableTexture(false);
gl_RenderState.Apply();
glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
// Use revertible color mask, to avoid stomping on anaglyph 3D state
glColorMask(0, 0, 0, 0); // don't write to the graphics buffer
glDrawArrays(GL_TRIANGLE_FAN, vindex, 4);
// restore old stencil op.
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glStencilFunc(GL_EQUAL, recursion, ~0);
glColorMask(1, 1, 1, 1);
glEnable(GL_DEPTH_TEST);
glDepthMask(true);
gl_RenderState.EnableTexture(true);
gl_RenderState.SetEffect(EFF_NONE);
}
//==========================================================================
//

View file

@ -128,6 +128,7 @@ void FDrawInfo::CreateScene()
HandleMissingTextures(in_area); // Missing upper/lower textures
HandleHackedSubsectors(); // open sector hacks for deep water
ProcessSectorStacks(in_area); // merge visplanes of sector stacks
PrepareUnhandledMissingTextures();
GLRenderer->mLights->Finish();
GLRenderer->mVBO->Unmap();
@ -208,28 +209,10 @@ void FDrawInfo::RenderScene(int recursion)
DrawDecals();
gl_RenderState.SetTextureMode(TM_MODULATE);
glDepthMask(true);
// Push bleeding floor/ceiling textures back a little in the z-buffer
// so they don't interfere with overlapping mid textures.
glPolygonOffset(1.0f, 128.0f);
// Part 5: flood all the gaps with the back sector's flat texture
// This will always be drawn like GLDL_PLAIN, depending on the fog settings
glDepthMask(false); // don't write to Z-buffer!
gl_RenderState.EnableFog(true);
gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f);
gl_RenderState.BlendFunc(GL_ONE,GL_ZERO);
DrawUnhandledMissingTextures();
glDepthMask(true);
glPolygonOffset(0.0f, 0.0f);
glDisable(GL_POLYGON_OFFSET_FILL);
glDepthMask(true);
RenderAll.Unclock();
}
//-----------------------------------------------------------------------------

View file

@ -47,32 +47,31 @@ sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool bac
//
//==========================================================================
template<class T>
inline void DeleteLinkedList(T *node)
{
while (node)
{
auto n = node;
node = node->next;
delete n;
}
}
void HWDrawInfo::ClearBuffers()
{
for(unsigned int i=0;i< otherfloorplanes.Size();i++)
{
gl_subsectorrendernode * node = otherfloorplanes[i];
while (node)
{
gl_subsectorrendernode * n = node;
node = node->next;
delete n;
}
}
for (auto node : otherfloorplanes) DeleteLinkedList(node);
otherfloorplanes.Clear();
for(unsigned int i=0;i< otherceilingplanes.Size();i++)
{
gl_subsectorrendernode * node = otherceilingplanes[i];
while (node)
{
gl_subsectorrendernode * n = node;
node = node->next;
delete n;
}
}
for (auto node : otherceilingplanes) DeleteLinkedList(node);
otherceilingplanes.Clear();
for (auto node : floodfloorsegs) DeleteLinkedList(node);
floodfloorsegs.Clear();
for (auto node : floodceilingsegs) DeleteLinkedList(node);
floodceilingsegs.Clear();
// clear all the lists that might not have been cleared already
MissingUpperTextures.Clear();
MissingLowerTextures.Clear();

View file

@ -35,6 +35,15 @@ struct gl_subsectorrendernode
gl_subsectorrendernode * next;
subsector_t * sub;
int lightindex;
int vertexindex;
};
struct gl_floodrendernode
{
gl_floodrendernode * next;
seg_t *seg;
int vertexindex;
// This will use the light list of the originating sector.
};
enum area_t : int;
@ -123,6 +132,8 @@ struct HWDrawInfo
TArray<gl_subsectorrendernode*> otherfloorplanes;
TArray<gl_subsectorrendernode*> otherceilingplanes;
TArray<gl_floodrendernode*> floodfloorsegs;
TArray<gl_floodrendernode*> floodceilingsegs;
TArray<sector_t *> CeilingStacks;
TArray<sector_t *> FloorStacks;
@ -162,8 +173,35 @@ private:
void RenderThings(subsector_t * sub, sector_t * sector);
void DoSubsector(subsector_t * sub);
int SetupLightsForOtherPlane(subsector_t * sub, FDynLightData &lightdata, const secplane_t *plane);
int CreateOtherPlaneVertices(subsector_t *sub, const secplane_t *plane);
public:
gl_subsectorrendernode * GetOtherFloorPlanes(unsigned int sector)
{
if (sector<otherfloorplanes.Size()) return otherfloorplanes[sector];
else return nullptr;
}
gl_subsectorrendernode * GetOtherCeilingPlanes(unsigned int sector)
{
if (sector<otherceilingplanes.Size()) return otherceilingplanes[sector];
else return nullptr;
}
gl_floodrendernode * GetFloodFloorSegs(unsigned int sector)
{
if (sector<floodfloorsegs.Size()) return floodfloorsegs[sector];
else return nullptr;
}
gl_floodrendernode * GetFloodCeilingSegs(unsigned int sector)
{
if (sector<floodceilingsegs.Size()) return floodceilingsegs[sector];
else return nullptr;
}
void SetCameraPos(const DVector3 &pos)
{
VPUniforms.mCameraPos = { (float)pos.X, (float)pos.Z, (float)pos.Y, 0.f };
@ -209,7 +247,12 @@ public:
void AddUpperMissingTexture(side_t * side, subsector_t *sub, float backheight);
void AddLowerMissingTexture(side_t * side, subsector_t *sub, float backheight);
void HandleMissingTextures(area_t in_area);
void DrawUnhandledMissingTextures();
void PrepareUnhandledMissingTextures();
void PrepareUpperGap(seg_t * seg);
void PrepareLowerGap(seg_t * seg);
void CreateFloodPoly(wallseg * ws, FFlatVertex *vertices, float planez, sector_t * sec, bool ceiling);
void CreateFloodStencilPoly(wallseg * ws, FFlatVertex *vertices);
void AddHackedSubsector(subsector_t * sub);
void HandleHackedSubsectors();
void AddFloorStack(sector_t * sec);
@ -236,8 +279,6 @@ public:
virtual void DrawFlat(GLFlat *flat, int pass, bool trans) = 0;
virtual void DrawSprite(GLSprite *sprite, int pass) = 0;
virtual void FloodUpperGap(seg_t * seg) = 0;
virtual void FloodLowerGap(seg_t * seg) = 0;
void ProcessLowerMinisegs(TArray<seg_t *> &lowersegs);
virtual void AddSubsectorToPortal(FSectorPortalGroup *portal, subsector_t *sub) = 0;

View file

@ -35,6 +35,7 @@
#include "hw_drawstructs.h"
#include "hwrenderer/utility/hw_clock.h"
#include "hwrenderer/dynlights/hw_dynlightdata.h"
#include "hwrenderer/data/flatvertices.h"
sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool back);
@ -75,6 +76,29 @@ int HWDrawInfo::SetupLightsForOtherPlane(subsector_t * sub, FDynLightData &light
else return -1;
}
//==========================================================================
//
// Vertex setup for extra planes
//
//==========================================================================
int HWDrawInfo::CreateOtherPlaneVertices(subsector_t *sub, const secplane_t *plane)
{
auto alloc = AllocVertices(sub->numlines);
auto ptr = alloc.first;
for (unsigned int k = 0; k < sub->numlines; k++)
{
vertex_t *vt = sub->firstline[k].v1;
ptr->x = vt->fX();
ptr->z = plane->ZatPoint(vt);
ptr->y = vt->fY();
ptr->u = vt->fX() / 64.f;
ptr->v = -vt->fY() / 64.f;
ptr++;
}
return alloc.second;
}
//==========================================================================
//
// Adds a subsector plane to a sector's render list
@ -85,13 +109,14 @@ void HWDrawInfo::AddOtherFloorPlane(int sector, gl_subsectorrendernode * node)
{
int oldcnt = otherfloorplanes.Size();
if (oldcnt<=sector)
if (oldcnt <= sector)
{
otherfloorplanes.Resize(sector+1);
for(int i=oldcnt;i<=sector;i++) otherfloorplanes[i]=NULL;
otherfloorplanes.Resize(sector + 1);
for (int i = oldcnt; i <= sector; i++) otherfloorplanes[i] = nullptr;
}
node->next = otherfloorplanes[sector];
node->lightindex = SetupLightsForOtherPlane(node->sub, lightdata, &node->sub->sector->floorplane);
node->lightindex = SetupLightsForOtherPlane(node->sub, lightdata, &level.sectors[sector].floorplane);
node->vertexindex = CreateOtherPlaneVertices(node->sub, &level.sectors[sector].floorplane);
otherfloorplanes[sector] = node;
}
@ -99,13 +124,14 @@ void HWDrawInfo::AddOtherCeilingPlane(int sector, gl_subsectorrendernode * node)
{
int oldcnt = otherceilingplanes.Size();
if (oldcnt<=sector)
if (oldcnt <= sector)
{
otherceilingplanes.Resize(sector+1);
for(int i=oldcnt;i<=sector;i++) otherceilingplanes[i]=NULL;
otherceilingplanes.Resize(sector + 1);
for (int i = oldcnt; i <= sector; i++) otherceilingplanes[i] = nullptr;
}
node->next = otherceilingplanes[sector];
node->lightindex = SetupLightsForOtherPlane(node->sub, lightdata, &node->sub->sector->ceilingplane);
node->lightindex = SetupLightsForOtherPlane(node->sub, lightdata, &level.sectors[sector].ceilingplane);
node->vertexindex = CreateOtherPlaneVertices(node->sub, &level.sectors[sector].ceilingplane);
otherceilingplanes[sector] = node;
}
@ -607,54 +633,229 @@ void HWDrawInfo::HandleMissingTextures(area_t in_area)
}
}
//==========================================================================
//
//
//
//==========================================================================
void HWDrawInfo::DrawUnhandledMissingTextures()
void HWDrawInfo::CreateFloodStencilPoly(wallseg * ws, FFlatVertex *vertices)
{
validcount++;
for (int i = MissingUpperSegs.Size() - 1; i >= 0; i--)
vertices[0].Set(ws->x1, ws->z1, ws->y1, 0, 0);
vertices[1].Set(ws->x1, ws->z2, ws->y1, 0, 0);
vertices[2].Set(ws->x2, ws->z2, ws->y2, 0, 0);
vertices[3].Set(ws->x2, ws->z1, ws->y2, 0, 0);
}
//==========================================================================
//
//
//
//==========================================================================
void HWDrawInfo::CreateFloodPoly(wallseg * ws, FFlatVertex *vertices, float planez, sector_t * sec, bool ceiling)
{
float fviewx = Viewpoint.Pos.X;
float fviewy = Viewpoint.Pos.Y;
float fviewz = Viewpoint.Pos.Z;
float prj_fac1 = (planez - fviewz) / (ws->z1 - fviewz);
float prj_fac2 = (planez - fviewz) / (ws->z2 - fviewz);
float px1 = fviewx + prj_fac1 * (ws->x1 - fviewx);
float py1 = fviewy + prj_fac1 * (ws->y1 - fviewy);
float px2 = fviewx + prj_fac2 * (ws->x1 - fviewx);
float py2 = fviewy + prj_fac2 * (ws->y1 - fviewy);
float px3 = fviewx + prj_fac2 * (ws->x2 - fviewx);
float py3 = fviewy + prj_fac2 * (ws->y2 - fviewy);
float px4 = fviewx + prj_fac1 * (ws->x2 - fviewx);
float py4 = fviewy + prj_fac1 * (ws->y2 - fviewy);
vertices[0].Set(px1, planez, py1, px1 / 64, -py1 / 64);
vertices[1].Set(px2, planez, py2, px2 / 64, -py2 / 64);
vertices[2].Set(px3, planez, py3, px3 / 64, -py3 / 64);
vertices[3].Set(px4, planez, py4, px4 / 64, -py4 / 64);
}
//==========================================================================
//
//
//
//==========================================================================
void HWDrawInfo::PrepareUpperGap(seg_t * seg)
{
wallseg ws;
sector_t ffake, bfake;
sector_t * fakefsector = hw_FakeFlat(seg->frontsector, &ffake, in_area, true);
sector_t * fakebsector = hw_FakeFlat(seg->backsector, &bfake, in_area, false);
vertex_t * v1, *v2;
// Although the plane can be sloped this code will only be called
// when the edge itself is not.
double backz = fakebsector->ceilingplane.ZatPoint(seg->v1);
double frontz = fakefsector->ceilingplane.ZatPoint(seg->v1);
if (fakebsector->GetTexture(sector_t::ceiling) == skyflatnum) return;
if (backz < Viewpoint.Pos.Z) return;
if (seg->sidedef == seg->linedef->sidedef[0])
{
int index = MissingUpperSegs[i].MTI_Index;
if (index >= 0 && MissingUpperTextures[index].seg == NULL) continue;
seg_t * seg = MissingUpperSegs[i].seg;
// already done!
if (seg->linedef->validcount == validcount) continue; // already done
seg->linedef->validcount = validcount;
if (seg->frontsector->GetPlaneTexZ(sector_t::ceiling) < Viewpoint.Pos.Z) continue; // out of sight
// FIXME: The check for degenerate subsectors should be more precise
if (seg->PartnerSeg && (seg->PartnerSeg->Subsector->flags & SSECF_DEGENERATE)) continue;
if (seg->backsector->transdoor) continue;
if (seg->backsector->GetTexture(sector_t::ceiling) == skyflatnum) continue;
if (seg->backsector->ValidatePortal(sector_t::ceiling) != NULL) continue;
if (!level.notexturefill) FloodUpperGap(seg);
v1 = seg->linedef->v1;
v2 = seg->linedef->v2;
}
else
{
v1 = seg->linedef->v2;
v2 = seg->linedef->v1;
}
validcount++;
for (int i = MissingLowerSegs.Size() - 1; i >= 0; i--)
ws.x1 = v1->fX();
ws.y1 = v1->fY();
ws.x2 = v2->fX();
ws.y2 = v2->fY();
ws.z1 = frontz;
ws.z2 = backz;
auto vertices = AllocVertices(8);
CreateFloodStencilPoly(&ws, vertices.first);
CreateFloodPoly(&ws, vertices.first+4, ws.z2, fakebsector, true);
gl_floodrendernode *node = new gl_floodrendernode;
int oldcnt = floodfloorsegs.Size();
auto sector = fakebsector->sectornum;
if (oldcnt <= sector)
{
int index = MissingLowerSegs[i].MTI_Index;
if (index >= 0 && MissingLowerTextures[index].seg == NULL) continue;
floodfloorsegs.Resize(sector + 1);
for (int i = oldcnt; i <= sector; i++) floodfloorsegs[i] = nullptr;
}
seg_t * seg = MissingLowerSegs[i].seg;
node->next = floodfloorsegs[sector];
node->seg = seg;
node->vertexindex = vertices.second;
floodfloorsegs[sector] = node;
}
if (seg->linedef->validcount == validcount) continue; // already done
seg->linedef->validcount = validcount;
if (!(sectorrenderflags[seg->backsector->sectornum] & SSRF_RENDERFLOOR)) continue;
if (seg->frontsector->GetPlaneTexZ(sector_t::floor) > Viewpoint.Pos.Z) continue; // out of sight
if (seg->backsector->transdoor) continue;
if (seg->backsector->GetTexture(sector_t::floor) == skyflatnum) continue;
if (seg->backsector->ValidatePortal(sector_t::floor) != NULL) continue;
if (!level.notexturefill) FloodLowerGap(seg);
//==========================================================================
//
//
//
//==========================================================================
void HWDrawInfo::PrepareLowerGap(seg_t * seg)
{
wallseg ws;
sector_t ffake, bfake;
sector_t * fakefsector = hw_FakeFlat(seg->frontsector, &ffake, in_area, true);
sector_t * fakebsector = hw_FakeFlat(seg->backsector, &bfake, in_area, false);
vertex_t * v1, *v2;
// Although the plane can be sloped this code will only be called
// when the edge itself is not.
double backz = fakebsector->floorplane.ZatPoint(seg->v1);
double frontz = fakefsector->floorplane.ZatPoint(seg->v1);
if (fakebsector->GetTexture(sector_t::floor) == skyflatnum) return;
if (fakebsector->GetPlaneTexZ(sector_t::floor) > Viewpoint.Pos.Z) return;
if (seg->sidedef == seg->linedef->sidedef[0])
{
v1 = seg->linedef->v1;
v2 = seg->linedef->v2;
}
else
{
v1 = seg->linedef->v2;
v2 = seg->linedef->v1;
}
ws.x1 = v1->fX();
ws.y1 = v1->fY();
ws.x2 = v2->fX();
ws.y2 = v2->fY();
ws.z2 = frontz;
ws.z1 = backz;
auto vertices = AllocVertices(8);
CreateFloodStencilPoly(&ws, vertices.first);
CreateFloodPoly(&ws, vertices.first+4, ws.z1, fakebsector, false);
gl_floodrendernode *node = new gl_floodrendernode;
int oldcnt = floodceilingsegs.Size();
auto sector = fakebsector->sectornum;
if (oldcnt <= sector)
{
floodceilingsegs.Resize(sector + 1);
for (int i = oldcnt; i <= sector; i++) floodceilingsegs[i] = nullptr;
}
node->next = floodceilingsegs[sector];
node->seg = seg;
node->vertexindex = vertices.second;
floodceilingsegs[sector] = node;
}
//==========================================================================
//
//
//
//==========================================================================
void HWDrawInfo::PrepareUnhandledMissingTextures()
{
if (!level.notexturefill)
{
validcount++;
for (int i = MissingUpperSegs.Size() - 1; i >= 0; i--)
{
int index = MissingUpperSegs[i].MTI_Index;
if (index >= 0 && MissingUpperTextures[index].seg == NULL) continue;
seg_t * seg = MissingUpperSegs[i].seg;
// already done!
if (seg->linedef->validcount == validcount) continue; // already done
seg->linedef->validcount = validcount;
if (seg->frontsector->GetPlaneTexZ(sector_t::ceiling) < Viewpoint.Pos.Z) continue; // out of sight
// FIXME: The check for degenerate subsectors should be more precise
if (seg->PartnerSeg && (seg->PartnerSeg->Subsector->flags & SSECF_DEGENERATE)) continue;
if (seg->backsector->transdoor) continue;
if (seg->backsector->GetTexture(sector_t::ceiling) == skyflatnum) continue;
if (seg->backsector->ValidatePortal(sector_t::ceiling) != NULL) continue;
PrepareUpperGap(seg);
}
validcount++;
for (int i = MissingLowerSegs.Size() - 1; i >= 0; i--)
{
int index = MissingLowerSegs[i].MTI_Index;
if (index >= 0 && MissingLowerTextures[index].seg == NULL) continue;
seg_t * seg = MissingLowerSegs[i].seg;
if (seg->linedef->validcount == validcount) continue; // already done
seg->linedef->validcount = validcount;
if (!(sectorrenderflags[seg->backsector->sectornum] & SSRF_RENDERFLOOR)) continue;
if (seg->frontsector->GetPlaneTexZ(sector_t::floor) > Viewpoint.Pos.Z) continue; // out of sight
if (seg->backsector->transdoor) continue;
if (seg->backsector->GetTexture(sector_t::floor) == skyflatnum) continue;
if (seg->backsector->ValidatePortal(sector_t::floor) != NULL) continue;
PrepareLowerGap(seg);
}
}
MissingUpperTextures.Clear();
MissingLowerTextures.Clear();