- Add support for drawing decals on 3d floors in the software renderer

This commit is contained in:
Magnus Norddahl 2017-05-02 22:26:13 +02:00
parent 17108e575a
commit c8070c65d4
4 changed files with 62 additions and 58 deletions

View file

@ -554,7 +554,7 @@ namespace swrenderer
// [ZZ] Only if not an active mirror // [ZZ] Only if not an active mirror
if (!markportal) if (!markportal)
{ {
RenderDecal::RenderDecals(Thread, mLineSegment->sidedef, draw_segment, wallshade, rw_lightleft, rw_lightstep, mLineSegment, WallC, foggy, basecolormap, walltop.ScreenY, wallbottom.ScreenY); RenderDecal::RenderDecals(Thread, mLineSegment->sidedef, draw_segment, wallshade, rw_lightleft, rw_lightstep, mLineSegment, WallC, foggy, basecolormap, walltop.ScreenY, wallbottom.ScreenY, false);
} }
if (markportal) if (markportal)

View file

@ -515,6 +515,8 @@ namespace swrenderer
RenderWallPart renderWallpart(Thread); RenderWallPart renderWallpart(Thread);
renderWallpart.Render(drawerargs, frontsector, curline, WallC, rw_pic, x1, x2, wallupper.ScreenY, walllower.ScreenY, texturemid, MaskedSWall, walltexcoords.UPos, yscale, top, bot, true, wallshade, rw_offset, rw_light, rw_lightstep, nullptr, ds->foggy, basecolormap); renderWallpart.Render(drawerargs, frontsector, curline, WallC, rw_pic, x1, x2, wallupper.ScreenY, walllower.ScreenY, texturemid, MaskedSWall, walltexcoords.UPos, yscale, top, bot, true, wallshade, rw_offset, rw_light, rw_lightstep, nullptr, ds->foggy, basecolormap);
RenderDecal::RenderDecals(Thread, curline->sidedef, ds, wallshade, rw_light, rw_lightstep, curline, WallC, ds->foggy, basecolormap, wallupper.ScreenY, walllower.ScreenY, true);
} }
// kg3D - walls of fake floors // kg3D - walls of fake floors
@ -926,7 +928,6 @@ namespace swrenderer
break; break;
} }
} }
return;
} }
// Clip a midtexture to the floor and ceiling of the sector in front of it. // Clip a midtexture to the floor and ceiling of the sector in front of it.

View file

@ -57,19 +57,15 @@ EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor);
namespace swrenderer namespace swrenderer
{ {
void RenderDecal::RenderDecals(RenderThread *thread, side_t *sidedef, DrawSegment *draw_segment, int wallshade, float lightleft, float lightstep, seg_t *curline, const FWallCoords &wallC, bool foggy, FDynamicColormap *basecolormap, const short *walltop, const short *wallbottom) void RenderDecal::RenderDecals(RenderThread *thread, side_t *sidedef, DrawSegment *draw_segment, int wallshade, float lightleft, float lightstep, seg_t *curline, const FWallCoords &wallC, bool foggy, FDynamicColormap *basecolormap, const short *walltop, const short *wallbottom, bool drawsegPass)
{ {
for (DBaseDecal *decal = sidedef->AttachedDecals; decal != NULL; decal = decal->WallNext) for (DBaseDecal *decal = sidedef->AttachedDecals; decal != NULL; decal = decal->WallNext)
{ {
Render(thread, sidedef, decal, draw_segment, wallshade, lightleft, lightstep, curline, wallC, foggy, basecolormap, walltop, wallbottom, 0); Render(thread, sidedef, decal, draw_segment, wallshade, lightleft, lightstep, curline, wallC, foggy, basecolormap, walltop, wallbottom, drawsegPass);
} }
} }
// pass = 0: when seg is first drawn void RenderDecal::Render(RenderThread *thread, side_t *wall, DBaseDecal *decal, DrawSegment *clipper, int wallshade, float lightleft, float lightstep, seg_t *curline, const FWallCoords &savecoord, bool foggy, FDynamicColormap *basecolormap, const short *walltop, const short *wallbottom, bool drawsegPass)
// = 1: drawing masked textures (including sprites)
// Currently, only pass = 0 is done or used
void RenderDecal::Render(RenderThread *thread, side_t *wall, DBaseDecal *decal, DrawSegment *clipper, int wallshade, float lightleft, float lightstep, seg_t *curline, const FWallCoords &savecoord, bool foggy, FDynamicColormap *basecolormap, const short *walltop, const short *wallbottom, int pass)
{ {
DVector2 decal_left, decal_right, decal_pos; DVector2 decal_left, decal_right, decal_pos;
int x1, x2; int x1, x2;
@ -77,7 +73,7 @@ namespace swrenderer
uint8_t flipx; uint8_t flipx;
double zpos; double zpos;
int needrepeat = 0; int needrepeat = 0;
sector_t *front, *back; sector_t *back;
bool calclighting; bool calclighting;
bool rereadcolormap; bool rereadcolormap;
FDynamicColormap *usecolormap; FDynamicColormap *usecolormap;
@ -90,8 +86,13 @@ namespace swrenderer
// Determine actor z // Determine actor z
zpos = decal->Z; zpos = decal->Z;
front = curline->frontsector;
back = (curline->backsector != NULL) ? curline->backsector : curline->frontsector; back = (curline->backsector != NULL) ? curline->backsector : curline->frontsector;
// for 3d-floor segments use the model sector as reference
sector_t *front;
if ((decal->RenderFlags&RF_CLIPMASK) == RF_CLIPMID) front = decal->Sector;
else front = curline->frontsector;
switch (decal->RenderFlags & RF_RELMASK) switch (decal->RenderFlags & RF_RELMASK)
{ {
default: default:
@ -171,62 +172,64 @@ namespace swrenderer
FWallTmapVals WallT; FWallTmapVals WallT;
WallT.InitFromWallCoords(thread, &WallC); WallT.InitFromWallCoords(thread, &WallC);
// Get the top and bottom clipping arrays if (drawsegPass)
switch (decal->RenderFlags & RF_CLIPMASK)
{ {
default: uint32_t clipMode = decal->RenderFlags & RF_CLIPMASK;
// keep GCC quiet. if (clipMode != RF_CLIPMID && clipMode != RF_CLIPFULL)
return; return;
case RF_CLIPFULL: // Clip decal to stay within the draw segment wall
if (curline->backsector == NULL) mceilingclip = walltop;
{ mfloorclip = wallbottom;
if (pass != 0)
{ // Rumor has it that if RT_CLIPMASK is specified then the decal should be clipped according
return; // to the full drawsegment visibility, as implemented in the remarked section below.
} //
mceilingclip = walltop; // This is problematic because not all 3d floors may have been drawn yet at this point. The
mfloorclip = wallbottom; // code below might work ok for cases where there is only one 3d floor.
}
else if (pass == 0) /*if (clipMode == RF_CLIPFULL)
{
mceilingclip = walltop;
mfloorclip = thread->OpaquePass->ceilingclip;
needrepeat = 1;
}
else
{ {
mceilingclip = clipper->sprtopclip - clipper->x1; mceilingclip = clipper->sprtopclip - clipper->x1;
mfloorclip = clipper->sprbottomclip - clipper->x1; mfloorclip = clipper->sprbottomclip - clipper->x1;
} }*/
break; }
else
case RF_CLIPUPPER: {
if (pass != 0) // Get the top and bottom clipping arrays
switch (decal->RenderFlags & RF_CLIPMASK)
{ {
default:
// keep GCC quiet.
return; return;
}
mceilingclip = walltop;
mfloorclip = thread->OpaquePass->ceilingclip;
break;
case RF_CLIPMID: case RF_CLIPFULL:
if (curline->backsector != NULL && pass != 2) if (curline->backsector == NULL)
{ {
return; mceilingclip = walltop;
} mfloorclip = wallbottom;
mceilingclip = clipper->sprtopclip - clipper->x1; }
mfloorclip = clipper->sprbottomclip - clipper->x1; else
break; {
mceilingclip = walltop;
mfloorclip = thread->OpaquePass->ceilingclip;
needrepeat = 1;
}
break;
case RF_CLIPLOWER: case RF_CLIPUPPER:
if (pass != 0) mceilingclip = walltop;
{ mfloorclip = thread->OpaquePass->ceilingclip;
break;
case RF_CLIPMID:
return; return;
case RF_CLIPLOWER:
mceilingclip = thread->OpaquePass->floorclip;
mfloorclip = wallbottom;
break;
} }
mceilingclip = thread->OpaquePass->floorclip;
mfloorclip = wallbottom;
break;
} }
yscale = decal->ScaleY; yscale = decal->ScaleY;

View file

@ -12,10 +12,10 @@ namespace swrenderer
class RenderDecal class RenderDecal
{ {
public: public:
static void RenderDecals(RenderThread *thread, side_t *wall, DrawSegment *draw_segment, int wallshade, float lightleft, float lightstep, seg_t *curline, const FWallCoords &wallC, bool foggy, FDynamicColormap *basecolormap, const short *walltop, const short *wallbottom); static void RenderDecals(RenderThread *thread, side_t *wall, DrawSegment *draw_segment, int wallshade, float lightleft, float lightstep, seg_t *curline, const FWallCoords &wallC, bool foggy, FDynamicColormap *basecolormap, const short *walltop, const short *wallbottom, bool drawsegPass);
private: private:
static void Render(RenderThread *thread, side_t *wall, DBaseDecal *first, DrawSegment *clipper, int wallshade, float lightleft, float lightstep, seg_t *curline, const FWallCoords &wallC, bool foggy, FDynamicColormap *basecolormap, const short *walltop, const short *wallbottom, int pass); static void Render(RenderThread *thread, side_t *wall, DBaseDecal *first, DrawSegment *clipper, int wallshade, float lightleft, float lightstep, seg_t *curline, const FWallCoords &wallC, bool foggy, FDynamicColormap *basecolormap, const short *walltop, const short *wallbottom, bool drawsegPass);
static void DrawColumn(RenderThread *thread, SpriteDrawerArgs &drawerargs, int x, FTexture *WallSpriteTile, const ProjectedWallTexcoords &walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short *mfloorclip, const short *mceilingclip); static void DrawColumn(RenderThread *thread, SpriteDrawerArgs &drawerargs, int x, FTexture *WallSpriteTile, const ProjectedWallTexcoords &walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short *mfloorclip, const short *mceilingclip);
}; };
} }