- refactored rotatesprite to really use the 2D drawer.

Mostly working, except clipping and weapon sprites.
This commit is contained in:
Christoph Oelckers 2019-12-29 21:36:21 +01:00
parent b34f3637ab
commit 6459f4e532
9 changed files with 261 additions and 175 deletions

View file

@ -11,6 +11,7 @@
#ifndef palette_h_
#define palette_h_
#include "renderstyle.h"
#include "filesystem/filesystem.h"
#define MAXBASEPALS 256
@ -128,7 +129,10 @@ typedef struct glblend_
extern glblend_t const nullglblend, defaultglblend;
extern glblend_t glblend[MAXBLENDTABS];
FRenderStyle GetBlend(int blend, int def);
extern void handle_blend(uint8_t enable, uint8_t blend, uint8_t def);
float float_trans(uint32_t maskprops, uint8_t blend);
#endif
#endif

View file

@ -6700,109 +6700,6 @@ static int32_t clippoly4(int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2)
}
// INTERNAL helper function for classic/polymost dorotatesprite
// sxptr, sxptr, z: in/out
// ret_yxaspect, ret_xyaspect: out
void dorotspr_handle_bit2(int32_t *sxptr, int32_t *syptr, int32_t *z, int32_t dastat,
int32_t cx1_plus_cx2, int32_t cy1_plus_cy2,
int32_t *ret_yxaspect, int32_t *ret_xyaspect)
{
if ((dastat & RS_AUTO) == 0)
{
if (!(dastat & RS_STRETCH) && 4*ydim <= 3*xdim)
{
*ret_yxaspect = (12<<16)/10;
*ret_xyaspect = (10<<16)/12;
}
else
{
*ret_yxaspect = yxaspect;
*ret_xyaspect = xyaspect;
}
// *sxptr and *syptr and *z are left unchanged
return;
}
else
{
// dastat&2: Auto window size scaling
const int32_t oxdim = xdim;
const int32_t oydim = ydim;
int32_t xdim = oxdim; // SHADOWS global
int32_t ydim = oydim;
int32_t zoomsc, sx=*sxptr, sy=*syptr;
int32_t ouryxaspect = yxaspect, ourxyaspect = xyaspect;
sy += rotatesprite_y_offset;
if (!(dastat & RS_STRETCH) && 4*ydim <= 3*xdim)
{
if ((dastat & RS_ALIGN_MASK) && (dastat & RS_ALIGN_MASK) != RS_ALIGN_MASK)
sx += NEGATE_ON_CONDITION(scale(120<<16,xdim,ydim) - (160<<16), !(dastat & RS_ALIGN_R));
if ((dastat & RS_ALIGN_MASK) == RS_ALIGN_MASK)
ydim = scale(xdim, 3, 4);
else
xdim = scale(ydim, 4, 3);
ouryxaspect = (12<<16)/10;
ourxyaspect = (10<<16)/12;
}
ouryxaspect = mulscale16(ouryxaspect, rotatesprite_yxaspect);
ourxyaspect = divscale16(ourxyaspect, rotatesprite_yxaspect);
// screen center to s[xy], 320<<16 coords.
const int32_t normxofs = sx-(320<<15), normyofs = sy-(200<<15);
// nasty hacks go here
if (!(dastat & RS_NOCLIP))
{
const int32_t twice_midcx = cx1_plus_cx2+2;
// screen x center to sx1, scaled to viewport
const int32_t scaledxofs = scale(normxofs, scale(xdimen, xdim, oxdim), 320);
sx = ((twice_midcx)<<15) + scaledxofs;
zoomsc = xdimenscale; //= scale(xdimen,yxaspect,320);
zoomsc = mulscale16(zoomsc, rotatesprite_yxaspect);
if ((dastat & RS_ALIGN_MASK) == RS_ALIGN_MASK)
zoomsc = scale(zoomsc, ydim, oydim);
sy = ((cy1_plus_cy2+2)<<15) + mulscale16(normyofs, zoomsc);
}
else
{
//If not clipping to startmosts, & auto-scaling on, as a
//hard-coded bonus, scale to full screen instead
sx = (xdim<<15)+32768 + scale(normxofs,xdim,320);
zoomsc = scale(xdim, ouryxaspect, 320);
sy = (ydim<<15)+32768 + mulscale16(normyofs, zoomsc);
if ((dastat & RS_ALIGN_MASK) == RS_ALIGN_MASK)
sy += (oydim-ydim)<<15;
else
sx += (oxdim-xdim)<<15;
if (dastat & RS_CENTERORIGIN)
sx += oxdim<<15;
}
*sxptr = sx;
*syptr = sy;
*z = mulscale16(*z, zoomsc);
*ret_yxaspect = ouryxaspect;
*ret_xyaspect = ourxyaspect;
}
}
static uint32_t msqrtasm(uint32_t c)
{
uint32_t a = 0x40000000l, b = 0x20000000l;

View file

@ -159,10 +159,6 @@ static FORCE_INLINE int32_t getpalookup(int32_t davis, int32_t dashade)
static FORCE_INLINE int32_t getpalookupsh(int32_t davis) { return getpalookup(davis, globalshade) << 8; }
void dorotspr_handle_bit2(int32_t *sx, int32_t *sy, int32_t *z, int32_t dastat,
int32_t cx1_plus_cx2, int32_t cy1_plus_cy2,
int32_t *ret_yxaspect, int32_t *ret_xyaspect);
////// yax'y stuff //////
#ifdef USE_OPENGL
extern void polymost_scansector(int32_t sectnum);

View file

@ -575,7 +575,7 @@ void setBlendFactor(int index, int alpha)
}
}
void handle_blend(uint8_t enable, uint8_t blend, uint8_t def)
FRenderStyle GetBlend(int blend, int def)
{
static uint8_t const blendFuncTokens[NUMBLENDFACTORS] =
{
@ -586,20 +586,42 @@ void handle_blend(uint8_t enable, uint8_t blend, uint8_t def)
STYLEALPHA_Src,
STYLEALPHA_InvSrc,
STYLEALPHA_Dst,
STYLEALPHA_InvDst,
STYLEALPHA_DstCol,
STYLEALPHA_InvDstCol,
};
STYLEALPHA_InvDst,
STYLEALPHA_DstCol,
STYLEALPHA_InvDstCol,
};
FRenderStyle rs;
rs.BlendOp = STYLEOP_Add;
glblenddef_t const* const glbdef = glblend[blend].def + def;
rs.SrcAlpha = blendFuncTokens[glbdef->src];
rs.SrcAlpha = blendFuncTokens[glbdef->dst];
rs.Flags = 0;
return rs;
}
void handle_blend(uint8_t enable, uint8_t blend, uint8_t def)
{
if (!enable)
{
GLInterface.SetBlendFunc(STYLEALPHA_Src, STYLEALPHA_InvSrc);
return;
}
glblenddef_t const * const glbdef = glblend[blend].def + def;
GLInterface.SetBlendFunc(blendFuncTokens[glbdef->src], blendFuncTokens[glbdef->dst]);
auto rs = GetBlend(blend, def);
GLInterface.SetBlendFunc(rs.SrcAlpha, rs.DestAlpha);
}
float float_trans(uint32_t maskprops, uint8_t blend)
{
switch (maskprops)
{
case DAMETH_TRANS1:
case DAMETH_TRANS2:
return glblend[blend].def[maskprops - 2].alpha;
default:
return 1.0f;
}
}
#endif
int32_t paletteSetLookupTable(int32_t palnum, const uint8_t *shtab)

View file

@ -133,18 +133,6 @@ int32_t r_yshearing = 0;
// used for fogcalc
static float fogresult, fogresult2;
static inline float float_trans(uint32_t maskprops, uint8_t blend)
{
switch (maskprops)
{
case DAMETH_TRANS1:
case DAMETH_TRANS2:
return glblend[blend].def[maskprops-2].alpha;
default:
return 1.0f;
}
}
char ptempbuf[MAXWALLSB<<1];
// polymost ART sky control
@ -624,9 +612,10 @@ static void polymost_drawpoly(vec2f_t const * const dpxy, int32_t const n, int32
float pc[4];
polytint_t const& tint = hictinting[globalpal];
pc[0] = (1.f - (tint.sr * (1.f / 255.f))) + (tint.sr * (1.f / 255.f));
pc[1] = (1.f - (tint.sg * (1.f / 255.f))) + (tint.sg * (1.f / 255.f));
pc[2] = (1.f - (tint.sb * (1.f / 255.f))) + (tint.sb * (1.f / 255.f));
// This makes no sense.
pc[0] = 1.f;// (1.f - (tint.sr * (1.f / 255.f))) + (tint.sr * (1.f / 255.f));
pc[1] = 1.f;// (1.f - (tint.sg * (1.f / 255.f))) + (tint.sg * (1.f / 255.f));
pc[2] = 1.f;// (1.f - (tint.sb * (1.f / 255.f))) + (tint.sb * (1.f / 255.f));
// spriteext full alpha control
pc[3] = float_trans(method & DAMETH_MASKPROPS, drawpoly_blend) * (1.f - drawpoly_alpha);
@ -4739,6 +4728,7 @@ void polymost_dorotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16
polymost_dorotatespritemodel(sx, sy, z, a, picnum, dashade, dapalnum, dastat, daalpha, dablend, uniqid);
return;
}
#if 0
polymost_outputGLDebugMessage(3, "polymost_dorotatesprite(sx:%d, sy:%d, z:%d, a:%hd, picnum:%hd, dashade:%hhd, dapalnum:%hhu, dastat:%d, daalpha:%hhu, dablend:%hhu, cx1:%d, cy1:%d, cx2:%d, cy2:%d, uniqid:%d)",
sx, sy, z, a, picnum, dashade, dapalnum, dastat, daalpha, dablend, cx1, cy1, cx2, cy2, uniqid);
@ -4976,6 +4966,7 @@ void polymost_dorotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16
gvrcorrection = ogvrcorrection;
polymost_identityrotmat();
#endif
}
static float trapextx[2];

View file

@ -579,32 +579,204 @@ void F2DDrawer::Clear()
//dastat&128 1:draw all pages (permanent - no longer used)
//cx1,... clip window (actual screen coords)
//==========================================================================
//
// INTERNAL helper function for classic/polymost dorotatesprite
// sxptr, sxptr, z: in/out
// ret_yxaspect, ret_xyaspect: out
//
//==========================================================================
static void dorotspr_handle_bit2(int32_t* sxptr, int32_t* syptr, int32_t* z, int32_t dastat,
int32_t cx1_plus_cx2, int32_t cy1_plus_cy2,
int32_t* ret_yxaspect, int32_t* ret_xyaspect)
{
if ((dastat & RS_AUTO) == 0)
{
if (!(dastat & RS_STRETCH) && 4 * ydim <= 3 * xdim)
{
*ret_yxaspect = (12 << 16) / 10;
*ret_xyaspect = (10 << 16) / 12;
}
else
{
*ret_yxaspect = yxaspect;
*ret_xyaspect = xyaspect;
}
// *sxptr and *syptr and *z are left unchanged
return;
}
else
{
// dastat&2: Auto window size scaling
const int32_t oxdim = xdim;
const int32_t oydim = ydim;
int32_t xdim = oxdim; // SHADOWS global
int32_t ydim = oydim;
int32_t zoomsc, sx = *sxptr, sy = *syptr;
int32_t ouryxaspect = yxaspect, ourxyaspect = xyaspect;
sy += rotatesprite_y_offset;
if (!(dastat & RS_STRETCH) && 4 * ydim <= 3 * xdim)
{
if ((dastat & RS_ALIGN_MASK) && (dastat & RS_ALIGN_MASK) != RS_ALIGN_MASK)
sx += NEGATE_ON_CONDITION(scale(120 << 16, xdim, ydim) - (160 << 16), !(dastat & RS_ALIGN_R));
if ((dastat & RS_ALIGN_MASK) == RS_ALIGN_MASK)
ydim = scale(xdim, 3, 4);
else
xdim = scale(ydim, 4, 3);
ouryxaspect = (12 << 16) / 10;
ourxyaspect = (10 << 16) / 12;
}
ouryxaspect = mulscale16(ouryxaspect, rotatesprite_yxaspect);
ourxyaspect = divscale16(ourxyaspect, rotatesprite_yxaspect);
// screen center to s[xy], 320<<16 coords.
const int32_t normxofs = sx - (320 << 15), normyofs = sy - (200 << 15);
// nasty hacks go here
if (!(dastat & RS_NOCLIP))
{
const int32_t twice_midcx = cx1_plus_cx2 + 2;
// screen x center to sx1, scaled to viewport
const int32_t scaledxofs = scale(normxofs, scale(xdimen, xdim, oxdim), 320);
sx = ((twice_midcx) << 15) + scaledxofs;
zoomsc = xdimenscale; //= scale(xdimen,yxaspect,320);
zoomsc = mulscale16(zoomsc, rotatesprite_yxaspect);
if ((dastat & RS_ALIGN_MASK) == RS_ALIGN_MASK)
zoomsc = scale(zoomsc, ydim, oydim);
sy = ((cy1_plus_cy2 + 2) << 15) + mulscale16(normyofs, zoomsc);
}
else
{
//If not clipping to startmosts, & auto-scaling on, as a
//hard-coded bonus, scale to full screen instead
sx = (xdim << 15) + 32768 + scale(normxofs, xdim, 320);
zoomsc = scale(xdim, ouryxaspect, 320);
sy = (ydim << 15) + 32768 + mulscale16(normyofs, zoomsc);
if ((dastat & RS_ALIGN_MASK) == RS_ALIGN_MASK)
sy += (oydim - ydim) << 15;
else
sx += (oxdim - xdim) << 15;
if (dastat & RS_CENTERORIGIN)
sx += oxdim << 15;
}
*sxptr = sx;
*syptr = sy;
*z = mulscale16(*z, zoomsc);
*ret_yxaspect = ouryxaspect;
*ret_xyaspect = ourxyaspect;
}
}
//==========================================================================
//
//
//
//==========================================================================
void F2DDrawer::rotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
int8_t dashade, uint8_t dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend,
int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2)
{
// This is mainly a hack because the rotatesprite code is far too messed up to integrate into the 2D drawer.
// This merely stores the parameters and later just calls polymost_rotatesprite do do the work.
// Cleanup can be done once everything is working.
RenderCommand dg;
RenderCommand dg = {};
int method = 0;
dg.mType = DrawTypeRotateSprite;
// Just store the values in the otherwise useless fields of the draw command instead of allocating separate memory.
dg.mVertIndex = sx;
dg.mVertCount = sy;
dg.mIndexIndex = z;
dg.mIndexCount = a;
dg.mSpecialColormap[0].d = picnum;
dg.mRemapIndex = dashade;
dg.mFlags = dapalnum;
dg.mSpecialColormap[1].d = dastat;
dg.mDesaturate = daalpha;
dg.mColor1.d = dablend;
dg.mScissor[0] = cx1;
dg.mScissor[1] = cy1;
dg.mScissor[2] = cx2;
dg.mScissor[3] = cy2;
mData.Push(dg); // don't even try to merge.
}
if (!(dastat & RS_NOMASK))
{
if (dastat & RS_TRANS1)
method |= (dastat & RS_TRANS2) ? DAMETH_TRANS2 : DAMETH_TRANS1;
else
method |= DAMETH_MASK;
dg.mRenderStyle = GetBlend(dablend, (dastat & RS_TRANS2) ? 1 : 0);
}
else
{
dg.mRenderStyle.SrcAlpha = STYLEALPHA_One;
dg.mRenderStyle.DestAlpha = STYLEALPHA_Zero;
dg.mRenderStyle.Flags = STYLEF_Alpha1;
dg.mRenderStyle.BlendOp = STYLEOP_Add;
}
float drawpoly_alpha = daalpha * (1.0f / 255.0f);
float alpha = float_trans(method, dablend) * (1.f - drawpoly_alpha); // Hmmm...
vec2_16_t const siz = tilesiz[picnum];
vec2_16_t ofs = { 0, 0 };
if (!(dastat & RS_TOPLEFT))
{
ofs = { int16_t(picanm[globalpicnum].xofs + (siz.x >> 1)),
int16_t(picanm[globalpicnum].yofs + (siz.y >> 1)) };
}
if (dastat & RS_YFLIP)
ofs.y = siz.y - ofs.y;
int32_t ourxyaspect = 65536, ouryxaspect = 65536;
dorotspr_handle_bit2(&sx, &sy, &z, dastat, cx1 + cx2, cy1 + cy2, &ouryxaspect, &ourxyaspect);
int32_t cosang = mulscale14(sintable[(a + 512) & 2047], z);
int32_t cosang2 = cosang;
int32_t sinang = mulscale14(sintable[a & 2047], z);
int32_t sinang2 = sinang;
if ((dastat & RS_AUTO) || (!(dastat & RS_NOCLIP))) // Don't aspect unscaled perms
{
cosang2 = mulscale16(cosang2, ourxyaspect);
sinang2 = mulscale16(sinang2, ourxyaspect);
}
int32_t const cx = sx - ofs.x * cosang2 + ofs.y * sinang2;
int32_t const cy = sy - ofs.x * sinang - ofs.y * cosang;
vec2_t pxy[8] = { { cx, cy },
{ cx + siz.x * cosang2, cy + siz.x * sinang },
{ 0, 0 },
{ cx - siz.y * sinang2, cy + siz.y * cosang } };
pxy[2] = { pxy[1].x + pxy[3].x - pxy[0].x,
pxy[1].y + pxy[3].y - pxy[0].y };
PalEntry p = 0xffffffff;
dg.mTexture = TileFiles.tiles[picnum];
dg.mRemapIndex = dapalnum | (dashade << 16);
dg.mVertCount = 4;
dg.mVertIndex = (int)mVertices.Reserve(4);
dg.mRenderStyle = LegacyRenderStyles[STYLE_Translucent];
auto ptr = &mVertices[dg.mVertIndex];
ptr->Set(pxy[0].x / 65536.f, pxy[0].y / 65536.f, 0.f, 0.f, 0.f, p); ptr++;
ptr->Set(pxy[1].x / 65536.f, pxy[1].y / 65536.f, 0.f, 1.f, 0.f, p); ptr++;
ptr->Set(pxy[2].x / 65536.f, pxy[2].y / 65536.f, 0.f, 1.f, 1.f, p); ptr++;
ptr->Set(pxy[3].x / 65536.f, pxy[3].y / 65536.f, 0.f, 0.f, 1.f, p); ptr++;
dg.mIndexIndex = mIndices.Size();
dg.mIndexCount += 6;
AddIndices(dg.mVertIndex, 6, 0, 1, 2, 0, 2, 3);
AddCommand(&dg);
}

View file

@ -409,6 +409,11 @@ void GLInstance::SetCull(int type, int winding)
}
}
void GLInstance::SetScissor(int x1, int y1, int x2, int y2)
{
glScissor(x1, y1, x2, y2);
}
void GLInstance::SetColor(float r, float g, float b, float a)
{
glVertexAttrib4f(2, r, g, b, a);

View file

@ -285,6 +285,7 @@ public:
SetColor(r * (1 / 255.f), g * (1 / 255.f), b * (1 / 255.f), a * (1 / 255.f));
}
void SetScissor(int x1, int y1, int x2, int y2);
void SetDepthFunc(int func);
void SetColorMask(bool on);
void SetDepthMask(bool on);

View file

@ -33,6 +33,7 @@
#include "v_draw.h"
#include "palette.h"
extern int16_t numshades;
//===========================================================================
//
// Vertex buffer for 2D drawer
@ -125,30 +126,12 @@ void GLInstance::Draw2D(F2DDrawer *drawer)
for(auto &cmd : commands)
{
if (cmd.mType == F2DDrawer::DrawTypeRotateSprite)
{
// This just gets forwarded to the original drawer. Long term this should not survive and all calls be refactored.
UseColorOnly(false);
SetFadeDisable(false);
SetVertexBuffer(nullptr, 0, 0);
SetIndexBuffer(nullptr);
polymost_dorotatesprite(cmd.mVertIndex, cmd.mVertCount, cmd.mIndexIndex, cmd.mIndexCount, cmd.mSpecialColormap[0].d, cmd.mRemapIndex, cmd.mFlags, cmd.mSpecialColormap[1].d,
cmd.mDesaturate, cmd.mColor1.d, cmd.mScissor[0], cmd.mScissor[1], cmd.mScissor[2], cmd.mScissor[3], 0);
// Reset everything to the default.
SetFadeDisable(true);
EnableDepthTest(false);
EnableMultisampling(false);
EnableBlend(true);
EnableAlphaTest(true);
SetBlendFunc(STYLEALPHA_Src, STYLEALPHA_InvSrc);
SetVertexBuffer(vb.GetBufferObjects().first, 0, 0);
SetIndexBuffer(vb.GetBufferObjects().second);
continue;
}
int gltrans = -1;
SetBlendFunc(cmd.mRenderStyle.SrcAlpha, cmd.mRenderStyle.DestAlpha);
EnableBlend(!(cmd.mRenderStyle.Flags & STYLEF_Alpha1));
//state.SetRenderStyle(cmd.mRenderStyle);
//state.EnableBrightmap(!(cmd.mRenderStyle.Flags & STYLEF_ColorIsFixed));
//state.SetTextureMode(cmd.mDrawMode);
@ -158,16 +141,16 @@ void GLInstance::Draw2D(F2DDrawer *drawer)
{
// scissor test doesn't use the current viewport for the coordinates, so use real screen coordinates
// Note that the origin here is the lower left corner!
sciX = /*screen->ScreenToWindowX*/(cmd.mScissor[0]);
sciY = /*screen->ScreenToWindowY*/(cmd.mScissor[3]);
sciW = /*screen->ScreenToWindowX*/(cmd.mScissor[2]) - sciX;
sciH = /*screen->ScreenToWindowY*/(cmd.mScissor[1]) - sciY;
sciX = screen->ScreenToWindowX(cmd.mScissor[0]);
sciY = screen->ScreenToWindowY(cmd.mScissor[3]);
sciW = screen->ScreenToWindowX(cmd.mScissor[2]) - sciX;
sciH = screen->ScreenToWindowY(cmd.mScissor[1]) - sciY;
}
else
{
sciX = sciY = sciW = sciH = -1;
}
//SetScissor(sciX, sciY, sciW, sciH);
SetScissor(sciX, sciY, sciW, sciH);
//state.SetFog(cmd.mColor1, 0);
SetColor(1, 1, 1);
@ -176,7 +159,19 @@ void GLInstance::Draw2D(F2DDrawer *drawer)
if (cmd.mTexture != nullptr)
{
auto tex = cmd.mTexture;
SetNamedTexture(cmd.mTexture, cmd.mRemapIndex, cmd.mFlags & F2DDrawer::DTF_Wrap ? SamplerRepeat : SamplerClampXY);
if (cmd.mType == F2DDrawer::DrawTypeRotateSprite)
{
// todo: Set up hictinting. (broken as the feature is...)
SetShade(cmd.mRemapIndex >> 16, numshades);
SetFadeDisable(false);
SetTexture(0, tex, cmd.mRemapIndex & 0xffff, 4/*DAMETH_CLAMPED*/, SamplerClampXY);
}
else
{
SetFadeDisable(true);
SetShade(0, numshades);
SetNamedTexture(cmd.mTexture, cmd.mRemapIndex, cmd.mFlags & F2DDrawer::DTF_Wrap ? SamplerRepeat : SamplerClampXY);
}
UseColorOnly(false);
}
else
@ -187,6 +182,7 @@ void GLInstance::Draw2D(F2DDrawer *drawer)
switch (cmd.mType)
{
case F2DDrawer::DrawTypeTriangles:
case F2DDrawer::DrawTypeRotateSprite:
Draw(DT_TRIANGLES, cmd.mIndexIndex, cmd.mIndexCount);
break;
@ -215,10 +211,12 @@ void GLInstance::Draw2D(F2DDrawer *drawer)
UseColorOnly(false);
//state.EnableBrightmap(true);
//state.SetTextureMode(TM_NORMAL);
SetShade(0, numshades);
SetFadeDisable(false);
SetColor(1, 1, 1);
//drawer->mIsFirstPass = false;
twod.Clear();
EnableBlend(true);
EnableMultisampling(true);
}