mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-12-28 12:30:46 +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;
|
di = _di;
|
||||||
clipper = c;
|
clipper = c;
|
||||||
viewx = view.x * (1/ 16.f);
|
viewx = view.x * (1/ 16.f);
|
||||||
|
@ -83,6 +85,7 @@ void BunchDrawer::StartScene()
|
||||||
Bunches.Clear();
|
Bunches.Clear();
|
||||||
CompareData.Clear();
|
CompareData.Clear();
|
||||||
gotsector.Zero();
|
gotsector.Zero();
|
||||||
|
gotwall.Zero();
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -232,8 +235,9 @@ void BunchDrawer::ProcessBunch(int bnch)
|
||||||
{
|
{
|
||||||
show2dwall.Set(i);
|
show2dwall.Set(i);
|
||||||
|
|
||||||
//if (gl_render_walls)
|
if (!gotwall[i])
|
||||||
{
|
{
|
||||||
|
gotwall.Set(i);
|
||||||
ClipWall.Unclock();
|
ClipWall.Unclock();
|
||||||
Bsp.Unclock();
|
Bsp.Unclock();
|
||||||
SetupWall.Clock();
|
SetupWall.Clock();
|
||||||
|
@ -480,36 +484,25 @@ void BunchDrawer::ProcessSector(int sectnum, bool portal)
|
||||||
DVector2 start = { WallStartX(thiswall), WallStartY(thiswall) };
|
DVector2 start = { WallStartX(thiswall), WallStartY(thiswall) };
|
||||||
DVector2 end = { WallStartX(thiswall->point2), WallStartY(thiswall->point2) };
|
DVector2 end = { WallStartX(thiswall->point2), WallStartY(thiswall->point2) };
|
||||||
#endif
|
#endif
|
||||||
binangle ang1 = thiswall->clipangle;
|
binangle walang1 = thiswall->clipangle;
|
||||||
binangle ang2 = wall[thiswall->point2].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;
|
inbunch = false;
|
||||||
}
|
}
|
||||||
/* disabled because it only fragments the bunches without any performance gain.
|
else if (!inbunch)
|
||||||
else if (!clipper->SafeCheckRange(ang1, ang2))
|
|
||||||
{
|
{
|
||||||
// is it visible?
|
startangle = walang1;
|
||||||
inbunch = false;
|
StartBunch(sectnum, sect->wallptr + i, walang1, walang2, portal);
|
||||||
}
|
|
||||||
*/
|
|
||||||
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);
|
|
||||||
inbunch = true;
|
inbunch = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AddLineToBunch(sect->wallptr + i, ang2);
|
AddLineToBunch(sect->wallptr + i, walang2);
|
||||||
}
|
}
|
||||||
if (thiswall->point2 != sect->wallptr + i + 1) inbunch = false;
|
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)
|
void BunchDrawer::RenderScene(const int* viewsectors, unsigned sectcount, bool portal)
|
||||||
{
|
{
|
||||||
Bsp.Clock();
|
auto process = [&]()
|
||||||
for(unsigned i=0;i<sectcount;i++)
|
|
||||||
ProcessSector(viewsectors[i], portal);
|
|
||||||
while (Bunches.Size() > 0)
|
|
||||||
{
|
{
|
||||||
int closest = FindClosestBunch();
|
for (unsigned i = 0; i < sectcount; i++)
|
||||||
ProcessBunch(closest);
|
ProcessSector(viewsectors[i], portal);
|
||||||
DeleteBunch(closest);
|
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();
|
Bsp.Unclock();
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,8 @@ class BunchDrawer
|
||||||
vec2_t iview;
|
vec2_t iview;
|
||||||
float gcosang, gsinang;
|
float gcosang, gsinang;
|
||||||
FixedBitArray<MAXSECTORS> gotsector;
|
FixedBitArray<MAXSECTORS> gotsector;
|
||||||
|
FixedBitArray<MAXWALLS> gotwall;
|
||||||
|
binangle ang1, ang2;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -51,7 +53,7 @@ private:
|
||||||
void ProcessSector(int sectnum, bool portal);
|
void ProcessSector(int sectnum, bool portal);
|
||||||
|
|
||||||
public:
|
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);
|
void RenderScene(const int* viewsectors, unsigned sectcount, bool portal);
|
||||||
const FixedBitArray<MAXSECTORS>& GotSector() const { return gotsector; }
|
const FixedBitArray<MAXSECTORS>& GotSector() const { return gotsector; }
|
||||||
};
|
};
|
||||||
|
|
|
@ -211,7 +211,7 @@ angle_t HWDrawInfo::FrustumAngle()
|
||||||
// but at least it doesn't overestimate too much...
|
// 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;
|
double floatangle = 2.0 + (45.0 + ((tilt / 1.9)))*Viewpoint.FieldOfView.Degrees*48.0 / AspectMultiplier(WidescreenRatio) / 90.0;
|
||||||
angle_t a1 = DAngle(floatangle).BAMs();
|
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;
|
return a1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -369,7 +369,7 @@ void HWDrawInfo::CreateScene(bool portal)
|
||||||
const auto& vp = Viewpoint;
|
const auto& vp = Viewpoint;
|
||||||
|
|
||||||
angle_t a1 = FrustumAngle();
|
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
|
// reset the portal manager
|
||||||
portalState.StartFrame();
|
portalState.StartFrame();
|
||||||
|
@ -385,7 +385,8 @@ void HWDrawInfo::CreateScene(bool portal)
|
||||||
geoofs = { 0,0 };
|
geoofs = { 0,0 };
|
||||||
|
|
||||||
vec2_t view = { int(vp.Pos.X * 16), int(vp.Pos.Y * -16) };
|
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)
|
if (vp.SectNums)
|
||||||
mDrawer.RenderScene(vp.SectNums, vp.SectCount, portal);
|
mDrawer.RenderScene(vp.SectNums, vp.SectCount, portal);
|
||||||
else
|
else
|
||||||
|
@ -421,7 +422,8 @@ void HWDrawInfo::CreateScene(bool portal)
|
||||||
|
|
||||||
mClipper->Clear();
|
mClipper->Clear();
|
||||||
mClipper->SafeAddClipRange(bamang(vp.RotAngle + a1), bamang(vp.RotAngle - a1));
|
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);
|
mDrawer.RenderScene(&drawsect, 1, false);
|
||||||
|
|
||||||
for (int i = 0; i < eff.geocnt; i++)
|
for (int i = 0; i < eff.geocnt; i++)
|
||||||
|
@ -452,7 +454,8 @@ void HWDrawInfo::CreateScene(bool portal)
|
||||||
|
|
||||||
mClipper->Clear();
|
mClipper->Clear();
|
||||||
mClipper->SafeAddClipRange(bamang(vp.RotAngle + a1), bamang(vp.RotAngle - a1));
|
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);
|
mDrawer.RenderScene(&drawsect, 1, false);
|
||||||
|
|
||||||
for (int i = 0; i < eff.geocnt; i++)
|
for (int i = 0; i < eff.geocnt; i++)
|
||||||
|
|
Loading…
Reference in a new issue