Merge branch 'opengl-sprite-billboarding' into 'master'

OpenGL Sprite Billboarding

See merge request STJr/SRB2!485
This commit is contained in:
Nev3r 2019-05-06 12:45:53 -04:00
commit 8b8e165d19
4 changed files with 124 additions and 27 deletions

View File

@ -4246,10 +4246,43 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t
}
}
// This is expecting a pointer to an array containing 4 wallVerts for a sprite
static void HWR_RotateSpritePolyToAim(gr_vissprite_t *spr, FOutVector *wallVerts)
{
if (cv_grspritebillboarding.value && spr && spr->mobj && wallVerts)
{
float basey = FIXED_TO_FLOAT(spr->mobj->z);
float lowy = wallVerts[0].y;
if (P_MobjFlip(spr->mobj) == -1)
{
basey = FIXED_TO_FLOAT(spr->mobj->z + spr->mobj->height);
}
// Rotate sprites to fully billboard with the camera
// 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
// be mobj->z or mobj->z + mobj->height
wallVerts[2].y = wallVerts[3].y = (spr->ty - basey) * gr_viewludsin + basey;
wallVerts[0].y = wallVerts[1].y = (lowy - basey) * gr_viewludsin + basey;
// translate back to be around 0 before translating back
wallVerts[3].x += ((spr->ty - basey) * gr_viewludcos) * gr_viewcos;
wallVerts[2].x += ((spr->ty - basey) * gr_viewludcos) * gr_viewcos;
wallVerts[0].x += ((lowy - basey) * gr_viewludcos) * gr_viewcos;
wallVerts[1].x += ((lowy - basey) * gr_viewludcos) * gr_viewcos;
wallVerts[3].z += ((spr->ty - basey) * gr_viewludcos) * gr_viewsin;
wallVerts[2].z += ((spr->ty - basey) * gr_viewludcos) * gr_viewsin;
wallVerts[0].z += ((lowy - basey) * gr_viewludcos) * gr_viewsin;
wallVerts[1].z += ((lowy - basey) * gr_viewludcos) * gr_viewsin;
}
}
static void HWR_SplitSprite(gr_vissprite_t *spr)
{
float this_scale = 1.0f;
FOutVector wallVerts[4];
FOutVector baseWallVerts[4]; // This is what the verts should end up as
GLPatch_t *gpatch;
FSurfaceInfo Surf;
const boolean hires = (spr->mobj && spr->mobj->skin && ((skin_t *)spr->mobj->skin)->flags & SF_HIRES);
@ -4262,11 +4295,13 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
float realtop, realbot, top, bot;
float towtop, towbot, towmult;
float bheight;
float realheight, heightmult;
const sector_t *sector = spr->mobj->subsector->sector;
const lightlist_t *list = sector->lightlist;
#ifdef ESLOPE
float endrealtop, endrealbot, endtop, endbot;
float endbheight;
float endrealheight;
fixed_t temp;
fixed_t v1x, v1y, v2x, v2y;
#endif
@ -4299,16 +4334,16 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
HWR_DrawSpriteShadow(spr, gpatch, this_scale);
}
wallVerts[0].x = wallVerts[3].x = spr->x1;
wallVerts[2].x = wallVerts[1].x = spr->x2;
wallVerts[0].z = wallVerts[3].z = spr->z1;
wallVerts[1].z = wallVerts[2].z = spr->z2;
baseWallVerts[0].x = baseWallVerts[3].x = spr->x1;
baseWallVerts[2].x = baseWallVerts[1].x = spr->x2;
baseWallVerts[0].z = baseWallVerts[3].z = spr->z1;
baseWallVerts[1].z = baseWallVerts[2].z = spr->z2;
wallVerts[2].y = wallVerts[3].y = spr->ty;
baseWallVerts[2].y = baseWallVerts[3].y = spr->ty;
if (spr->mobj && fabsf(this_scale - 1.0f) > 1.0E-36f)
wallVerts[0].y = wallVerts[1].y = spr->ty - gpatch->height * this_scale;
baseWallVerts[0].y = baseWallVerts[1].y = spr->ty - gpatch->height * this_scale;
else
wallVerts[0].y = wallVerts[1].y = spr->ty - gpatch->height;
baseWallVerts[0].y = baseWallVerts[1].y = spr->ty - gpatch->height;
v1x = FLOAT_TO_FIXED(spr->x1);
v1y = FLOAT_TO_FIXED(spr->z1);
@ -4317,44 +4352,56 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
if (spr->flip)
{
wallVerts[0].sow = wallVerts[3].sow = gpatch->max_s;
wallVerts[2].sow = wallVerts[1].sow = 0;
}else{
wallVerts[0].sow = wallVerts[3].sow = 0;
wallVerts[2].sow = wallVerts[1].sow = gpatch->max_s;
baseWallVerts[0].sow = baseWallVerts[3].sow = gpatch->max_s;
baseWallVerts[2].sow = baseWallVerts[1].sow = 0;
}
else
{
baseWallVerts[0].sow = baseWallVerts[3].sow = 0;
baseWallVerts[2].sow = baseWallVerts[1].sow = gpatch->max_s;
}
// flip the texture coords (look familiar?)
if (spr->vflip)
{
wallVerts[3].tow = wallVerts[2].tow = gpatch->max_t;
wallVerts[0].tow = wallVerts[1].tow = 0;
}else{
wallVerts[3].tow = wallVerts[2].tow = 0;
wallVerts[0].tow = wallVerts[1].tow = gpatch->max_t;
baseWallVerts[3].tow = baseWallVerts[2].tow = gpatch->max_t;
baseWallVerts[0].tow = baseWallVerts[1].tow = 0;
}
else
{
baseWallVerts[3].tow = baseWallVerts[2].tow = 0;
baseWallVerts[0].tow = baseWallVerts[1].tow = gpatch->max_t;
}
// if it has a dispoffset, push it a little towards the camera
if (spr->dispoffset) {
float co = -gr_viewcos*(0.05f*spr->dispoffset);
float si = -gr_viewsin*(0.05f*spr->dispoffset);
wallVerts[0].z = wallVerts[3].z = wallVerts[0].z+si;
wallVerts[1].z = wallVerts[2].z = wallVerts[1].z+si;
wallVerts[0].x = wallVerts[3].x = wallVerts[0].x+co;
wallVerts[1].x = wallVerts[2].x = wallVerts[1].x+co;
baseWallVerts[0].z = baseWallVerts[3].z = baseWallVerts[0].z+si;
baseWallVerts[1].z = baseWallVerts[2].z = baseWallVerts[1].z+si;
baseWallVerts[0].x = baseWallVerts[3].x = baseWallVerts[0].x+co;
baseWallVerts[1].x = baseWallVerts[2].x = baseWallVerts[1].x+co;
}
realtop = top = wallVerts[3].y;
realbot = bot = wallVerts[0].y;
towtop = wallVerts[3].tow;
towbot = wallVerts[0].tow;
// Let dispoffset work first since this adjust each vertex
HWR_RotateSpritePolyToAim(spr, baseWallVerts);
realtop = top = baseWallVerts[3].y;
realbot = bot = baseWallVerts[0].y;
towtop = baseWallVerts[3].tow;
towbot = baseWallVerts[0].tow;
towmult = (towbot - towtop) / (top - bot);
#ifdef ESLOPE
endrealtop = endtop = wallVerts[2].y;
endrealbot = endbot = wallVerts[1].y;
endrealtop = endtop = baseWallVerts[2].y;
endrealbot = endbot = baseWallVerts[1].y;
#endif
// copy the contents of baseWallVerts into the drawn wallVerts array
// baseWallVerts is used to know the final shape to easily get the vertex
// co-ordinates
memcpy(wallVerts, baseWallVerts, sizeof(baseWallVerts));
if (!cv_translucency.value) // translucency disabled
{
Surf.FlatColor.s.alpha = 0xFF;
@ -4481,12 +4528,53 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
wallVerts[2].y = endtop;
wallVerts[0].y = bot;
wallVerts[1].y = endbot;
// The x and y only need to be adjusted in the case that it's not a papersprite
if (cv_grspritebillboarding.value && spr->mobj)
{
// Get the x and z of the vertices so billboarding draws correctly
realheight = realbot - realtop;
endrealheight = endrealbot - endrealtop;
heightmult = (realtop - top) / realheight;
wallVerts[3].x = baseWallVerts[3].x + (baseWallVerts[3].x - baseWallVerts[0].x) * heightmult;
wallVerts[3].z = baseWallVerts[3].z + (baseWallVerts[3].z - baseWallVerts[0].z) * heightmult;
heightmult = (endrealtop - endtop) / endrealheight;
wallVerts[2].x = baseWallVerts[2].x + (baseWallVerts[2].x - baseWallVerts[1].x) * heightmult;
wallVerts[2].z = baseWallVerts[2].z + (baseWallVerts[2].z - baseWallVerts[1].z) * heightmult;
heightmult = (realtop - bot) / realheight;
wallVerts[0].x = baseWallVerts[3].x + (baseWallVerts[3].x - baseWallVerts[0].x) * heightmult;
wallVerts[0].z = baseWallVerts[3].z + (baseWallVerts[3].z - baseWallVerts[0].z) * heightmult;
heightmult = (endrealtop - endbot) / endrealheight;
wallVerts[1].x = baseWallVerts[2].x + (baseWallVerts[2].x - baseWallVerts[1].x) * heightmult;
wallVerts[1].z = baseWallVerts[2].z + (baseWallVerts[2].z - baseWallVerts[1].z) * heightmult;
}
#else
wallVerts[3].tow = wallVerts[2].tow = towtop + ((realtop - top) * towmult);
wallVerts[0].tow = wallVerts[1].tow = towtop + ((realtop - bot) * towmult);
wallVerts[2].y = wallVerts[3].y = top;
wallVerts[0].y = wallVerts[1].y = bot;
// The x and y only need to be adjusted in the case that it's not a papersprite
if (cv_grspritebillboarding.value && spr->mobj)
{
// Get the x and z of the vertices so billboarding draws correctly
realheight = realbot - realtop;
heightmult = (realtop - top) / realheight;
wallVerts[3].x = baseWallVerts[3].x + (baseWallVerts[3].x - baseWallVerts[0].x) * heightmult;
wallVerts[3].z = baseWallVerts[3].z + (baseWallVerts[3].z - baseWallVerts[0].z) * heightmult;
wallVerts[2].x = baseWallVerts[2].x + (baseWallVerts[2].x - baseWallVerts[1].x) * heightmult;
wallVerts[2].z = baseWallVerts[2].z + (baseWallVerts[2].z - baseWallVerts[1].z) * heightmult;
heightmult = (realtop - bot) / realheight;
wallVerts[0].x = baseWallVerts[3].x + (baseWallVerts[3].x - baseWallVerts[0].x) * heightmult;
wallVerts[0].z = baseWallVerts[3].z + (baseWallVerts[3].z - baseWallVerts[0].z) * heightmult;
wallVerts[1].x = baseWallVerts[2].x + (baseWallVerts[2].x - baseWallVerts[1].x) * heightmult;
wallVerts[1].z = baseWallVerts[2].z + (baseWallVerts[2].z - baseWallVerts[1].z) * heightmult;
}
#endif
if (colormap)
@ -4655,6 +4743,9 @@ static void HWR_DrawSprite(gr_vissprite_t *spr)
wallVerts[1].x = wallVerts[2].x = wallVerts[1].x+co;
}
// Let dispoffset work first since this adjust each vertex
HWR_RotateSpritePolyToAim(spr, wallVerts);
// This needs to be AFTER the shadows so that the regular sprites aren't drawn completely black.
// sprite lighting by modulating the RGB components
/// \todo coloured
@ -4736,6 +4827,9 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr)
wallVerts[0].z = wallVerts[3].z = spr->z1;
wallVerts[1].z = wallVerts[2].z = spr->z2;
// Let dispoffset work first since this adjust each vertex
HWR_RotateSpritePolyToAim(spr, wallVerts);
wallVerts[0].sow = wallVerts[3].sow = 0;
wallVerts[2].sow = wallVerts[1].sow = gpatch->max_s;

View File

@ -95,6 +95,7 @@ extern consvar_t cv_grcorrecttricks;
extern consvar_t cv_voodoocompatibility;
extern consvar_t cv_grfovchange;
extern consvar_t cv_grsolvetjoin;
extern consvar_t cv_grspritebillboarding;
extern float gr_viewwidth, gr_viewheight, gr_baseviewwindowy;

View File

@ -1407,6 +1407,7 @@ void R_RegisterEngineStuff(void)
CV_RegisterVar(&cv_grcoronasize);
#endif
CV_RegisterVar(&cv_grmd2);
CV_RegisterVar(&cv_grspritebillboarding);
#endif
#ifdef HWRENDER

View File

@ -81,6 +81,7 @@ consvar_t cv_grcoronasize = {"gr_coronasize", "1", CV_SAVE| CV_FLOAT, 0, NULL, 0
static CV_PossibleValue_t CV_MD2[] = {{0, "Off"}, {1, "On"}, {2, "Old"}, {0, NULL}};
// console variables in development
consvar_t cv_grmd2 = {"gr_md2", "Off", CV_SAVE, CV_MD2, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_grspritebillboarding = {"gr_spritebillboarding", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
#endif
const UINT8 gammatable[5][256] =