mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-02-01 06:10:42 +00:00
- 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:
parent
c5d1b884dd
commit
e5ff500c5a
7 changed files with 401 additions and 394 deletions
|
@ -237,248 +237,6 @@ FDrawInfo *FDrawInfo::EndDrawInfo()
|
||||||
return gl_drawinfo;
|
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.
|
// Same here for the dependency on the portal.
|
||||||
void FDrawInfo::AddSubsectorToPortal(FSectorPortalGroup *ptg, subsector_t *sub)
|
void FDrawInfo::AddSubsectorToPortal(FSectorPortalGroup *ptg, subsector_t *sub)
|
||||||
{
|
{
|
||||||
|
|
|
@ -57,11 +57,11 @@ struct FDrawInfo : public HWDrawInfo
|
||||||
void DrawDecalsForMirror(GLWall *wall);
|
void DrawDecalsForMirror(GLWall *wall);
|
||||||
|
|
||||||
void StartScene();
|
void StartScene();
|
||||||
void SetupFloodStencil(wallseg * ws);
|
void SetupFloodStencil(int vindex);
|
||||||
void ClearFloodStencil(wallseg * ws);
|
void ClearFloodStencil(int vindex);
|
||||||
void DrawFloodedPlane(wallseg * ws, float planez, sector_t * sec, bool ceiling);
|
void DrawFloodedPlane(wallseg * ws, float planez, sector_t * sec, bool ceiling);
|
||||||
void FloodUpperGap(seg_t * seg) override;
|
void FloodUpperGap(seg_t * seg);
|
||||||
void FloodLowerGap(seg_t * seg) override;
|
void FloodLowerGap(seg_t * seg);
|
||||||
|
|
||||||
// Wall drawer
|
// Wall drawer
|
||||||
void RenderWall(GLWall *wall, int textured);
|
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 DrawFlat(GLFlat *flat, int pass, bool trans) override; // trans only has meaning for GLPASS_LIGHTSONLY
|
||||||
void DrawSkyboxSector(GLFlat *flat, int pass);
|
void DrawSkyboxSector(GLFlat *flat, int pass);
|
||||||
void DrawSubsectors(GLFlat *flat, int pass, bool istrans);
|
void DrawSubsectors(GLFlat *flat, int pass, bool istrans);
|
||||||
void DrawSubsector(GLFlat *flat, subsector_t * sub);
|
|
||||||
|
|
||||||
// Sprite drawer
|
// Sprite drawer
|
||||||
void DrawSprite(GLSprite *sprite, int pass);
|
void DrawSprite(GLSprite *sprite, int pass);
|
||||||
|
@ -100,18 +99,6 @@ struct FDrawInfo : public HWDrawInfo
|
||||||
static FDrawInfo *StartDrawInfo(FRenderViewpoint &parentvp, HWViewpointUniforms *uniforms);
|
static FDrawInfo *StartDrawInfo(FRenderViewpoint &parentvp, HWViewpointUniforms *uniforms);
|
||||||
FDrawInfo *EndDrawInfo();
|
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)
|
void SetColor(int light, int rellight, const FColormap &cm, float alpha, bool weapon = false)
|
||||||
{
|
{
|
||||||
gl_SetColor(light, rellight, isFullbrightScene(), cm, alpha, weapon);
|
gl_SetColor(light, rellight, isFullbrightScene(), cm, alpha, weapon);
|
||||||
|
|
|
@ -47,55 +47,6 @@
|
||||||
#include "gl/scene/gl_drawinfo.h"
|
#include "gl/scene/gl_drawinfo.h"
|
||||||
#include "gl/renderer/gl_quaddrawer.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))
|
if (!(flat->renderflags&SSRF_RENDER3DPLANES))
|
||||||
{
|
{
|
||||||
|
// Draw the subsectors assigned to it due to missing textures
|
||||||
gl_subsectorrendernode * node = (flat->renderflags&SSRF_RENDERFLOOR)?
|
gl_subsectorrendernode * node = (flat->renderflags&SSRF_RENDERFLOOR)?
|
||||||
GetOtherFloorPlanes(flat->sector->sectornum) :
|
GetOtherFloorPlanes(flat->sector->sectornum) :
|
||||||
GetOtherCeilingPlanes(flat->sector->sectornum);
|
GetOtherCeilingPlanes(flat->sector->sectornum);
|
||||||
|
@ -156,12 +107,99 @@ void FDrawInfo::DrawSubsectors(GLFlat *flat, int pass, bool istrans)
|
||||||
while (node)
|
while (node)
|
||||||
{
|
{
|
||||||
gl_RenderState.ApplyLightIndex(node->lightindex);
|
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;
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
|
|
@ -128,6 +128,7 @@ void FDrawInfo::CreateScene()
|
||||||
HandleMissingTextures(in_area); // Missing upper/lower textures
|
HandleMissingTextures(in_area); // Missing upper/lower textures
|
||||||
HandleHackedSubsectors(); // open sector hacks for deep water
|
HandleHackedSubsectors(); // open sector hacks for deep water
|
||||||
ProcessSectorStacks(in_area); // merge visplanes of sector stacks
|
ProcessSectorStacks(in_area); // merge visplanes of sector stacks
|
||||||
|
PrepareUnhandledMissingTextures();
|
||||||
GLRenderer->mLights->Finish();
|
GLRenderer->mLights->Finish();
|
||||||
GLRenderer->mVBO->Unmap();
|
GLRenderer->mVBO->Unmap();
|
||||||
|
|
||||||
|
@ -208,28 +209,10 @@ void FDrawInfo::RenderScene(int recursion)
|
||||||
DrawDecals();
|
DrawDecals();
|
||||||
|
|
||||||
gl_RenderState.SetTextureMode(TM_MODULATE);
|
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);
|
glPolygonOffset(0.0f, 0.0f);
|
||||||
glDisable(GL_POLYGON_OFFSET_FILL);
|
glDisable(GL_POLYGON_OFFSET_FILL);
|
||||||
|
glDepthMask(true);
|
||||||
RenderAll.Unclock();
|
RenderAll.Unclock();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
|
@ -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()
|
void HWDrawInfo::ClearBuffers()
|
||||||
{
|
{
|
||||||
for(unsigned int i=0;i< otherfloorplanes.Size();i++)
|
for (auto node : otherfloorplanes) DeleteLinkedList(node);
|
||||||
{
|
|
||||||
gl_subsectorrendernode * node = otherfloorplanes[i];
|
|
||||||
while (node)
|
|
||||||
{
|
|
||||||
gl_subsectorrendernode * n = node;
|
|
||||||
node = node->next;
|
|
||||||
delete n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
otherfloorplanes.Clear();
|
otherfloorplanes.Clear();
|
||||||
|
|
||||||
for(unsigned int i=0;i< otherceilingplanes.Size();i++)
|
for (auto node : otherceilingplanes) DeleteLinkedList(node);
|
||||||
{
|
|
||||||
gl_subsectorrendernode * node = otherceilingplanes[i];
|
|
||||||
while (node)
|
|
||||||
{
|
|
||||||
gl_subsectorrendernode * n = node;
|
|
||||||
node = node->next;
|
|
||||||
delete n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
otherceilingplanes.Clear();
|
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
|
// clear all the lists that might not have been cleared already
|
||||||
MissingUpperTextures.Clear();
|
MissingUpperTextures.Clear();
|
||||||
MissingLowerTextures.Clear();
|
MissingLowerTextures.Clear();
|
||||||
|
|
|
@ -35,6 +35,15 @@ struct gl_subsectorrendernode
|
||||||
gl_subsectorrendernode * next;
|
gl_subsectorrendernode * next;
|
||||||
subsector_t * sub;
|
subsector_t * sub;
|
||||||
int lightindex;
|
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;
|
enum area_t : int;
|
||||||
|
@ -123,6 +132,8 @@ struct HWDrawInfo
|
||||||
|
|
||||||
TArray<gl_subsectorrendernode*> otherfloorplanes;
|
TArray<gl_subsectorrendernode*> otherfloorplanes;
|
||||||
TArray<gl_subsectorrendernode*> otherceilingplanes;
|
TArray<gl_subsectorrendernode*> otherceilingplanes;
|
||||||
|
TArray<gl_floodrendernode*> floodfloorsegs;
|
||||||
|
TArray<gl_floodrendernode*> floodceilingsegs;
|
||||||
|
|
||||||
TArray<sector_t *> CeilingStacks;
|
TArray<sector_t *> CeilingStacks;
|
||||||
TArray<sector_t *> FloorStacks;
|
TArray<sector_t *> FloorStacks;
|
||||||
|
@ -162,8 +173,35 @@ private:
|
||||||
void RenderThings(subsector_t * sub, sector_t * sector);
|
void RenderThings(subsector_t * sub, sector_t * sector);
|
||||||
void DoSubsector(subsector_t * sub);
|
void DoSubsector(subsector_t * sub);
|
||||||
int SetupLightsForOtherPlane(subsector_t * sub, FDynLightData &lightdata, const secplane_t *plane);
|
int SetupLightsForOtherPlane(subsector_t * sub, FDynLightData &lightdata, const secplane_t *plane);
|
||||||
|
int CreateOtherPlaneVertices(subsector_t *sub, const secplane_t *plane);
|
||||||
public:
|
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)
|
void SetCameraPos(const DVector3 &pos)
|
||||||
{
|
{
|
||||||
VPUniforms.mCameraPos = { (float)pos.X, (float)pos.Z, (float)pos.Y, 0.f };
|
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 AddUpperMissingTexture(side_t * side, subsector_t *sub, float backheight);
|
||||||
void AddLowerMissingTexture(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 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 AddHackedSubsector(subsector_t * sub);
|
||||||
void HandleHackedSubsectors();
|
void HandleHackedSubsectors();
|
||||||
void AddFloorStack(sector_t * sec);
|
void AddFloorStack(sector_t * sec);
|
||||||
|
@ -236,8 +279,6 @@ public:
|
||||||
virtual void DrawFlat(GLFlat *flat, int pass, bool trans) = 0;
|
virtual void DrawFlat(GLFlat *flat, int pass, bool trans) = 0;
|
||||||
virtual void DrawSprite(GLSprite *sprite, int pass) = 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);
|
void ProcessLowerMinisegs(TArray<seg_t *> &lowersegs);
|
||||||
virtual void AddSubsectorToPortal(FSectorPortalGroup *portal, subsector_t *sub) = 0;
|
virtual void AddSubsectorToPortal(FSectorPortalGroup *portal, subsector_t *sub) = 0;
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include "hw_drawstructs.h"
|
#include "hw_drawstructs.h"
|
||||||
#include "hwrenderer/utility/hw_clock.h"
|
#include "hwrenderer/utility/hw_clock.h"
|
||||||
#include "hwrenderer/dynlights/hw_dynlightdata.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);
|
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;
|
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
|
// 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();
|
int oldcnt = otherfloorplanes.Size();
|
||||||
|
|
||||||
if (oldcnt<=sector)
|
if (oldcnt <= sector)
|
||||||
{
|
{
|
||||||
otherfloorplanes.Resize(sector+1);
|
otherfloorplanes.Resize(sector + 1);
|
||||||
for(int i=oldcnt;i<=sector;i++) otherfloorplanes[i]=NULL;
|
for (int i = oldcnt; i <= sector; i++) otherfloorplanes[i] = nullptr;
|
||||||
}
|
}
|
||||||
node->next = otherfloorplanes[sector];
|
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;
|
otherfloorplanes[sector] = node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,13 +124,14 @@ void HWDrawInfo::AddOtherCeilingPlane(int sector, gl_subsectorrendernode * node)
|
||||||
{
|
{
|
||||||
int oldcnt = otherceilingplanes.Size();
|
int oldcnt = otherceilingplanes.Size();
|
||||||
|
|
||||||
if (oldcnt<=sector)
|
if (oldcnt <= sector)
|
||||||
{
|
{
|
||||||
otherceilingplanes.Resize(sector+1);
|
otherceilingplanes.Resize(sector + 1);
|
||||||
for(int i=oldcnt;i<=sector;i++) otherceilingplanes[i]=NULL;
|
for (int i = oldcnt; i <= sector; i++) otherceilingplanes[i] = nullptr;
|
||||||
}
|
}
|
||||||
node->next = otherceilingplanes[sector];
|
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;
|
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++;
|
vertices[0].Set(ws->x1, ws->z1, ws->y1, 0, 0);
|
||||||
for (int i = MissingUpperSegs.Size() - 1; i >= 0; i--)
|
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;
|
v1 = seg->linedef->v1;
|
||||||
if (index >= 0 && MissingUpperTextures[index].seg == NULL) continue;
|
v2 = seg->linedef->v2;
|
||||||
|
}
|
||||||
seg_t * seg = MissingUpperSegs[i].seg;
|
else
|
||||||
|
{
|
||||||
// already done!
|
v1 = seg->linedef->v2;
|
||||||
if (seg->linedef->validcount == validcount) continue; // already done
|
v2 = seg->linedef->v1;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
validcount++;
|
ws.x1 = v1->fX();
|
||||||
for (int i = MissingLowerSegs.Size() - 1; i >= 0; i--)
|
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;
|
floodfloorsegs.Resize(sector + 1);
|
||||||
if (index >= 0 && MissingLowerTextures[index].seg == NULL) continue;
|
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();
|
MissingUpperTextures.Clear();
|
||||||
MissingLowerTextures.Clear();
|
MissingLowerTextures.Clear();
|
||||||
|
|
Loading…
Reference in a new issue