Support spritexscale and spriteyscale in OpenGL

Fix papersprite scaling with spritexscale and spriteyscale in Software
This commit is contained in:
Jaime Passos 2020-10-12 17:25:18 -03:00
parent cc97e22e2f
commit b620f4835a
4 changed files with 56 additions and 50 deletions

View file

@ -62,7 +62,8 @@ typedef struct
typedef struct gl_vissprite_s typedef struct gl_vissprite_s
{ {
float x1, x2; float x1, x2;
float tz, ty; float gz, gzt;
float tz;
float tracertz; // for MF2_LINKDRAW sprites, this contains tracer's tz for use in sorting float tracertz; // for MF2_LINKDRAW sprites, this contains tracer's tz for use in sorting
patch_t *gpatch; patch_t *gpatch;
boolean flip; boolean flip;

View file

@ -3605,17 +3605,17 @@ static void HWR_RotateSpritePolyToAim(gl_vissprite_t *spr, FOutVector *wallVerts
// X, Y, AND Z need to be manipulated for the polys to rotate around the // X, Y, AND Z need to be manipulated for the polys to rotate around the
// origin, because of how the origin setting works I believe that should // origin, because of how the origin setting works I believe that should
// be mobj->z or mobj->z + mobj->height // be mobj->z or mobj->z + mobj->height
wallVerts[2].y = wallVerts[3].y = (spr->ty - basey) * gl_viewludsin + basey; wallVerts[2].y = wallVerts[3].y = (spr->gzt - basey) * gl_viewludsin + basey;
wallVerts[0].y = wallVerts[1].y = (lowy - basey) * gl_viewludsin + basey; wallVerts[0].y = wallVerts[1].y = (lowy - basey) * gl_viewludsin + basey;
// translate back to be around 0 before translating back // translate back to be around 0 before translating back
wallVerts[3].x += ((spr->ty - basey) * gl_viewludcos) * gl_viewcos; wallVerts[3].x += ((spr->gzt - basey) * gl_viewludcos) * gl_viewcos;
wallVerts[2].x += ((spr->ty - basey) * gl_viewludcos) * gl_viewcos; wallVerts[2].x += ((spr->gzt - basey) * gl_viewludcos) * gl_viewcos;
wallVerts[0].x += ((lowy - basey) * gl_viewludcos) * gl_viewcos; wallVerts[0].x += ((lowy - basey) * gl_viewludcos) * gl_viewcos;
wallVerts[1].x += ((lowy - basey) * gl_viewludcos) * gl_viewcos; wallVerts[1].x += ((lowy - basey) * gl_viewludcos) * gl_viewcos;
wallVerts[3].z += ((spr->ty - basey) * gl_viewludcos) * gl_viewsin; wallVerts[3].z += ((spr->gzt - basey) * gl_viewludcos) * gl_viewsin;
wallVerts[2].z += ((spr->ty - basey) * gl_viewludcos) * gl_viewsin; wallVerts[2].z += ((spr->gzt - basey) * gl_viewludcos) * gl_viewsin;
wallVerts[0].z += ((lowy - basey) * gl_viewludcos) * gl_viewsin; wallVerts[0].z += ((lowy - basey) * gl_viewludcos) * gl_viewsin;
wallVerts[1].z += ((lowy - basey) * gl_viewludcos) * gl_viewsin; wallVerts[1].z += ((lowy - basey) * gl_viewludcos) * gl_viewsin;
@ -3624,14 +3624,13 @@ static void HWR_RotateSpritePolyToAim(gl_vissprite_t *spr, FOutVector *wallVerts
static void HWR_SplitSprite(gl_vissprite_t *spr) static void HWR_SplitSprite(gl_vissprite_t *spr)
{ {
float this_scale = 1.0f;
FOutVector wallVerts[4]; FOutVector wallVerts[4];
FOutVector baseWallVerts[4]; // This is what the verts should end up as FOutVector baseWallVerts[4]; // This is what the verts should end up as
patch_t *gpatch; patch_t *gpatch;
FSurfaceInfo Surf; FSurfaceInfo Surf;
const boolean hires = (spr->mobj && spr->mobj->skin && ((skin_t *)spr->mobj->skin)->flags & SF_HIRES);
extracolormap_t *colormap; extracolormap_t *colormap;
FUINT lightlevel; FUINT lightlevel;
boolean lightset = true;
FBITFIELD blend = 0; FBITFIELD blend = 0;
FBITFIELD occlusion; FBITFIELD occlusion;
boolean use_linkdraw_hack = false; boolean use_linkdraw_hack = false;
@ -3650,11 +3649,6 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
fixed_t temp; fixed_t temp;
fixed_t v1x, v1y, v2x, v2y; fixed_t v1x, v1y, v2x, v2y;
this_scale = FIXED_TO_FLOAT(spr->mobj->scale);
if (hires)
this_scale = this_scale * FIXED_TO_FLOAT(((skin_t *)spr->mobj->skin)->highresscale);
gpatch = spr->gpatch; gpatch = spr->gpatch;
// cache the patch in the graphics card memory // cache the patch in the graphics card memory
@ -3667,11 +3661,8 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
baseWallVerts[0].z = baseWallVerts[3].z = spr->z1; baseWallVerts[0].z = baseWallVerts[3].z = spr->z1;
baseWallVerts[1].z = baseWallVerts[2].z = spr->z2; baseWallVerts[1].z = baseWallVerts[2].z = spr->z2;
baseWallVerts[2].y = baseWallVerts[3].y = spr->ty; baseWallVerts[2].y = baseWallVerts[3].y = spr->gzt;
if (spr->mobj && fabsf(this_scale - 1.0f) > 1.0E-36f) baseWallVerts[0].y = baseWallVerts[1].y = spr->gz;
baseWallVerts[0].y = baseWallVerts[1].y = spr->ty - gpatch->height * this_scale;
else
baseWallVerts[0].y = baseWallVerts[1].y = spr->ty - gpatch->height;
v1x = FLOAT_TO_FIXED(spr->x1); v1x = FLOAT_TO_FIXED(spr->x1);
v1y = FLOAT_TO_FIXED(spr->z1); v1y = FLOAT_TO_FIXED(spr->z1);
@ -3767,15 +3758,19 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
i = 0; i = 0;
temp = FLOAT_TO_FIXED(realtop); temp = FLOAT_TO_FIXED(realtop);
if (spr->mobj->frame & FF_FULLBRIGHT) if (R_ThingIsFullBright(spr->mobj))
lightlevel = 255; lightlevel = 255;
else if (R_ThingIsFullDark(spr->mobj))
lightlevel = 0;
else
lightset = false;
for (i = 1; i < sector->numlights; i++) for (i = 1; i < sector->numlights; i++)
{ {
fixed_t h = P_GetLightZAt(&sector->lightlist[i], spr->mobj->x, spr->mobj->y); fixed_t h = P_GetLightZAt(&sector->lightlist[i], spr->mobj->x, spr->mobj->y);
if (h <= temp) if (h <= temp)
{ {
if (!(spr->mobj->frame & FF_FULLBRIGHT)) if (!lightset)
lightlevel = *list[i-1].lightlevel > 255 ? 255 : *list[i-1].lightlevel; lightlevel = *list[i-1].lightlevel > 255 ? 255 : *list[i-1].lightlevel;
colormap = *list[i-1].extra_colormap; colormap = *list[i-1].extra_colormap;
break; break;
@ -3790,7 +3785,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
// even if we aren't changing colormap or lightlevel, we still need to continue drawing down the sprite // even if we aren't changing colormap or lightlevel, we still need to continue drawing down the sprite
if (!(list[i].flags & FF_NOSHADE) && (list[i].flags & FF_CUTSPRITES)) if (!(list[i].flags & FF_NOSHADE) && (list[i].flags & FF_CUTSPRITES))
{ {
if (!(spr->mobj->frame & FF_FULLBRIGHT)) if (!lightset)
lightlevel = *list[i].lightlevel > 255 ? 255 : *list[i].lightlevel; lightlevel = *list[i].lightlevel > 255 ? 255 : *list[i].lightlevel;
colormap = *list[i].extra_colormap; colormap = *list[i].extra_colormap;
} }
@ -3901,16 +3896,10 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
// -----------------+ // -----------------+
static void HWR_DrawSprite(gl_vissprite_t *spr) static void HWR_DrawSprite(gl_vissprite_t *spr)
{ {
float this_scale = 1.0f;
FOutVector wallVerts[4]; FOutVector wallVerts[4];
patch_t *gpatch; // sprite patch converted to hardware patch_t *gpatch; // sprite patch converted to hardware
FSurfaceInfo Surf; FSurfaceInfo Surf;
const boolean hires = (spr->mobj && spr->mobj->skin && ((skin_t *)spr->mobj->skin)->flags & SF_HIRES);
//const boolean papersprite = R_ThingIsPaperSprite(spr->mobj); //const boolean papersprite = R_ThingIsPaperSprite(spr->mobj);
if (spr->mobj)
this_scale = FIXED_TO_FLOAT(spr->mobj->scale);
if (hires)
this_scale = this_scale * FIXED_TO_FLOAT(((skin_t *)spr->mobj->skin)->highresscale);
if (!spr->mobj) if (!spr->mobj)
return; return;
@ -3948,11 +3937,8 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
// these were already scaled in HWR_ProjectSprite // these were already scaled in HWR_ProjectSprite
wallVerts[0].x = wallVerts[3].x = spr->x1; wallVerts[0].x = wallVerts[3].x = spr->x1;
wallVerts[2].x = wallVerts[1].x = spr->x2; wallVerts[2].x = wallVerts[1].x = spr->x2;
wallVerts[2].y = wallVerts[3].y = spr->ty; wallVerts[2].y = wallVerts[3].y = spr->gzt;
if (spr->mobj && fabsf(this_scale - 1.0f) > 1.0E-36f) wallVerts[0].y = wallVerts[1].y = spr->gz;
wallVerts[0].y = wallVerts[1].y = spr->ty - gpatch->height * this_scale;
else
wallVerts[0].y = wallVerts[1].y = spr->ty - gpatch->height;
// make a wall polygon (with 2 triangles), using the floor/ceiling heights, // make a wall polygon (with 2 triangles), using the floor/ceiling heights,
// and the 2d map coords of start/end vertices // and the 2d map coords of start/end vertices
@ -4003,10 +3989,14 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
// colormap test // colormap test
{ {
sector_t *sector = spr->mobj->subsector->sector; sector_t *sector = spr->mobj->subsector->sector;
UINT8 lightlevel = 255; UINT8 lightlevel;
extracolormap_t *colormap = sector->extra_colormap; extracolormap_t *colormap = sector->extra_colormap;
if (!(spr->mobj->frame & FF_FULLBRIGHT)) if (R_ThingIsFullBright(spr->mobj))
lightlevel = 255;
else if (R_ThingIsFullDark(spr->mobj))
lightlevel = 0;
else
lightlevel = sector->lightlevel > 255 ? 255 : sector->lightlevel; lightlevel = sector->lightlevel > 255 ? 255 : sector->lightlevel;
HWR_Lighting(&Surf, lightlevel, colormap); HWR_Lighting(&Surf, lightlevel, colormap);
@ -4081,8 +4071,8 @@ static inline void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr)
// 0--1 // 0--1
wallVerts[0].x = wallVerts[3].x = spr->x1; wallVerts[0].x = wallVerts[3].x = spr->x1;
wallVerts[2].x = wallVerts[1].x = spr->x2; wallVerts[2].x = wallVerts[1].x = spr->x2;
wallVerts[2].y = wallVerts[3].y = spr->ty; wallVerts[2].y = wallVerts[3].y = spr->gzt;
wallVerts[0].y = wallVerts[1].y = spr->ty - gpatch->height; wallVerts[0].y = wallVerts[1].y = spr->gz;
// make a wall polygon (with 2 triangles), using the floor/ceiling heights, // make a wall polygon (with 2 triangles), using the floor/ceiling heights,
// and the 2d map coords of start/end vertices // and the 2d map coords of start/end vertices
@ -4680,6 +4670,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
float x1, x2; float x1, x2;
float rightsin, rightcos; float rightsin, rightcos;
float this_scale; float this_scale;
float spritexscale, spriteyscale;
float gz, gzt; float gz, gzt;
spritedef_t *sprdef; spritedef_t *sprdef;
spriteframe_t *sprframe; spriteframe_t *sprframe;
@ -4714,6 +4705,8 @@ static void HWR_ProjectSprite(mobj_t *thing)
dispoffset = thing->info->dispoffset; dispoffset = thing->info->dispoffset;
this_scale = FIXED_TO_FLOAT(thing->scale); this_scale = FIXED_TO_FLOAT(thing->scale);
spritexscale = FIXED_TO_FLOAT(thing->spritexscale);
spriteyscale = FIXED_TO_FLOAT(thing->spriteyscale);
// transform the origin point // transform the origin point
tr_x = FIXED_TO_FLOAT(thing->x) - gl_viewx; tr_x = FIXED_TO_FLOAT(thing->x) - gl_viewx;
@ -4867,15 +4860,18 @@ static void HWR_ProjectSprite(mobj_t *thing)
flip = !flip != !hflip; flip = !flip != !hflip;
spritexscale *= this_scale;
spriteyscale *= this_scale;
if (flip) if (flip)
{ {
x1 = (FIXED_TO_FLOAT(spr_width - spr_offset) * this_scale); x1 = (FIXED_TO_FLOAT(spr_width - spr_offset) * spritexscale);
x2 = (FIXED_TO_FLOAT(spr_offset) * this_scale); x2 = (FIXED_TO_FLOAT(spr_offset) * spritexscale);
} }
else else
{ {
x1 = (FIXED_TO_FLOAT(spr_offset) * this_scale); x1 = (FIXED_TO_FLOAT(spr_offset) * spritexscale);
x2 = (FIXED_TO_FLOAT(spr_width - spr_offset) * this_scale); x2 = (FIXED_TO_FLOAT(spr_width - spr_offset) * spritexscale);
} }
// test if too close // test if too close
@ -4897,13 +4893,13 @@ static void HWR_ProjectSprite(mobj_t *thing)
if (vflip) if (vflip)
{ {
gz = FIXED_TO_FLOAT(thing->z+thing->height) - FIXED_TO_FLOAT(spr_topoffset) * this_scale; gz = FIXED_TO_FLOAT(thing->z+thing->height) - (FIXED_TO_FLOAT(spr_topoffset) * spriteyscale);
gzt = gz + FIXED_TO_FLOAT(spr_height) * this_scale; gzt = gz + (FIXED_TO_FLOAT(spr_height) * spriteyscale);
} }
else else
{ {
gzt = FIXED_TO_FLOAT(thing->z) + FIXED_TO_FLOAT(spr_topoffset) * this_scale; gzt = FIXED_TO_FLOAT(thing->z) + (FIXED_TO_FLOAT(spr_topoffset) * spriteyscale);
gz = gzt - FIXED_TO_FLOAT(spr_height) * this_scale; gz = gzt - (FIXED_TO_FLOAT(spr_height) * spriteyscale);
} }
if (thing->subsector->sector->cullheight) if (thing->subsector->sector->cullheight)
@ -5010,7 +5006,8 @@ static void HWR_ProjectSprite(mobj_t *thing)
vis->colormap = colormaps; vis->colormap = colormaps;
// set top/bottom coords // set top/bottom coords
vis->ty = gzt; vis->gzt = gzt;
vis->gz = gz;
//CONS_Debug(DBG_RENDER, "------------------\nH: sprite : %d\nH: frame : %x\nH: type : %d\nH: sname : %s\n\n", //CONS_Debug(DBG_RENDER, "------------------\nH: sprite : %d\nH: frame : %x\nH: type : %d\nH: sname : %s\n\n",
// thing->sprite, thing->frame, thing->type, sprnames[thing->sprite]); // thing->sprite, thing->frame, thing->type, sprnames[thing->sprite]);
@ -5110,7 +5107,8 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing)
vis->colormap = colormaps; vis->colormap = colormaps;
// set top/bottom coords // set top/bottom coords
vis->ty = FIXED_TO_FLOAT(thing->z + spritecachedinfo[lumpoff].topoffset); vis->gzt = FIXED_TO_FLOAT(thing->z + spritecachedinfo[lumpoff].topoffset);
vis->gz = vis->gzt - FIXED_TO_FLOAT(spritecachedinfo[lumpoff].height);
vis->precip = true; vis->precip = true;

View file

@ -923,13 +923,16 @@ static void R_DrawVisSprite(vissprite_t *vis)
// Split drawing loops for paper and non-paper to reduce conditional checks per sprite // Split drawing loops for paper and non-paper to reduce conditional checks per sprite
if (vis->scalestep) if (vis->scalestep)
{ {
fixed_t horzscale = FixedMul(vis->spritexscale, this_scale);
fixed_t scalestep = FixedMul(vis->scalestep, vis->spriteyscale);
pwidth = SHORT(patch->width); pwidth = SHORT(patch->width);
// Papersprite drawing loop // Papersprite drawing loop
for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, spryscale += vis->scalestep) for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, spryscale += scalestep)
{ {
angle_t angle = ((vis->centerangle + xtoviewangle[dc_x]) >> ANGLETOFINESHIFT) & 0xFFF; angle_t angle = ((vis->centerangle + xtoviewangle[dc_x]) >> ANGLETOFINESHIFT) & 0xFFF;
texturecolumn = (vis->paperoffset - FixedMul(FINETANGENT(angle), vis->paperdistance)) / this_scale; texturecolumn = (vis->paperoffset - FixedMul(FINETANGENT(angle), vis->paperdistance)) / horzscale;
if (texturecolumn < 0 || texturecolumn >= pwidth) if (texturecolumn < 0 || texturecolumn >= pwidth)
continue; continue;
@ -1946,6 +1949,9 @@ static void R_ProjectSprite(mobj_t *thing)
vis->xscale = FixedMul(spritexscale, xscale); //SoM: 4/17/2000 vis->xscale = FixedMul(spritexscale, xscale); //SoM: 4/17/2000
vis->scale = FixedMul(spriteyscale, yscale); //<<detailshift; vis->scale = FixedMul(spriteyscale, yscale); //<<detailshift;
vis->spritexscale = spritexscale;
vis->spriteyscale = spriteyscale;
if (shadowdraw || shadoweffects) if (shadowdraw || shadoweffects)
{ {
iscale = (patch->width<<FRACBITS)/(x2-x1+1); // fuck it iscale = (patch->width<<FRACBITS)/(x2-x1+1); // fuck it
@ -1969,8 +1975,8 @@ static void R_ProjectSprite(mobj_t *thing)
if (vis->x1 > x1) if (vis->x1 > x1)
{ {
vis->startfrac += FixedDiv(vis->xiscale, this_scale)*(vis->x1-x1); vis->startfrac += FixedDiv(vis->xiscale, this_scale) * (vis->x1 - x1);
vis->scale += scalestep*(vis->x1 - x1); vis->scale += FixedMul(scalestep, spriteyscale) * (vis->x1 - x1);
} }
vis->patch = patch; vis->patch = patch;

View file

@ -192,6 +192,7 @@ typedef struct vissprite_s
UINT32 renderflags; UINT32 renderflags;
UINT8 rotateflags; UINT8 rotateflags;
fixed_t spritexscale, spriteyscale;
fixed_t shadowscale; fixed_t shadowscale;
INT16 clipbot[MAXVIDWIDTH], cliptop[MAXVIDWIDTH]; INT16 clipbot[MAXVIDWIDTH], cliptop[MAXVIDWIDTH];