mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-12-27 20:20:40 +00:00
- fixed a major clipping issue with the new renderer.
* the bunch drawer can at most process an angular range of 180°. If this gets exceeded it can run into wraparound issues that may cause holes in the geometry. * there was no clipping to the current field of view so it always checked the full 360°.
This commit is contained in:
parent
d823ae255e
commit
3d846f341a
3 changed files with 55 additions and 36 deletions
|
@ -49,8 +49,10 @@
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void BunchDrawer::Init(HWDrawInfo *_di, Clipper* c, vec2_t& view)
|
||||
void BunchDrawer::Init(HWDrawInfo *_di, Clipper* c, vec2_t& view, binangle a1, binangle a2)
|
||||
{
|
||||
ang1 = a1;
|
||||
ang2 = a2;
|
||||
di = _di;
|
||||
clipper = c;
|
||||
viewx = view.x * (1/ 16.f);
|
||||
|
@ -83,6 +85,7 @@ void BunchDrawer::StartScene()
|
|||
Bunches.Clear();
|
||||
CompareData.Clear();
|
||||
gotsector.Zero();
|
||||
gotwall.Zero();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -232,8 +235,9 @@ void BunchDrawer::ProcessBunch(int bnch)
|
|||
{
|
||||
show2dwall.Set(i);
|
||||
|
||||
//if (gl_render_walls)
|
||||
if (!gotwall[i])
|
||||
{
|
||||
gotwall.Set(i);
|
||||
ClipWall.Unclock();
|
||||
Bsp.Unclock();
|
||||
SetupWall.Clock();
|
||||
|
@ -480,36 +484,25 @@ void BunchDrawer::ProcessSector(int sectnum, bool portal)
|
|||
DVector2 start = { WallStartX(thiswall), WallStartY(thiswall) };
|
||||
DVector2 end = { WallStartX(thiswall->point2), WallStartY(thiswall->point2) };
|
||||
#endif
|
||||
binangle ang1 = thiswall->clipangle;
|
||||
binangle ang2 = wall[thiswall->point2].clipangle;
|
||||
binangle walang1 = thiswall->clipangle;
|
||||
binangle walang2 = wall[thiswall->point2].clipangle;
|
||||
|
||||
if (ang1.asbam() - ang2.asbam() < ANGLE_180)
|
||||
// outside the visible area or seen from the backside.
|
||||
if ((walang1.asbam() - ang1.asbam() > ANGLE_180 && walang2.asbam() - ang1.asbam() > ANGLE_180) ||
|
||||
(walang1.asbam() - ang2.asbam() < ANGLE_180 && walang2.asbam() - ang2.asbam() < ANGLE_180) ||
|
||||
(walang1.asbam() - walang2.asbam() < ANGLE_180))
|
||||
{
|
||||
// Backside
|
||||
inbunch = false;
|
||||
}
|
||||
/* disabled because it only fragments the bunches without any performance gain.
|
||||
else if (!clipper->SafeCheckRange(ang1, ang2))
|
||||
else if (!inbunch)
|
||||
{
|
||||
// is it visible?
|
||||
inbunch = false;
|
||||
}
|
||||
*/
|
||||
else if (!inbunch || ang2.asbam() - startangle.asbam() >= ANGLE_180)
|
||||
{
|
||||
// don't let a bunch span more than 180° to avoid problems.
|
||||
// This limitation ensures that the combined range of 2
|
||||
// bunches will always be less than 360° which simplifies
|
||||
// the distance comparison code because it prevents a
|
||||
// situation where 2 bunches may overlap at both ends.
|
||||
|
||||
startangle = ang1;
|
||||
StartBunch(sectnum, sect->wallptr + i, ang1, ang2, portal);
|
||||
startangle = walang1;
|
||||
StartBunch(sectnum, sect->wallptr + i, walang1, walang2, portal);
|
||||
inbunch = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
AddLineToBunch(sect->wallptr + i, ang2);
|
||||
AddLineToBunch(sect->wallptr + i, walang2);
|
||||
}
|
||||
if (thiswall->point2 != sect->wallptr + i + 1) inbunch = false;
|
||||
}
|
||||
|
@ -523,14 +516,35 @@ void BunchDrawer::ProcessSector(int sectnum, bool portal)
|
|||
|
||||
void BunchDrawer::RenderScene(const int* viewsectors, unsigned sectcount, bool portal)
|
||||
{
|
||||
Bsp.Clock();
|
||||
for(unsigned i=0;i<sectcount;i++)
|
||||
ProcessSector(viewsectors[i], portal);
|
||||
while (Bunches.Size() > 0)
|
||||
auto process = [&]()
|
||||
{
|
||||
int closest = FindClosestBunch();
|
||||
ProcessBunch(closest);
|
||||
DeleteBunch(closest);
|
||||
for (unsigned i = 0; i < sectcount; i++)
|
||||
ProcessSector(viewsectors[i], portal);
|
||||
while (Bunches.Size() > 0)
|
||||
{
|
||||
int closest = FindClosestBunch();
|
||||
ProcessBunch(closest);
|
||||
DeleteBunch(closest);
|
||||
}
|
||||
};
|
||||
|
||||
Bsp.Clock();
|
||||
if (ang1.asbam() != 0 || ang2.asbam() != 0)
|
||||
{
|
||||
process();
|
||||
}
|
||||
else
|
||||
{
|
||||
// with a 360° field of view we need to split the scene into two halves.
|
||||
// The BunchInFront check can fail with angles that may wrap around.
|
||||
auto rotang = di->Viewpoint.RotAngle;
|
||||
ang1 = bamang(rotang - ANGLE_90);
|
||||
ang2 = bamang(rotang + ANGLE_90);
|
||||
process();
|
||||
clipper->Clear();
|
||||
ang1 = bamang(rotang + ANGLE_90);
|
||||
ang2 = bamang(rotang - ANGLE_90);
|
||||
process();
|
||||
}
|
||||
Bsp.Unclock();
|
||||
}
|
||||
|
|
|
@ -28,6 +28,8 @@ class BunchDrawer
|
|||
vec2_t iview;
|
||||
float gcosang, gsinang;
|
||||
FixedBitArray<MAXSECTORS> gotsector;
|
||||
FixedBitArray<MAXWALLS> gotwall;
|
||||
binangle ang1, ang2;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -51,7 +53,7 @@ private:
|
|||
void ProcessSector(int sectnum, bool portal);
|
||||
|
||||
public:
|
||||
void Init(HWDrawInfo* _di, Clipper* c, vec2_t& view);
|
||||
void Init(HWDrawInfo* _di, Clipper* c, vec2_t& view, binangle a1, binangle a2);
|
||||
void RenderScene(const int* viewsectors, unsigned sectcount, bool portal);
|
||||
const FixedBitArray<MAXSECTORS>& GotSector() const { return gotsector; }
|
||||
};
|
||||
|
|
|
@ -211,7 +211,7 @@ angle_t HWDrawInfo::FrustumAngle()
|
|||
// but at least it doesn't overestimate too much...
|
||||
double floatangle = 2.0 + (45.0 + ((tilt / 1.9)))*Viewpoint.FieldOfView.Degrees*48.0 / AspectMultiplier(WidescreenRatio) / 90.0;
|
||||
angle_t a1 = DAngle(floatangle).BAMs();
|
||||
if (a1 >= ANGLE_180) return 0xffffffff;
|
||||
if (a1 >= ANGLE_90) return 0xffffffff; // it's either below 90 or bust.
|
||||
return a1;
|
||||
}
|
||||
|
||||
|
@ -369,7 +369,7 @@ void HWDrawInfo::CreateScene(bool portal)
|
|||
const auto& vp = Viewpoint;
|
||||
|
||||
angle_t a1 = FrustumAngle();
|
||||
mClipper->SafeAddClipRange(bamang(vp.RotAngle + a1), bamang(vp.RotAngle - a1));
|
||||
if (a1 != 0xffffffff) mClipper->SafeAddClipRange(bamang(vp.RotAngle + a1), bamang(vp.RotAngle - a1));
|
||||
|
||||
// reset the portal manager
|
||||
portalState.StartFrame();
|
||||
|
@ -385,7 +385,8 @@ void HWDrawInfo::CreateScene(bool portal)
|
|||
geoofs = { 0,0 };
|
||||
|
||||
vec2_t view = { int(vp.Pos.X * 16), int(vp.Pos.Y * -16) };
|
||||
mDrawer.Init(this, mClipper, view);
|
||||
if (a1 != 0xffffffff) mDrawer.Init(this, mClipper, view, bamang(vp.RotAngle - a1), bamang(vp.RotAngle + a1));
|
||||
else mDrawer.Init(this, mClipper, view, bamang(0), bamang(0));
|
||||
if (vp.SectNums)
|
||||
mDrawer.RenderScene(vp.SectNums, vp.SectCount, portal);
|
||||
else
|
||||
|
@ -421,7 +422,8 @@ void HWDrawInfo::CreateScene(bool portal)
|
|||
|
||||
mClipper->Clear();
|
||||
mClipper->SafeAddClipRange(bamang(vp.RotAngle + a1), bamang(vp.RotAngle - a1));
|
||||
mDrawer.Init(this, mClipper, view);
|
||||
if (a1 != 0xffffffff) mDrawer.Init(this, mClipper, view, bamang(vp.RotAngle - a1), bamang(vp.RotAngle + a1));
|
||||
else mDrawer.Init(this, mClipper, view, bamang(0), bamang(0));
|
||||
mDrawer.RenderScene(&drawsect, 1, false);
|
||||
|
||||
for (int i = 0; i < eff.geocnt; i++)
|
||||
|
@ -452,7 +454,8 @@ void HWDrawInfo::CreateScene(bool portal)
|
|||
|
||||
mClipper->Clear();
|
||||
mClipper->SafeAddClipRange(bamang(vp.RotAngle + a1), bamang(vp.RotAngle - a1));
|
||||
mDrawer.Init(this, mClipper, view);
|
||||
if (a1 != 0xffffffff) mDrawer.Init(this, mClipper, view, bamang(vp.RotAngle - a1), bamang(vp.RotAngle + a1));
|
||||
else mDrawer.Init(this, mClipper, view, bamang(0), bamang(0));
|
||||
mDrawer.RenderScene(&drawsect, 1, false);
|
||||
|
||||
for (int i = 0; i < eff.geocnt; i++)
|
||||
|
|
Loading…
Reference in a new issue