Merge pull request #14 from alufolie91/fixbinaryclipping

Fix issues with Clipping and Skywalls in kart binary maps in Opengl. Thanks Alug!
This commit is contained in:
NepDisk 2024-09-11 10:23:08 -04:00 committed by GitHub
commit dd8f5c3da9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 268 additions and 75 deletions

View file

@ -322,16 +322,13 @@ void gld_clipper_Clear(void)
#define RMUL (1.6f/1.333333f)
angle_t gld_FrustumAngle(angle_t tiltangle)
angle_t gld_FrustumAngle(float render_fov, angle_t tiltangle)
{
double floatangle;
angle_t a1;
float tilt = (float)fabs(((double)(int)tiltangle) / ANG1);
// NEWCLIP TODO: SRB2CBTODO: make a global render_fov for this function
float render_fov = FIXED_TO_FLOAT(cv_fov[viewssnum].value);
float render_fovratio = (float)BASEVIDWIDTH / (float)BASEVIDHEIGHT; // SRB2CBTODO: NEWCLIPTODO: Is this right?
float render_multiplier = 64.0f / render_fovratio / RMUL;

View file

@ -17,7 +17,7 @@
boolean gld_clipper_SafeCheckRange(angle_t startAngle, angle_t endAngle);
void gld_clipper_SafeAddClipRange(angle_t startangle, angle_t endangle);
void gld_clipper_Clear(void);
angle_t gld_FrustumAngle(angle_t tiltangle);
angle_t gld_FrustumAngle(float render_fov, angle_t tiltangle);
#ifdef HAVE_SPHEREFRUSTRUM
void gld_FrustrumSetup(void);
boolean gld_SphereInFrustum(float x, float y, float z, float radius);

View file

@ -1170,25 +1170,112 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
SLOPEPARAMS(gl_backsector->c_slope, worldhigh, worldhighslope, gl_backsector->ceilingheight)
SLOPEPARAMS(gl_backsector->f_slope, worldlow, worldlowslope, gl_backsector->floorheight)
// hack to allow height changes in outdoor areas
// This is what gets rid of the upper textures if there should be sky
if (gl_frontsector->ceilingpic == skyflatnum
&& gl_backsector->ceilingpic == skyflatnum)
if (udmf)
{
bothceilingssky = true;
}
// hack to allow height changes in outdoor areas
// This is what gets rid of the upper textures if there should be sky
if (gl_frontsector->ceilingpic == skyflatnum
&& gl_backsector->ceilingpic == skyflatnum)
{
bothceilingssky = true;
}
// likewise, but for floors and upper textures
if (gl_frontsector->floorpic == skyflatnum
&& gl_backsector->floorpic == skyflatnum)
// likewise, but for floors and upper textures
if (gl_frontsector->floorpic == skyflatnum
&& gl_backsector->floorpic == skyflatnum)
{
bothfloorssky = true;
}
if (!bothceilingssky)
gl_toptexture = R_GetTextureNum(gl_sidedef->toptexture);
if (!bothfloorssky)
gl_bottomtexture = R_GetTextureNum(gl_sidedef->bottomtexture);
}
else
{
bothfloorssky = true;
}
// Sky Ceilings
wallVerts[3].y = wallVerts[2].y = FIXED_TO_FLOAT(INT32_MAX);
if (gl_frontsector->ceilingpic == skyflatnum)
{
if (gl_backsector->ceilingpic == skyflatnum)
{
// Both front and back sectors are sky, needs skywall from the frontsector's ceiling, but only if the
// backsector is lower
if ((worldhigh <= worldtop && worldhighslope <= worldtopslope)// Assuming ESLOPE is always on with my changes
&& (worldhigh != worldtop || worldhighslope != worldtopslope))
// Removing the second line above will render more rarely visible skywalls. Example: Cave garden ceiling in Dark race
{
wallVerts[0].y = FIXED_TO_FLOAT(worldhigh);
wallVerts[1].y = FIXED_TO_FLOAT(worldhighslope);
HWR_DrawSkyWall(wallVerts, &Surf);
}
}
else
{
// Only the frontsector is sky, just draw a skywall from the front ceiling
wallVerts[0].y = FIXED_TO_FLOAT(worldtop);
wallVerts[1].y = FIXED_TO_FLOAT(worldtopslope);
HWR_DrawSkyWall(wallVerts, &Surf);
}
}
else if (gl_backsector->ceilingpic == skyflatnum)
{
// Only the backsector is sky, just draw a skywall from the front ceiling
wallVerts[0].y = FIXED_TO_FLOAT(worldtop);
wallVerts[1].y = FIXED_TO_FLOAT(worldtopslope);
HWR_DrawSkyWall(wallVerts, &Surf);
}
// Sky Floors
wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(INT32_MIN);
if (gl_frontsector->floorpic == skyflatnum)
{
if (gl_backsector->floorpic == skyflatnum)
{
// Both front and back sectors are sky, needs skywall from the backsector's floor, but only if the
// it's higher, also needs to check for bottomtexture as the floors don't usually move down
// when both sides are sky floors
if ((worldlow >= worldbottom && worldlowslope >= worldbottomslope)
&& (worldlow != worldbottom || worldlowslope != worldbottomslope)
// Removing the second line above will render more rarely visible skywalls. Example: Cave garden ceiling in Dark race
&& !(gl_sidedef->bottomtexture))
{
wallVerts[3].y = FIXED_TO_FLOAT(worldlow);
wallVerts[2].y = FIXED_TO_FLOAT(worldlowslope);
HWR_DrawSkyWall(wallVerts, &Surf);
}
}
else
{
// Only the backsector has sky, just draw a skywall from the back floor
wallVerts[3].y = FIXED_TO_FLOAT(worldbottom);
wallVerts[2].y = FIXED_TO_FLOAT(worldbottomslope);
HWR_DrawSkyWall(wallVerts, &Surf);
}
}
else if ((gl_backsector->floorpic == skyflatnum) && !(gl_sidedef->bottomtexture))
{
// Only the backsector has sky, just draw a skywall from the back floor if there's no bottomtexture
wallVerts[3].y = FIXED_TO_FLOAT(worldlow);
wallVerts[2].y = FIXED_TO_FLOAT(worldlowslope);
HWR_DrawSkyWall(wallVerts, &Surf);
}
// hack to allow height changes in outdoor areas
// This is what gets rid of the upper textures if there should be sky
if (gl_frontsector->ceilingpic == skyflatnum
&& gl_backsector->ceilingpic == skyflatnum)
{
worldtop = worldhigh;
worldtopslope = worldhighslope;
}
if (!bothceilingssky)
gl_toptexture = R_GetTextureNum(gl_sidedef->toptexture);
if (!bothfloorssky)
gl_bottomtexture = R_GetTextureNum(gl_sidedef->bottomtexture);
}
// check TOP TEXTURE
if ((worldhighslope < worldtopslope || worldhigh < worldtop) && gl_toptexture)
@ -1333,7 +1420,9 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
HWR_ProjectWall(wallVerts, &Surf, polyflags, lightnum, colormap);
}
}
gl_midtexture = R_GetTextureNum(gl_sidedef->midtexture);
if (gl_midtexture)
{
FBITFIELD blendmode;
@ -1547,27 +1636,32 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
// Sky culling
// No longer so much a mess as before!
if (!gl_curline->polyseg) // Don't do it for polyobjects
// It now is a mess again, thx kart!
// see above!
if (udmf)
{
if (gl_frontsector->ceilingpic == skyflatnum)
if (!gl_curline->polyseg) // Don't do it for polyobjects
{
if (gl_backsector->ceilingpic != skyflatnum) // don't cull if back sector is also sky
if (gl_frontsector->ceilingpic == skyflatnum)
{
wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(INT32_MAX); // draw to top of map space
wallVerts[0].y = FIXED_TO_FLOAT(worldtop);
wallVerts[1].y = FIXED_TO_FLOAT(worldtopslope);
HWR_DrawSkyWall(wallVerts, &Surf);
if (gl_backsector->ceilingpic != skyflatnum) // don't cull if back sector is also sky
{
wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(INT32_MAX); // draw to top of map space
wallVerts[0].y = FIXED_TO_FLOAT(worldtop);
wallVerts[1].y = FIXED_TO_FLOAT(worldtopslope);
HWR_DrawSkyWall(wallVerts, &Surf);
}
}
}
if (gl_frontsector->floorpic == skyflatnum)
{
if (gl_backsector->floorpic != skyflatnum) // don't cull if back sector is also sky
if (gl_frontsector->floorpic == skyflatnum)
{
wallVerts[3].y = FIXED_TO_FLOAT(worldbottom);
wallVerts[2].y = FIXED_TO_FLOAT(worldbottomslope);
wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(INT32_MIN); // draw to bottom of map space
HWR_DrawSkyWall(wallVerts, &Surf);
if (gl_backsector->floorpic != skyflatnum) // don't cull if back sector is also sky
{
wallVerts[3].y = FIXED_TO_FLOAT(worldbottom);
wallVerts[2].y = FIXED_TO_FLOAT(worldbottomslope);
wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(INT32_MIN); // draw to bottom of map space
HWR_DrawSkyWall(wallVerts, &Surf);
}
}
}
}
@ -1638,6 +1732,17 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
}
}
}
else if (!udmf)
{
//Set textures properly on single sided walls that are sloped
wallVerts[3].y = FIXED_TO_FLOAT(worldtop);
wallVerts[0].y = FIXED_TO_FLOAT(worldbottom);
wallVerts[2].y = FIXED_TO_FLOAT(worldtopslope);
wallVerts[1].y = FIXED_TO_FLOAT(worldbottomslope);
// When there's no midtexture, draw a skywall to prevent rendering behind it
HWR_DrawSkyWall(wallVerts, &Surf);
}
if (!gl_curline->polyseg)
{
@ -1979,12 +2084,16 @@ static boolean CheckClip(seg_t * seg, sector_t * afrontsector, sector_t * abacks
{
fixed_t frontf1,frontf2, frontc1, frontc2; // front floor/ceiling ends
fixed_t backf1, backf2, backc1, backc2; // back floor ceiling ends
boolean bothceilingssky = false, bothfloorssky = false;
if (abacksector->ceilingpic == skyflatnum && afrontsector->ceilingpic == skyflatnum)
bothceilingssky = true;
if (abacksector->floorpic == skyflatnum && afrontsector->floorpic == skyflatnum)
bothfloorssky = true;
if (udmf)
{
if (abacksector->ceilingpic == skyflatnum && afrontsector->ceilingpic == skyflatnum)
bothceilingssky = true;
if (abacksector->floorpic == skyflatnum && afrontsector->floorpic == skyflatnum)
bothfloorssky = true;
}
// GZDoom method of sloped line clipping
@ -2028,40 +2137,124 @@ static boolean CheckClip(seg_t * seg, sector_t * afrontsector, sector_t * abacks
backf1 = backf2 = abacksector-> floorheight;
backc1 = backc2 = abacksector->ceilingheight;
}
// properly render skies (consider door "open" if both ceilings are sky)
// same for floors
if (!bothceilingssky && !bothfloorssky)
// lug: but only on udmf maps :chaosleep:
// kart does some funky crap on its binary maps and thus using this code breaks many maps visually and generally makes performance really bad
if (udmf)
{
if (!bothceilingssky && !bothfloorssky)
{
// now check for closed sectors!
if ((backc1 <= frontf1 && backc2 <= frontf2)
|| (backf1 >= frontc1 && backf2 >= frontc2))
{
checkforemptylines = false;
return true;
}
if (backc1 <= backf1 && backc2 <= backf2)
{
// preserve a kind of transparent door/lift special effect:
if (((backc1 >= frontc1 && backc2 >= frontc2) || seg->sidedef->toptexture)
&& ((backf1 <= frontf1 && backf2 <= frontf2) || seg->sidedef->bottomtexture))
{
checkforemptylines = false;
return true;
}
}
}
if (!bothceilingssky)
{
if (backc1 != frontc1 || backc2 != frontc2)
{
checkforemptylines = false;
return false;
}
}
if (!bothfloorssky)
{
if (backf1 != frontf1 || backf2 != frontf2)
{
checkforemptylines = false;
return false;
}
}
}
else
{
// not in vanilla kart, but this makes noclipcam alot more bearable when its stuck in walls
// otherwise it may cull half your view which is not really desirable
if (afrontsector == viewsector || abacksector == viewsector)
{
fixed_t viewf1, viewf2, viewc1, viewc2;
if (afrontsector == viewsector)
{
viewf1 = frontf1;
viewf2 = frontf2;
viewc1 = frontc1;
viewc2 = frontc2;
}
else
{
viewf1 = backf1;
viewf2 = backf2;
viewc1 = backc1;
viewc2 = backc2;
}
// check if camera is outside the bounds of the floor and the ceiling (noclipping)
// either above the ceiling or below the floor
if ((viewz > viewc1 && viewz > viewc2) || (viewz < viewf1 && viewz < viewf2))
return false;
}
// now check for closed sectors!
if ((backc1 <= frontf1 && backc2 <= frontf2)
|| (backf1 >= frontc1 && backf2 >= frontc2))
// here we're talking about a CEILING lower than a floor. ...yeah we don't even need to bother.
if (backc1 <= frontf1 && backc2 <= frontf2)
{
checkforemptylines = false;
return true;
}
if (backc1 <= backf1 && backc2 <= backf2)
{
// preserve a kind of transparent door/lift special effect:
if (((backc1 >= frontc1 && backc2 >= frontc2) || seg->sidedef->toptexture)
&& ((backf1 <= frontf1 && backf2 <= frontf2) || seg->sidedef->bottomtexture))
{
checkforemptylines = false;
return true;
}
}
}
if (!bothceilingssky) {
if (backc1 != frontc1 || backc2 != frontc2)
// here we're talking about floors higher than ceilings, don't even bother either.
if (backf1 >= frontc1 && backf2 >= frontc2)
{
checkforemptylines = false;
return false;
return true;
}
}
if (!bothfloorssky) {
if (backf1 != frontf1 || backf2 != frontf2)
// Lat: Ok, here's what we need to do, we want to draw thok barriers. Let's define what a thok barrier is;
// -Must have ceilheight <= floorheight
// -ceilpic must be skyflatnum
// -an adjacant sector needs to have a ceilingheight or a floor height different than the one we have, otherwise, it's just a huge ass wall, we shouldn't render past it.
// -said adjacant sector cannot also be a thok barrier, because that's also dumb and we could render far more than we need to as a result :V
if (backc1 <= backf1 && backc2 <= backf2)
{
checkforemptylines = false;
// before we do anything, if both sectors are thok barriers, GET ME OUT OF HERE!
if (frontc1 <= backc1 && frontc2 <= backc2)
return true; // STOP RENDERING.
// draw floors at the top of thok barriers:
if (backc1 < frontc1 || backc2 < frontc2)
return false;
if (backf1 > frontf1 || backf2 > frontf2)
return false;
return true;
}
// Window.
// We know it's a window when the above isn't true and the back and front sectors don't match
if (backc1 != frontc1 || backc2 != frontc2 || backf1 != frontf1 || backf2 != frontf2)
{
checkforemptylines = false;
return false;
@ -2410,7 +2603,7 @@ static void HWR_AddLine(seg_t * line)
#ifdef NEWCLIP
// PrBoom: Back side, i.e. backface culling - read: endAngle >= startAngle!
if (angle2 - angle1 < ANGLE_180)
if (angle2 - angle1 < ANGLE_180 || !gl_curline->linedef)
return;
// PrBoom: use REAL clipping math YAYYYYYYY!!!
@ -2515,21 +2708,24 @@ static void HWR_AddLine(seg_t * line)
gl_backsector = R_FakeFlat(gl_backsector, &tempsec, NULL, NULL, true);
if (gl_backsector->ceilingpic == skyflatnum && gl_frontsector->ceilingpic == skyflatnum)
bothceilingssky = true;
if (gl_backsector->floorpic == skyflatnum && gl_frontsector->floorpic == skyflatnum)
bothfloorssky = true;
if (bothceilingssky && bothfloorssky) // everything's sky? let's save us a bit of time then
if (udmf) // same here, thisll most likely break kart maps
{
if (!line->polyseg &&
!line->sidedef->midtexture
&& ((!gl_frontsector->ffloors && !gl_backsector->ffloors)
|| Tag_Compare(&gl_frontsector->tags, &gl_backsector->tags)))
return; // line is empty, don't even bother
// treat like wide open window instead
HWR_ProcessSeg(); // Doesn't need arguments because they're defined globally :D
return;
if (gl_backsector->ceilingpic == skyflatnum && gl_frontsector->ceilingpic == skyflatnum)
bothceilingssky = true;
if (gl_backsector->floorpic == skyflatnum && gl_frontsector->floorpic == skyflatnum)
bothfloorssky = true;
if (bothceilingssky && bothfloorssky) // everything's sky? let's save us a bit of time then
{
if (!line->polyseg &&
!line->sidedef->midtexture
&& ((!gl_frontsector->ffloors && !gl_backsector->ffloors)
|| Tag_Compare(&gl_frontsector->tags, &gl_backsector->tags)))
return; // line is empty, don't even bother
// treat like wide open window instead
HWR_ProcessSeg(); // Doesn't need arguments because they're defined globally :D
return;
}
}
if (CheckClip(line, gl_frontsector, gl_backsector))
@ -6403,7 +6599,7 @@ void HWR_RenderSkyboxView(player_t *player)
#ifdef NEWCLIP
{
angle_t a1 = gld_FrustumAngle(gl_aimingangle);
angle_t a1 = gld_FrustumAngle(fpov, gl_aimingangle);
gld_clipper_Clear();
gld_clipper_SafeAddClipRange(viewangle + a1, viewangle - a1);
#ifdef HAVE_SPHEREFRUSTRUM
@ -6615,7 +6811,7 @@ void HWR_RenderPlayerView(void)
#ifdef NEWCLIP
{
angle_t a1 = gld_FrustumAngle(gl_aimingangle);
angle_t a1 = gld_FrustumAngle(fpov, gl_aimingangle);
gld_clipper_Clear();
gld_clipper_SafeAddClipRange(viewangle + a1, viewangle - a1);
#ifdef HAVE_SPHEREFRUSTRUM