- change ProjectedWallTexcoords to use gradients for its texture coordinate calculations
- change SpriteDrawerArgs to draw a full sprite instead of one column at a time - add r_noaccel cvar to allow forced software rendering of the psprites (useful for debugging and also one person on the forum actually requested this feature) - remove FWallTmapVals and calculate texture coordinates directly from FWallCoords - move portal clipping out of the inner sprite drawing loop
This commit is contained in:
parent
1085287af1
commit
236b476933
16 changed files with 676 additions and 845 deletions
|
|
@ -67,7 +67,6 @@
|
|||
#include "a_dynlight.h"
|
||||
#include "r_data/r_vanillatrans.h"
|
||||
|
||||
EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor)
|
||||
EXTERN_CVAR(Bool, gl_light_sprites)
|
||||
|
||||
namespace swrenderer
|
||||
|
|
@ -75,32 +74,20 @@ namespace swrenderer
|
|||
void RenderSprite::Project(RenderThread *thread, AActor *thing, const DVector3 &pos, FTexture *ttex, const DVector2 &spriteScale, int renderflags, WaterFakeSide fakeside, F3DFloor *fakefloor, F3DFloor *fakeceiling, sector_t *current_sector, int lightlevel, bool foggy, FDynamicColormap *basecolormap)
|
||||
{
|
||||
FSoftwareTexture *tex = ttex->GetSoftwareTexture();
|
||||
// transform the origin point
|
||||
double tr_x = pos.X - thread->Viewport->viewpoint.Pos.X;
|
||||
double tr_y = pos.Y - thread->Viewport->viewpoint.Pos.Y;
|
||||
|
||||
double tz = tr_x * thread->Viewport->viewpoint.TanCos + tr_y * thread->Viewport->viewpoint.TanSin;
|
||||
auto viewport = thread->Viewport.get();
|
||||
|
||||
// thing is behind view plane?
|
||||
if (tz < MINZ)
|
||||
const double thingxscalemul = spriteScale.X / tex->GetScale().X;
|
||||
|
||||
// Calculate billboard line for the sprite
|
||||
DVector2 dir = { viewport->viewpoint.Sin, -viewport->viewpoint.Cos };
|
||||
DVector2 pt1 = pos.XY() - viewport->viewpoint.Pos.XY() - dir * (((renderflags & RF_XFLIP) ? (tex->GetWidth() - tex->GetLeftOffsetSW() - 1) : tex->GetLeftOffsetSW()) * thingxscalemul);
|
||||
DVector2 pt2 = pt1 + dir * (tex->GetWidth() * thingxscalemul);
|
||||
|
||||
FWallCoords wallc;
|
||||
if (wallc.Init(thread, pt1, pt2))
|
||||
return;
|
||||
|
||||
double tx = tr_x * thread->Viewport->viewpoint.Sin - tr_y * thread->Viewport->viewpoint.Cos;
|
||||
|
||||
// [RH] Flip for mirrors
|
||||
RenderPortal *renderportal = thread->Portal.get();
|
||||
if (renderportal->MirrorFlags & RF_XFLIP)
|
||||
{
|
||||
tx = -tx;
|
||||
}
|
||||
//tx2 = tx >> 4;
|
||||
|
||||
// too far off the side?
|
||||
if (fabs(tx / 64) > fabs(tz))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// [RH] Added scaling
|
||||
int scaled_to = tex->GetScaledTopOffsetSW();
|
||||
int scaled_bo = scaled_to - tex->GetScaledHeight();
|
||||
|
|
@ -134,86 +121,41 @@ namespace swrenderer
|
|||
}
|
||||
}
|
||||
|
||||
auto viewport = thread->Viewport.get();
|
||||
|
||||
double xscale = viewport->CenterX / tz;
|
||||
|
||||
// [RH] Reject sprites that are off the top or bottom of the screen
|
||||
if (viewport->globaluclip * tz > viewport->viewpoint.Pos.Z - gzb || viewport->globaldclip * tz < viewport->viewpoint.Pos.Z - gzt)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// [RH] Flip for mirrors
|
||||
auto renderportal = thread->Portal.get();
|
||||
renderflags ^= renderportal->MirrorFlags & RF_XFLIP;
|
||||
|
||||
// [SP] SpriteFlip
|
||||
if (thing->renderflags & RF_SPRITEFLIP)
|
||||
renderflags ^= RF_XFLIP;
|
||||
|
||||
// calculate edges of the shape
|
||||
const double thingxscalemul = spriteScale.X / tex->GetScale().X;
|
||||
|
||||
tx -= ((renderflags & RF_XFLIP) ? (tex->GetWidth() - tex->GetLeftOffsetSW() - 1) : tex->GetLeftOffsetSW()) * thingxscalemul;
|
||||
double dtx1 = tx * xscale;
|
||||
int x1 = viewport->viewwindow.centerx + xs_RoundToInt(dtx1);
|
||||
|
||||
// off the right side?
|
||||
if (x1 >= renderportal->WindowRight)
|
||||
return;
|
||||
|
||||
tx += tex->GetWidth() * thingxscalemul;
|
||||
int x2 = viewport->viewwindow.centerx + xs_RoundToInt(tx * xscale);
|
||||
|
||||
// off the left side or too small?
|
||||
if ((x2 < renderportal->WindowLeft || x2 <= x1))
|
||||
return;
|
||||
|
||||
xscale = spriteScale.X * xscale / tex->GetScale().X;
|
||||
fixed_t iscale = (fixed_t)(FRACUNIT / xscale); // Round towards zero to avoid wrapping in edge cases
|
||||
|
||||
double yscale = spriteScale.Y / tex->GetScale().Y;
|
||||
|
||||
// store information in a vissprite
|
||||
RenderSprite *vis = thread->FrameMemory->NewObject<RenderSprite>();
|
||||
|
||||
vis->wallc = wallc;
|
||||
vis->SpriteScale = yscale;
|
||||
vis->CurrentPortalUniq = renderportal->CurrentPortalUniq;
|
||||
vis->xscale = FLOAT2FIXED(xscale);
|
||||
vis->yscale = float(viewport->InvZtoScale * yscale / tz);
|
||||
vis->idepth = float(1 / tz);
|
||||
vis->yscale = float(viewport->InvZtoScale * yscale / wallc.sz1);
|
||||
vis->idepth = float(1 / wallc.sz1);
|
||||
vis->floorclip = thing->Floorclip / yscale;
|
||||
vis->texturemid = tex->GetTopOffsetSW() - (viewport->viewpoint.Pos.Z - pos.Z + thing->Floorclip) / yscale;
|
||||
vis->x1 = x1 < renderportal->WindowLeft ? renderportal->WindowLeft : x1;
|
||||
vis->x2 = x2 > renderportal->WindowRight ? renderportal->WindowRight : x2;
|
||||
//vis->Angle = thing->Angles.Yaw;
|
||||
|
||||
if (renderflags & RF_XFLIP)
|
||||
{
|
||||
vis->startfrac = (tex->GetWidth() << FRACBITS) - 1;
|
||||
vis->xiscale = -iscale;
|
||||
}
|
||||
else
|
||||
{
|
||||
vis->startfrac = 0;
|
||||
vis->xiscale = iscale;
|
||||
}
|
||||
|
||||
vis->startfrac += (fixed_t)(vis->xiscale * (vis->x1 - viewport->viewwindow.centerx + 0.5 - dtx1));
|
||||
|
||||
// killough 3/27/98: save sector for special clipping later
|
||||
vis->x1 = wallc.sx1 < renderportal->WindowLeft ? renderportal->WindowLeft : wallc.sx1;
|
||||
vis->x2 = wallc.sx2 > renderportal->WindowRight ? renderportal->WindowRight : wallc.sx2;
|
||||
vis->heightsec = heightsec;
|
||||
vis->sector = thing->Sector;
|
||||
vis->section = thing->section;
|
||||
|
||||
vis->depth = (float)tz;
|
||||
vis->depth = (float)wallc.sz1;
|
||||
vis->gpos = { (float)pos.X, (float)pos.Y, (float)pos.Z };
|
||||
vis->gzb = (float)gzb; // [RH] use gzb, not thing->z
|
||||
vis->gzt = (float)gzt; // killough 3/27/98
|
||||
vis->gzb = (float)gzb;
|
||||
vis->gzt = (float)gzt;
|
||||
vis->deltax = float(pos.X - viewport->viewpoint.Pos.X);
|
||||
vis->deltay = float(pos.Y - viewport->viewpoint.Pos.Y);
|
||||
vis->renderflags = renderflags;
|
||||
if (thing->flags5 & MF5_BRIGHT)
|
||||
vis->renderflags |= RF_FULLBRIGHT; // kg3D
|
||||
vis->renderflags |= RF_FULLBRIGHT;
|
||||
vis->RenderStyle = thing->RenderStyle;
|
||||
if (r_UseVanillaTransparency)
|
||||
{
|
||||
|
|
@ -226,11 +168,7 @@ namespace swrenderer
|
|||
vis->Alpha = float(thing->Alpha);
|
||||
vis->fakefloor = fakefloor;
|
||||
vis->fakeceiling = fakeceiling;
|
||||
//vis->bInMirror = renderportal->MirrorFlags & RF_XFLIP;
|
||||
//vis->bSplitSprite = false;
|
||||
|
||||
vis->pic = tex;
|
||||
|
||||
vis->foggy = foggy;
|
||||
|
||||
// The software renderer cannot invert the source without inverting the overlay
|
||||
|
|
@ -300,74 +238,36 @@ namespace swrenderer
|
|||
vis->dynlightcolor = 0;
|
||||
}
|
||||
|
||||
vis->Light.SetColormap(thread, tz, lightlevel, foggy, basecolormap, fullbright, invertcolormap, fadeToBlack, false, false);
|
||||
vis->Light.SetColormap(thread, wallc.sz1, lightlevel, foggy, basecolormap, fullbright, invertcolormap, fadeToBlack, false, false);
|
||||
|
||||
thread->SpriteList->Push(vis);
|
||||
}
|
||||
|
||||
void RenderSprite::Render(RenderThread *thread, short *mfloorclip, short *mceilingclip, int, int, Fake3DTranslucent)
|
||||
{
|
||||
auto vis = this;
|
||||
|
||||
fixed_t frac;
|
||||
FSoftwareTexture *tex;
|
||||
int x2;
|
||||
fixed_t xiscale;
|
||||
|
||||
double spryscale, sprtopscreen;
|
||||
bool sprflipvert;
|
||||
|
||||
if (vis->xscale == 0 || fabs(vis->yscale) < (1.0f / 32000.0f))
|
||||
{ // scaled to 0; can't see
|
||||
return;
|
||||
}
|
||||
|
||||
SpriteDrawerArgs drawerargs;
|
||||
drawerargs.SetDynamicLight(dynlightcolor);
|
||||
bool visible = drawerargs.SetStyle(thread->Viewport.get(), vis->RenderStyle, vis->Alpha, vis->Translation, vis->FillColor, vis->Light);
|
||||
|
||||
bool visible = drawerargs.SetStyle(thread->Viewport.get(), RenderStyle, Alpha, Translation, FillColor, Light);
|
||||
if (visible)
|
||||
{
|
||||
tex = vis->pic;
|
||||
spryscale = vis->yscale;
|
||||
sprflipvert = false;
|
||||
fixed_t iscale = FLOAT2FIXED(1 / vis->yscale);
|
||||
frac = vis->startfrac;
|
||||
xiscale = vis->xiscale;
|
||||
double texturemid = vis->texturemid;
|
||||
|
||||
auto viewport = thread->Viewport.get();
|
||||
|
||||
if (vis->renderflags & RF_YFLIP)
|
||||
RenderTranslucentPass *translucentPass = thread->TranslucentPass.get();
|
||||
short portalfloorclip[MAXWIDTH];
|
||||
int x2 = wallc.sx2;
|
||||
for (int x = wallc.sx1; x < x2; x++)
|
||||
{
|
||||
sprflipvert = true;
|
||||
spryscale = -spryscale;
|
||||
iscale = -iscale;
|
||||
texturemid -= vis->pic->GetHeight();
|
||||
sprtopscreen = viewport->CenterY + texturemid * spryscale;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprflipvert = false;
|
||||
sprtopscreen = viewport->CenterY - texturemid * spryscale;
|
||||
if (translucentPass->ClipSpriteColumnWithPortals(x, this))
|
||||
portalfloorclip[x] = mceilingclip[x];
|
||||
else
|
||||
portalfloorclip[x] = mfloorclip[x];
|
||||
}
|
||||
|
||||
int x = vis->x1;
|
||||
x2 = vis->x2;
|
||||
thread->PrepareTexture(pic, RenderStyle);
|
||||
|
||||
if (x < x2)
|
||||
{
|
||||
RenderTranslucentPass *translucentPass = thread->TranslucentPass.get();
|
||||
ProjectedWallLight mlight;
|
||||
mlight.SetSpriteLight();
|
||||
|
||||
thread->PrepareTexture(tex, vis->RenderStyle);
|
||||
while (x < x2)
|
||||
{
|
||||
if (!translucentPass->ClipSpriteColumnWithPortals(x, vis))
|
||||
drawerargs.DrawMaskedColumn(thread, x, iscale, tex, frac, spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, vis->RenderStyle, false);
|
||||
x++;
|
||||
frac += xiscale;
|
||||
}
|
||||
}
|
||||
drawerargs.SetBaseColormap(Light.BaseColormap);
|
||||
drawerargs.DrawMasked(thread, gzt - floorclip, SpriteScale, renderflags & RF_XFLIP, renderflags & RF_YFLIP, wallc, mlight, pic, portalfloorclip, mceilingclip, RenderStyle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue