mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-28 15:02:01 +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;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// 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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
|
|
@ -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();
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue