WIP OpenGL extra textures

This commit is contained in:
Lactozilla 2024-01-24 00:16:15 -03:00
parent a50e6bd769
commit e448e60a44

View file

@ -274,7 +274,7 @@ UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap) // Let's see if
return surfcolor.s.alpha; return surfcolor.s.alpha;
} }
static FUINT HWR_CalcWallLight(FUINT lightnum, fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t v2y) static UINT32 HWR_CalcWallLight(UINT32 lightnum, fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t v2y)
{ {
INT16 finallight = lightnum; INT16 finallight = lightnum;
@ -310,10 +310,10 @@ static FUINT HWR_CalcWallLight(FUINT lightnum, fixed_t v1x, fixed_t v1y, fixed_t
} }
} }
return (FUINT)finallight; return (UINT32)finallight;
} }
static FUINT HWR_CalcSlopeLight(FUINT lightnum, angle_t dir, fixed_t delta) static UINT32 HWR_CalcSlopeLight(UINT32 lightnum, angle_t dir, fixed_t delta)
{ {
INT16 finallight = lightnum; INT16 finallight = lightnum;
@ -354,7 +354,7 @@ static FUINT HWR_CalcSlopeLight(FUINT lightnum, angle_t dir, fixed_t delta)
} }
} }
return (FUINT)finallight; return (UINT32)finallight;
} }
// ========================================================================== // ==========================================================================
@ -847,7 +847,7 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum,
fixed_t v2y = FloatToFixed(wallVerts[1].z); fixed_t v2y = FloatToFixed(wallVerts[1].z);
const UINT8 alpha = Surf->PolyColor.s.alpha; const UINT8 alpha = Surf->PolyColor.s.alpha;
FUINT lightnum = HWR_CalcWallLight(sector->lightlevel, v1x, v1y, v2x, v2y); UINT32 lightnum = HWR_CalcWallLight(sector->lightlevel, v1x, v1y, v2x, v2y);
extracolormap_t *colormap = NULL; extracolormap_t *colormap = NULL;
realtop = top = wallVerts[3].y; realtop = top = wallVerts[3].y;
@ -1050,6 +1050,704 @@ static boolean HWR_BlendMidtextureSurface(FSurfaceInfo *pSurf)
return true; return true;
} }
static void HWR_RenderMidtexture(INT32 gl_midtexture, float cliplow, float cliphigh, fixed_t worldtop, fixed_t worldbottom, fixed_t worldhigh, fixed_t worldlow, fixed_t worldtopslope, fixed_t worldbottomslope, fixed_t worldhighslope, fixed_t worldlowslope, UINT32 lightnum, FOutVector *inWallVerts)
{
FOutVector wallVerts[4];
FSurfaceInfo Surf;
Surf.PolyColor.s.alpha = 255;
// Determine if it's visible
if (!HWR_BlendMidtextureSurface(&Surf))
return;
fixed_t texheight = FixedDiv(textureheight[gl_midtexture], abs(gl_sidedef->scaley_mid));
INT32 repeats;
if (gl_sidedef->repeatcnt)
repeats = 1 + gl_sidedef->repeatcnt;
else if (gl_linedef->flags & ML_WRAPMIDTEX)
{
fixed_t high, low;
if (gl_frontsector->ceilingheight > gl_backsector->ceilingheight)
high = gl_backsector->ceilingheight;
else
high = gl_frontsector->ceilingheight;
if (gl_frontsector->floorheight > gl_backsector->floorheight)
low = gl_frontsector->floorheight;
else
low = gl_backsector->floorheight;
repeats = (high - low) / texheight;
if ((high - low) % texheight)
repeats++; // tile an extra time to fill the gap -- Monster Iestyn
}
else
repeats = 1;
GLMapTexture_t *grTex = HWR_GetTexture(gl_midtexture);
float xscale = FixedToFloat(gl_sidedef->scalex_mid);
float yscale = FixedToFloat(gl_sidedef->scaley_mid);
// SoM: a little note: popentop and popenbottom
// record the limits the texture can be displayed in.
// polytop and polybottom, are the ideal (i.e. unclipped)
// heights of the polygon, and h & l, are the final (clipped)
// poly coords.
fixed_t popentop, popenbottom, polytop, polybottom, lowcut, highcut;
fixed_t popentopslope, popenbottomslope, polytopslope, polybottomslope, lowcutslope, highcutslope;
// NOTE: With polyobjects, whenever you need to check the properties of the polyobject sector it belongs to,
// you must use the linedef's backsector to be correct
// From CB
if (gl_curline->polyseg)
{
popentop = popentopslope = gl_backsector->ceilingheight;
popenbottom = popenbottomslope = gl_backsector->floorheight;
}
else
{
popentop = min(worldtop, worldhigh);
popenbottom = max(worldbottom, worldlow);
popentopslope = min(worldtopslope, worldhighslope);
popenbottomslope = max(worldbottomslope, worldlowslope);
}
// Find the wall's coordinates
fixed_t midtexheight = texheight * repeats;
fixed_t rowoffset = FixedDiv(gl_sidedef->rowoffset + gl_sidedef->offsety_mid, abs(gl_sidedef->scaley_mid));
// Texture is not skewed
if (gl_linedef->flags & ML_NOSKEW)
{
// Peg it to the floor
if (gl_linedef->flags & ML_MIDPEG)
{
polybottom = max(gl_frontsector->floorheight, gl_backsector->floorheight) + rowoffset;
polytop = polybottom + midtexheight;
}
// Peg it to the ceiling
else
{
polytop = min(gl_frontsector->ceilingheight, gl_backsector->ceilingheight) + rowoffset;
polybottom = polytop - midtexheight;
}
// The right side's coordinates are the the same as the left side
polytopslope = polytop;
polybottomslope = polybottom;
}
// Skew the texture, but peg it to the floor
else if (gl_linedef->flags & ML_MIDPEG)
{
polybottom = popenbottom + rowoffset;
polytop = polybottom + midtexheight;
polybottomslope = popenbottomslope + rowoffset;
polytopslope = polybottomslope + midtexheight;
}
// Skew it according to the ceiling's slope
else
{
polytop = popentop + rowoffset;
polybottom = polytop - midtexheight;
polytopslope = popentopslope + rowoffset;
polybottomslope = polytopslope - midtexheight;
}
// CB
// NOTE: With polyobjects, whenever you need to check the properties of the polyobject sector it belongs to,
// you must use the linedef's backsector to be correct
if (gl_curline->polyseg)
{
lowcut = polybottom;
highcut = polytop;
lowcutslope = polybottomslope;
highcutslope = polytopslope;
}
else
{
// The cut-off values of a linedef can always be constant, since every line has an absoulute front and or back sector
lowcut = popenbottom;
highcut = popentop;
lowcutslope = popenbottomslope;
highcutslope = popentopslope;
}
fixed_t h = min(highcut, polytop);
fixed_t l = max(polybottom, lowcut);
fixed_t hS = min(highcutslope, polytopslope);
fixed_t lS = max(polybottomslope, lowcutslope);
// PEGGING
fixed_t texturevpeg, texturevpegslope;
if (gl_linedef->flags & ML_MIDPEG)
{
texturevpeg = midtexheight - h + polybottom;
texturevpegslope = midtexheight - hS + polybottomslope;
}
else
{
texturevpeg = polytop - h;
texturevpegslope = polytopslope - hS;
}
memcpy(wallVerts, inWallVerts, sizeof(wallVerts));
// Left side
wallVerts[3].t = texturevpeg * yscale * grTex->scaleY;
wallVerts[0].t = (h - l + texturevpeg) * yscale * grTex->scaleY;
wallVerts[0].s = wallVerts[3].s = ((cliplow * xscale) + gl_sidedef->offsetx_mid) * grTex->scaleX;
// Right side
wallVerts[2].t = texturevpegslope * yscale * grTex->scaleY;
wallVerts[1].t = (hS - lS + texturevpegslope) * yscale * grTex->scaleY;
wallVerts[2].s = wallVerts[1].s = ((cliphigh * xscale) + gl_sidedef->offsetx_mid) * grTex->scaleX;
// set top/bottom coords
// Take the texture peg into account, rather than changing the offsets past
// where the polygon might not be.
wallVerts[3].y = FIXED_TO_FLOAT(h);
wallVerts[0].y = FIXED_TO_FLOAT(l);
wallVerts[2].y = FIXED_TO_FLOAT(hS);
wallVerts[1].y = FIXED_TO_FLOAT(lS);
// TODO: Actually use the surface's flags so that I don't have to do this
FUINT blendmode = Surf.PolyFlags;
// Render midtextures on two-sided lines with a z-buffer offset.
// This will cause the midtexture appear on top, if a FOF overlaps with it.
blendmode |= PF_Decal;
extracolormap_t *colormap = gl_frontsector->extra_colormap;
if (gl_frontsector->numlights)
{
if (!(blendmode & PF_Masked))
HWR_SplitWall(gl_frontsector, wallVerts, gl_midtexture, &Surf, FOF_TRANSLUCENT, NULL, blendmode);
else
HWR_SplitWall(gl_frontsector, wallVerts, gl_midtexture, &Surf, FOF_CUTLEVEL, NULL, blendmode);
}
else if (!(blendmode & PF_Masked))
HWR_AddTransparentWall(wallVerts, &Surf, gl_midtexture, blendmode, false, lightnum, colormap);
else
HWR_ProjectWall(wallVerts, &Surf, blendmode, lightnum, colormap);
}
static void HWR_GetExtraTextureCoords(unsigned which, fixed_t *top, fixed_t *bottom, fixed_t *topslope, fixed_t *bottomslope, fixed_t worldtop, fixed_t worldbottom, fixed_t worldhigh, fixed_t worldlow, fixed_t worldtopslope, fixed_t worldbottomslope, fixed_t worldhighslope, fixed_t worldlowslope, fixed_t midtexheight)
{
fixed_t polytop, polybottom;
fixed_t polytopslope, polybottomslope;
fixed_t rowoffset = FixedDiv(gl_sidedef->rowoffset + gl_sidedef->overlays[which].offsety, abs(gl_sidedef->overlays[which].scaley));
if (gl_sidedef->flags & GET_SIDEFLAG_EDGENOSKEW(which))
{
if (IS_TOP_EDGE_TEXTURE(which))
{
if (gl_backsector)
{
if (IS_UPPER_EDGE_TEXTURE(which))
polybottom = max(gl_frontsector->ceilingheight, gl_backsector->ceilingheight);
else
{
polybottom = min(gl_frontsector->ceilingheight, gl_backsector->ceilingheight);
polybottom += midtexheight;
}
}
else
polybottom = gl_frontsector->ceilingheight;
polybottom += rowoffset;
polytop = polybottom - midtexheight;
}
else
{
if (gl_backsector)
{
if (IS_UPPER_EDGE_TEXTURE(which))
polytop = max(gl_frontsector->floorheight, gl_backsector->floorheight);
else
{
polytop = min(gl_frontsector->floorheight, gl_backsector->floorheight);
polytop += midtexheight;
}
}
else
polytop = gl_frontsector->floorheight;
polytop += rowoffset;
polybottom = polytop + midtexheight;
}
// The right side's coordinates are the the same as the left side
polytopslope = polytop;
polybottomslope = polybottom;
}
else if (IS_TOP_EDGE_TEXTURE(which))
{
if (IS_UPPER_EDGE_TEXTURE(which))
{
polytop = worldtop + rowoffset;
polybottom = worldtop - midtexheight;
polytopslope = worldtopslope + rowoffset;
polybottomslope = worldtopslope - midtexheight;
}
else
{
polybottom = worldhigh + rowoffset;
polytop = polybottom + midtexheight;
polybottomslope = worldhighslope + rowoffset;
polytopslope = polybottomslope + midtexheight;
}
}
else
{
if (IS_UPPER_EDGE_TEXTURE(which))
{
polytop = worldlow + rowoffset;
polybottom = worldlow - midtexheight;
polytopslope = worldlowslope + rowoffset;
polybottomslope = worldlowslope - midtexheight;
}
else
{
polybottom = worldbottom + rowoffset;
polytop = polybottom + midtexheight;
polybottomslope = worldbottomslope + rowoffset;
polytopslope = polybottomslope + midtexheight;
}
}
*top = polytop;
*topslope = polytopslope;
*bottom = polybottom;
*bottomslope = polybottomslope;
}
// Draws an extra texture (WIP)
// This function is huge and lengthy (sorry) as it may need to split a wall in half
static void HWR_RenderExtraTexture(unsigned which, v2d_t vs, v2d_t ve, fixed_t texturehpeg, fixed_t worldtop, fixed_t worldbottom, fixed_t worldhigh, fixed_t worldlow, fixed_t worldtopslope, fixed_t worldbottomslope, fixed_t worldhighslope, fixed_t worldlowslope, UINT32 lightnum, FOutVector *inWallVerts)
{
INT32 texnum = R_GetTextureNum(gl_sidedef->overlays[which].texture);
if (texnum <= 0 || texnum >= numtextures)
return;
FOutVector wallVerts[4];
UINT8 intersected = 0;
fixed_t v1x = 0, v1y = 0, v2x = 0, v2y = 0;
float ptx = 0.0f, pty = 0.0f;
fixed_t cliptop = 0, clipbottom = 0, cliphigh = 0, cliplow = 0;
fixed_t cliptopslope = 0, clipbottomslope = 0, cliphighslope = 0, cliplowslope = 0;
sector_t *back = gl_backsector ? gl_backsector : gl_frontsector;
FSurfaceInfo Surf;
Surf.PolyColor.s.alpha = 255;
Surf.PolyFlags = PF_Masked;
fixed_t texheight = FixedDiv(textureheight[texnum], abs(gl_sidedef->overlays[which].scaley));
INT32 repeats;
if (gl_sidedef->flags & GET_SIDEFLAG_EDGEWRAP(which))
{
fixed_t high, low;
if (backsector)
{
if (IS_TOP_EDGE_TEXTURE(which))
{
high = max(
P_GetSectorCeilingZAt(gl_frontsector, gl_curline->v1->x, gl_curline->v1->y),
P_GetSectorCeilingZAt(gl_frontsector, gl_curline->v2->x, gl_curline->v2->y)
);
low = min(
P_GetSectorCeilingZAt(gl_backsector, gl_curline->v1->x, gl_curline->v1->y),
P_GetSectorCeilingZAt(gl_backsector, gl_curline->v2->x, gl_curline->v2->y)
);
}
else
{
high = max(
P_GetSectorFloorZAt(gl_frontsector, gl_curline->v1->x, gl_curline->v1->y),
P_GetSectorFloorZAt(gl_frontsector, gl_curline->v2->x, gl_curline->v2->y)
);
low = min(
P_GetSectorFloorZAt(gl_backsector, gl_curline->v1->x, gl_curline->v1->y),
P_GetSectorFloorZAt(gl_backsector, gl_curline->v2->x, gl_curline->v2->y)
);
}
}
else
{
high = max(
P_GetSectorCeilingZAt(gl_frontsector, gl_curline->v1->x, gl_curline->v1->y),
P_GetSectorCeilingZAt(gl_frontsector, gl_curline->v2->x, gl_curline->v2->y)
);
low = min(
P_GetSectorFloorZAt(gl_backsector, gl_curline->v1->x, gl_curline->v1->y),
P_GetSectorFloorZAt(gl_backsector, gl_curline->v2->x, gl_curline->v2->y)
);
}
repeats = (high - low) / texheight;
if ((high - low) % texheight)
repeats++; // tile an extra time to fill the gap -- Monster Iestyn
}
else
repeats = 1;
GLMapTexture_t *grTex = HWR_GetTexture(texnum);
float xscale = FixedToFloat(gl_sidedef->overlays[which].scalex);
float yscale = FixedToFloat(gl_sidedef->overlays[which].scaley);
float xcliplow = (float)texturehpeg;
float xcliphigh = (float)(texturehpeg + (gl_curline->flength*FRACUNIT));
float xclipoffset = 0.0f;
fixed_t polytop, polybottom;
fixed_t polytopslope, polybottomslope;
// Find the wall's coordinates
fixed_t midtexheight = texheight * repeats;
HWR_GetExtraTextureCoords(which, &polytop, &polybottom, &polytopslope, &polybottomslope, worldtop, worldbottom, worldhigh, worldlow, worldtopslope, worldbottomslope, worldhighslope, worldlowslope, midtexheight);
// Find where to cut it
fixed_t lowcut, highcut;
fixed_t lowcutslope, highcutslope;
if (IS_TOP_EDGE_TEXTURE(which))
{
lowcut = worldhigh;
highcut = worldtop;
lowcutslope = worldhighslope;
highcutslope = worldtopslope;
}
else
{
lowcut = worldbottom;
highcut = worldlow;
lowcutslope = worldbottomslope;
highcutslope = worldlowslope;
}
// Time to render the wall (or so you thought)
fixed_t h = polytop;
fixed_t l = polybottom;
fixed_t hS = polytopslope;
fixed_t lS = polybottomslope;
memcpy(wallVerts, inWallVerts, sizeof(wallVerts));
// If this edge extends over a wall that is sloped, it needs to be split
if (h > highcut || hS > highcutslope || l < lowcut || lS < lowcutslope)
{
float polypos = 0.0f;
float polyslope = 0.0f;
float cutf = 0.0f;
float cutslopef = 0.0f;
float t = 1.0f;
UINT8 clipside = 0;
boolean clip_low = false;
if (hS > highcutslope || h > highcut // If the top of the texture is above the top of the wall
|| hS < lowcutslope || h < lowcut) // If the top of the texture is under the bottom of the wall
{
polypos = FixedToFloat(h);
polyslope = FixedToFloat(hS);
if (hS > highcutslope)
{
clipside = 1;
}
else if (hS < lowcutslope)
{
clip_low = true;
clipside = 1;
}
else if (h > highcut)
{
clipside = 2;
}
else if (h < lowcut)
{
clip_low = true;
clipside = 2;
}
if (clip_low)
{
cutf = FixedToFloat(lowcut);
cutslopef = FixedToFloat(lowcutslope);
}
else
{
cutf = FixedToFloat(highcut);
cutslopef = FixedToFloat(highcutslope);
}
}
else if (lS > highcutslope || l > highcut // If the bottom of the texture is under the top of the wall
|| lS < lowcutslope || l < lowcut) // If the bottom of the texture is under the bottom of the wall
{
polypos = FixedToFloat(l);
polyslope = FixedToFloat(lS);
if (lS > highcutslope)
{
clipside = 1;
}
else if (lS < lowcutslope)
{
clip_low = true;
clipside = 1;
}
else if (l > highcut)
{
clipside = 2;
}
else if (l < lowcut)
{
clip_low = true;
clipside = 2;
}
if (clip_low)
{
cutf = FixedToFloat(lowcut);
cutslopef = FixedToFloat(lowcutslope);
}
else
{
cutf = FixedToFloat(highcut);
cutslopef = FixedToFloat(highcutslope);
}
}
// See if it intersects
if (clipside != 0)
{
float polydiff = polyslope - polypos;
float cutdiff = cutslopef - cutf;
t = (polypos - cutf) / (-polydiff + cutdiff);
if (t >= 0.0 && t <= 1.0)
intersected = clipside;
}
// If it did, split the wall
if (intersected)
{
v1x = FloatToFixed(vs.x);
v1y = FloatToFixed(vs.y);
v2x = FloatToFixed(ve.x);
v2y = FloatToFixed(ve.y);
ptx = vs.x + (ve.x - vs.x)*t;
pty = vs.y + (ve.y - vs.y)*t;
// Right side
if (intersected == 1)
{
v2x = FloatToFixed(ptx);
v2y = FloatToFixed(pty);
wallVerts[2].x = wallVerts[1].x = ptx;
wallVerts[2].z = wallVerts[1].z = pty;
xclipoffset = gl_curline->flength * t * FRACUNIT;
xcliphigh = (float)(texturehpeg + xclipoffset);
}
// Left side
else if (intersected == 2)
{
ptx = vs.x + (ve.x - vs.x)*t;
pty = vs.y + (ve.y - vs.y)*t;
v1x = FloatToFixed(ptx);
v1y = FloatToFixed(pty);
wallVerts[0].x = wallVerts[3].x = ptx;
wallVerts[0].z = wallVerts[3].z = pty;
xcliplow = (float)(xcliphigh - (gl_curline->flength*(1.0-t)*FRACUNIT));
}
// Get new coordinates based on this split
cliptop = P_GetSectorCeilingZAt(gl_frontsector, v1x, v1y);
cliptopslope = P_GetSectorCeilingZAt(gl_frontsector, v2x, v2y);
clipbottom = P_GetSectorFloorZAt(gl_frontsector, v1x, v1y);
clipbottomslope = P_GetSectorFloorZAt(gl_frontsector, v2x, v2y);
cliphigh = P_GetSectorCeilingZAt(back, v1x, v1y);
cliphighslope = P_GetSectorCeilingZAt(back, v2x, v2y);
cliplow = P_GetSectorFloorZAt(back, v1x, v1y);
cliplowslope = P_GetSectorFloorZAt(back, v2x, v2y);
HWR_GetExtraTextureCoords(which, &polytop, &polybottom, &polytopslope, &polybottomslope, cliptop, clipbottom, cliphigh, cliplow, cliptopslope, clipbottomslope, cliphighslope, cliplowslope, midtexheight);
h = polytop;
l = polybottom;
hS = polytopslope;
lS = polybottomslope;
}
// If it didn't intersect, render it normally
else
{
h = min(highcut, h);
l = max(l, lowcut);
hS = min(highcutslope, hS);
lS = max(lS, lowcutslope);
}
}
// PEGGING
fixed_t texturevpeg, texturevpegslope;
if (IS_UPPER_EDGE_TEXTURE(which))
{
texturevpeg = midtexheight - h + polybottom;
texturevpegslope = midtexheight - hS + polybottomslope;
}
else
{
texturevpeg = polytop - h;
texturevpegslope = polytopslope - hS;
}
// Left side
wallVerts[3].t = texturevpeg * yscale * grTex->scaleY;
wallVerts[0].t = (h - l + texturevpeg) * yscale * grTex->scaleY;
wallVerts[0].s = wallVerts[3].s = ((xcliplow * xscale) + gl_sidedef->overlays[which].offsetx) * grTex->scaleX;
// Right side
wallVerts[2].t = texturevpegslope * yscale * grTex->scaleY;
wallVerts[1].t = (hS - lS + texturevpegslope) * yscale * grTex->scaleY;
wallVerts[2].s = wallVerts[1].s = ((xcliphigh * xscale) + gl_sidedef->overlays[which].offsetx) * grTex->scaleX;
// set top/bottom coords
// Take the texture peg into account, rather than changing the offsets past
// where the polygon might not be.
wallVerts[3].y = FIXED_TO_FLOAT(h);
wallVerts[0].y = FIXED_TO_FLOAT(l);
wallVerts[2].y = FIXED_TO_FLOAT(hS);
wallVerts[1].y = FIXED_TO_FLOAT(lS);
// TODO: Actually use the surface's flags so that I don't have to do this
FUINT blendmode = Surf.PolyFlags | PF_Decal;
extracolormap_t *colormap = gl_frontsector->extra_colormap;
if (gl_frontsector->numlights)
HWR_SplitWall(gl_frontsector, wallVerts, texnum, &Surf, FOF_CUTLEVEL, NULL, blendmode);
else
HWR_ProjectWall(wallVerts, &Surf, blendmode, lightnum, colormap);
// Wall wasn't split, stop here
if (!intersected)
return;
// Draw the rest of the wall if it was split
float fv1x, fv1y, fv2x, fv2y;
float flength;
// Right side
if (intersected == 1)
{
fv1x = ptx;
fv1y = pty;
fv2x = ve.x;
fv2y = ve.y;
}
// Left side
else
{
fv1x = vs.x;
fv1y = vs.y;
fv2x = ptx;
fv2y = pty;
}
v1x = FloatToFixed(fv1x);
v1y = FloatToFixed(fv1y);
v2x = FloatToFixed(fv2x);
v2y = FloatToFixed(fv2y);
wallVerts[0].x = wallVerts[3].x = fv1x;
wallVerts[0].z = wallVerts[3].z = fv1y;
wallVerts[2].x = wallVerts[1].x = fv2x;
wallVerts[2].z = wallVerts[1].z = fv2y;
flength = hypotf(fv2x - fv1x, fv2y - fv1y);
xcliplow = (float)texturehpeg + xclipoffset;
xcliphigh = xcliplow + (flength * FRACUNIT);
cliptop = P_GetSectorCeilingZAt(gl_frontsector, v1x, v1y);
cliptopslope = P_GetSectorCeilingZAt(gl_frontsector, v2x, v2y);
clipbottom = P_GetSectorFloorZAt(gl_frontsector, v1x, v1y);
clipbottomslope = P_GetSectorFloorZAt(gl_frontsector, v2x, v2y);
cliphigh = P_GetSectorCeilingZAt(back, v1x, v1y);
cliphighslope = P_GetSectorCeilingZAt(back, v2x, v2y);
cliplow = P_GetSectorFloorZAt(back, v1x, v1y);
cliplowslope = P_GetSectorFloorZAt(back, v2x, v2y);
HWR_GetExtraTextureCoords(which, &polytop, &polybottom, &polytopslope, &polybottomslope, cliptop, clipbottom, cliphigh, cliplow, cliptopslope, clipbottomslope, cliphighslope, cliplowslope, midtexheight);
h = min(highcut, polytop);
l = max(polybottom, lowcut);
hS = min(highcutslope, polytopslope);
lS = max(polybottomslope, lowcutslope);
#if 0
if (l > highcut)
l = highcut;
if (lS > highcutslope)
lS = highcutslope;
#endif
wallVerts[3].y = FixedToFloat(h);
wallVerts[0].y = FixedToFloat(l);
wallVerts[2].y = FixedToFloat(hS);
wallVerts[1].y = FixedToFloat(lS);
if (IS_UPPER_EDGE_TEXTURE(which))
{
texturevpeg = midtexheight - h + polybottom;
texturevpegslope = midtexheight - hS + polybottomslope;
}
else
{
texturevpeg = polytop - h;
texturevpegslope = polytopslope - hS;
}
// Left side
wallVerts[3].t = texturevpeg * yscale * grTex->scaleY;
wallVerts[0].t = (h - l + texturevpeg) * yscale * grTex->scaleY;
wallVerts[0].s = wallVerts[3].s = ((xcliplow * xscale) + gl_sidedef->overlays[which].offsetx) * grTex->scaleX;
// Right side
wallVerts[2].t = texturevpegslope * yscale * grTex->scaleY;
wallVerts[1].t = (hS - lS + texturevpegslope) * yscale * grTex->scaleY;
wallVerts[2].s = wallVerts[1].s = ((xcliphigh * xscale) + gl_sidedef->overlays[which].offsetx) * grTex->scaleX;
if (gl_frontsector->numlights)
HWR_SplitWall(gl_frontsector, wallVerts, texnum, &Surf, FOF_CUTLEVEL, NULL, blendmode);
else
HWR_ProjectWall(wallVerts, &Surf, blendmode, lightnum, colormap);
}
// //
// HWR_ProcessSeg // HWR_ProcessSeg
// A portion or all of a wall segment will be drawn, from startfrac to endfrac, // A portion or all of a wall segment will be drawn, from startfrac to endfrac,
@ -1125,7 +1823,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
float cliplow = (float)texturehpeg; float cliplow = (float)texturehpeg;
float cliphigh = (float)(texturehpeg + (gl_curline->flength*FRACUNIT)); float cliphigh = (float)(texturehpeg + (gl_curline->flength*FRACUNIT));
FUINT lightnum = HWR_CalcWallLight(gl_frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y); UINT32 lightnum = HWR_CalcWallLight(gl_frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y);
extracolormap_t *colormap = gl_frontsector->extra_colormap; extracolormap_t *colormap = gl_frontsector->extra_colormap;
FSurfaceInfo Surf; FSurfaceInfo Surf;
@ -1336,191 +2034,13 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap); HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap);
} }
// Render midtexture if there's one. Determine if it's visible first, though // Render midtexture if there's one
if (gl_midtexture && HWR_BlendMidtextureSurface(&Surf)) if (gl_midtexture)
{ HWR_RenderMidtexture(gl_midtexture, cliplow, cliphigh, worldtop, worldbottom, worldhigh, worldlow, worldtopslope, worldbottomslope, worldhighslope, worldlowslope, lightnum, wallVerts);
sector_t *front, *back;
fixed_t texheight = FixedDiv(textureheight[gl_midtexture], abs(gl_sidedef->scaley_mid));
INT32 repeats;
if (gl_linedef->frontsector->heightsec != -1) // Render extra textures
front = &sectors[gl_linedef->frontsector->heightsec]; for (unsigned i = 0; i < NUM_WALL_OVERLAYS; i++)
else HWR_RenderExtraTexture(i, vs, ve, texturehpeg, worldtop, worldbottom, worldhigh, worldlow, worldtopslope, worldbottomslope, worldhighslope, worldlowslope, lightnum, wallVerts);
front = gl_linedef->frontsector;
if (gl_linedef->backsector->heightsec != -1)
back = &sectors[gl_linedef->backsector->heightsec];
else
back = gl_linedef->backsector;
if (gl_sidedef->repeatcnt)
repeats = 1 + gl_sidedef->repeatcnt;
else if (gl_linedef->flags & ML_WRAPMIDTEX)
{
fixed_t high, low;
if (front->ceilingheight > back->ceilingheight)
high = back->ceilingheight;
else
high = front->ceilingheight;
if (front->floorheight > back->floorheight)
low = front->floorheight;
else
low = back->floorheight;
repeats = (high - low) / texheight;
if ((high - low) % texheight)
repeats++; // tile an extra time to fill the gap -- Monster Iestyn
}
else
repeats = 1;
grTex = HWR_GetTexture(gl_midtexture);
xscale = FixedToFloat(gl_sidedef->scalex_mid);
yscale = FixedToFloat(gl_sidedef->scaley_mid);
// SoM: a little note: popentop and popenbottom
// record the limits the texture can be displayed in.
// polytop and polybottom, are the ideal (i.e. unclipped)
// heights of the polygon, and h & l, are the final (clipped)
// poly coords.
fixed_t popentop, popenbottom, polytop, polybottom, lowcut, highcut;
fixed_t popentopslope, popenbottomslope, polytopslope, polybottomslope, lowcutslope, highcutslope;
// NOTE: With polyobjects, whenever you need to check the properties of the polyobject sector it belongs to,
// you must use the linedef's backsector to be correct
// From CB
if (gl_curline->polyseg)
{
popentop = popentopslope = back->ceilingheight;
popenbottom = popenbottomslope = back->floorheight;
}
else
{
popentop = min(worldtop, worldhigh);
popenbottom = max(worldbottom, worldlow);
popentopslope = min(worldtopslope, worldhighslope);
popenbottomslope = max(worldbottomslope, worldlowslope);
}
// Find the wall's coordinates
fixed_t midtexheight = texheight * repeats;
fixed_t rowoffset = FixedDiv(gl_sidedef->rowoffset + gl_sidedef->offsety_mid, abs(gl_sidedef->scaley_mid));
// Texture is not skewed
if (gl_linedef->flags & ML_NOSKEW)
{
// Peg it to the floor
if (gl_linedef->flags & ML_MIDPEG)
{
polybottom = max(front->floorheight, back->floorheight) + rowoffset;
polytop = polybottom + midtexheight;
}
// Peg it to the ceiling
else
{
polytop = min(front->ceilingheight, back->ceilingheight) + rowoffset;
polybottom = polytop - midtexheight;
}
// The right side's coordinates are the the same as the left side
polytopslope = polytop;
polybottomslope = polybottom;
}
// Skew the texture, but peg it to the floor
else if (gl_linedef->flags & ML_MIDPEG)
{
polybottom = popenbottom + rowoffset;
polytop = polybottom + midtexheight;
polybottomslope = popenbottomslope + rowoffset;
polytopslope = polybottomslope + midtexheight;
}
// Skew it according to the ceiling's slope
else
{
polytop = popentop + rowoffset;
polybottom = polytop - midtexheight;
polytopslope = popentopslope + rowoffset;
polybottomslope = polytopslope - midtexheight;
}
// CB
// NOTE: With polyobjects, whenever you need to check the properties of the polyobject sector it belongs to,
// you must use the linedef's backsector to be correct
if (gl_curline->polyseg)
{
lowcut = polybottom;
highcut = polytop;
lowcutslope = polybottomslope;
highcutslope = polytopslope;
}
else
{
// The cut-off values of a linedef can always be constant, since every line has an absoulute front and or back sector
lowcut = popenbottom;
highcut = popentop;
lowcutslope = popenbottomslope;
highcutslope = popentopslope;
}
h = min(highcut, polytop);
l = max(polybottom, lowcut);
hS = min(highcutslope, polytopslope);
lS = max(polybottomslope, lowcutslope);
// PEGGING
fixed_t texturevpegslope;
if (gl_linedef->flags & ML_MIDPEG)
{
texturevpeg = midtexheight - h + polybottom;
texturevpegslope = midtexheight - hS + polybottomslope;
}
else
{
texturevpeg = polytop - h;
texturevpegslope = polytopslope - hS;
}
// Left side
wallVerts[3].t = texturevpeg * yscale * grTex->scaleY;
wallVerts[0].t = (h - l + texturevpeg) * yscale * grTex->scaleY;
wallVerts[0].s = wallVerts[3].s = ((cliplow * xscale) + gl_sidedef->offsetx_mid) * grTex->scaleX;
// Right side
wallVerts[2].t = texturevpegslope * yscale * grTex->scaleY;
wallVerts[1].t = (hS - lS + texturevpegslope) * yscale * grTex->scaleY;
wallVerts[2].s = wallVerts[1].s = ((cliphigh * xscale) + gl_sidedef->offsetx_mid) * grTex->scaleX;
// set top/bottom coords
// Take the texture peg into account, rather than changing the offsets past
// where the polygon might not be.
wallVerts[3].y = FIXED_TO_FLOAT(h);
wallVerts[0].y = FIXED_TO_FLOAT(l);
wallVerts[2].y = FIXED_TO_FLOAT(hS);
wallVerts[1].y = FIXED_TO_FLOAT(lS);
// TODO: Actually use the surface's flags so that I don't have to do this
FUINT blendmode = Surf.PolyFlags;
// Render midtextures on two-sided lines with a z-buffer offset.
// This will cause the midtexture appear on top, if a FOF overlaps with it.
blendmode |= PF_Decal;
if (gl_frontsector->numlights)
{
if (!(blendmode & PF_Masked))
HWR_SplitWall(gl_frontsector, wallVerts, gl_midtexture, &Surf, FOF_TRANSLUCENT, NULL, blendmode);
else
HWR_SplitWall(gl_frontsector, wallVerts, gl_midtexture, &Surf, FOF_CUTLEVEL, NULL, blendmode);
}
else if (!(blendmode & PF_Masked))
HWR_AddTransparentWall(wallVerts, &Surf, gl_midtexture, blendmode, false, lightnum, colormap);
else
HWR_ProjectWall(wallVerts, &Surf, blendmode, lightnum, colormap);
}
// Sky culling // Sky culling
// No longer so much a mess as before! // No longer so much a mess as before!
@ -1604,6 +2124,10 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
} }
} }
// Render extra textures
for (unsigned i = 0; i < NUM_WALL_OVERLAYS; i++)
HWR_RenderExtraTexture(i, vs, ve, texturehpeg, worldtop, worldbottom, worldtop, worldbottom, worldtopslope, worldbottomslope, worldtopslope, worldbottomslope, lightnum, wallVerts);
if (!gl_curline->polyseg) if (!gl_curline->polyseg)
{ {
if (gl_frontsector->ceilingpic == skyflatnum) // It's a single-sided line with sky for its sector if (gl_frontsector->ceilingpic == skyflatnum) // It's a single-sided line with sky for its sector
@ -3803,7 +4327,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
patch_t *gpatch; patch_t *gpatch;
FSurfaceInfo Surf; FSurfaceInfo Surf;
extracolormap_t *colormap = NULL; extracolormap_t *colormap = NULL;
FUINT lightlevel; UINT32 lightlevel;
boolean lightset = true; boolean lightset = true;
FBITFIELD blend = 0; FBITFIELD blend = 0;
FBITFIELD occlusion; FBITFIELD occlusion;