Added DrawerContext class

This commit is contained in:
Magnus Norddahl 2016-06-16 06:47:30 +02:00
parent 77c4786b9d
commit 312776621e
19 changed files with 1922 additions and 1291 deletions

View file

@ -892,6 +892,7 @@ set( FASTMATH_PCH_SOURCES
r_swrenderer.cpp r_swrenderer.cpp
r_3dfloors.cpp r_3dfloors.cpp
r_bsp.cpp r_bsp.cpp
r_drawer_context.cpp
r_draw.cpp r_draw.cpp
r_draw_rgba.cpp r_draw_rgba.cpp
r_drawt.cpp r_drawt.cpp

View file

@ -41,7 +41,7 @@
#include "r_local.h" #include "r_local.h"
#include "r_main.h" #include "r_main.h"
#include "r_plane.h" #include "r_plane.h"
#include "r_draw.h" #include "r_drawer_context.h"
#include "r_things.h" #include "r_things.h"
#include "r_3dfloors.h" #include "r_3dfloors.h"
#include "a_sharedglobal.h" #include "a_sharedglobal.h"
@ -545,7 +545,7 @@ void R_AddLine (seg_t *line)
curline = line; curline = line;
// [RH] Color if not texturing line // [RH] Color if not texturing line
dc_color = (((int)(line - segs) * 8) + 4) & 255; DrawerContext::SetFlatColor((((int)(line - segs) * 8) + 4) & 255);
pt1 = line->v1->fPos() - ViewPos; pt1 = line->v1->fPos() - ViewPos;
pt2 = line->v2->fPos() - ViewPos; pt2 = line->v2->fPos() - ViewPos;

View file

@ -23,6 +23,8 @@
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#define DRAWER_INTERNALS
#include <stddef.h> #include <stddef.h>
#include "templates.h" #include "templates.h"
@ -40,6 +42,8 @@
#include "r_data/colormaps.h" #include "r_data/colormaps.h"
#include "r_plane.h" #include "r_plane.h"
#include "r_draw_rgba.h" #include "r_draw_rgba.h"
#include "r_drawer_context.h"
#include "d_net.h"
#include "gi.h" #include "gi.h"
#include "stats.h" #include "stats.h"
@ -66,6 +70,7 @@ int ylookup[MAXHEIGHT];
BYTE *dc_destorg; BYTE *dc_destorg;
} }
int scaledviewwidth; int scaledviewwidth;
DCanvas *dc_canvas;
// [RH] Pointers to the different column drawers. // [RH] Pointers to the different column drawers.
// These get changed depending on the current // These get changed depending on the current
@ -97,9 +102,9 @@ void (*R_DrawSpanMaskedAddClamp)(void);
void (*R_FillSpan)(void); void (*R_FillSpan)(void);
void (*R_FillColumnHoriz)(void); void (*R_FillColumnHoriz)(void);
void (*R_DrawFogBoundary)(int x1, int x2, short *uclip, short *dclip); void (*R_DrawFogBoundary)(int x1, int x2, short *uclip, short *dclip);
void (*R_MapTiltedPlane)(int y, int x1); void (*R_DrawTiltedSpan)(int y, int x1, int x2);
void (*R_MapColoredPlane)(int y, int x1); void (*R_DrawColoredSpan)(int y, int x1, int x2);
void (*R_DrawParticle)(vissprite_t *); void (*R_FillTransColumn)(int x, int y1, int y2, int color, int alpha);
fixed_t (*tmvline1_add)(); fixed_t (*tmvline1_add)();
void (*tmvline4_add)(); void (*tmvline4_add)();
fixed_t (*tmvline1_addclamp)(); fixed_t (*tmvline1_addclamp)();
@ -134,6 +139,24 @@ void (*rt_tlatesubclamp4cols)(int sx, int yl, int yh);
void (*rt_tlaterevsubclamp4cols)(int sx, int yl, int yh); void (*rt_tlaterevsubclamp4cols)(int sx, int yl, int yh);
void (*rt_initcols)(BYTE *buffer); void (*rt_initcols)(BYTE *buffer);
void (*rt_span_coverage)(int x, int start, int stop); void (*rt_span_coverage)(int x, int start, int stop);
void (*colfunc) (void);
void (*basecolfunc) (void);
void (*fuzzcolfunc) (void);
void (*transcolfunc) (void);
void (*spanfunc) (void);
void (*hcolfunc_pre) (void);
void (*hcolfunc_post1) (int hx, int sx, int yl, int yh);
void (*hcolfunc_post2) (int hx, int sx, int yl, int yh);
void (*hcolfunc_post4) (int sx, int yl, int yh);
extern "C" void R_DrawTiltedPlane_ASM(int y, int x1);
#ifdef X86_ASM
extern "C" void R_SetSpanSource_ASM(const BYTE *flat);
extern "C" void R_SetSpanSize_ASM(int xbits, int ybits);
extern "C" void R_SetSpanColormap_ASM(BYTE *colormap);
extern "C" void R_SetTiltedSpanSource_ASM(const BYTE *flat);
extern "C" BYTE *ds_curcolormap, *ds_cursource, *ds_curtiltedsource;
#endif
// //
// R_DrawColumn // R_DrawColumn
@ -1040,13 +1063,6 @@ const BYTE* ds_source;
// just for profiling // just for profiling
int dscount; int dscount;
#ifdef X86_ASM
extern "C" void R_SetSpanSource_ASM (const BYTE *flat);
extern "C" void R_SetSpanSize_ASM (int xbits, int ybits);
extern "C" void R_SetSpanColormap_ASM (BYTE *colormap);
extern "C" BYTE *ds_curcolormap, *ds_cursource, *ds_curtiltedsource;
#endif
} }
//========================================================================== //==========================================================================
@ -1076,9 +1092,8 @@ void R_SetSpanSource(const BYTE *pixels)
// //
//========================================================================== //==========================================================================
void R_SetSpanColormap(FDynamicColormap *colormap, int shade) void R_SetSpanColormap()
{ {
R_SetDSColorMapLight(colormap, 0, shade);
#ifdef X86_ASM #ifdef X86_ASM
if (!r_swtruecolor && ds_colormap != ds_curcolormap) if (!r_swtruecolor && ds_colormap != ds_curcolormap)
{ {
@ -2297,9 +2312,9 @@ void R_InitColumnDrawers ()
R_FillColumnHoriz = R_FillColumnHoriz_rgba; R_FillColumnHoriz = R_FillColumnHoriz_rgba;
R_DrawFogBoundary = R_DrawFogBoundary_rgba; R_DrawFogBoundary = R_DrawFogBoundary_rgba;
R_MapTiltedPlane = R_MapTiltedPlane_rgba; R_DrawTiltedSpan = R_DrawTiltedSpan_rgba;
R_MapColoredPlane = R_MapColoredPlane_rgba; R_DrawColoredSpan = R_DrawColoredSpan_rgba;
R_DrawParticle = R_DrawParticle_rgba; R_FillTransColumn = R_FillTransColumn_rgba;
tmvline1_add = tmvline1_add_rgba; tmvline1_add = tmvline1_add_rgba;
tmvline4_add = tmvline4_add_rgba; tmvline4_add = tmvline4_add_rgba;
@ -2394,9 +2409,15 @@ void R_InitColumnDrawers ()
R_FillColumnHoriz = R_FillColumnHorizP_C; R_FillColumnHoriz = R_FillColumnHorizP_C;
R_DrawFogBoundary = R_DrawFogBoundary_C; R_DrawFogBoundary = R_DrawFogBoundary_C;
R_MapTiltedPlane = R_MapTiltedPlane_C; R_DrawColoredSpan = R_DrawColoredSpan_C;
R_MapColoredPlane = R_MapColoredPlane_C; R_FillTransColumn = R_FillTransColumn_C;
R_DrawParticle = R_DrawParticle_C;
#ifdef X86_ASM
// To do: update R_DrawTiltedPlane_ASM to use x2 rather than spanend[y]
R_DrawTiltedSpan = [](int y, int x1, int x2) { R_DrawTiltedPlane_ASM(y, x1); };
#else
R_DrawTiltedSpan = R_DrawTiltedSpan_C;
#endif
tmvline1_add = tmvline1_add_C; tmvline1_add = tmvline1_add_C;
tmvline4_add = tmvline4_add_C; tmvline4_add = tmvline4_add_C;
@ -2829,3 +2850,744 @@ void R_SetDSColorMapLight(FColormap *base_colormap, float light, int shade)
ds_colormap = base_colormap->Maps + (GETPALOOKUP(light, shade) << COLORMAPSHIFT); ds_colormap = base_colormap->Maps + (GETPALOOKUP(light, shade) << COLORMAPSHIFT);
} }
} }
/////////////////////////////////////////////////////////////////////////////
FVector3 ds_plane_sz, ds_plane_su, ds_plane_sv;
bool ds_plane_shade;
float ds_planelightfloat;
fixed_t ds_pviewx, ds_pviewy;
int ds_planeshade;
extern "C" BYTE *tiltlighting[MAXWIDTH];
extern "C" { void R_CalcTiltedLighting(double lval, double lend, int width); }
#ifdef _MSC_VER
#pragma warning(disable:4244) // warning C4244: conversion from 'SQWORD' to 'DWORD', possible loss of data
#endif
//==========================================================================
//
// R_CalcTiltedLighting
//
// Calculates the lighting for one row of a tilted plane. If the definition
// of GETPALOOKUP changes, this needs to change, too.
//
//==========================================================================
extern "C" {
void R_CalcTiltedLighting (double lval, double lend, int width)
{
double lstep;
BYTE *lightfiller;
BYTE *basecolormapdata = ds_fcolormap->Maps;
int i = 0;
if (width == 0 || lval == lend)
{ // Constant lighting
lightfiller = basecolormapdata + (GETPALOOKUP(lval, ds_planeshade) << COLORMAPSHIFT);
}
else
{
lstep = (lend - lval) / width;
if (lval >= MAXLIGHTVIS)
{ // lval starts "too bright".
lightfiller = basecolormapdata + (GETPALOOKUP(lval, ds_planeshade) << COLORMAPSHIFT);
for (; i <= width && lval >= MAXLIGHTVIS; ++i)
{
tiltlighting[i] = lightfiller;
lval += lstep;
}
}
if (lend >= MAXLIGHTVIS)
{ // lend ends "too bright".
lightfiller = basecolormapdata + (GETPALOOKUP(lend, ds_planeshade) << COLORMAPSHIFT);
for (; width > i && lend >= MAXLIGHTVIS; --width)
{
tiltlighting[width] = lightfiller;
lend -= lstep;
}
}
if (width > 0)
{
lval = FIXED2DBL(ds_planeshade) - lval;
lend = FIXED2DBL(ds_planeshade) - lend;
lstep = (lend - lval) / width;
if (lstep < 0)
{ // Going from dark to light
if (lval < 1.)
{ // All bright
lightfiller = basecolormapdata;
}
else
{
if (lval >= NUMCOLORMAPS)
{ // Starts beyond the dark end
BYTE *clight = basecolormapdata + ((NUMCOLORMAPS-1) << COLORMAPSHIFT);
while (lval >= NUMCOLORMAPS && i <= width)
{
tiltlighting[i++] = clight;
lval += lstep;
}
if (i > width)
return;
}
while (i <= width && lval >= 0)
{
tiltlighting[i++] = basecolormapdata + (xs_ToInt(lval) << COLORMAPSHIFT);
lval += lstep;
}
lightfiller = basecolormapdata;
}
}
else
{ // Going from light to dark
if (lval >= (NUMCOLORMAPS-1))
{ // All dark
lightfiller = basecolormapdata + ((NUMCOLORMAPS-1) << COLORMAPSHIFT);
}
else
{
while (lval < 0 && i <= width)
{
tiltlighting[i++] = basecolormapdata;
lval += lstep;
}
if (i > width)
return;
while (i <= width && lval < (NUMCOLORMAPS-1))
{
tiltlighting[i++] = basecolormapdata + (xs_ToInt(lval) << COLORMAPSHIFT);
lval += lstep;
}
lightfiller = basecolormapdata + ((NUMCOLORMAPS-1) << COLORMAPSHIFT);
}
}
}
}
for (; i <= width; i++)
{
tiltlighting[i] = lightfiller;
}
}
} // extern "C"
void R_DrawTiltedSpan_C (int y, int x1, int x2)
{
int width = x2 - x1;
double iz, uz, vz;
BYTE *fb;
DWORD u, v;
int i;
iz = ds_plane_sz[2] + ds_plane_sz[1]*(centery-y) + ds_plane_sz[0]*(x1-centerx);
// Lighting is simple. It's just linear interpolation from start to end
if (ds_plane_shade)
{
uz = (iz + ds_plane_sz[0]*width) * ds_planelightfloat;
vz = iz * ds_planelightfloat;
R_CalcTiltedLighting (vz, uz, width);
}
uz = ds_plane_su[2] + ds_plane_su[1]*(centery-y) + ds_plane_su[0]*(x1-centerx);
vz = ds_plane_sv[2] + ds_plane_sv[1]*(centery-y) + ds_plane_sv[0]*(x1-centerx);
fb = ylookup[y] + x1 + dc_destorg;
BYTE vshift = 32 - ds_ybits;
BYTE ushift = vshift - ds_xbits;
int umask = ((1 << ds_xbits) - 1) << ds_ybits;
#if 0 // The "perfect" reference version of this routine. Pretty slow.
// Use it only to see how things are supposed to look.
i = 0;
do
{
double z = 1.f/iz;
u = SQWORD(uz*z) + ds_pviewx;
v = SQWORD(vz*z) + ds_pviewy;
R_SetDSColorMapLight(tiltlighting[i], 0, 0);
fb[i++] = ds_colormap[ds_source[(v >> vshift) | ((u >> ushift) & umask)]];
iz += ds_plane_sz[0];
uz += ds_plane_su[0];
vz += ds_plane_sv[0];
} while (--width >= 0);
#else
//#define SPANSIZE 32
//#define INVSPAN 0.03125f
//#define SPANSIZE 8
//#define INVSPAN 0.125f
#define SPANSIZE 16
#define INVSPAN 0.0625f
double startz = 1.f/iz;
double startu = uz*startz;
double startv = vz*startz;
double izstep, uzstep, vzstep;
izstep = ds_plane_sz[0] * SPANSIZE;
uzstep = ds_plane_su[0] * SPANSIZE;
vzstep = ds_plane_sv[0] * SPANSIZE;
x1 = 0;
width++;
while (width >= SPANSIZE)
{
iz += izstep;
uz += uzstep;
vz += vzstep;
double endz = 1.f/iz;
double endu = uz*endz;
double endv = vz*endz;
DWORD stepu = SQWORD((endu - startu) * INVSPAN);
DWORD stepv = SQWORD((endv - startv) * INVSPAN);
u = SQWORD(startu) + ds_pviewx;
v = SQWORD(startv) + ds_pviewy;
for (i = SPANSIZE-1; i >= 0; i--)
{
fb[x1] = *(tiltlighting[x1] + ds_source[(v >> vshift) | ((u >> ushift) & umask)]);
x1++;
u += stepu;
v += stepv;
}
startu = endu;
startv = endv;
width -= SPANSIZE;
}
if (width > 0)
{
if (width == 1)
{
u = SQWORD(startu);
v = SQWORD(startv);
fb[x1] = *(tiltlighting[x1] + ds_source[(v >> vshift) | ((u >> ushift) & umask)]);
}
else
{
double left = width;
iz += ds_plane_sz[0] * left;
uz += ds_plane_su[0] * left;
vz += ds_plane_sv[0] * left;
double endz = 1.f/iz;
double endu = uz*endz;
double endv = vz*endz;
left = 1.f/left;
DWORD stepu = SQWORD((endu - startu) * left);
DWORD stepv = SQWORD((endv - startv) * left);
u = SQWORD(startu) + ds_pviewx;
v = SQWORD(startv) + ds_pviewy;
for (; width != 0; width--)
{
fb[x1] = *(tiltlighting[x1] + ds_source[(v >> vshift) | ((u >> ushift) & umask)]);
x1++;
u += stepu;
v += stepv;
}
}
}
#endif
}
void R_DrawColoredSpan_C (int y, int x1, int x2)
{
memset (ylookup[y] + x1 + dc_destorg, ds_color, x2 - x1 + 1);
}
/////////////////////////////////////////////////////////////////////////////
// Draw a column with support for non-power-of-two ranges
uint32_t wallscan_drawcol1(int x, int y1, int y2, uint32_t uv_start, uint32_t uv_step, uint32_t uv_max, const BYTE *source, DWORD(*draw1column)())
{
int pixelsize = r_swtruecolor ? 4 : 1;
if (uv_max == 0) // power of two
{
int count = y2 - y1;
dc_source = source;
dc_dest = (ylookup[y1] + x) * pixelsize + dc_destorg;
dc_count = count;
dc_iscale = uv_step;
dc_texturefrac = uv_start;
draw1column();
uint64_t step64 = uv_step;
uint64_t pos64 = uv_start;
return (uint32_t)(pos64 + step64 * count);
}
else
{
uint32_t uv_pos = uv_start;
uint32_t left = y2 - y1;
while (left > 0)
{
uint32_t available = uv_max - uv_pos;
uint32_t next_uv_wrap = available / uv_step;
if (available % uv_step != 0)
next_uv_wrap++;
uint32_t count = MIN(left, next_uv_wrap);
dc_source = source;
dc_dest = (ylookup[y1] + x) * pixelsize + dc_destorg;
dc_count = count;
dc_iscale = uv_step;
dc_texturefrac = uv_pos;
draw1column();
left -= count;
uv_pos += uv_step * count;
if (uv_pos >= uv_max)
uv_pos -= uv_max;
}
return uv_pos;
}
}
// Draw four columns with support for non-power-of-two ranges
void wallscan_drawcol4(int x, int y1, int y2, uint32_t *uv_pos, uint32_t *uv_step, uint32_t uv_max, const BYTE **source, void(*draw4columns)())
{
int pixelsize = r_swtruecolor ? 4 : 1;
if (uv_max == 0) // power of two, no wrap handling needed
{
int count = y2 - y1;
for (int i = 0; i < 4; i++)
{
bufplce[i] = source[i];
vplce[i] = uv_pos[i];
vince[i] = uv_step[i];
uint64_t step64 = uv_step[i];
uint64_t pos64 = uv_pos[i];
uv_pos[i] = (uint32_t)(pos64 + step64 * count);
}
dc_dest = (ylookup[y1] + x) * pixelsize + dc_destorg;
dc_count = count;
draw4columns();
}
else
{
dc_dest = (ylookup[y1] + x) * pixelsize + dc_destorg;
for (int i = 0; i < 4; i++)
bufplce[i] = source[i];
uint32_t left = y2 - y1;
while (left > 0)
{
// Find which column wraps first
uint32_t count = left;
for (int i = 0; i < 4; i++)
{
uint32_t available = uv_max - uv_pos[i];
uint32_t next_uv_wrap = available / uv_step[i];
if (available % uv_step[i] != 0)
next_uv_wrap++;
count = MIN(next_uv_wrap, count);
}
// Draw until that column wraps
for (int i = 0; i < 4; i++)
{
vplce[i] = uv_pos[i];
vince[i] = uv_step[i];
}
dc_count = count;
draw4columns();
// Wrap the uv position
for (int i = 0; i < 4; i++)
{
uv_pos[i] += uv_step[i] * count;
if (uv_pos[i] >= uv_max)
uv_pos[i] -= uv_max;
}
left -= count;
}
}
}
// Calculates a wrapped uv start position value for a column
void calc_uv_start_and_step(int y1, float swal, double yrepeat, uint32_t uv_height, int fracbits, uint32_t &uv_start_out, uint32_t &uv_step_out)
{
double uv_stepd = swal * yrepeat;
// Find start uv in [0-uv_height[ range.
// Not using xs_ToFixed because it rounds the result and we need something that always rounds down to stay within the range.
double v = (dc_texturemid + uv_stepd * (y1 - CenterY + 0.5)) / uv_height;
v = v - floor(v);
v *= uv_height;
v *= (1 << fracbits);
uv_start_out = (uint32_t)v;
uv_step_out = xs_ToFixed(fracbits, uv_stepd);
}
typedef DWORD(*Draw1ColumnFuncPtr)();
typedef void(*Draw4ColumnsFuncPtr)();
void wallscan_any(
int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat,
FTexture *rw_pic, fixed_t rw_offset, const BYTE *(*getcol)(FTexture *tex, int x),
void(setupwallscan(int bits, Draw1ColumnFuncPtr &draw1, Draw4ColumnsFuncPtr &draw2)))
{
if (rw_pic->UseType == FTexture::TEX_Null)
return;
uint32_t uv_height = rw_pic->GetHeight();
uint32_t fracbits = 32 - rw_pic->HeightBits;
uint32_t uv_max = uv_height << fracbits;
DWORD(*draw1column)();
void(*draw4columns)();
setupwallscan(fracbits, draw1column, draw4columns);
fixed_t xoffset = rw_offset;
bool fixed = (fixedcolormap != NULL || fixedlightlev >= 0);
if (fixed)
{
palookupoffse[0] = dc_colormap;
palookupoffse[1] = dc_colormap;
palookupoffse[2] = dc_colormap;
palookupoffse[3] = dc_colormap;
palookuplight[0] = 0;
palookuplight[1] = 0;
palookuplight[2] = 0;
palookuplight[3] = 0;
}
if (fixedcolormap)
R_SetColorMapLight(fixedcolormap, 0, 0);
else
R_SetColorMapLight(basecolormap, 0, 0);
float light = rw_light;
// Calculate where 4 column alignment begins and ends:
int aligned_x1 = clamp((x1 + 3) / 4 * 4, x1, x2);
int aligned_x2 = clamp(x2 / 4 * 4, x1, x2);
// First unaligned columns:
for (int x = x1; x < aligned_x1; x++, light += rw_lightstep)
{
int y1 = uwal[x];
int y2 = dwal[x];
if (y2 <= y1)
continue;
if (!fixed)
R_SetColorMapLight(basecolormap, light, wallshade);
const BYTE *source = getcol(rw_pic, (lwal[x] + xoffset) >> FRACBITS);
uint32_t uv_start, uv_step;
calc_uv_start_and_step(y1, swal[x], yrepeat, uv_height, fracbits, uv_start, uv_step);
wallscan_drawcol1(x, y1, y2, uv_start, uv_step, uv_max, source, draw1column);
}
// The aligned columns
for (int x = aligned_x1; x < aligned_x2; x += 4)
{
// Find y1, y2, light and uv values for four columns:
int y1[4] = { uwal[x], uwal[x + 1], uwal[x + 2], uwal[x + 3] };
int y2[4] = { dwal[x], dwal[x + 1], dwal[x + 2], dwal[x + 3] };
const BYTE *source[4];
for (int i = 0; i < 4; i++)
source[i] = getcol(rw_pic, (lwal[x + i] + xoffset) >> FRACBITS);
float lights[4];
for (int i = 0; i < 4; i++)
{
lights[i] = light;
light += rw_lightstep;
}
uint32_t uv_pos[4], uv_step[4];
for (int i = 0; i < 4; i++)
calc_uv_start_and_step(y1[i], swal[x + i], yrepeat, uv_height, fracbits, uv_pos[i], uv_step[i]);
// Figure out where we vertically can start and stop drawing 4 columns in one go
int middle_y1 = y1[0];
int middle_y2 = y2[0];
for (int i = 1; i < 4; i++)
{
middle_y1 = MAX(y1[i], middle_y1);
middle_y2 = MIN(y2[i], middle_y2);
}
// If we got an empty column in our set we cannot draw 4 columns in one go:
bool empty_column_in_set = false;
for (int i = 0; i < 4; i++)
{
if (y2[i] <= y1[i])
empty_column_in_set = true;
}
if (empty_column_in_set || middle_y2 <= middle_y1)
{
for (int i = 0; i < 4; i++)
{
if (y2[i] <= y1[i])
continue;
if (!fixed)
R_SetColorMapLight(basecolormap, lights[i], wallshade);
wallscan_drawcol1(x + i, y1[i], y2[i], uv_pos[i], uv_step[i], uv_max, source[i], draw1column);
}
continue;
}
// Draw the first rows where not all 4 columns are active
for (int i = 0; i < 4; i++)
{
if (!fixed)
R_SetColorMapLight(basecolormap, lights[i], wallshade);
if (y1[i] < middle_y1)
uv_pos[i] = wallscan_drawcol1(x + i, y1[i], middle_y1, uv_pos[i], uv_step[i], uv_max, source[i], draw1column);
}
// Draw the area where all 4 columns are active
if (!fixed)
{
for (int i = 0; i < 4; i++)
{
if (r_swtruecolor)
{
palookupoffse[i] = basecolormap->Maps;
palookuplight[i] = LIGHTSCALE(lights[i], wallshade);
}
else
{
palookupoffse[i] = basecolormap->Maps + (GETPALOOKUP(lights[i], wallshade) << COLORMAPSHIFT);
palookuplight[i] = 0;
}
}
}
wallscan_drawcol4(x, middle_y1, middle_y2, uv_pos, uv_step, uv_max, source, draw4columns);
// Draw the last rows where not all 4 columns are active
for (int i = 0; i < 4; i++)
{
if (!fixed)
R_SetColorMapLight(basecolormap, lights[i], wallshade);
if (middle_y2 < y2[i])
uv_pos[i] = wallscan_drawcol1(x + i, middle_y2, y2[i], uv_pos[i], uv_step[i], uv_max, source[i], draw1column);
}
}
// The last unaligned columns:
for (int x = aligned_x2; x < x2; x++, light += rw_lightstep)
{
int y1 = uwal[x];
int y2 = dwal[x];
if (y2 <= y1)
continue;
if (!fixed)
R_SetColorMapLight(basecolormap, light, wallshade);
const BYTE *source = getcol(rw_pic, (lwal[x] + xoffset) >> FRACBITS);
uint32_t uv_start, uv_step;
calc_uv_start_and_step(y1, swal[x], yrepeat, uv_height, fracbits, uv_start, uv_step);
wallscan_drawcol1(x, y1, y2, uv_start, uv_step, uv_max, source, draw1column);
}
NetUpdate();
}
void wallscan(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, FTexture *rw_pic, fixed_t rw_offset, const BYTE *(*getcol)(FTexture *tex, int x))
{
wallscan_any(x1, x2, uwal, dwal, swal, lwal, yrepeat, rw_pic, rw_offset, getcol, [](int bits, Draw1ColumnFuncPtr &line1, Draw4ColumnsFuncPtr &line4)
{
setupvline(bits);
line1 = dovline1;
line4 = dovline4;
});
}
void maskwallscan(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, FTexture *rw_pic, fixed_t rw_offset, const BYTE *(*getcol)(FTexture *tex, int x))
{
if (!rw_pic->bMasked) // Textures that aren't masked can use the faster wallscan.
{
wallscan(x1, x2, uwal, dwal, swal, lwal, yrepeat, rw_pic, rw_offset, getcol);
}
else
{
wallscan_any(x1, x2, uwal, dwal, swal, lwal, yrepeat, rw_pic, rw_offset, getcol, [](int bits, Draw1ColumnFuncPtr &line1, Draw4ColumnsFuncPtr &line4)
{
setupmvline(bits);
line1 = domvline1;
line4 = domvline4;
});
}
}
void transmaskwallscan(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, FTexture *rw_pic, fixed_t rw_offset, const BYTE *(*getcol)(FTexture *tex, int x))
{
static fixed_t(*tmvline1)();
static void(*tmvline4)();
if (!R_GetTransMaskDrawers(&tmvline1, &tmvline4))
{
// The current translucency is unsupported, so draw with regular maskwallscan instead.
maskwallscan(x1, x2, uwal, dwal, swal, lwal, yrepeat, rw_pic, rw_offset, getcol);
}
else
{
wallscan_any(x1, x2, uwal, dwal, swal, lwal, yrepeat, rw_pic, rw_offset, getcol, [](int bits, Draw1ColumnFuncPtr &line1, Draw4ColumnsFuncPtr &line4)
{
setuptmvline(bits);
line1 = reinterpret_cast<DWORD(*)()>(tmvline1);
line4 = tmvline4;
});
}
}
/////////////////////////////////////////////////////////////////////////////
void R_FillTransColumn_C(int x, int y1, int y2, int color, int alpha)
{
fixed_t fglevel, bglevel;
DWORD *fg2rgb;
DWORD *bg2rgb;
int spacing;
BYTE *dest;
DWORD fg;
fglevel = ((alpha + 1) << 8) & ~0x3ff;
bglevel = FRACUNIT - fglevel;
fg2rgb = Col2RGB8[fglevel >> 10];
bg2rgb = Col2RGB8[bglevel >> 10];
fg = fg2rgb[color];
spacing = dc_pitch;
int ycount = y2 - y1 + 1;
dest = ylookup[y1] + x + dc_destorg;
for (int y = 0; y < ycount; y++)
{
DWORD bg = bg2rgb[*dest];
bg = (fg + bg) | 0x1f07c1f;
*dest = RGB32k.All[bg & (bg >> 15)];
dest += spacing;
}
}
/////////////////////////////////////////////////////////////////////////////
//
// R_DrawMaskedColumn
// Used for sprites and masked mid textures.
// Masked means: partly transparent, i.e. stored
// in posts/runs of opaque pixels.
//
short* dc_mfloorclip;
short* dc_mceilingclip;
double dc_spryscale;
double dc_sprtopscreen;
bool dc_sprflipvert;
void R_DrawMaskedColumn(int x, const BYTE *column, const FTexture::Span *span)
{
int pixelsize = r_swtruecolor ? 4 : 1;
const fixed_t centeryfrac = FLOAT2FIXED(CenterY);
const fixed_t texturemid = FLOAT2FIXED(dc_texturemid);
while (span->Length != 0)
{
const int length = span->Length;
const int top = span->TopOffset;
fixed_t texturefrac = dc_texturefrac;
fixed_t iscale = dc_iscale;
// calculate unclipped screen coordinates for post
int yl = xs_RoundToInt(dc_sprtopscreen + dc_spryscale * top);
int yh = xs_RoundToInt(dc_sprtopscreen + dc_spryscale * (top + length)) - 1;
if (dc_sprflipvert)
{
swapvalues(yl, yh);
}
if (yh >= dc_mfloorclip[x])
{
yh = dc_mfloorclip[x] - 1;
}
if (yl < dc_mceilingclip[x])
{
yl = dc_mceilingclip[x];
}
if (yl <= yh)
{
if (dc_sprflipvert)
{
texturefrac = (yl*iscale) - (top << FRACBITS)
- FixedMul(centeryfrac, iscale) - texturemid;
const fixed_t maxfrac = length << FRACBITS;
while (texturefrac >= maxfrac)
{
if (++yl > yh)
goto nextpost;
texturefrac += iscale;
}
fixed_t endfrac = texturefrac + (yh - yl)*iscale;
while (endfrac < 0)
{
if (--yh < yl)
goto nextpost;
endfrac -= iscale;
}
}
else
{
texturefrac = texturemid - (top << FRACBITS)
+ (yl*iscale) - FixedMul(centeryfrac - FRACUNIT, iscale);
while (texturefrac < 0)
{
if (++yl > yh)
goto nextpost;
texturefrac += iscale;
}
fixed_t endfrac = texturefrac + (yh - yl)*iscale;
const fixed_t maxfrac = length << FRACBITS;
if (yh < dc_mfloorclip[x] - 1 && endfrac < maxfrac - iscale)
{
yh++;
}
else while (endfrac >= maxfrac)
{
if (--yh < yl)
goto nextpost;
endfrac -= iscale;
}
}
dc_yl = yl;
dc_yh = yh;
dc_x = x;
dc_texturefrac = texturefrac;
dc_iscale = iscale;
dc_source = column + top;
dc_count = yh - yl + 1;
dc_dest = (ylookup[yl] + x) * pixelsize + dc_destorg;
colfunc();
}
nextpost:
span++;
}
}

View file

@ -25,6 +25,11 @@
#include "r_defs.h" #include "r_defs.h"
// Prevents files outside the DrawerContext class getting good ideas about
// accessing the private globals. Any drawer actions should be facilitated
// via the DrawerContext class!
#ifdef DRAWER_INTERNALS
// Spectre/Invisibility. // Spectre/Invisibility.
#define FUZZTABLE 50 #define FUZZTABLE 50
extern "C" int fuzzoffset[FUZZTABLE + 1]; // [RH] +1 for the assembly routine extern "C" int fuzzoffset[FUZZTABLE + 1]; // [RH] +1 for the assembly routine
@ -71,6 +76,7 @@ extern "C" fixed_t dc_destalpha;
// first pixel in a column // first pixel in a column
extern "C" const BYTE* dc_source; extern "C" const BYTE* dc_source;
extern DCanvas *dc_canvas;
extern "C" BYTE *dc_dest, *dc_destorg; extern "C" BYTE *dc_dest, *dc_destorg;
extern "C" int dc_count; extern "C" int dc_count;
@ -86,6 +92,23 @@ extern "C" unsigned int dc_tspans[4][MAXHEIGHT];
extern "C" unsigned int *dc_ctspan[4]; extern "C" unsigned int *dc_ctspan[4];
extern "C" unsigned int horizspans[4]; extern "C" unsigned int horizspans[4];
//
// Function pointers to switch refresh/drawing functions.
// Used to select shadow mode etc.
//
extern void (*colfunc) (void);
extern void (*basecolfunc) (void);
extern void (*fuzzcolfunc) (void);
extern void (*transcolfunc) (void);
// No shadow effects on floors.
extern void (*spanfunc) (void);
// [RH] Function pointers for the horizontal column drawers.
extern void (*hcolfunc_pre) (void);
extern void (*hcolfunc_post1) (int hx, int sx, int yl, int yh);
extern void (*hcolfunc_post2) (int hx, int sx, int yl, int yh);
extern void (*hcolfunc_post4) (int sx, int yl, int yh);
// [RH] Pointers to the different column and span drawers... // [RH] Pointers to the different column and span drawers...
// The span blitting interface. // The span blitting interface.
@ -116,7 +139,7 @@ extern void (*R_DrawTranslatedColumn)(void);
// Span drawing for rows, floor/ceiling. No Spectre effect needed. // Span drawing for rows, floor/ceiling. No Spectre effect needed.
extern void (*R_DrawSpan)(void); extern void (*R_DrawSpan)(void);
void R_SetupSpanBits(FTexture *tex); void R_SetupSpanBits(FTexture *tex);
void R_SetSpanColormap(FDynamicColormap *colormap, int shade); void R_SetSpanColormap();
void R_SetSpanSource(const BYTE *pixels); void R_SetSpanSource(const BYTE *pixels);
// Span drawing for masked textures. // Span drawing for masked textures.
@ -281,6 +304,15 @@ void R_FillColumnP_C (void);
void R_FillColumnHorizP_C (void); void R_FillColumnHorizP_C (void);
void R_FillSpan_C (void); void R_FillSpan_C (void);
// vars for R_DrawMaskedColumn
extern short* dc_mfloorclip;
extern short* dc_mceilingclip;
extern double dc_spryscale;
extern double dc_sprtopscreen;
extern bool dc_sprflipvert;
void R_DrawMaskedColumn(int x, const BYTE *column, const FTexture::Span *spans);
#ifdef X86_ASM #ifdef X86_ASM
#define R_SetupDrawSlab R_SetupDrawSlabA #define R_SetupDrawSlab R_SetupDrawSlabA
#define R_DrawSlab R_DrawSlabA #define R_DrawSlab R_DrawSlabA
@ -325,12 +357,7 @@ void R_InitShadeMaps();
void R_InitFuzzTable (int fuzzoff); void R_InitFuzzTable (int fuzzoff);
// [RH] Consolidate column drawer selection // [RH] Consolidate column drawer selection
enum ESPSResult enum ESPSResult;
{
DontDraw, // not useful to draw this
DoDraw0, // draw this as if r_columnmethod is 0
DoDraw1, // draw this as if r_columnmethod is 1
};
ESPSResult R_SetPatchStyle (FRenderStyle style, fixed_t alpha, int translation, DWORD color); ESPSResult R_SetPatchStyle (FRenderStyle style, fixed_t alpha, int translation, DWORD color);
inline ESPSResult R_SetPatchStyle(FRenderStyle style, float alpha, int translation, DWORD color) inline ESPSResult R_SetPatchStyle(FRenderStyle style, float alpha, int translation, DWORD color)
{ {
@ -353,18 +380,6 @@ extern void(*tmvline4_revsubclamp)();
// transmaskwallscan calls this to find out what column drawers to use // transmaskwallscan calls this to find out what column drawers to use
bool R_GetTransMaskDrawers (fixed_t (**tmvline1)(), void (**tmvline4)()); bool R_GetTransMaskDrawers (fixed_t (**tmvline1)(), void (**tmvline4)());
// Retrieve column data for wallscan. Should probably be removed
// to just use the texture's GetColumn() method. It just exists
// for double-layer skies.
const BYTE *R_GetColumn (FTexture *tex, int col);
void wallscan (int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, const BYTE *(*getcol)(FTexture *tex, int col)=R_GetColumn);
// maskwallscan is exactly like wallscan but does not draw anything where the texture is color 0.
void maskwallscan (int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, const BYTE *(*getcol)(FTexture *tex, int col)=R_GetColumn);
// transmaskwallscan is like maskwallscan, but it can also blend to the background
void transmaskwallscan (int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, const BYTE *(*getcol)(FTexture *tex, int col)=R_GetColumn);
// Sets dc_colormap and dc_light to their appropriate values depending on the output format (pal vs true color) // Sets dc_colormap and dc_light to their appropriate values depending on the output format (pal vs true color)
void R_SetColorMapLight(FColormap *base_colormap, float light, int shade); void R_SetColorMapLight(FColormap *base_colormap, float light, int shade);
@ -373,4 +388,40 @@ void R_SetDSColorMapLight(FColormap *base_colormap, float light, int shade);
void R_SetTranslationMap(lighttable_t *translation); void R_SetTranslationMap(lighttable_t *translation);
// Retrieve column data for wallscan. Should probably be removed
// to just use the texture's GetColumn() method. It just exists
// for double-layer skies.
const BYTE *R_GetColumn (FTexture *tex, int col);
void wallscan (int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, FTexture *rw_pic, fixed_t rw_offset, const BYTE *(*getcol)(FTexture *tex, int col)=R_GetColumn);
// maskwallscan is exactly like wallscan but does not draw anything where the texture is color 0.
void maskwallscan (int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, FTexture *rw_pic, fixed_t rw_offset, const BYTE *(*getcol)(FTexture *tex, int col)=R_GetColumn);
// transmaskwallscan is like maskwallscan, but it can also blend to the background
void transmaskwallscan (int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, FTexture *rw_pic, fixed_t rw_offset, const BYTE *(*getcol)(FTexture *tex, int col)=R_GetColumn);
extern void(*R_DrawColoredSpan)(int y, int x1, int x2);
extern void(*R_DrawTiltedSpan)(int y, int x1, int x2);
void R_DrawTiltedSpan_C(int y, int x1, int x2);
void R_DrawTiltedSpan_rgba(int y, int x1, int x2);
void R_DrawColoredSpan_C(int y, int x1, int x2);
void R_DrawColoredSpan_rgba(int y, int x1, int x2);
extern FVector3 ds_plane_sz, ds_plane_su, ds_plane_sv;
extern bool ds_plane_shade;
extern float ds_planelightfloat;
extern fixed_t ds_pviewx, ds_pviewy;
extern int ds_planeshade;
extern "C" BYTE *tiltlighting[MAXWIDTH];
extern "C" { void R_CalcTiltedLighting(double lval, double lend, int width); }
struct vissprite_t;
extern void(*R_FillTransColumn)(int x, int y1, int y2, int color, int alpha);
void R_FillTransColumn_C(int x, int y1, int y2, int color, int alpha);
void R_FillTransColumn_rgba(int x, int y1, int y2, int color, int alpha);
#endif
#endif #endif

View file

@ -21,6 +21,8 @@
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#define DRAWER_INTERNALS
#include <stddef.h> #include <stddef.h>
#include "templates.h" #include "templates.h"
@ -3492,6 +3494,158 @@ public:
} }
}; };
class DrawTiltedSpanRGBACommand : public DrawerCommand
{
int _y;
int _x1;
int _x2;
BYTE *dc_destorg;
fixed_t dc_light;
ShadeConstants dc_shade_constants;
const BYTE *ds_source;
public:
DrawTiltedSpanRGBACommand(int y, int x1, int x2)
{
_y = y;
_x1 = x1;
_x2 = x2;
dc_destorg = ::dc_destorg;
ds_source = ::ds_source;
}
void Execute(DrawerThread *thread) override
{
if (thread->line_skipped_by_thread(_y))
return;
int y = _y;
int x1 = _x1;
int x2 = _x2;
// Slopes are broken currently in master.
// Until R_DrawTiltedPlane is fixed we are just going to fill with a solid color.
uint32_t *source = (uint32_t*)ds_source;
uint32_t *dest = ylookup[y] + x1 + (uint32_t*)dc_destorg;
int count = x2 - x1 + 1;
while (count > 0)
{
*(dest++) = source[0];
count--;
}
}
};
class DrawColoredSpanRGBACommand : public DrawerCommand
{
int _y;
int _x1;
int _x2;
BYTE *dc_destorg;
fixed_t ds_light;
int ds_color;
public:
DrawColoredSpanRGBACommand(int y, int x1, int x2)
{
_y = y;
_x1 = x1;
_x2 = x2;
dc_destorg = ::dc_destorg;
ds_light = ::ds_light;
ds_color = ::ds_color;
}
void Execute(DrawerThread *thread) override
{
if (thread->line_skipped_by_thread(_y))
return;
int y = _y;
int x1 = _x1;
int x2 = _x2;
uint32_t *dest = ylookup[y] + x1 + (uint32_t*)dc_destorg;
int count = (x2 - x1 + 1);
uint32_t light = calc_light_multiplier(ds_light);
uint32_t color = shade_pal_index_simple(ds_color, light);
for (int i = 0; i < count; i++)
dest[i] = color;
}
};
class FillTransColumnRGBACommand : public DrawerCommand
{
int _x;
int _y1;
int _y2;
int _color;
int _a;
BYTE *dc_destorg;
int dc_pitch;
fixed_t ds_light;
int ds_color;
public:
FillTransColumnRGBACommand(int x, int y1, int y2, int color, int a)
{
_x = x;
_y1 = y1;
_y2 = y2;
_color = color;
_a = a;
dc_destorg = ::dc_destorg;
dc_pitch = ::dc_pitch;
}
void Execute(DrawerThread *thread) override
{
int x = _x;
int y1 = _y1;
int y2 = _y2;
int color = _color;
int a = _a;
int ycount = thread->count_for_thread(y1, y2 - y1 + 1);
if (ycount <= 0)
return;
uint32_t fg = GPalette.BaseColors[color].d;
uint32_t fg_red = (fg >> 16) & 0xff;
uint32_t fg_green = (fg >> 8) & 0xff;
uint32_t fg_blue = fg & 0xff;
uint32_t alpha = a + 1;
uint32_t inv_alpha = 256 - alpha;
fg_red *= alpha;
fg_green *= alpha;
fg_blue *= alpha;
int spacing = dc_pitch * thread->num_cores;
uint32_t *dest = thread->dest_for_thread(y1, dc_pitch, ylookup[y1] + x + (uint32_t*)dc_destorg);
for (int y = 0; y < ycount; y++)
{
uint32_t bg_red = (*dest >> 16) & 0xff;
uint32_t bg_green = (*dest >> 8) & 0xff;
uint32_t bg_blue = (*dest) & 0xff;
uint32_t red = (fg_red + bg_red * inv_alpha) / 256;
uint32_t green = (fg_green + bg_green * inv_alpha) / 256;
uint32_t blue = (fg_blue + bg_blue * inv_alpha) / 256;
*dest = 0xff000000 | (red << 16) | (green << 8) | blue;
dest += spacing;
}
}
};
ApplySpecialColormapRGBACommand::ApplySpecialColormapRGBACommand(FSpecialColormap *colormap, DFrameBuffer *screen) ApplySpecialColormapRGBACommand::ApplySpecialColormapRGBACommand(FSpecialColormap *colormap, DFrameBuffer *screen)
{ {
buffer = screen->GetBuffer(); buffer = screen->GetBuffer();
@ -3968,3 +4122,18 @@ void R_DrawFogBoundary_rgba(int x1, int x2, short *uclip, short *dclip)
R_DrawFogBoundarySection_rgba(t2, b2, x1); R_DrawFogBoundarySection_rgba(t2, b2, x1);
} }
} }
void R_DrawTiltedSpan_rgba(int y, int x1, int x2)
{
DrawerCommandQueue::QueueCommand<DrawTiltedSpanRGBACommand>(y, x1, x2);
}
void R_DrawColoredSpan_rgba(int y, int x1, int x2)
{
DrawerCommandQueue::QueueCommand<DrawColoredSpanRGBACommand>(y, x1, x2);
}
void R_FillTransColumn_rgba(int x, int y1, int y2, int color, int a)
{
DrawerCommandQueue::QueueCommand<FillTransColumnRGBACommand>(x, y1, y2, color, a);
}

View file

@ -23,6 +23,11 @@
#ifndef __R_DRAW_RGBA__ #ifndef __R_DRAW_RGBA__
#define __R_DRAW_RGBA__ #define __R_DRAW_RGBA__
// Prevents files outside the DrawerContext class getting good ideas about
// accessing the private globals. Any drawer actions should be facilitated
// via the DrawerContext class!
#ifdef DRAWER_INTERNALS
#include "r_draw.h" #include "r_draw.h"
#include "v_palette.h" #include "v_palette.h"
#include <vector> #include <vector>
@ -487,3 +492,5 @@ FORCEINLINE uint32_t alpha_blend(uint32_t fg, uint32_t bg)
} }
#endif #endif
#endif

464
src/r_drawer_context.cpp Normal file
View file

@ -0,0 +1,464 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id:$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This source is available for distribution and/or modification
// only under the terms of the DOOM Source Code License as
// published by id Software. All rights reserved.
//
// The source is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
// for more details.
//
// $Log:$
//
// DESCRIPTION:
// The actual span/column drawing functions.
// Here find the main potential for optimization,
// e.g. inline assembly, different algorithms.
//
//-----------------------------------------------------------------------------
#define DRAWER_INTERNALS
#include <stddef.h>
#include "templates.h"
#include "doomdef.h"
#include "i_system.h"
#include "w_wad.h"
#include "r_local.h"
#include "v_video.h"
#include "doomstat.h"
#include "st_stuff.h"
#include "g_game.h"
#include "g_level.h"
#include "r_data/r_translate.h"
#include "v_palette.h"
#include "r_data/colormaps.h"
#include "r_plane.h"
#include "r_draw_rgba.h"
#include "d_net.h"
#include "r_drawer_context.h"
#include "gi.h"
#include "stats.h"
#include "x86.h"
#ifdef X86_ASM
extern "C" void R_SetSpanSource_ASM (const BYTE *flat);
extern "C" void R_SetSpanSize_ASM (int xbits, int ybits);
extern "C" void R_SetSpanColormap_ASM (BYTE *colormap);
extern "C" void R_SetTiltedSpanSource_ASM(const BYTE *flat);
extern "C" BYTE *ds_curcolormap, *ds_cursource, *ds_curtiltedsource;
#endif
DCanvas *DrawerContext::Canvas()
{
return dc_canvas;
}
uint8_t DrawerContext::FlatColor()
{
return dc_color;
}
FColormap *DrawerContext::LightColormap()
{
return dc_fcolormap;
}
fixed_t DrawerContext::TextureFrac()
{
return dc_texturefrac;
}
fixed_t DrawerContext::TextureStep()
{
return dc_iscale;
}
double DrawerContext::TextureMid()
{
return dc_texturemid;
}
int DrawerContext::SpanXBits()
{
return ds_xbits;
}
int DrawerContext::SpanYBits()
{
return ds_ybits;
}
lighttable_t *DrawerContext::SpanLitColormap()
{
return ds_colormap;
}
bool DrawerContext::IsFuzzColumn()
{
return colfunc == fuzzcolfunc;
}
bool DrawerContext::IsFillColumn()
{
return colfunc == R_FillColumn;
}
bool DrawerContext::IsBaseColumn()
{
return colfunc == basecolfunc;
}
void DrawerContext::SetDest(int x, int y)
{
int pixelsize = r_swtruecolor ? 4 : 1;
dc_dest = dc_destorg + (ylookup[y] + x) * pixelsize;
}
void DrawerContext::SetFlatColor(uint8_t color_index)
{
dc_color = color_index;
}
void DrawerContext::SetLight(FColormap *base_colormap, float light, int shade)
{
R_SetColorMapLight(base_colormap, light, shade);
}
void DrawerContext::SetX(int x)
{
dc_x = x;
}
void DrawerContext::SetY1(int y)
{
dc_yl = y;
}
void DrawerContext::SetY2(int y)
{
dc_yh = y;
}
void DrawerContext::SetSource(const BYTE *source)
{
dc_source = source;
}
void DrawerContext::SetTextureFrac(fixed_t pos)
{
dc_texturefrac = pos;
}
void DrawerContext::SetTextureStep(fixed_t step)
{
dc_iscale = step;
}
void DrawerContext::SetTextureMid(double value)
{
dc_texturemid = value;
}
void DrawerContext::SetDrawCount(int count)
{
dc_count = count;
}
void DrawerContext::SetSpanY(int y)
{
ds_y = y;
}
void DrawerContext::SetSpanX1(int x)
{
ds_x1 = x;
}
void DrawerContext::SetSpanX2(int x)
{
ds_x2 = x;
}
void DrawerContext::SetSpanXStep(dsfixed_t step)
{
ds_xstep = step;
}
void DrawerContext::SetSpanYStep(dsfixed_t step)
{
ds_ystep = step;
}
void DrawerContext::SetSpanXBits(int bits)
{
ds_xbits = bits;
}
void DrawerContext::SetSpanYBits(int bits)
{
ds_ybits = bits;
}
void DrawerContext::SetSpanXFrac(dsfixed_t frac)
{
ds_xfrac = frac;
}
void DrawerContext::SetSpanYFrac(dsfixed_t frac)
{
ds_yfrac = frac;
}
void DrawerContext::SetSpanLight(FColormap *base_colormap, float light, int shade)
{
R_SetDSColorMapLight(base_colormap ? base_colormap : &identitycolormap, light, shade);
R_SetSpanColormap();
}
ESPSResult DrawerContext::SetPatchStyle(FRenderStyle style, fixed_t alpha, int translation, DWORD color)
{
return R_SetPatchStyle(style, alpha, translation, color);
}
ESPSResult DrawerContext::SetPatchStyle(FRenderStyle style, float alpha, int translation, DWORD color)
{
return R_SetPatchStyle(style, FLOAT2FIXED(alpha), translation, color);
}
void DrawerContext::FinishSetPatchStyle()
{
R_FinishSetPatchStyle();
}
void DrawerContext::SetCanvas(DCanvas *canvas)
{
dc_canvas = canvas;
dc_destorg = canvas->GetBuffer();
if (r_swtruecolor != canvas->IsBgra())
{
r_swtruecolor = canvas->IsBgra();
R_InitColumnDrawers();
}
}
void DrawerContext::SetTranslationMap(lighttable_t *translation)
{
R_SetTranslationMap(translation ? translation : identitymap);
}
void DrawerContext::SetSpanSource(FTexture *tex)
{
R_SetupSpanBits(tex);
if (r_swtruecolor)
ds_source = (const BYTE*)tex->GetPixelsBgra();
else
ds_source = tex->GetPixels();
#ifdef X86_ASM
if (!r_swtruecolor && ds_source != ds_cursource)
{
R_SetSpanSource_ASM (ds_source);
}
if (!r_swtruecolor)
{
if (ds_source != ds_curtiltedsource)
R_SetTiltedSpanSource_ASM(ds_source);
}
#endif
}
void DrawerContext::SetTiltedSpanState(FVector3 plane_sz, FVector3 plane_su, FVector3 plane_sv, bool plane_shade, float planelightfloat, fixed_t pviewx, fixed_t pviewy)
{
ds_plane_sz = plane_sz;
ds_plane_su = plane_su;
ds_plane_sv = plane_sv;
ds_plane_shade = plane_shade;
ds_planelightfloat = planelightfloat;
ds_pviewx = pviewx;
ds_pviewy = pviewy;
if (!plane_shade)
{
for (int i = 0; i < viewwidth; ++i)
{
tiltlighting[i] = DrawerContext::SpanLitColormap();
}
}
}
void DrawerContext::SetSlabLight(const BYTE *colormap)
{
R_SetupDrawSlab(colormap);
}
void DrawerContext::DrawSlab(int dx, fixed_t v, int dy, fixed_t vi, const BYTE *source, int dest_x, int dest_y)
{
int pixelsize = r_swtruecolor ? 4 : 1;
R_DrawSlab(dx, v, dy, vi, source, (ylookup[dest_y] + dest_x) * pixelsize + dc_destorg);
}
void DrawerContext::SetSpanStyle(fixed_t alpha, bool additive, bool masked)
{
if (spanfunc != R_FillSpan)
{
if (masked)
{
if (alpha < OPAQUE || additive)
{
if (!additive)
{
spanfunc = R_DrawSpanMaskedTranslucent;
dc_srcblend = Col2RGB8[alpha >> 10];
dc_destblend = Col2RGB8[(OPAQUE - alpha) >> 10];
dc_srcalpha = alpha;
dc_destalpha = OPAQUE - alpha;
}
else
{
spanfunc = R_DrawSpanMaskedAddClamp;
dc_srcblend = Col2RGB8_LessPrecision[alpha >> 10];
dc_destblend = Col2RGB8_LessPrecision[FRACUNIT >> 10];
dc_srcalpha = alpha;
dc_destalpha = OPAQUE - alpha;
}
}
else
{
spanfunc = R_DrawSpanMasked;
}
}
else
{
if (alpha < OPAQUE || additive)
{
if (!additive)
{
spanfunc = R_DrawSpanTranslucent;
dc_srcblend = Col2RGB8[alpha >> 10];
dc_destblend = Col2RGB8[(OPAQUE - alpha) >> 10];
dc_srcalpha = alpha;
dc_destalpha = OPAQUE - alpha;
}
else
{
spanfunc = R_DrawSpanAddClamp;
dc_srcblend = Col2RGB8_LessPrecision[alpha >> 10];
dc_destblend = Col2RGB8_LessPrecision[FRACUNIT >> 10];
dc_srcalpha = alpha;
dc_destalpha = OPAQUE - alpha;
}
}
else
{
spanfunc = R_DrawSpan;
}
}
}
}
void DrawerContext::RtInitCols(BYTE *buffer)
{
rt_initcols(buffer);
}
void DrawerContext::RtSpanCoverage(int x, int start, int stop)
{
rt_span_coverage(x, start, stop);
}
void DrawerContext::SetMaskedColumnState(short *mfloorclip, short *mceilingclip, double spryscale, double sprtopscreen, bool sprflipvert)
{
dc_mfloorclip = mfloorclip;
dc_mceilingclip = mceilingclip;
dc_spryscale = spryscale;
dc_sprtopscreen = sprtopscreen;
dc_sprflipvert = sprflipvert;
}
void DrawerContext::DrawMaskedColumn(int x, const BYTE *column, const FTexture::Span *spans)
{
R_DrawMaskedColumn(x, column, spans);
}
void DrawerContext::DrawMaskedColumnHoriz(int x, const BYTE *column, const FTexture::Span *spans)
{
dc_x = x;
R_DrawMaskedColumnHoriz(column, spans);
}
void DrawerContext::DrawFogBoundary(int x1, int x2, short *uclip, short *dclip)
{
R_DrawFogBoundary(x1, x2, uclip, dclip);
}
void DrawerContext::DrawRt4cols(int sx)
{
rt_draw4cols(sx);
}
void DrawerContext::DrawColumn()
{
colfunc();
}
void DrawerContext::DrawSpan()
{
spanfunc();
}
void DrawerContext::DrawHColumnPre()
{
hcolfunc_pre();
}
void DrawerContext::DrawSimplePolySpan()
{
R_DrawSpan();
}
void DrawerContext::SetBaseStyle()
{
colfunc = basecolfunc;
hcolfunc_post1 = rt_map1col;
hcolfunc_post4 = rt_map4cols;
}
void DrawerContext::DrawWall(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, FTexture *rw_pic, fixed_t rw_offset, const BYTE *(*getcol)(FTexture *tex, int col))
{
wallscan(x1, x2, uwal, dwal, swal, lwal, yrepeat, rw_pic, rw_offset, getcol ? getcol : R_GetColumn);
}
void DrawerContext::DrawMaskedWall(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, FTexture *rw_pic, fixed_t rw_offset, const BYTE *(*getcol)(FTexture *tex, int col))
{
maskwallscan(x1, x2, uwal, dwal, swal, lwal, yrepeat, rw_pic, rw_offset, getcol ? getcol : R_GetColumn);
}
void DrawerContext::DrawTransMaskedWall(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, FTexture *rw_pic, fixed_t rw_offset, const BYTE *(*getcol)(FTexture *tex, int col))
{
transmaskwallscan(x1, x2, uwal, dwal, swal, lwal, yrepeat, rw_pic, rw_offset, getcol ? getcol : R_GetColumn);
}
void DrawerContext::DrawColoredSpan(int y, int x1, int x2)
{
R_DrawColoredSpan(y, x1, x2);
}
void DrawerContext::DrawTiltedSpan(int y, int x1, int x2)
{
R_DrawTiltedSpan(y, x1, x2);
}
void DrawerContext::FillTransColumn(int x, int y1, int y2, int color, int alpha)
{
R_FillTransColumn(x, y1, y2, color, alpha);
}

123
src/r_drawer_context.h Normal file
View file

@ -0,0 +1,123 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id:$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This source is available for distribution and/or modification
// only under the terms of the DOOM Source Code License as
// published by id Software. All rights reserved.
//
// The source is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
// for more details.
//
// DESCRIPTION:
// System specific interface stuff.
//
//-----------------------------------------------------------------------------
#ifndef __R_DRAWER_CONTEXT__
#define __R_DRAWER_CONTEXT__
#include "r_defs.h"
// [RH] Consolidate column drawer selection
enum ESPSResult
{
DontDraw, // not useful to draw this
DoDraw0, // draw this as if r_columnmethod is 0
DoDraw1, // draw this as if r_columnmethod is 1
};
struct TiltedPlaneData;
// Immediate graphics context for column/span based software rendering.
class DrawerContext
{
public:
static DCanvas *Canvas(); // dc_destorg
static uint8_t FlatColor(); // dc_color
static FColormap *LightColormap(); // dc_fcolormap
static fixed_t TextureFrac(); // dc_texturefrac
static fixed_t TextureStep(); // dc_iscale
static double TextureMid(); // dc_texturemid
static int SpanXBits(); // ds_xbits
static int SpanYBits(); // ds_ybits
static lighttable_t *SpanLitColormap(); // ds_colormap
static bool IsFuzzColumn(); // colfunc == fuzzcolfunc
static bool IsFillColumn(); // colfunc == R_FillColumn
static bool IsBaseColumn(); // colfunc == basecolfunc
static void SetCanvas(DCanvas *canvas); // dc_destorg
static void SetFlatColor(uint8_t color_index); // dc_color
static void SetLight(FColormap *base_colormap, float light, int shade);
static void SetTranslationMap(lighttable_t *translation);
static void SetX(int x); // dc_x
static void SetY1(int y); // dc_yl
static void SetY2(int y); // dc_yh
static void SetSource(const BYTE *source); // dc_source
static void SetTextureFrac(fixed_t pos); // dc_texturefrac
static void SetTextureStep(fixed_t step); // dc_iscale
static void SetTextureMid(double value); // dc_texturemid
static void SetDest(int x, int y); // dc_dest
static void SetDrawCount(int count); // dc_count
static void SetSpanY(int y); // ds_y
static void SetSpanX1(int x); // ds_x1
static void SetSpanX2(int x); // ds_x2
static void SetSpanXStep(dsfixed_t step); // ds_xstep
static void SetSpanYStep(dsfixed_t step); // ds_ystep
static void SetSpanXBits(int bits); // ds_xbits
static void SetSpanYBits(int bits); // ds_ybits
static void SetSpanXFrac(dsfixed_t frac); // ds_xfrac
static void SetSpanYFrac(dsfixed_t frac); // ds_yfrac
static void SetSpanLight(FColormap *base_colormap, float light, int shade);
static void SetSpanSource(FTexture *texture);
static void SetSpanStyle(fixed_t alpha, bool additive, bool masked);
static void SetSlabLight(const BYTE *colormap);
static ESPSResult SetPatchStyle(FRenderStyle style, fixed_t alpha, int translation, DWORD color);
static ESPSResult SetPatchStyle(FRenderStyle style, float alpha, int translation, DWORD color);
// Call this after finished drawing the current thing, in case its style was STYLE_Shade
static void SetBaseStyle();
static void FinishSetPatchStyle();
static void SetMaskedColumnState(short *mfloorclip, short *mceilingclip, double spryscale, double sprtopscreen, bool sprflipvert);
static void SetTiltedSpanState(FVector3 plane_sz, FVector3 plane_su, FVector3 plane_sv, bool plane_shade, float planelightfloat, fixed_t pviewx, fixed_t pviewy);
static void RtInitCols(BYTE *buffer);
static void RtSpanCoverage(int x, int start, int stop);
static void DrawMaskedColumn(int x, const BYTE *column, const FTexture::Span *spans);
static void DrawMaskedColumnHoriz(int x, const BYTE *column, const FTexture::Span *spans);
static void DrawRt4cols(int sx);
static void DrawColumn();
static void DrawHColumnPre();
static void DrawSpan();
static void DrawSimplePolySpan();
static void DrawWall(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, FTexture *texture, fixed_t texturefrac, const BYTE *(*getcol)(FTexture *tex, int col) = nullptr);
static void DrawMaskedWall(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, FTexture *texture, fixed_t texturefrac, const BYTE *(*getcol)(FTexture *tex, int col) = nullptr);
static void DrawTransMaskedWall(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, FTexture *texture, fixed_t texturefrac, const BYTE *(*getcol)(FTexture *tex, int col) = nullptr);
static void DrawColoredSpan(int y, int x1, int x2);
static void DrawTiltedSpan(int y, int x1, int x2);
static void DrawSlab(int dx, fixed_t v, int dy, fixed_t vi, const BYTE *source, int dest_x, int dest_y);
static void FillTransColumn(int x, int y1, int y2, int color, int alpha);
static void DrawFogBoundary(int x1, int x2, short *uclip, short *dclip);
};
#endif

View file

@ -38,6 +38,8 @@
** Let's hope so. :-) ** Let's hope so. :-)
*/ */
#define DRAWER_INTERNALS
#include "templates.h" #include "templates.h"
#include "doomtype.h" #include "doomtype.h"
#include "doomdef.h" #include "doomdef.h"
@ -1128,26 +1130,26 @@ void R_DrawMaskedColumnHoriz (const BYTE *column, const FTexture::Span *span)
const int top = span->TopOffset; const int top = span->TopOffset;
// calculate unclipped screen coordinates for post // calculate unclipped screen coordinates for post
dc_yl = xs_RoundToInt(sprtopscreen + spryscale * top); dc_yl = xs_RoundToInt(dc_sprtopscreen + dc_spryscale * top);
dc_yh = xs_RoundToInt(sprtopscreen + spryscale * (top + length) - 1); dc_yh = xs_RoundToInt(dc_sprtopscreen + dc_spryscale * (top + length) - 1);
if (sprflipvert) if (dc_sprflipvert)
{ {
swapvalues (dc_yl, dc_yh); swapvalues (dc_yl, dc_yh);
} }
if (dc_yh >= mfloorclip[dc_x]) if (dc_yh >= dc_mfloorclip[dc_x])
{ {
dc_yh = mfloorclip[dc_x] - 1; dc_yh = dc_mfloorclip[dc_x] - 1;
} }
if (dc_yl < mceilingclip[dc_x]) if (dc_yl < dc_mceilingclip[dc_x])
{ {
dc_yl = mceilingclip[dc_x]; dc_yl = dc_mceilingclip[dc_x];
} }
if (dc_yl <= dc_yh) if (dc_yl <= dc_yh)
{ {
if (sprflipvert) if (dc_sprflipvert)
{ {
dc_texturefrac = (dc_yl*dc_iscale) - (top << FRACBITS) dc_texturefrac = (dc_yl*dc_iscale) - (top << FRACBITS)
- fixed_t(CenterY * dc_iscale) - texturemid; - fixed_t(CenterY * dc_iscale) - texturemid;
@ -1178,7 +1180,7 @@ void R_DrawMaskedColumnHoriz (const BYTE *column, const FTexture::Span *span)
} }
fixed_t endfrac = dc_texturefrac + (dc_yh-dc_yl)*dc_iscale; fixed_t endfrac = dc_texturefrac + (dc_yh-dc_yl)*dc_iscale;
const fixed_t maxfrac = length << FRACBITS; const fixed_t maxfrac = length << FRACBITS;
if (dc_yh < mfloorclip[dc_x]-1 && endfrac < maxfrac - dc_iscale) if (dc_yh < dc_mfloorclip[dc_x]-1 && endfrac < maxfrac - dc_iscale)
{ {
dc_yh++; dc_yh++;
} }
@ -1198,7 +1200,7 @@ nextpost:
span++; span++;
} }
if (sprflipvert) if (dc_sprflipvert)
{ {
unsigned int *front = horizspan[dc_x&3]; unsigned int *front = horizspan[dc_x&3];
unsigned int *back = dc_ctspan[dc_x&3] - 2; unsigned int *back = dc_ctspan[dc_x&3] - 2;

View file

@ -34,6 +34,8 @@
** Please see r_drawt.cpp for a description of the globals used. ** Please see r_drawt.cpp for a description of the globals used.
*/ */
#define DRAWER_INTERNALS
#include "templates.h" #include "templates.h"
#include "doomtype.h" #include "doomtype.h"
#include "doomdef.h" #include "doomdef.h"

View file

@ -23,6 +23,8 @@
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#define DRAWER_INTERNALS
// HEADER FILES ------------------------------------------------------------ // HEADER FILES ------------------------------------------------------------
#include <stdlib.h> #include <stdlib.h>
@ -150,17 +152,6 @@ angle_t xtoviewangle[MAXWIDTH+1];
bool foggy; // [RH] ignore extralight and fullbright? bool foggy; // [RH] ignore extralight and fullbright?
int r_actualextralight; int r_actualextralight;
void (*colfunc) (void);
void (*basecolfunc) (void);
void (*fuzzcolfunc) (void);
void (*transcolfunc) (void);
void (*spanfunc) (void);
void (*hcolfunc_pre) (void);
void (*hcolfunc_post1) (int hx, int sx, int yl, int yh);
void (*hcolfunc_post2) (int hx, int sx, int yl, int yh);
void (*hcolfunc_post4) (int sx, int yl, int yh);
cycle_t WallCycles, PlaneCycles, MaskedCycles, WallScanCycles; cycle_t WallCycles, PlaneCycles, MaskedCycles, WallScanCycles;
// PRIVATE DATA DEFINITIONS ------------------------------------------------ // PRIVATE DATA DEFINITIONS ------------------------------------------------
@ -820,6 +811,7 @@ void R_SetupBuffer ()
ASM_PatchPitch (); ASM_PatchPitch ();
#endif #endif
} }
dc_canvas = RenderTarget;
dc_destorg = lineptr; dc_destorg = lineptr;
for (int i = 0; i < RenderTarget->GetHeight(); i++) for (int i = 0; i < RenderTarget->GetHeight(); i++)
{ {

View file

@ -110,22 +110,6 @@ extern FColormap* fixedcolormap;
extern FSpecialColormap*realfixedcolormap; extern FSpecialColormap*realfixedcolormap;
//
// Function pointers to switch refresh/drawing functions.
// Used to select shadow mode etc.
//
extern void (*colfunc) (void);
extern void (*basecolfunc) (void);
extern void (*fuzzcolfunc) (void);
extern void (*transcolfunc) (void);
// No shadow effects on floors.
extern void (*spanfunc) (void);
// [RH] Function pointers for the horizontal column drawers.
extern void (*hcolfunc_pre) (void);
extern void (*hcolfunc_post1) (int hx, int sx, int yl, int yh);
extern void (*hcolfunc_post2) (int hx, int sx, int yl, int yh);
extern void (*hcolfunc_post4) (int sx, int yl, int yh);
void R_InitTextureMapping (); void R_InitTextureMapping ();

View file

@ -58,7 +58,7 @@
#include "r_3dfloors.h" #include "r_3dfloors.h"
#include "v_palette.h" #include "v_palette.h"
#include "r_data/colormaps.h" #include "r_data/colormaps.h"
#include "r_draw_rgba.h" #include "r_drawer_context.h"
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(disable:4244) #pragma warning(disable:4244)
@ -138,8 +138,6 @@ FVector3 plane_sz, plane_su, plane_sv;
float planelightfloat; float planelightfloat;
bool plane_shade; bool plane_shade;
fixed_t pviewx, pviewy; fixed_t pviewx, pviewy;
void R_DrawTiltedPlane_ASM (int y, int x1);
} }
float yslope[MAXHEIGHT]; float yslope[MAXHEIGHT];
@ -147,13 +145,6 @@ static fixed_t xscale, yscale;
static double xstepscale, ystepscale; static double xstepscale, ystepscale;
static double basexfrac, baseyfrac; static double basexfrac, baseyfrac;
#ifdef X86_ASM
extern "C" void R_SetSpanSource_ASM (const BYTE *flat);
extern "C" void R_SetSpanSize_ASM (int xbits, int ybits);
extern "C" void R_SetSpanColormap_ASM (BYTE *colormap);
extern "C" void R_SetTiltedSpanSource_ASM (const BYTE *flat);
extern "C" BYTE *ds_curcolormap, *ds_cursource, *ds_curtiltedsource;
#endif
void R_DrawSinglePlane (visplane_t *, fixed_t alpha, bool additive, bool masked); void R_DrawSinglePlane (visplane_t *, fixed_t alpha, bool additive, bool masked);
//========================================================================== //==========================================================================
@ -220,304 +211,22 @@ void R_MapPlane (int y, int x1)
distance = planeheight * yslope[y]; distance = planeheight * yslope[y];
ds_xstep = xs_ToFixed(32-ds_xbits, distance * xstepscale); DrawerContext::SetSpanXStep(xs_ToFixed(32 - DrawerContext::SpanXBits(), distance * xstepscale));
ds_ystep = xs_ToFixed(32-ds_ybits, distance * ystepscale); DrawerContext::SetSpanYStep(xs_ToFixed(32 - DrawerContext::SpanYBits(), distance * ystepscale));
ds_xfrac = xs_ToFixed(32-ds_xbits, distance * basexfrac) + pviewx; DrawerContext::SetSpanXFrac(xs_ToFixed(32 - DrawerContext::SpanXBits(), distance * basexfrac) + pviewx);
ds_yfrac = xs_ToFixed(32-ds_ybits, distance * baseyfrac) + pviewy; DrawerContext::SetSpanYFrac(xs_ToFixed(32 - DrawerContext::SpanYBits(), distance * baseyfrac) + pviewy);
if (plane_shade) if (plane_shade)
{ {
// Determine lighting based on the span's distance from the viewer. // Determine lighting based on the span's distance from the viewer.
R_SetDSColorMapLight(basecolormap, GlobVis * fabs(CenterY - y), planeshade); DrawerContext::SetSpanLight(basecolormap, GlobVis * fabs(CenterY - y), planeshade);
} }
#ifdef X86_ASM DrawerContext::SetSpanY(y);
if (!r_swtruecolor && ds_colormap != ds_curcolormap) DrawerContext::SetSpanX1(x1);
R_SetSpanColormap_ASM (ds_colormap); DrawerContext::SetSpanX2(x2);
#endif
ds_y = y; DrawerContext::DrawSpan();
ds_x1 = x1;
ds_x2 = x2;
spanfunc ();
}
//==========================================================================
//
// R_CalcTiltedLighting
//
// Calculates the lighting for one row of a tilted plane. If the definition
// of GETPALOOKUP changes, this needs to change, too.
//
//==========================================================================
extern "C" {
void R_CalcTiltedLighting (double lval, double lend, int width)
{
double lstep;
BYTE *lightfiller;
BYTE *basecolormapdata = basecolormap->Maps;
int i = 0;
if (width == 0 || lval == lend)
{ // Constant lighting
lightfiller = basecolormapdata + (GETPALOOKUP(lval, planeshade) << COLORMAPSHIFT);
}
else
{
lstep = (lend - lval) / width;
if (lval >= MAXLIGHTVIS)
{ // lval starts "too bright".
lightfiller = basecolormapdata + (GETPALOOKUP(lval, planeshade) << COLORMAPSHIFT);
for (; i <= width && lval >= MAXLIGHTVIS; ++i)
{
tiltlighting[i] = lightfiller;
lval += lstep;
}
}
if (lend >= MAXLIGHTVIS)
{ // lend ends "too bright".
lightfiller = basecolormapdata + (GETPALOOKUP(lend, planeshade) << COLORMAPSHIFT);
for (; width > i && lend >= MAXLIGHTVIS; --width)
{
tiltlighting[width] = lightfiller;
lend -= lstep;
}
}
if (width > 0)
{
lval = FIXED2DBL(planeshade) - lval;
lend = FIXED2DBL(planeshade) - lend;
lstep = (lend - lval) / width;
if (lstep < 0)
{ // Going from dark to light
if (lval < 1.)
{ // All bright
lightfiller = basecolormapdata;
}
else
{
if (lval >= NUMCOLORMAPS)
{ // Starts beyond the dark end
BYTE *clight = basecolormapdata + ((NUMCOLORMAPS-1) << COLORMAPSHIFT);
while (lval >= NUMCOLORMAPS && i <= width)
{
tiltlighting[i++] = clight;
lval += lstep;
}
if (i > width)
return;
}
while (i <= width && lval >= 0)
{
tiltlighting[i++] = basecolormapdata + (xs_ToInt(lval) << COLORMAPSHIFT);
lval += lstep;
}
lightfiller = basecolormapdata;
}
}
else
{ // Going from light to dark
if (lval >= (NUMCOLORMAPS-1))
{ // All dark
lightfiller = basecolormapdata + ((NUMCOLORMAPS-1) << COLORMAPSHIFT);
}
else
{
while (lval < 0 && i <= width)
{
tiltlighting[i++] = basecolormapdata;
lval += lstep;
}
if (i > width)
return;
while (i <= width && lval < (NUMCOLORMAPS-1))
{
tiltlighting[i++] = basecolormapdata + (xs_ToInt(lval) << COLORMAPSHIFT);
lval += lstep;
}
lightfiller = basecolormapdata + ((NUMCOLORMAPS-1) << COLORMAPSHIFT);
}
}
}
}
for (; i <= width; i++)
{
tiltlighting[i] = lightfiller;
}
}
} // extern "C"
//==========================================================================
//
// R_MapTiltedPlane
//
//==========================================================================
void R_MapTiltedPlane_C (int y, int x1)
{
int x2 = spanend[y];
int width = x2 - x1;
double iz, uz, vz;
BYTE *fb;
DWORD u, v;
int i;
iz = plane_sz[2] + plane_sz[1]*(centery-y) + plane_sz[0]*(x1-centerx);
// Lighting is simple. It's just linear interpolation from start to end
if (plane_shade)
{
uz = (iz + plane_sz[0]*width) * planelightfloat;
vz = iz * planelightfloat;
R_CalcTiltedLighting (vz, uz, width);
}
uz = plane_su[2] + plane_su[1]*(centery-y) + plane_su[0]*(x1-centerx);
vz = plane_sv[2] + plane_sv[1]*(centery-y) + plane_sv[0]*(x1-centerx);
fb = ylookup[y] + x1 + dc_destorg;
BYTE vshift = 32 - ds_ybits;
BYTE ushift = vshift - ds_xbits;
int umask = ((1 << ds_xbits) - 1) << ds_ybits;
#if 0 // The "perfect" reference version of this routine. Pretty slow.
// Use it only to see how things are supposed to look.
i = 0;
do
{
double z = 1.f/iz;
u = SQWORD(uz*z) + pviewx;
v = SQWORD(vz*z) + pviewy;
R_SetDSColorMapLight(tiltlighting[i], 0, 0);
fb[i++] = ds_colormap[ds_source[(v >> vshift) | ((u >> ushift) & umask)]];
iz += plane_sz[0];
uz += plane_su[0];
vz += plane_sv[0];
} while (--width >= 0);
#else
//#define SPANSIZE 32
//#define INVSPAN 0.03125f
//#define SPANSIZE 8
//#define INVSPAN 0.125f
#define SPANSIZE 16
#define INVSPAN 0.0625f
double startz = 1.f/iz;
double startu = uz*startz;
double startv = vz*startz;
double izstep, uzstep, vzstep;
izstep = plane_sz[0] * SPANSIZE;
uzstep = plane_su[0] * SPANSIZE;
vzstep = plane_sv[0] * SPANSIZE;
x1 = 0;
width++;
while (width >= SPANSIZE)
{
iz += izstep;
uz += uzstep;
vz += vzstep;
double endz = 1.f/iz;
double endu = uz*endz;
double endv = vz*endz;
DWORD stepu = SQWORD((endu - startu) * INVSPAN);
DWORD stepv = SQWORD((endv - startv) * INVSPAN);
u = SQWORD(startu) + pviewx;
v = SQWORD(startv) + pviewy;
for (i = SPANSIZE-1; i >= 0; i--)
{
fb[x1] = *(tiltlighting[x1] + ds_source[(v >> vshift) | ((u >> ushift) & umask)]);
x1++;
u += stepu;
v += stepv;
}
startu = endu;
startv = endv;
width -= SPANSIZE;
}
if (width > 0)
{
if (width == 1)
{
u = SQWORD(startu);
v = SQWORD(startv);
fb[x1] = *(tiltlighting[x1] + ds_source[(v >> vshift) | ((u >> ushift) & umask)]);
}
else
{
double left = width;
iz += plane_sz[0] * left;
uz += plane_su[0] * left;
vz += plane_sv[0] * left;
double endz = 1.f/iz;
double endu = uz*endz;
double endv = vz*endz;
left = 1.f/left;
DWORD stepu = SQWORD((endu - startu) * left);
DWORD stepv = SQWORD((endv - startv) * left);
u = SQWORD(startu) + pviewx;
v = SQWORD(startv) + pviewy;
for (; width != 0; width--)
{
fb[x1] = *(tiltlighting[x1] + ds_source[(v >> vshift) | ((u >> ushift) & umask)]);
x1++;
u += stepu;
v += stepv;
}
}
}
#endif
}
void R_MapTiltedPlane_rgba (int y, int x1)
{
int x2 = spanend[y];
// Slopes are broken currently in master.
// Until R_DrawTiltedPlane is fixed we are just going to fill with a solid color.
uint32_t *source = (uint32_t*)ds_source;
int source_width = 1 << ds_xbits;
int source_height = 1 << ds_ybits;
uint32_t *dest = ylookup[y] + x1 + (uint32_t*)dc_destorg;
int count = x2 - x1 + 1;
while (count > 0)
{
*(dest++) = source[0];
count--;
}
}
//==========================================================================
//
// R_MapColoredPlane
//
//==========================================================================
void R_MapColoredPlane_C (int y, int x1)
{
memset (ylookup[y] + x1 + dc_destorg, ds_color, spanend[y] - x1 + 1);
}
void R_MapColoredPlane_rgba(int y, int x1)
{
uint32_t *dest = ylookup[y] + x1 + (uint32_t*)dc_destorg;
int count = (spanend[y] - x1 + 1);
uint32_t light = calc_light_multiplier(ds_light);
uint32_t color = shade_pal_index_simple(ds_color, light);
for (int i = 0; i < count; i++)
dest[i] = color;
} }
//========================================================================== //==========================================================================
@ -1014,7 +723,7 @@ static void R_DrawSky (visplane_t *pl)
rw_offset = 0; rw_offset = 0;
frontyScale = rw_pic->Scale.Y; frontyScale = rw_pic->Scale.Y;
dc_texturemid = skymid * frontyScale; DrawerContext::SetTextureMid(skymid * frontyScale);
if (1 << frontskytex->HeightBits == frontskytex->GetHeight()) if (1 << frontskytex->HeightBits == frontskytex->GetHeight())
{ // The texture tiles nicely { // The texture tiles nicely
@ -1023,8 +732,8 @@ static void R_DrawSky (visplane_t *pl)
lastskycol[x] = 0xffffffff; lastskycol[x] = 0xffffffff;
lastskycol_bgra[x] = 0xffffffff; lastskycol_bgra[x] = 0xffffffff;
} }
wallscan (pl->left, pl->right, (short *)pl->top, (short *)pl->bottom, swall, lwall, DrawerContext::DrawWall (pl->left, pl->right, (short *)pl->top, (short *)pl->bottom, swall, lwall,
frontyScale, backskytex == NULL ? R_GetOneSkyColumn : R_GetTwoSkyColumns); frontyScale, rw_pic, rw_offset, backskytex == NULL ? R_GetOneSkyColumn : R_GetTwoSkyColumns);
} }
else else
{ // The texture does not tile nicely { // The texture does not tile nicely
@ -1047,7 +756,7 @@ static void R_DrawSkyStriped (visplane_t *pl)
if (topfrac < 0) topfrac += frontskytex->GetHeight(); if (topfrac < 0) topfrac += frontskytex->GetHeight();
yl = 0; yl = 0;
yh = short((frontskytex->GetHeight() - topfrac) * frontyScale); yh = short((frontskytex->GetHeight() - topfrac) * frontyScale);
dc_texturemid = topfrac - iscale * (1 - CenterY); DrawerContext::SetTextureMid(topfrac - iscale * (1 - CenterY));
while (yl < viewheight) while (yl < viewheight)
{ {
@ -1061,11 +770,11 @@ static void R_DrawSkyStriped (visplane_t *pl)
lastskycol[x] = 0xffffffff; lastskycol[x] = 0xffffffff;
lastskycol_bgra[x] = 0xffffffff; lastskycol_bgra[x] = 0xffffffff;
} }
wallscan (pl->left, pl->right, top, bot, swall, lwall, rw_pic->Scale.Y, DrawerContext::DrawWall(pl->left, pl->right, top, bot, swall, lwall, rw_pic->Scale.Y,
backskytex == NULL ? R_GetOneSkyColumn : R_GetTwoSkyColumns); rw_pic, rw_offset, backskytex == NULL ? R_GetOneSkyColumn : R_GetTwoSkyColumns);
yl = yh; yl = yh;
yh += drawheight; yh += drawheight;
dc_texturemid = iscale * (centery-yl-1); DrawerContext::SetTextureMid(iscale * (centery-yl-1));
} }
} }
@ -1086,7 +795,7 @@ int R_DrawPlanes ()
int i; int i;
int vpcount = 0; int vpcount = 0;
ds_color = 3; DrawerContext::SetFlatColor(3);
for (i = 0; i < MAXVISPLANES; i++) for (i = 0; i < MAXVISPLANES; i++)
{ {
@ -1111,7 +820,7 @@ void R_DrawHeightPlanes(double height)
visplane_t *pl; visplane_t *pl;
int i; int i;
ds_color = 3; DrawerContext::SetFlatColor(3);
DVector3 oViewPos = ViewPos; DVector3 oViewPos = ViewPos;
DAngle oViewAngle = ViewAngle; DAngle oViewAngle = ViewAngle;
@ -1151,8 +860,8 @@ void R_DrawSinglePlane (visplane_t *pl, fixed_t alpha, bool additive, bool maske
if (r_drawflat) if (r_drawflat)
{ // [RH] no texture mapping { // [RH] no texture mapping
ds_color += 4; DrawerContext::SetFlatColor(DrawerContext::FlatColor() + 4);
R_MapVisPlane (pl, R_MapColoredPlane); R_MapVisPlane (pl, [](int y, int x1) { DrawerContext::DrawColoredSpan(y, x1, spanend[y]); });
} }
else if (pl->picnum == skyflatnum) else if (pl->picnum == skyflatnum)
{ // sky flat { // sky flat
@ -1175,13 +884,9 @@ void R_DrawSinglePlane (visplane_t *pl, fixed_t alpha, bool additive, bool maske
{ // Don't waste time on a masked texture if it isn't really masked. { // Don't waste time on a masked texture if it isn't really masked.
masked = false; masked = false;
} }
R_SetupSpanBits(tex);
double xscale = pl->xform.xScale * tex->Scale.X; double xscale = pl->xform.xScale * tex->Scale.X;
double yscale = pl->xform.yScale * tex->Scale.Y; double yscale = pl->xform.yScale * tex->Scale.Y;
if (r_swtruecolor) DrawerContext::SetSpanSource(tex);
ds_source = (const BYTE*)tex->GetPixelsBgra();
else
ds_source = tex->GetPixels();
basecolormap = pl->colormap; basecolormap = pl->colormap;
planeshade = LIGHT2SHADE(pl->lightlevel); planeshade = LIGHT2SHADE(pl->lightlevel);
@ -1544,13 +1249,13 @@ void R_DrawSkyPlane (visplane_t *pl)
bool fakefixed = false; bool fakefixed = false;
if (fixedcolormap) if (fixedcolormap)
{ {
R_SetColorMapLight(fixedcolormap, 0, 0); DrawerContext::SetLight(fixedcolormap, 0, 0);
} }
else else
{ {
fakefixed = true; fakefixed = true;
fixedcolormap = &NormalLight; fixedcolormap = &NormalLight;
R_SetColorMapLight(fixedcolormap, 0, 0); DrawerContext::SetLight(fixedcolormap, 0, 0);
} }
R_DrawSky (pl); R_DrawSky (pl);
@ -1567,13 +1272,6 @@ void R_DrawSkyPlane (visplane_t *pl)
void R_DrawNormalPlane (visplane_t *pl, double _xscale, double _yscale, fixed_t alpha, bool additive, bool masked) void R_DrawNormalPlane (visplane_t *pl, double _xscale, double _yscale, fixed_t alpha, bool additive, bool masked)
{ {
#ifdef X86_ASM
if (!r_swtruecolor && ds_source != ds_cursource)
{
R_SetSpanSource_ASM (ds_source);
}
#endif
if (alpha <= 0) if (alpha <= 0)
{ {
return; return;
@ -1583,8 +1281,8 @@ void R_DrawNormalPlane (visplane_t *pl, double _xscale, double _yscale, fixed_t
double xstep, ystep, leftxfrac, leftyfrac, rightxfrac, rightyfrac; double xstep, ystep, leftxfrac, leftyfrac, rightxfrac, rightyfrac;
double x; double x;
xscale = xs_ToFixed(32 - ds_xbits, _xscale); xscale = xs_ToFixed(32 - DrawerContext::SpanXBits(), _xscale);
yscale = xs_ToFixed(32 - ds_ybits, _yscale); yscale = xs_ToFixed(32 - DrawerContext::SpanYBits(), _yscale);
if (planeang != 0) if (planeang != 0)
{ {
double cosine = cos(planeang), sine = sin(planeang); double cosine = cos(planeang), sine = sin(planeang);
@ -1631,15 +1329,14 @@ void R_DrawNormalPlane (visplane_t *pl, double _xscale, double _yscale, fixed_t
planeheight = fabs(pl->height.Zat0() - ViewPos.Z); planeheight = fabs(pl->height.Zat0() - ViewPos.Z);
GlobVis = r_FloorVisibility / planeheight; GlobVis = r_FloorVisibility / planeheight;
ds_light = 0;
if (fixedlightlev >= 0) if (fixedlightlev >= 0)
{ {
R_SetDSColorMapLight(basecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev)); DrawerContext::SetSpanLight(basecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev));
plane_shade = false; plane_shade = false;
} }
else if (fixedcolormap) else if (fixedcolormap)
{ {
R_SetDSColorMapLight(fixedcolormap, 0, 0); DrawerContext::SetSpanLight(fixedcolormap, 0, 0);
plane_shade = false; plane_shade = false;
} }
else else
@ -1647,61 +1344,8 @@ void R_DrawNormalPlane (visplane_t *pl, double _xscale, double _yscale, fixed_t
plane_shade = true; plane_shade = true;
} }
if (spanfunc != R_FillSpan) DrawerContext::SetSpanStyle(alpha, additive, masked);
{
if (masked)
{
if (alpha < OPAQUE || additive)
{
if (!additive)
{
spanfunc = R_DrawSpanMaskedTranslucent;
dc_srcblend = Col2RGB8[alpha>>10];
dc_destblend = Col2RGB8[(OPAQUE-alpha)>>10];
dc_srcalpha = alpha;
dc_destalpha = OPAQUE - alpha;
}
else
{
spanfunc = R_DrawSpanMaskedAddClamp;
dc_srcblend = Col2RGB8_LessPrecision[alpha>>10];
dc_destblend = Col2RGB8_LessPrecision[FRACUNIT>>10];
dc_srcalpha = alpha;
dc_destalpha = OPAQUE - alpha;
}
}
else
{
spanfunc = R_DrawSpanMasked;
}
}
else
{
if (alpha < OPAQUE || additive)
{
if (!additive)
{
spanfunc = R_DrawSpanTranslucent;
dc_srcblend = Col2RGB8[alpha>>10];
dc_destblend = Col2RGB8[(OPAQUE-alpha)>>10];
dc_srcalpha = alpha;
dc_destalpha = OPAQUE - alpha;
}
else
{
spanfunc = R_DrawSpanAddClamp;
dc_srcblend = Col2RGB8_LessPrecision[alpha>>10];
dc_destblend = Col2RGB8_LessPrecision[FRACUNIT>>10];
dc_srcalpha = alpha;
dc_destalpha = OPAQUE - alpha;
}
}
else
{
spanfunc = R_DrawSpan;
}
}
}
R_MapVisPlane (pl, R_MapPlane); R_MapVisPlane (pl, R_MapPlane);
} }
@ -1733,14 +1377,14 @@ void R_DrawTiltedPlane (visplane_t *pl, double _xscale, double _yscale, fixed_t
return; return;
} }
lxscale = _xscale * ifloatpow2[ds_xbits]; lxscale = _xscale * ifloatpow2[DrawerContext::SpanXBits()];
lyscale = _yscale * ifloatpow2[ds_ybits]; lyscale = _yscale * ifloatpow2[DrawerContext::SpanYBits()];
xscale = 64.f / lxscale; xscale = 64.f / lxscale;
yscale = 64.f / lyscale; yscale = 64.f / lyscale;
zeroheight = pl->height.ZatPoint(ViewPos); zeroheight = pl->height.ZatPoint(ViewPos);
pviewx = xs_ToFixed(32 - ds_xbits, pl->xform.xOffs * pl->xform.xScale); pviewx = xs_ToFixed(32 - DrawerContext::SpanXBits(), pl->xform.xOffs * pl->xform.xScale);
pviewy = xs_ToFixed(32 - ds_ybits, pl->xform.yOffs * pl->xform.yScale); pviewy = xs_ToFixed(32 - DrawerContext::SpanYBits(), pl->xform.yOffs * pl->xform.yScale);
planeang = (pl->xform.Angle + pl->xform.baseAngle).Radians(); planeang = (pl->xform.Angle + pl->xform.baseAngle).Radians();
// p is the texture origin in view space // p is the texture origin in view space
@ -1810,42 +1454,22 @@ void R_DrawTiltedPlane (visplane_t *pl, double _xscale, double _yscale, fixed_t
if (fixedlightlev >= 0) if (fixedlightlev >= 0)
{ {
R_SetDSColorMapLight(basecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev)); DrawerContext::SetSpanLight(basecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev));
plane_shade = false; plane_shade = false;
} }
else if (fixedcolormap) else if (fixedcolormap)
{ {
R_SetDSColorMapLight(fixedcolormap, 0, 0); DrawerContext::SetSpanLight(fixedcolormap, 0, 0);
plane_shade = false; plane_shade = false;
} }
else else
{ {
R_SetDSColorMapLight(basecolormap, 0, 0); DrawerContext::SetSpanLight(basecolormap, 0, 0);
plane_shade = true; plane_shade = true;
} }
if (!plane_shade) DrawerContext::SetTiltedSpanState(plane_sz, plane_su, plane_sv, plane_shade, planelightfloat, pviewx, pviewy);
{ R_MapVisPlane (pl, [](int y, int x1) { DrawerContext::DrawTiltedSpan(y, x1, spanend[y]); });
for (int i = 0; i < viewwidth; ++i)
{
tiltlighting[i] = ds_colormap;
}
}
#if defined(X86_ASM)
if (!r_swtruecolor)
{
if (ds_source != ds_curtiltedsource)
R_SetTiltedSpanSource_ASM(ds_source);
R_MapVisPlane(pl, R_DrawTiltedPlane_ASM);
}
else
{
R_MapVisPlane(pl, R_MapTiltedPlane);
}
#else
R_MapVisPlane (pl, R_MapTiltedPlane);
#endif
} }
//========================================================================== //==========================================================================

View file

@ -93,14 +93,6 @@ void R_DrawNormalPlane (visplane_t *pl, double xscale, double yscale, fixed_t al
void R_DrawTiltedPlane (visplane_t *pl, double xscale, double yscale, fixed_t alpha, bool additive, bool masked); void R_DrawTiltedPlane (visplane_t *pl, double xscale, double yscale, fixed_t alpha, bool additive, bool masked);
void R_MapVisPlane (visplane_t *pl, void (*mapfunc)(int y, int x1)); void R_MapVisPlane (visplane_t *pl, void (*mapfunc)(int y, int x1));
extern void(*R_MapColoredPlane)(int y, int x1);
extern void(*R_MapTiltedPlane)(int y, int x1);
void R_MapTiltedPlane_C(int y, int x1);
void R_MapTiltedPlane_rgba(int y, int x);
void R_MapColoredPlane_C(int y, int x1);
void R_MapColoredPlane_rgba(int y, int x1);
visplane_t *R_FindPlane visplane_t *R_FindPlane
( const secplane_t &height, ( const secplane_t &height,
FTextureID picnum, FTextureID picnum,

View file

@ -52,6 +52,7 @@
#include "r_3dfloors.h" #include "r_3dfloors.h"
#include "v_palette.h" #include "v_palette.h"
#include "r_data/colormaps.h" #include "r_data/colormaps.h"
#include "r_drawer_context.h"
#define WALLYREPEAT 8 #define WALLYREPEAT 8
@ -172,19 +173,19 @@ CVAR(Bool, r_drawmirrors, true, 0)
float *MaskedSWall; float *MaskedSWall;
float MaskedScaleY; float MaskedScaleY;
static void BlastMaskedColumn (void (*blastfunc)(const BYTE *pixels, const FTexture::Span *spans), FTexture *tex) static void BlastMaskedColumn (int x, void (*blastfunc)(int x, const BYTE *pixels, const FTexture::Span *spans), FTexture *tex)
{ {
// calculate lighting // calculate lighting
if (fixedcolormap == NULL && fixedlightlev < 0) if (fixedcolormap == NULL && fixedlightlev < 0)
{ {
R_SetColorMapLight(basecolormap, rw_light, wallshade); DrawerContext::SetLight(basecolormap, rw_light, wallshade);
} }
dc_iscale = xs_Fix<16>::ToFix(MaskedSWall[dc_x] * MaskedScaleY); DrawerContext::SetTextureStep(xs_Fix<16>::ToFix(MaskedSWall[x] * MaskedScaleY));
if (sprflipvert) if (sprflipvert)
sprtopscreen = CenterY + dc_texturemid * spryscale; sprtopscreen = CenterY + DrawerContext::TextureMid() * spryscale;
else else
sprtopscreen = CenterY - dc_texturemid * spryscale; sprtopscreen = CenterY - DrawerContext::TextureMid() * spryscale;
// killough 1/25/98: here's where Medusa came in, because // killough 1/25/98: here's where Medusa came in, because
// it implicitly assumed that the column was all one patch. // it implicitly assumed that the column was all one patch.
@ -194,10 +195,12 @@ static void BlastMaskedColumn (void (*blastfunc)(const BYTE *pixels, const FText
// the Medusa effect. The fix is to construct true columns // the Medusa effect. The fix is to construct true columns
// when forming multipatched textures (see r_data.c). // when forming multipatched textures (see r_data.c).
DrawerContext::SetMaskedColumnState(mfloorclip, mceilingclip, spryscale, sprtopscreen, sprflipvert);
// draw the texture // draw the texture
const FTexture::Span *spans; const FTexture::Span *spans;
const BYTE *pixels = tex->GetColumn (maskedtexturecol[dc_x] >> FRACBITS, &spans); const BYTE *pixels = tex->GetColumn (maskedtexturecol[x] >> FRACBITS, &spans);
blastfunc (pixels, spans); blastfunc (x, pixels, spans);
rw_light += rw_lightstep; rw_light += rw_lightstep;
spryscale += rw_scalestep; spryscale += rw_scalestep;
} }
@ -243,7 +246,7 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2)
// [RH] modified because we don't use user-definable translucency maps // [RH] modified because we don't use user-definable translucency maps
ESPSResult drawmode; ESPSResult drawmode;
drawmode = R_SetPatchStyle (LegacyRenderStyles[curline->linedef->flags & ML_ADDTRANS ? STYLE_Add : STYLE_Translucent], drawmode = DrawerContext::SetPatchStyle (LegacyRenderStyles[curline->linedef->flags & ML_ADDTRANS ? STYLE_Add : STYLE_Translucent],
(float)MIN(curline->linedef->alpha, 1.), 0, 0); (float)MIN(curline->linedef->alpha, 1.), 0, 0);
if ((drawmode == DontDraw && !ds->bFogBoundary && !ds->bFakeBoundary)) if ((drawmode == DontDraw && !ds->bFogBoundary && !ds->bFakeBoundary))
@ -295,7 +298,7 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2)
// [RH] Draw fog partition // [RH] Draw fog partition
if (ds->bFogBoundary) if (ds->bFogBoundary)
{ {
R_DrawFogBoundary (x1, x2, mceilingclip, mfloorclip); DrawerContext::DrawFogBoundary (x1, x2, mceilingclip, mfloorclip);
if (ds->maskedtexturecol == -1) if (ds->maskedtexturecol == -1)
{ {
goto clearfog; goto clearfog;
@ -313,9 +316,9 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2)
rw_scalestep = ds->iscalestep; rw_scalestep = ds->iscalestep;
if (fixedlightlev >= 0) if (fixedlightlev >= 0)
R_SetColorMapLight(basecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev)); DrawerContext::SetLight(basecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev));
else if (fixedcolormap != NULL) else if (fixedcolormap != NULL)
R_SetColorMapLight(fixedcolormap, 0, 0); DrawerContext::SetLight(fixedcolormap, 0, 0);
// find positioning // find positioning
texheight = tex->GetScaledHeightDouble(); texheight = tex->GetScaledHeightDouble();
@ -326,11 +329,11 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2)
} }
if (curline->linedef->flags & ML_DONTPEGBOTTOM) if (curline->linedef->flags & ML_DONTPEGBOTTOM)
{ {
dc_texturemid = MAX(frontsector->GetPlaneTexZ(sector_t::floor), backsector->GetPlaneTexZ(sector_t::floor)) + texheight; DrawerContext::SetTextureMid(MAX(frontsector->GetPlaneTexZ(sector_t::floor), backsector->GetPlaneTexZ(sector_t::floor)) + texheight);
} }
else else
{ {
dc_texturemid = MIN(frontsector->GetPlaneTexZ(sector_t::ceiling), backsector->GetPlaneTexZ(sector_t::ceiling)); DrawerContext::SetTextureMid(MIN(frontsector->GetPlaneTexZ(sector_t::ceiling), backsector->GetPlaneTexZ(sector_t::ceiling)));
} }
rowoffset = curline->sidedef->GetTextureYOffset(side_t::mid); rowoffset = curline->sidedef->GetTextureYOffset(side_t::mid);
@ -349,21 +352,21 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2)
{ {
// rowoffset is added before the multiply so that the masked texture will // rowoffset is added before the multiply so that the masked texture will
// still be positioned in world units rather than texels. // still be positioned in world units rather than texels.
dc_texturemid += rowoffset - ViewPos.Z; DrawerContext::SetTextureMid(DrawerContext::TextureMid() + rowoffset - ViewPos.Z);
textop = dc_texturemid; textop = DrawerContext::TextureMid();
dc_texturemid *= MaskedScaleY; DrawerContext::SetTextureMid(DrawerContext::TextureMid() * MaskedScaleY);
} }
else else
{ {
// rowoffset is added outside the multiply so that it positions the texture // rowoffset is added outside the multiply so that it positions the texture
// by texels instead of world units. // by texels instead of world units.
textop = dc_texturemid + rowoffset / MaskedScaleY - ViewPos.Z; textop = DrawerContext::TextureMid() + rowoffset / MaskedScaleY - ViewPos.Z;
dc_texturemid = (dc_texturemid - ViewPos.Z) * MaskedScaleY + rowoffset; DrawerContext::SetTextureMid((DrawerContext::TextureMid() - ViewPos.Z) * MaskedScaleY + rowoffset);
} }
if (sprflipvert) if (sprflipvert)
{ {
MaskedScaleY = -MaskedScaleY; MaskedScaleY = -MaskedScaleY;
dc_texturemid -= tex->GetHeight() << FRACBITS; DrawerContext::SetTextureMid(DrawerContext::TextureMid() - tex->GetHeight());
} }
// [RH] Don't bother drawing segs that are completely offscreen // [RH] Don't bother drawing segs that are completely offscreen
@ -438,9 +441,9 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2)
// draw the columns one at a time // draw the columns one at a time
if (drawmode == DoDraw0) if (drawmode == DoDraw0)
{ {
for (dc_x = x1; dc_x < x2; ++dc_x) for (int x = x1; x < x2; ++x)
{ {
BlastMaskedColumn (R_DrawMaskedColumn, tex); BlastMaskedColumn (x, DrawerContext::DrawMaskedColumn, tex);
} }
} }
else else
@ -451,29 +454,29 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2)
if (x1 >= x2) if (x1 >= x2)
goto clearfog; goto clearfog;
dc_x = x1; int x = x1;
while ((dc_x < stop) && (dc_x & 3)) while ((x < stop) && (x & 3))
{ {
BlastMaskedColumn (R_DrawMaskedColumn, tex); BlastMaskedColumn (x, DrawerContext::DrawMaskedColumn, tex);
dc_x++; x++;
} }
while (dc_x < stop) while (x < stop)
{ {
rt_initcols(nullptr); DrawerContext::RtInitCols(nullptr);
BlastMaskedColumn (R_DrawMaskedColumnHoriz, tex); dc_x++; BlastMaskedColumn (x, DrawerContext::DrawMaskedColumnHoriz, tex);
BlastMaskedColumn (R_DrawMaskedColumnHoriz, tex); dc_x++; BlastMaskedColumn (x + 1, DrawerContext::DrawMaskedColumnHoriz, tex);
BlastMaskedColumn (R_DrawMaskedColumnHoriz, tex); dc_x++; BlastMaskedColumn (x + 2, DrawerContext::DrawMaskedColumnHoriz, tex);
BlastMaskedColumn (R_DrawMaskedColumnHoriz, tex); BlastMaskedColumn (x + 3, DrawerContext::DrawMaskedColumnHoriz, tex);
rt_draw4cols (dc_x - 3); DrawerContext::DrawRt4cols (x);
dc_x++; x += 4;
} }
while (dc_x < x2) while (x < x2)
{ {
BlastMaskedColumn (R_DrawMaskedColumn, tex); BlastMaskedColumn (x, DrawerContext::DrawMaskedColumn, tex);
dc_x++; x++;
} }
} }
} }
@ -483,13 +486,13 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2)
{ {
// rowoffset is added before the multiply so that the masked texture will // rowoffset is added before the multiply so that the masked texture will
// still be positioned in world units rather than texels. // still be positioned in world units rather than texels.
dc_texturemid = (dc_texturemid - ViewPos.Z + rowoffset) * MaskedScaleY; DrawerContext::SetTextureMid((DrawerContext::TextureMid() - ViewPos.Z + rowoffset) * MaskedScaleY);
} }
else else
{ {
// rowoffset is added outside the multiply so that it positions the texture // rowoffset is added outside the multiply so that it positions the texture
// by texels instead of world units. // by texels instead of world units.
dc_texturemid = (dc_texturemid - ViewPos.Z) * MaskedScaleY + rowoffset; DrawerContext::SetTextureMid((DrawerContext::TextureMid() - ViewPos.Z) * MaskedScaleY + rowoffset);
} }
WallC.sz1 = ds->sz1; WallC.sz1 = ds->sz1;
@ -535,7 +538,7 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2)
} }
clearfog: clearfog:
R_FinishSetPatchStyle (); DrawerContext::FinishSetPatchStyle ();
if (ds->bFakeBoundary & 3) if (ds->bFakeBoundary & 3)
{ {
R_RenderFakeWallRange(ds, x1, x2); R_RenderFakeWallRange(ds, x1, x2);
@ -567,11 +570,11 @@ void R_RenderFakeWall(drawseg_t *ds, int x1, int x2, F3DFloor *rover)
fixed_t Alpha = Scale(rover->alpha, OPAQUE, 255); fixed_t Alpha = Scale(rover->alpha, OPAQUE, 255);
ESPSResult drawmode; ESPSResult drawmode;
drawmode = R_SetPatchStyle (LegacyRenderStyles[rover->flags & FF_ADDITIVETRANS ? STYLE_Add : STYLE_Translucent], drawmode = DrawerContext::SetPatchStyle (LegacyRenderStyles[rover->flags & FF_ADDITIVETRANS ? STYLE_Add : STYLE_Translucent],
Alpha, 0, 0); Alpha, 0, 0);
if(drawmode == DontDraw) { if(drawmode == DontDraw) {
R_FinishSetPatchStyle(); DrawerContext::FinishSetPatchStyle();
return; return;
} }
@ -613,26 +616,26 @@ void R_RenderFakeWall(drawseg_t *ds, int x1, int x2, F3DFloor *rover)
{ {
rowoffset += rw_pic->GetHeight(); rowoffset += rw_pic->GetHeight();
} }
dc_texturemid = (planez - ViewPos.Z) * yscale; DrawerContext::SetTextureMid((planez - ViewPos.Z) * yscale);
if (rw_pic->bWorldPanning) if (rw_pic->bWorldPanning)
{ {
// rowoffset is added before the multiply so that the masked texture will // rowoffset is added before the multiply so that the masked texture will
// still be positioned in world units rather than texels. // still be positioned in world units rather than texels.
dc_texturemid = dc_texturemid + rowoffset * yscale; DrawerContext::SetTextureMid(DrawerContext::TextureMid() + rowoffset * yscale);
rw_offset = xs_RoundToInt(rw_offset * xscale); rw_offset = xs_RoundToInt(rw_offset * xscale);
} }
else else
{ {
// rowoffset is added outside the multiply so that it positions the texture // rowoffset is added outside the multiply so that it positions the texture
// by texels instead of world units. // by texels instead of world units.
dc_texturemid += rowoffset; DrawerContext::SetTextureMid(DrawerContext::TextureMid() + rowoffset);
} }
if (fixedlightlev >= 0) if (fixedlightlev >= 0)
R_SetColorMapLight(basecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev)); DrawerContext::SetLight(basecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev));
else if (fixedcolormap != NULL) else if (fixedcolormap != NULL)
R_SetColorMapLight(fixedcolormap, 0, 0); DrawerContext::SetLight(fixedcolormap, 0, 0);
WallC.sz1 = ds->sz1; WallC.sz1 = ds->sz1;
WallC.sz2 = ds->sz2; WallC.sz2 = ds->sz2;
@ -660,7 +663,7 @@ void R_RenderFakeWall(drawseg_t *ds, int x1, int x2, F3DFloor *rover)
PrepLWall (lwall, curline->sidedef->TexelLength*xscale, ds->sx1, ds->sx2); PrepLWall (lwall, curline->sidedef->TexelLength*xscale, ds->sx1, ds->sx2);
wallscan_np2_ds(ds, x1, x2, wallupper, walllower, MaskedSWall, lwall, yscale); wallscan_np2_ds(ds, x1, x2, wallupper, walllower, MaskedSWall, lwall, yscale);
R_FinishSetPatchStyle(); DrawerContext::FinishSetPatchStyle();
} }
// kg3D - walls of fake floors // kg3D - walls of fake floors
@ -1065,360 +1068,6 @@ void R_RenderFakeWallRange (drawseg_t *ds, int x1, int x2)
return; return;
} }
// Draw a column with support for non-power-of-two ranges
uint32_t wallscan_drawcol1(int x, int y1, int y2, uint32_t uv_start, uint32_t uv_step, uint32_t uv_max, const BYTE *source, DWORD(*draw1column)())
{
int pixelsize = r_swtruecolor ? 4 : 1;
if (uv_max == 0) // power of two
{
int count = y2 - y1;
dc_source = source;
dc_dest = (ylookup[y1] + x) * pixelsize + dc_destorg;
dc_count = count;
dc_iscale = uv_step;
dc_texturefrac = uv_start;
draw1column();
uint64_t step64 = uv_step;
uint64_t pos64 = uv_start;
return (uint32_t)(pos64 + step64 * count);
}
else
{
uint32_t uv_pos = uv_start;
uint32_t left = y2 - y1;
while (left > 0)
{
uint32_t available = uv_max - uv_pos;
uint32_t next_uv_wrap = available / uv_step;
if (available % uv_step != 0)
next_uv_wrap++;
uint32_t count = MIN(left, next_uv_wrap);
dc_source = source;
dc_dest = (ylookup[y1] + x) * pixelsize + dc_destorg;
dc_count = count;
dc_iscale = uv_step;
dc_texturefrac = uv_pos;
draw1column();
left -= count;
uv_pos += uv_step * count;
if (uv_pos >= uv_max)
uv_pos -= uv_max;
}
return uv_pos;
}
}
// Draw four columns with support for non-power-of-two ranges
void wallscan_drawcol4(int x, int y1, int y2, uint32_t *uv_pos, uint32_t *uv_step, uint32_t uv_max, const BYTE **source, void(*draw4columns)())
{
int pixelsize = r_swtruecolor ? 4 : 1;
if (uv_max == 0) // power of two, no wrap handling needed
{
int count = y2 - y1;
for (int i = 0; i < 4; i++)
{
bufplce[i] = source[i];
vplce[i] = uv_pos[i];
vince[i] = uv_step[i];
uint64_t step64 = uv_step[i];
uint64_t pos64 = uv_pos[i];
uv_pos[i] = (uint32_t)(pos64 + step64 * count);
}
dc_dest = (ylookup[y1] + x) * pixelsize + dc_destorg;
dc_count = count;
draw4columns();
}
else
{
dc_dest = (ylookup[y1] + x) * pixelsize + dc_destorg;
for (int i = 0; i < 4; i++)
bufplce[i] = source[i];
uint32_t left = y2 - y1;
while (left > 0)
{
// Find which column wraps first
uint32_t count = left;
for (int i = 0; i < 4; i++)
{
uint32_t available = uv_max - uv_pos[i];
uint32_t next_uv_wrap = available / uv_step[i];
if (available % uv_step[i] != 0)
next_uv_wrap++;
count = MIN(next_uv_wrap, count);
}
// Draw until that column wraps
for (int i = 0; i < 4; i++)
{
vplce[i] = uv_pos[i];
vince[i] = uv_step[i];
}
dc_count = count;
draw4columns();
// Wrap the uv position
for (int i = 0; i < 4; i++)
{
uv_pos[i] += uv_step[i] * count;
if (uv_pos[i] >= uv_max)
uv_pos[i] -= uv_max;
}
left -= count;
}
}
}
// Calculates a wrapped uv start position value for a column
void calc_uv_start_and_step(int y1, float swal, double yrepeat, uint32_t uv_height, int fracbits, uint32_t &uv_start_out, uint32_t &uv_step_out)
{
double uv_stepd = swal * yrepeat;
// Find start uv in [0-uv_height[ range.
// Not using xs_ToFixed because it rounds the result and we need something that always rounds down to stay within the range.
double v = (dc_texturemid + uv_stepd * (y1 - CenterY + 0.5)) / uv_height;
v = v - floor(v);
v *= uv_height;
v *= (1 << fracbits);
uv_start_out = (uint32_t)v;
uv_step_out = xs_ToFixed(fracbits, uv_stepd);
}
typedef DWORD(*Draw1ColumnFuncPtr)();
typedef void(*Draw4ColumnsFuncPtr)();
void wallscan_any(
int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat,
const BYTE *(*getcol)(FTexture *tex, int x),
void(setupwallscan(int bits,Draw1ColumnFuncPtr &draw1, Draw4ColumnsFuncPtr &draw2)))
{
if (rw_pic->UseType == FTexture::TEX_Null)
return;
uint32_t uv_height = rw_pic->GetHeight();
uint32_t fracbits = 32 - rw_pic->HeightBits;
uint32_t uv_max = uv_height << fracbits;
DWORD(*draw1column)();
void(*draw4columns)();
setupwallscan(fracbits, draw1column, draw4columns);
fixed_t xoffset = rw_offset;
bool fixed = (fixedcolormap != NULL || fixedlightlev >= 0);
if (fixed)
{
palookupoffse[0] = dc_colormap;
palookupoffse[1] = dc_colormap;
palookupoffse[2] = dc_colormap;
palookupoffse[3] = dc_colormap;
palookuplight[0] = 0;
palookuplight[1] = 0;
palookuplight[2] = 0;
palookuplight[3] = 0;
}
if (fixedcolormap)
R_SetColorMapLight(fixedcolormap, 0, 0);
else
R_SetColorMapLight(basecolormap, 0, 0);
float light = rw_light;
// Calculate where 4 column alignment begins and ends:
int aligned_x1 = clamp((x1 + 3) / 4 * 4, x1, x2);
int aligned_x2 = clamp(x2 / 4 * 4, x1, x2);
// First unaligned columns:
for (int x = x1; x < aligned_x1; x++, light += rw_lightstep)
{
int y1 = uwal[x];
int y2 = dwal[x];
if (y2 <= y1)
continue;
if (!fixed)
R_SetColorMapLight(basecolormap, light, wallshade);
const BYTE *source = getcol(rw_pic, (lwal[x] + xoffset) >> FRACBITS);
uint32_t uv_start, uv_step;
calc_uv_start_and_step(y1, swal[x], yrepeat, uv_height, fracbits, uv_start, uv_step);
wallscan_drawcol1(x, y1, y2, uv_start, uv_step, uv_max, source, draw1column);
}
// The aligned columns
for (int x = aligned_x1; x < aligned_x2; x += 4)
{
// Find y1, y2, light and uv values for four columns:
int y1[4] = { uwal[x], uwal[x + 1], uwal[x + 2], uwal[x + 3] };
int y2[4] = { dwal[x], dwal[x + 1], dwal[x + 2], dwal[x + 3] };
const BYTE *source[4];
for (int i = 0; i < 4; i++)
source[i] = getcol(rw_pic, (lwal[x + i] + xoffset) >> FRACBITS);
float lights[4];
for (int i = 0; i < 4; i++)
{
lights[i] = light;
light += rw_lightstep;
}
uint32_t uv_pos[4], uv_step[4];
for (int i = 0; i < 4; i++)
calc_uv_start_and_step(y1[i], swal[x + i], yrepeat, uv_height, fracbits, uv_pos[i], uv_step[i]);
// Figure out where we vertically can start and stop drawing 4 columns in one go
int middle_y1 = y1[0];
int middle_y2 = y2[0];
for (int i = 1; i < 4; i++)
{
middle_y1 = MAX(y1[i], middle_y1);
middle_y2 = MIN(y2[i], middle_y2);
}
// If we got an empty column in our set we cannot draw 4 columns in one go:
bool empty_column_in_set = false;
for (int i = 0; i < 4; i++)
{
if (y2[i] <= y1[i])
empty_column_in_set = true;
}
if (empty_column_in_set || middle_y2 <= middle_y1)
{
for (int i = 0; i < 4; i++)
{
if (y2[i] <= y1[i])
continue;
if (!fixed)
R_SetColorMapLight(basecolormap, lights[i], wallshade);
wallscan_drawcol1(x + i, y1[i], y2[i], uv_pos[i], uv_step[i], uv_max, source[i], draw1column);
}
continue;
}
// Draw the first rows where not all 4 columns are active
for (int i = 0; i < 4; i++)
{
if (!fixed)
R_SetColorMapLight(basecolormap, lights[i], wallshade);
if (y1[i] < middle_y1)
uv_pos[i] = wallscan_drawcol1(x + i, y1[i], middle_y1, uv_pos[i], uv_step[i], uv_max, source[i], draw1column);
}
// Draw the area where all 4 columns are active
if (!fixed)
{
for (int i = 0; i < 4; i++)
{
if (r_swtruecolor)
{
palookupoffse[i] = basecolormap->Maps;
palookuplight[i] = LIGHTSCALE(lights[i], wallshade);
}
else
{
palookupoffse[i] = basecolormap->Maps + (GETPALOOKUP(lights[i], wallshade) << COLORMAPSHIFT);
palookuplight[i] = 0;
}
}
}
wallscan_drawcol4(x, middle_y1, middle_y2, uv_pos, uv_step, uv_max, source, draw4columns);
// Draw the last rows where not all 4 columns are active
for (int i = 0; i < 4; i++)
{
if (!fixed)
R_SetColorMapLight(basecolormap, lights[i], wallshade);
if (middle_y2 < y2[i])
uv_pos[i] = wallscan_drawcol1(x + i, middle_y2, y2[i], uv_pos[i], uv_step[i], uv_max, source[i], draw1column);
}
}
// The last unaligned columns:
for (int x = aligned_x2; x < x2; x++, light += rw_lightstep)
{
int y1 = uwal[x];
int y2 = dwal[x];
if (y2 <= y1)
continue;
if (!fixed)
R_SetColorMapLight(basecolormap, light, wallshade);
const BYTE *source = getcol(rw_pic, (lwal[x] + xoffset) >> FRACBITS);
uint32_t uv_start, uv_step;
calc_uv_start_and_step(y1, swal[x], yrepeat, uv_height, fracbits, uv_start, uv_step);
wallscan_drawcol1(x, y1, y2, uv_start, uv_step, uv_max, source, draw1column);
}
NetUpdate ();
}
void wallscan(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, const BYTE *(*getcol)(FTexture *tex, int x))
{
wallscan_any(x1, x2, uwal, dwal, swal, lwal, yrepeat, getcol, [](int bits, Draw1ColumnFuncPtr &line1, Draw4ColumnsFuncPtr &line4)
{
setupvline(bits);
line1 = dovline1;
line4 = dovline4;
});
}
void maskwallscan(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, const BYTE *(*getcol)(FTexture *tex, int x))
{
if (!rw_pic->bMasked) // Textures that aren't masked can use the faster wallscan.
{
wallscan(x1, x2, uwal, dwal, swal, lwal, yrepeat, getcol);
}
else
{
wallscan_any(x1, x2, uwal, dwal, swal, lwal, yrepeat, getcol, [](int bits, Draw1ColumnFuncPtr &line1, Draw4ColumnsFuncPtr &line4)
{
setupmvline(bits);
line1 = domvline1;
line4 = domvline4;
});
}
}
void transmaskwallscan(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, const BYTE *(*getcol)(FTexture *tex, int x))
{
static fixed_t(*tmvline1)();
static void(*tmvline4)();
if (!R_GetTransMaskDrawers(&tmvline1, &tmvline4))
{
// The current translucency is unsupported, so draw with regular maskwallscan instead.
maskwallscan(x1, x2, uwal, dwal, swal, lwal, yrepeat, getcol);
}
else
{
wallscan_any(x1, x2, uwal, dwal, swal, lwal, yrepeat, getcol, [](int bits, Draw1ColumnFuncPtr &line1, Draw4ColumnsFuncPtr &line4)
{
setuptmvline(bits);
line1 = reinterpret_cast<DWORD(*)()>(tmvline1);
line4 = tmvline4;
});
}
}
void wallscan_striped (int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat) void wallscan_striped (int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat)
{ {
FDynamicColormap *startcolormap = basecolormap; FDynamicColormap *startcolormap = basecolormap;
@ -1444,7 +1093,7 @@ void wallscan_striped (int x1, int x2, short *uwal, short *dwal, float *swal, fi
{ {
down[j] = clamp (most3[j], up[j], dwal[j]); down[j] = clamp (most3[j], up[j], dwal[j]);
} }
wallscan (x1, x2, up, down, swal, lwal, yrepeat); DrawerContext::DrawWall (x1, x2, up, down, swal, lwal, yrepeat, rw_pic, rw_offset);
up = down; up = down;
down = (down == most1) ? most2 : most1; down = (down == most1) ? most2 : most1;
} }
@ -1455,7 +1104,7 @@ void wallscan_striped (int x1, int x2, short *uwal, short *dwal, float *swal, fi
*lit->p_lightlevel, lit->lightsource != NULL) + r_actualextralight); *lit->p_lightlevel, lit->lightsource != NULL) + r_actualextralight);
} }
wallscan (x1, x2, up, dwal, swal, lwal, yrepeat); DrawerContext::DrawWall (x1, x2, up, dwal, swal, lwal, yrepeat, rw_pic, rw_offset);
basecolormap = startcolormap; basecolormap = startcolormap;
wallshade = startshade; wallshade = startshade;
} }
@ -1464,20 +1113,20 @@ static void call_wallscan(int x1, int x2, short *uwal, short *dwal, float *swal,
{ {
if (mask) if (mask)
{ {
if (colfunc == basecolfunc) if (DrawerContext::IsBaseColumn())
{ {
maskwallscan(x1, x2, uwal, dwal, swal, lwal, yrepeat); DrawerContext::DrawMaskedWall(x1, x2, uwal, dwal, swal, lwal, yrepeat, rw_pic, rw_offset);
} }
else else
{ {
transmaskwallscan(x1, x2, uwal, dwal, swal, lwal, yrepeat); DrawerContext::DrawTransMaskedWall(x1, x2, uwal, dwal, swal, lwal, yrepeat, rw_pic, rw_offset);
} }
} }
else else
{ {
if (fixedcolormap != NULL || fixedlightlev >= 0 || !(frontsector->e && frontsector->e->XFloor.lightlist.Size())) if (fixedcolormap != NULL || fixedlightlev >= 0 || !(frontsector->e && frontsector->e->XFloor.lightlist.Size()))
{ {
wallscan(x1, x2, uwal, dwal, swal, lwal, yrepeat); DrawerContext::DrawWall(x1, x2, uwal, dwal, swal, lwal, yrepeat, rw_pic, rw_offset);
} }
else else
{ {
@ -1513,14 +1162,14 @@ void wallscan_np2(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t
if (yrepeat >= 0) if (yrepeat >= 0)
{ // normal orientation: draw strips from top to bottom { // normal orientation: draw strips from top to bottom
partition = top - fmod(top - dc_texturemid / yrepeat - ViewPos.Z, scaledtexheight); partition = top - fmod(top - DrawerContext::TextureMid() / yrepeat - ViewPos.Z, scaledtexheight);
if (partition == top) if (partition == top)
{ {
partition -= scaledtexheight; partition -= scaledtexheight;
} }
up = uwal; up = uwal;
down = most1; down = most1;
dc_texturemid = (partition - ViewPos.Z) * yrepeat + texheight; DrawerContext::SetTextureMid((partition - ViewPos.Z) * yrepeat + texheight);
while (partition > bot) while (partition > bot)
{ {
int j = OWallMost(most3, partition - ViewPos.Z, &WallC); int j = OWallMost(most3, partition - ViewPos.Z, &WallC);
@ -1535,16 +1184,16 @@ void wallscan_np2(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t
down = (down == most1) ? most2 : most1; down = (down == most1) ? most2 : most1;
} }
partition -= scaledtexheight; partition -= scaledtexheight;
dc_texturemid -= texheight; DrawerContext::SetTextureMid(DrawerContext::TextureMid() - texheight);
} }
call_wallscan(x1, x2, up, dwal, swal, lwal, yrepeat, mask); call_wallscan(x1, x2, up, dwal, swal, lwal, yrepeat, mask);
} }
else else
{ // upside down: draw strips from bottom to top { // upside down: draw strips from bottom to top
partition = bot - fmod(bot - dc_texturemid / yrepeat - ViewPos.Z, scaledtexheight); partition = bot - fmod(bot - DrawerContext::TextureMid() / yrepeat - ViewPos.Z, scaledtexheight);
up = most1; up = most1;
down = dwal; down = dwal;
dc_texturemid = (partition - ViewPos.Z) * yrepeat + texheight; DrawerContext::SetTextureMid((partition - ViewPos.Z) * yrepeat + texheight);
while (partition < top) while (partition < top)
{ {
int j = OWallMost(most3, partition - ViewPos.Z, &WallC); int j = OWallMost(most3, partition - ViewPos.Z, &WallC);
@ -1559,7 +1208,7 @@ void wallscan_np2(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t
up = (up == most1) ? most2 : most1; up = (up == most1) ? most2 : most1;
} }
partition -= scaledtexheight; partition -= scaledtexheight;
dc_texturemid -= texheight; DrawerContext::SetTextureMid(DrawerContext::TextureMid() - texheight);
} }
call_wallscan(x1, x2, uwal, down, swal, lwal, yrepeat, mask); call_wallscan(x1, x2, uwal, down, swal, lwal, yrepeat, mask);
} }
@ -1612,9 +1261,9 @@ void R_RenderSegLoop ()
fixed_t xoffset = rw_offset; fixed_t xoffset = rw_offset;
if (fixedlightlev >= 0) if (fixedlightlev >= 0)
R_SetColorMapLight(basecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev)); DrawerContext::SetLight(basecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev));
else if (fixedcolormap != NULL) else if (fixedcolormap != NULL)
R_SetColorMapLight(fixedcolormap, 0, 0); DrawerContext::SetLight(fixedcolormap, 0, 0);
// clip wall to the floor and ceiling // clip wall to the floor and ceiling
for (x = x1; x < x2; ++x) for (x = x1; x < x2; ++x)
@ -1695,7 +1344,7 @@ void R_RenderSegLoop ()
{ // one sided line { // one sided line
if (midtexture->UseType != FTexture::TEX_Null && viewactive) if (midtexture->UseType != FTexture::TEX_Null && viewactive)
{ {
dc_texturemid = rw_midtexturemid; DrawerContext::SetTextureMid(rw_midtexturemid);
rw_pic = midtexture; rw_pic = midtexture;
xscale = rw_pic->Scale.X * rw_midtexturescalex; xscale = rw_pic->Scale.X * rw_midtexturescalex;
yscale = rw_pic->Scale.Y * rw_midtexturescaley; yscale = rw_pic->Scale.Y * rw_midtexturescaley;
@ -1738,7 +1387,7 @@ void R_RenderSegLoop ()
} }
if (viewactive) if (viewactive)
{ {
dc_texturemid = rw_toptexturemid; DrawerContext::SetTextureMid(rw_toptexturemid);
rw_pic = toptexture; rw_pic = toptexture;
xscale = rw_pic->Scale.X * rw_toptexturescalex; xscale = rw_pic->Scale.X * rw_toptexturescalex;
yscale = rw_pic->Scale.Y * rw_toptexturescaley; yscale = rw_pic->Scale.Y * rw_toptexturescaley;
@ -1784,7 +1433,7 @@ void R_RenderSegLoop ()
} }
if (viewactive) if (viewactive)
{ {
dc_texturemid = rw_bottomtexturemid; DrawerContext::SetTextureMid(rw_bottomtexturemid);
rw_pic = bottomtexture; rw_pic = bottomtexture;
xscale = rw_pic->Scale.X * rw_bottomtexturescalex; xscale = rw_pic->Scale.X * rw_bottomtexturescalex;
yscale = rw_pic->Scale.Y * rw_bottomtexturescaley; yscale = rw_pic->Scale.Y * rw_bottomtexturescaley;
@ -2974,7 +2623,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper,
} }
yscale = decal->ScaleY; yscale = decal->ScaleY;
dc_texturemid = WallSpriteTile->TopOffset + (zpos - ViewPos.Z) / yscale; DrawerContext::SetTextureMid(WallSpriteTile->TopOffset + (zpos - ViewPos.Z) / yscale);
// Clip sprite to drawseg // Clip sprite to drawseg
x1 = MAX<int>(clipper->x1, x1); x1 = MAX<int>(clipper->x1, x1);
@ -3011,11 +2660,11 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper,
rw_light = rw_lightleft + (x1 - WallC.sx1) * rw_lightstep; rw_light = rw_lightleft + (x1 - WallC.sx1) * rw_lightstep;
if (fixedlightlev >= 0) if (fixedlightlev >= 0)
R_SetColorMapLight(usecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev)); DrawerContext::SetLight(usecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev));
else if (fixedcolormap != NULL) else if (fixedcolormap != NULL)
R_SetColorMapLight(fixedcolormap, 0, 0); DrawerContext::SetLight(fixedcolormap, 0, 0);
else if (!foggy && (decal->RenderFlags & RF_FULLBRIGHT)) else if (!foggy && (decal->RenderFlags & RF_FULLBRIGHT))
R_SetColorMapLight(usecolormap, 0, 0); DrawerContext::SetLight(usecolormap, 0, 0);
else else
calclighting = true; calclighting = true;
@ -3024,7 +2673,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper,
{ {
sprflipvert = true; sprflipvert = true;
yscale = -yscale; yscale = -yscale;
dc_texturemid -= WallSpriteTile->GetHeight(); DrawerContext::SetTextureMid(DrawerContext::TextureMid() - WallSpriteTile->GetHeight());
} }
else else
{ {
@ -3034,10 +2683,9 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper,
MaskedScaleY = float(1 / yscale); MaskedScaleY = float(1 / yscale);
do do
{ {
dc_x = x1;
ESPSResult mode; ESPSResult mode;
mode = R_SetPatchStyle (decal->RenderStyle, (float)decal->Alpha, decal->Translation, decal->AlphaColor); mode = DrawerContext::SetPatchStyle (decal->RenderStyle, (float)decal->Alpha, decal->Translation, decal->AlphaColor);
// R_SetPatchStyle can modify basecolormap. // R_SetPatchStyle can modify basecolormap.
if (rereadcolormap) if (rereadcolormap)
@ -3053,48 +2701,50 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper,
{ {
int stop4; int stop4;
int x = x1;
if (mode == DoDraw0) if (mode == DoDraw0)
{ // 1 column at a time { // 1 column at a time
stop4 = dc_x; stop4 = x;
} }
else // DoDraw1 else // DoDraw1
{ // up to 4 columns at a time { // up to 4 columns at a time
stop4 = x2 & ~3; stop4 = x2 & ~3;
} }
while ((dc_x < stop4) && (dc_x & 3)) while ((x < stop4) && (x & 3))
{ {
if (calclighting) if (calclighting)
{ // calculate lighting { // calculate lighting
R_SetColorMapLight(usecolormap, rw_light, wallshade); DrawerContext::SetLight(usecolormap, rw_light, wallshade);
} }
R_WallSpriteColumn (R_DrawMaskedColumn); R_WallSpriteColumn (x, DrawerContext::DrawMaskedColumn);
dc_x++; x++;
} }
while (dc_x < stop4) while (x < stop4)
{ {
if (calclighting) if (calclighting)
{ // calculate lighting { // calculate lighting
R_SetColorMapLight(usecolormap, rw_light, wallshade); DrawerContext::SetLight(usecolormap, rw_light, wallshade);
} }
rt_initcols(nullptr); DrawerContext::RtInitCols(nullptr);
for (int zz = 4; zz; --zz) for (int zz = 0; zz < 4; ++zz)
{ {
R_WallSpriteColumn (R_DrawMaskedColumnHoriz); R_WallSpriteColumn (x + zz, DrawerContext::DrawMaskedColumnHoriz);
dc_x++;
} }
rt_draw4cols (dc_x - 4); DrawerContext::DrawRt4cols (x);
x += 4;
} }
while (dc_x < x2) while (x < x2)
{ {
if (calclighting) if (calclighting)
{ // calculate lighting { // calculate lighting
R_SetColorMapLight(usecolormap, rw_light, wallshade); DrawerContext::SetLight(usecolormap, rw_light, wallshade);
} }
R_WallSpriteColumn (R_DrawMaskedColumn); R_WallSpriteColumn (x, DrawerContext::DrawMaskedColumn);
dc_x++; x++;
} }
} }
@ -3103,14 +2753,11 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper,
// needrepeat will be 0, and the while will fail. // needrepeat will be 0, and the while will fail.
mceilingclip = floorclip; mceilingclip = floorclip;
mfloorclip = wallbottom; mfloorclip = wallbottom;
R_FinishSetPatchStyle (); DrawerContext::FinishSetPatchStyle ();
} while (needrepeat--); } while (needrepeat--);
colfunc = basecolfunc; DrawerContext::SetBaseStyle();
hcolfunc_post1 = rt_map1col; DrawerContext::FinishSetPatchStyle ();
hcolfunc_post4 = rt_map4cols;
R_FinishSetPatchStyle ();
done: done:
WallC = savecoord; WallC = savecoord;
} }

View file

@ -32,6 +32,7 @@
** **
*/ */
#define DRAWER_INTERNALS
#include "r_local.h" #include "r_local.h"
#include "v_palette.h" #include "v_palette.h"

View file

@ -58,7 +58,7 @@
#include "r_plane.h" #include "r_plane.h"
#include "r_segs.h" #include "r_segs.h"
#include "r_3dfloors.h" #include "r_3dfloors.h"
#include "r_draw_rgba.h" #include "r_drawer_context.h"
#include "v_palette.h" #include "v_palette.h"
#include "r_data/r_translate.h" #include "r_data/r_translate.h"
#include "r_data/colormaps.h" #include "r_data/colormaps.h"
@ -229,12 +229,6 @@ vissprite_t *R_NewVisSprite (void)
return *(vissprite_p-1); return *(vissprite_p-1);
} }
//
// R_DrawMaskedColumn
// Used for sprites and masked mid textures.
// Masked means: partly transparent, i.e. stored
// in posts/runs of opaque pixels.
//
short* mfloorclip; short* mfloorclip;
short* mceilingclip; short* mceilingclip;
@ -243,88 +237,6 @@ double sprtopscreen;
bool sprflipvert; bool sprflipvert;
void R_DrawMaskedColumn (const BYTE *column, const FTexture::Span *span)
{
int pixelsize = r_swtruecolor ? 4 : 1;
const fixed_t centeryfrac = FLOAT2FIXED(CenterY);
const fixed_t texturemid = FLOAT2FIXED(dc_texturemid);
while (span->Length != 0)
{
const int length = span->Length;
const int top = span->TopOffset;
// calculate unclipped screen coordinates for post
dc_yl = xs_RoundToInt(sprtopscreen + spryscale * top);
dc_yh = xs_RoundToInt(sprtopscreen + spryscale * (top + length)) - 1;
if (sprflipvert)
{
swapvalues (dc_yl, dc_yh);
}
if (dc_yh >= mfloorclip[dc_x])
{
dc_yh = mfloorclip[dc_x] - 1;
}
if (dc_yl < mceilingclip[dc_x])
{
dc_yl = mceilingclip[dc_x];
}
if (dc_yl <= dc_yh)
{
if (sprflipvert)
{
dc_texturefrac = (dc_yl*dc_iscale) - (top << FRACBITS)
- FixedMul (centeryfrac, dc_iscale) - texturemid;
const fixed_t maxfrac = length << FRACBITS;
while (dc_texturefrac >= maxfrac)
{
if (++dc_yl > dc_yh)
goto nextpost;
dc_texturefrac += dc_iscale;
}
fixed_t endfrac = dc_texturefrac + (dc_yh-dc_yl)*dc_iscale;
while (endfrac < 0)
{
if (--dc_yh < dc_yl)
goto nextpost;
endfrac -= dc_iscale;
}
}
else
{
dc_texturefrac = texturemid - (top << FRACBITS)
+ (dc_yl*dc_iscale) - FixedMul (centeryfrac-FRACUNIT, dc_iscale);
while (dc_texturefrac < 0)
{
if (++dc_yl > dc_yh)
goto nextpost;
dc_texturefrac += dc_iscale;
}
fixed_t endfrac = dc_texturefrac + (dc_yh-dc_yl)*dc_iscale;
const fixed_t maxfrac = length << FRACBITS;
if (dc_yh < mfloorclip[dc_x]-1 && endfrac < maxfrac - dc_iscale)
{
dc_yh++;
}
else while (endfrac >= maxfrac)
{
if (--dc_yh < dc_yl)
goto nextpost;
endfrac -= dc_iscale;
}
}
dc_source = column + top;
dc_dest = (ylookup[dc_yl] + dc_x) * pixelsize + dc_destorg;
dc_count = dc_yh - dc_yl + 1;
colfunc ();
}
nextpost:
span++;
}
}
// [ZZ] // [ZZ]
// R_ClipSpriteColumnWithPortals // R_ClipSpriteColumnWithPortals
// //
@ -361,7 +273,7 @@ static inline void R_CollectPortals()
} }
} }
static inline bool R_ClipSpriteColumnWithPortals(vissprite_t* spr) bool R_ClipSpriteColumnWithPortals(int x, vissprite_t* spr)
{ {
// [ZZ] 10.01.2016: don't clip sprites from the root of a skybox. // [ZZ] 10.01.2016: don't clip sprites from the root of a skybox.
if (CurrentPortalInSkybox) if (CurrentPortalInSkybox)
@ -380,7 +292,7 @@ static inline bool R_ClipSpriteColumnWithPortals(vissprite_t* spr)
continue; continue;
// now if current column is covered by this drawseg, we clip it away // now if current column is covered by this drawseg, we clip it away
if ((dc_x >= seg->x1) && (dc_x < seg->x2)) if ((x >= seg->x1) && (x < seg->x2))
return true; return true;
} }
@ -409,15 +321,15 @@ void R_DrawVisSprite (vissprite_t *vis)
} }
fixed_t centeryfrac = FLOAT2FIXED(CenterY); fixed_t centeryfrac = FLOAT2FIXED(CenterY);
R_SetColorMapLight(vis->Style.BaseColormap, 0, vis->Style.ColormapNum << FRACBITS); DrawerContext::SetLight(vis->Style.BaseColormap, 0, vis->Style.ColormapNum << FRACBITS);
mode = R_SetPatchStyle (vis->Style.RenderStyle, vis->Style.Alpha, vis->Translation, vis->FillColor); mode = DrawerContext::SetPatchStyle (vis->Style.RenderStyle, vis->Style.Alpha, vis->Translation, vis->FillColor);
if (vis->Style.RenderStyle == LegacyRenderStyles[STYLE_Shaded]) if (vis->Style.RenderStyle == LegacyRenderStyles[STYLE_Shaded])
{ // For shaded sprites, R_SetPatchStyle sets a dc_colormap to an alpha table, but { // For shaded sprites, R_SetPatchStyle sets a dc_colormap to an alpha table, but
// it is the brightest one. We need to get back to the proper light level for // it is the brightest one. We need to get back to the proper light level for
// this sprite. // this sprite.
R_SetColorMapLight(dc_fcolormap, 0, vis->Style.ColormapNum << FRACBITS); DrawerContext::SetLight(DrawerContext::LightColormap(), 0, vis->Style.ColormapNum << FRACBITS);
} }
if (mode != DontDraw) if (mode != DontDraw)
@ -436,65 +348,67 @@ void R_DrawVisSprite (vissprite_t *vis)
tex = vis->pic; tex = vis->pic;
spryscale = vis->yscale; spryscale = vis->yscale;
sprflipvert = false; sprflipvert = false;
dc_iscale = FLOAT2FIXED(1 / vis->yscale); DrawerContext::SetTextureStep(FLOAT2FIXED(1 / vis->yscale));
frac = vis->startfrac; frac = vis->startfrac;
xiscale = vis->xiscale; xiscale = vis->xiscale;
dc_texturemid = vis->texturemid; DrawerContext::SetTextureMid(vis->texturemid);
if (vis->renderflags & RF_YFLIP) if (vis->renderflags & RF_YFLIP)
{ {
sprflipvert = true; sprflipvert = true;
spryscale = -spryscale; spryscale = -spryscale;
dc_iscale = -dc_iscale; DrawerContext::SetTextureStep(-DrawerContext::TextureStep());
dc_texturemid -= vis->pic->GetHeight(); DrawerContext::SetTextureMid(DrawerContext::TextureMid() - vis->pic->GetHeight());
sprtopscreen = CenterY + dc_texturemid * spryscale; sprtopscreen = CenterY + DrawerContext::TextureMid() * spryscale;
} }
else else
{ {
sprflipvert = false; sprflipvert = false;
sprtopscreen = CenterY - dc_texturemid * spryscale; sprtopscreen = CenterY - DrawerContext::TextureMid() * spryscale;
} }
dc_x = vis->x1; int x = vis->x1;
x2 = vis->x2; x2 = vis->x2;
if (dc_x < x2) if (x < x2)
{ {
while ((dc_x < stop4) && (dc_x & 3)) DrawerContext::SetMaskedColumnState(mfloorclip, mceilingclip, spryscale, sprtopscreen, sprflipvert);
while ((x < stop4) && (x & 3))
{ {
pixels = tex->GetColumn (frac >> FRACBITS, &spans); pixels = tex->GetColumn (frac >> FRACBITS, &spans);
if (ispsprite || !R_ClipSpriteColumnWithPortals(vis)) if (ispsprite || !R_ClipSpriteColumnWithPortals(x, vis))
R_DrawMaskedColumn (pixels, spans); DrawerContext::DrawMaskedColumn (x, pixels, spans);
dc_x++; x++;
frac += xiscale; frac += xiscale;
} }
while (dc_x < stop4) while (x < stop4)
{ {
rt_initcols(nullptr); DrawerContext::RtInitCols(nullptr);
for (int zz = 4; zz; --zz) for (int zz = 0; zz < 4; ++zz)
{ {
pixels = tex->GetColumn (frac >> FRACBITS, &spans); pixels = tex->GetColumn (frac >> FRACBITS, &spans);
if (ispsprite || !R_ClipSpriteColumnWithPortals(vis)) if (ispsprite || !R_ClipSpriteColumnWithPortals(x + zz, vis))
R_DrawMaskedColumnHoriz (pixels, spans); DrawerContext::DrawMaskedColumnHoriz (x + zz, pixels, spans);
dc_x++;
frac += xiscale; frac += xiscale;
} }
rt_draw4cols (dc_x - 4); DrawerContext::DrawRt4cols(x);
x += 4;
} }
while (dc_x < x2) while (x < x2)
{ {
pixels = tex->GetColumn (frac >> FRACBITS, &spans); pixels = tex->GetColumn (frac >> FRACBITS, &spans);
if (ispsprite || !R_ClipSpriteColumnWithPortals(vis)) if (ispsprite || !R_ClipSpriteColumnWithPortals(x, vis))
R_DrawMaskedColumn (pixels, spans); DrawerContext::DrawMaskedColumn (x, pixels, spans);
dc_x++; x++;
frac += xiscale; frac += xiscale;
} }
} }
} }
R_FinishSetPatchStyle (); DrawerContext::FinishSetPatchStyle ();
NetUpdate (); NetUpdate ();
} }
@ -511,7 +425,7 @@ void R_DrawWallSprite(vissprite_t *spr)
WallT.InitFromWallCoords(&spr->wallc); WallT.InitFromWallCoords(&spr->wallc);
PrepWall(swall, lwall, spr->pic->GetWidth() << FRACBITS, x1, x2); PrepWall(swall, lwall, spr->pic->GetWidth() << FRACBITS, x1, x2);
iyscale = 1 / spr->yscale; iyscale = 1 / spr->yscale;
dc_texturemid = (spr->gzt - ViewPos.Z) * iyscale; DrawerContext::SetTextureMid((spr->gzt - ViewPos.Z) * iyscale);
if (spr->renderflags & RF_XFLIP) if (spr->renderflags & RF_XFLIP)
{ {
int right = (spr->pic->GetWidth() << FRACBITS) - 1; int right = (spr->pic->GetWidth() << FRACBITS) - 1;
@ -539,11 +453,11 @@ void R_DrawWallSprite(vissprite_t *spr)
rw_lightstep = float((GlobVis / spr->wallc.sz2 - rw_lightleft) / (spr->wallc.sx2 - spr->wallc.sx1)); rw_lightstep = float((GlobVis / spr->wallc.sz2 - rw_lightleft) / (spr->wallc.sx2 - spr->wallc.sx1));
rw_light = rw_lightleft + (x1 - spr->wallc.sx1) * rw_lightstep; rw_light = rw_lightleft + (x1 - spr->wallc.sx1) * rw_lightstep;
if (fixedlightlev >= 0) if (fixedlightlev >= 0)
R_SetColorMapLight(usecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev)); DrawerContext::SetLight(usecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev));
else if (fixedcolormap != NULL) else if (fixedcolormap != NULL)
R_SetColorMapLight(fixedcolormap, 0, 0); DrawerContext::SetLight(fixedcolormap, 0, 0);
else if (!foggy && (spr->renderflags & RF_FULLBRIGHT)) else if (!foggy && (spr->renderflags & RF_FULLBRIGHT))
R_SetColorMapLight(usecolormap, 0, 0); DrawerContext::SetLight(usecolormap, 0, 0);
else else
calclighting = true; calclighting = true;
@ -553,7 +467,7 @@ void R_DrawWallSprite(vissprite_t *spr)
{ {
sprflipvert = true; sprflipvert = true;
iyscale = -iyscale; iyscale = -iyscale;
dc_texturemid -= spr->pic->GetHeight(); DrawerContext::SetTextureMid(DrawerContext::TextureMid() - spr->pic->GetHeight());
} }
else else
{ {
@ -562,10 +476,9 @@ void R_DrawWallSprite(vissprite_t *spr)
MaskedScaleY = (float)iyscale; MaskedScaleY = (float)iyscale;
dc_x = x1;
ESPSResult mode; ESPSResult mode;
mode = R_SetPatchStyle (spr->Style.RenderStyle, spr->Style.Alpha, spr->Translation, spr->FillColor); mode = DrawerContext::SetPatchStyle (spr->Style.RenderStyle, spr->Style.Alpha, spr->Translation, spr->FillColor);
// R_SetPatchStyle can modify basecolormap. // R_SetPatchStyle can modify basecolormap.
if (rereadcolormap) if (rereadcolormap)
@ -581,71 +494,74 @@ void R_DrawWallSprite(vissprite_t *spr)
{ {
int stop4; int stop4;
int x = x1;
if (mode == DoDraw0) if (mode == DoDraw0)
{ // 1 column at a time { // 1 column at a time
stop4 = dc_x; stop4 = x;
} }
else // DoDraw1 else // DoDraw1
{ // up to 4 columns at a time { // up to 4 columns at a time
stop4 = x2 & ~3; stop4 = x2 & ~3;
} }
while ((dc_x < stop4) && (dc_x & 3)) while ((x < stop4) && (x & 3))
{ {
if (calclighting) if (calclighting)
{ // calculate lighting { // calculate lighting
R_SetColorMapLight(usecolormap, rw_light, shade); DrawerContext::SetLight(usecolormap, rw_light, shade);
} }
if (!R_ClipSpriteColumnWithPortals(spr)) if (!R_ClipSpriteColumnWithPortals(x, spr))
R_WallSpriteColumn(R_DrawMaskedColumn); R_WallSpriteColumn(x, DrawerContext::DrawMaskedColumn);
dc_x++; x++;
} }
while (dc_x < stop4) while (x < stop4)
{ {
if (calclighting) if (calclighting)
{ // calculate lighting { // calculate lighting
R_SetColorMapLight(usecolormap, rw_light, shade); DrawerContext::SetLight(usecolormap, rw_light, shade);
} }
rt_initcols(nullptr); DrawerContext::RtInitCols(nullptr);
for (int zz = 4; zz; --zz) for (int zz = 0; zz < 4; ++zz)
{ {
if (!R_ClipSpriteColumnWithPortals(spr)) if (!R_ClipSpriteColumnWithPortals(x + zz, spr))
R_WallSpriteColumn(R_DrawMaskedColumnHoriz); R_WallSpriteColumn(x + zz, DrawerContext::DrawMaskedColumnHoriz);
dc_x++;
} }
rt_draw4cols(dc_x - 4); DrawerContext::DrawRt4cols(x);
x += 4;
} }
while (dc_x < x2) while (x < x2)
{ {
if (calclighting) if (calclighting)
{ // calculate lighting { // calculate lighting
R_SetColorMapLight(usecolormap, rw_light, shade); DrawerContext::SetLight(usecolormap, rw_light, shade);
} }
if (!R_ClipSpriteColumnWithPortals(spr)) if (!R_ClipSpriteColumnWithPortals(x, spr))
R_WallSpriteColumn(R_DrawMaskedColumn); R_WallSpriteColumn(x, DrawerContext::DrawMaskedColumn);
dc_x++; x++;
} }
} }
R_FinishSetPatchStyle(); DrawerContext::FinishSetPatchStyle();
} }
void R_WallSpriteColumn (void (*drawfunc)(const BYTE *column, const FTexture::Span *spans)) void R_WallSpriteColumn (int x, void (*drawfunc)(int x, const BYTE *column, const FTexture::Span *spans))
{ {
float iscale = swall[dc_x] * MaskedScaleY; float iscale = swall[x] * MaskedScaleY;
dc_iscale = FLOAT2FIXED(iscale); DrawerContext::SetTextureStep(FLOAT2FIXED(iscale));
spryscale = 1 / iscale; spryscale = 1 / iscale;
if (sprflipvert) if (sprflipvert)
sprtopscreen = CenterY + dc_texturemid * spryscale; sprtopscreen = CenterY + DrawerContext::TextureMid() * spryscale;
else else
sprtopscreen = CenterY - dc_texturemid * spryscale; sprtopscreen = CenterY - DrawerContext::TextureMid() * spryscale;
const BYTE *column; const BYTE *column;
const FTexture::Span *spans; const FTexture::Span *spans;
column = WallSpriteTile->GetColumn (lwall[dc_x] >> FRACBITS, &spans); column = WallSpriteTile->GetColumn (lwall[x] >> FRACBITS, &spans);
dc_texturefrac = 0; DrawerContext::SetTextureFrac(0);
drawfunc (column, spans); DrawerContext::SetMaskedColumnState(mfloorclip, mceilingclip, spryscale, sprtopscreen, sprflipvert);
drawfunc (x, column, spans);
rw_light += rw_lightstep; rw_light += rw_lightstep;
} }
@ -655,18 +571,18 @@ void R_DrawVisVoxel(vissprite_t *spr, int minslabz, int maxslabz, short *cliptop
int flags = 0; int flags = 0;
// Do setup for blending. // Do setup for blending.
R_SetColorMapLight(spr->Style.BaseColormap, 0, spr->Style.ColormapNum << FRACBITS); DrawerContext::SetLight(spr->Style.BaseColormap, 0, spr->Style.ColormapNum << FRACBITS);
mode = R_SetPatchStyle(spr->Style.RenderStyle, spr->Style.Alpha, spr->Translation, spr->FillColor); mode = DrawerContext::SetPatchStyle(spr->Style.RenderStyle, spr->Style.Alpha, spr->Translation, spr->FillColor);
if (mode == DontDraw) if (mode == DontDraw)
{ {
return; return;
} }
if (colfunc == fuzzcolfunc || colfunc == R_FillColumn) if (DrawerContext::IsFuzzColumn() || DrawerContext::IsFillColumn())
{ {
flags = DVF_OFFSCREEN | DVF_SPANSONLY; flags = DVF_OFFSCREEN | DVF_SPANSONLY;
} }
else if (colfunc != basecolfunc) else if (!DrawerContext::IsBaseColumn())
{ {
flags = DVF_OFFSCREEN; flags = DVF_OFFSCREEN;
} }
@ -692,32 +608,32 @@ void R_DrawVisVoxel(vissprite_t *spr, int minslabz, int maxslabz, short *cliptop
{ {
if (!(flags & DVF_SPANSONLY) && (x & 3) == 0) if (!(flags & DVF_SPANSONLY) && (x & 3) == 0)
{ {
rt_initcols(OffscreenColorBuffer + x * OffscreenBufferHeight); DrawerContext::RtInitCols(OffscreenColorBuffer + x * OffscreenBufferHeight);
} }
for (FCoverageBuffer::Span *span = OffscreenCoverageBuffer->Spans[x]; span != NULL; span = span->NextSpan) for (FCoverageBuffer::Span *span = OffscreenCoverageBuffer->Spans[x]; span != NULL; span = span->NextSpan)
{ {
if (flags & DVF_SPANSONLY) if (flags & DVF_SPANSONLY)
{ {
dc_x = x; DrawerContext::SetX(x);
dc_yl = span->Start; DrawerContext::SetY1(span->Start);
dc_yh = span->Stop - 1; DrawerContext::SetY2(span->Stop - 1);
dc_count = span->Stop - span->Start; DrawerContext::SetDrawCount(span->Stop - span->Start);
dc_dest = (ylookup[span->Start] + x) * pixelsize + dc_destorg; DrawerContext::SetDest(x, span->Start);
colfunc(); DrawerContext::DrawColumn();
} }
else else
{ {
rt_span_coverage(x, span->Start, span->Stop - 1); DrawerContext::RtSpanCoverage(x, span->Start, span->Stop - 1);
} }
} }
if (!(flags & DVF_SPANSONLY) && (x & 3) == 3) if (!(flags & DVF_SPANSONLY) && (x & 3) == 3)
{ {
rt_draw4cols(x - 3); DrawerContext::DrawRt4cols(x - 3);
} }
} }
} }
R_FinishSetPatchStyle(); DrawerContext::FinishSetPatchStyle();
NetUpdate(); NetUpdate();
} }
@ -2585,7 +2501,7 @@ void R_ProjectParticle (particle_t *particle, const sector_t *sector, int shade,
} }
} }
static void R_DrawMaskedSegsBehindParticle (const vissprite_t *vis) void R_DrawMaskedSegsBehindParticle (const vissprite_t *vis)
{ {
const int x1 = vis->x1; const int x1 = vis->x1;
const int x2 = vis->x2; const int x2 = vis->x2;
@ -2610,120 +2526,24 @@ static void R_DrawMaskedSegsBehindParticle (const vissprite_t *vis)
} }
} }
void R_DrawParticle_C (vissprite_t *vis) void R_DrawParticle(vissprite_t *vis)
{ {
DWORD *bg2rgb;
int spacing;
BYTE *dest;
DWORD fg;
BYTE color = vis->Style.BaseColormap->Maps[(vis->Style.ColormapNum << COLORMAPSHIFT) + vis->startfrac]; BYTE color = vis->Style.BaseColormap->Maps[(vis->Style.ColormapNum << COLORMAPSHIFT) + vis->startfrac];
int yl = vis->y1; int yl = vis->y1;
int ycount = vis->y2 - yl + 1; int yh = vis->y2;
int x1 = vis->x1;
int countbase = vis->x2 - x1;
R_DrawMaskedSegsBehindParticle (vis);
// vis->renderflags holds translucency level (0-255)
{
fixed_t fglevel, bglevel;
DWORD *fg2rgb;
fglevel = ((vis->renderflags + 1) << 8) & ~0x3ff;
bglevel = FRACUNIT-fglevel;
fg2rgb = Col2RGB8[fglevel>>10];
bg2rgb = Col2RGB8[bglevel>>10];
fg = fg2rgb[color];
}
/*
spacing = RenderTarget->GetPitch() - countbase;
dest = ylookup[yl] + x1 + dc_destorg;
do
{
int count = countbase;
do
{
DWORD bg = bg2rgb[*dest];
bg = (fg+bg) | 0x1f07c1f;
*dest++ = RGB32k.All[bg & (bg>>15)];
} while (--count);
dest += spacing;
} while (--ycount);*/
// original was row-wise
// width = countbase
// height = ycount
spacing = RenderTarget->GetPitch();
for (int x = x1; x < (x1+countbase); x++)
{
dc_x = x;
if (R_ClipSpriteColumnWithPortals(vis))
continue;
dest = ylookup[yl] + x + dc_destorg;
for (int y = 0; y < ycount; y++)
{
DWORD bg = bg2rgb[*dest];
bg = (fg+bg) | 0x1f07c1f;
*dest = RGB32k.All[bg & (bg>>15)];
dest += spacing;
}
}
}
void R_DrawParticle_rgba(vissprite_t *vis)
{
int spacing;
uint32_t *dest;
BYTE color = vis->Style.BaseColormap->Maps[vis->startfrac];
int yl = vis->y1;
int ycount = vis->y2 - yl + 1;
int x1 = vis->x1; int x1 = vis->x1;
int countbase = vis->x2 - x1; int countbase = vis->x2 - x1;
R_DrawMaskedSegsBehindParticle(vis); R_DrawMaskedSegsBehindParticle(vis);
DrawerCommandQueue::WaitForWorkers();
uint32_t fg = shade_pal_index_simple(color, calc_light_multiplier(LIGHTSCALE(0, vis->Style.ColormapNum << FRACBITS)));
uint32_t fg_red = (fg >> 16) & 0xff;
uint32_t fg_green = (fg >> 8) & 0xff;
uint32_t fg_blue = fg & 0xff;
// vis->renderflags holds translucency level (0-255) // vis->renderflags holds translucency level (0-255)
fixed_t fglevel = ((vis->renderflags + 1) << 8) & ~0x3ff; int alpha = vis->renderflags;
uint32_t alpha = fglevel * 256 / FRACUNIT;
uint32_t inv_alpha = 256 - alpha;
fg_red *= alpha;
fg_green *= alpha;
fg_blue *= alpha;
spacing = RenderTarget->GetPitch();
for (int x = x1; x < (x1 + countbase); x++) for (int x = x1; x < (x1 + countbase); x++)
{ {
dc_x = x; if (R_ClipSpriteColumnWithPortals(x, vis))
if (R_ClipSpriteColumnWithPortals(vis))
continue; continue;
dest = ylookup[yl] + x + (uint32_t*)dc_destorg; DrawerContext::FillTransColumn(x, yl, yh, color, alpha);
for (int y = 0; y < ycount; y++)
{
uint32_t bg_red = (*dest >> 16) & 0xff;
uint32_t bg_green = (*dest >> 8) & 0xff;
uint32_t bg_blue = (*dest) & 0xff;
uint32_t red = (fg_red + bg_red * inv_alpha) / 256;
uint32_t green = (fg_green + bg_green * inv_alpha) / 256;
uint32_t blue = (fg_blue + bg_blue * inv_alpha) / 256;
*dest = 0xff000000 | (red << 16) | (green << 8) | blue;
dest += spacing;
}
} }
} }
@ -2769,9 +2589,7 @@ void R_DrawVoxel(const FVector3 &globalpos, FAngle viewangle,
sprcosang = FLOAT2FIXED(dasprang.Cos()) >> 2; sprcosang = FLOAT2FIXED(dasprang.Cos()) >> 2;
sprsinang = FLOAT2FIXED(-dasprang.Sin()) >> 2; sprsinang = FLOAT2FIXED(-dasprang.Sin()) >> 2;
R_SetupDrawSlab(colormap); DrawerContext::SetSlabLight(colormap);
int pixelsize = r_swtruecolor ? 4 : 1;
// Select mip level // Select mip level
i = abs(DMulScale6(dasprx - globalposx, cosang, daspry - globalposy, sinang)); i = abs(DMulScale6(dasprx - globalposx, cosang, daspry - globalposy, sinang));
@ -3026,25 +2844,25 @@ void R_DrawVoxel(const FVector3 &globalpos, FAngle viewangle,
if (!(flags & DVF_OFFSCREEN)) if (!(flags & DVF_OFFSCREEN))
{ {
// Draw directly to the screen. // Draw directly to the screen.
R_DrawSlab(xxr - xxl, yplc[xxl], z2 - z1, yinc, col, (ylookup[z1] + lxt + xxl) * pixelsize + dc_destorg); DrawerContext::DrawSlab(xxr - xxl, yplc[xxl], z2 - z1, yinc, col, lxt + xxl, z1);
} }
else else
{ {
// Record the area covered and possibly draw to an offscreen buffer. // Record the area covered and possibly draw to an offscreen buffer.
dc_yl = z1; DrawerContext::SetY1(z1);
dc_yh = z2 - 1; DrawerContext::SetY2(z2 - 1);
dc_count = z2 - z1; DrawerContext::SetDrawCount(z2 - z1);
dc_iscale = yinc; DrawerContext::SetTextureStep(yinc);
for (int x = xxl; x < xxr; ++x) for (int x = xxl; x < xxr; ++x)
{ {
OffscreenCoverageBuffer->InsertSpan(lxt + x, z1, z2); OffscreenCoverageBuffer->InsertSpan(lxt + x, z1, z2);
if (!(flags & DVF_SPANSONLY)) if (!(flags & DVF_SPANSONLY))
{ {
dc_x = lxt + x; DrawerContext::RtInitCols(OffscreenColorBuffer + ((lxt + x) & ~3) * OffscreenBufferHeight);
rt_initcols(OffscreenColorBuffer + (dc_x & ~3) * OffscreenBufferHeight); DrawerContext::SetX(lxt + x);
dc_source = col; DrawerContext::SetSource(col);
dc_texturefrac = yplc[xxl]; DrawerContext::SetTextureFrac(yplc[xxl]);
hcolfunc_pre(); DrawerContext::DrawHColumnPre();
} }
} }
} }

View file

@ -96,11 +96,8 @@ struct vissprite_t
struct particle_t; struct particle_t;
extern void(*R_DrawParticle)(vissprite_t *);
void R_DrawParticle_C (vissprite_t *);
void R_DrawParticle_rgba (vissprite_t *);
void R_ProjectParticle (particle_t *, const sector_t *sector, int shade, int fakeside); void R_ProjectParticle (particle_t *, const sector_t *sector, int shade, int fakeside);
void R_DrawParticle (vissprite_t *vis);
extern int MaxVisSprites; extern int MaxVisSprites;
@ -112,7 +109,6 @@ extern vissprite_t **vissprite_p;
extern short zeroarray[MAXWIDTH]; extern short zeroarray[MAXWIDTH];
extern short screenheightarray[MAXWIDTH]; extern short screenheightarray[MAXWIDTH];
// vars for R_DrawMaskedColumn
extern short* mfloorclip; extern short* mfloorclip;
extern short* mceilingclip; extern short* mceilingclip;
extern double spryscale; extern double spryscale;
@ -126,8 +122,7 @@ extern double pspriteyscale;
extern FTexture *WallSpriteTile; extern FTexture *WallSpriteTile;
void R_DrawMaskedColumn (const BYTE *column, const FTexture::Span *spans); void R_WallSpriteColumn (int x, void (*drawfunc)(int x, const BYTE *column, const FTexture::Span *spans));
void R_WallSpriteColumn (void (*drawfunc)(const BYTE *column, const FTexture::Span *spans));
void R_CacheSprite (spritedef_t *sprite); void R_CacheSprite (spritedef_t *sprite);
void R_SortVisSprites (int (*compare)(const void *, const void *), size_t first); void R_SortVisSprites (int (*compare)(const void *, const void *), size_t first);

View file

@ -43,8 +43,7 @@
#include "r_defs.h" #include "r_defs.h"
#include "r_utility.h" #include "r_utility.h"
#ifndef NO_SWRENDER #ifndef NO_SWRENDER
#include "r_draw.h" #include "r_drawer_context.h"
#include "r_draw_rgba.h"
#include "r_main.h" #include "r_main.h"
#include "r_things.h" #include "r_things.h"
#endif #endif
@ -130,12 +129,14 @@ void DCanvas::DrawTextureParms(FTexture *img, DrawParms &parms)
static short bottomclipper[MAXWIDTH], topclipper[MAXWIDTH]; static short bottomclipper[MAXWIDTH], topclipper[MAXWIDTH];
const BYTE *translation = NULL; const BYTE *translation = NULL;
if (r_swtruecolor != IsBgra()) DCanvas *destorgsave = DrawerContext::Canvas();
if (screen->GetBuffer() == NULL)
{ {
r_swtruecolor = IsBgra(); I_FatalError("Attempt to write to buffer of hardware canvas");
R_InitColumnDrawers();
} }
DrawerContext::SetCanvas(screen);
if (parms.masked) if (parms.masked)
{ {
spanptr = &spans; spanptr = &spans;
@ -172,22 +173,15 @@ void DCanvas::DrawTextureParms(FTexture *img, DrawParms &parms)
if (translation != NULL) if (translation != NULL)
{ {
R_SetTranslationMap((lighttable_t *)translation); DrawerContext::SetTranslationMap((lighttable_t *)translation);
} }
else else
{ {
R_SetTranslationMap(identitymap); DrawerContext::SetTranslationMap(nullptr);
} }
fixedcolormap = dc_fcolormap; fixedcolormap = DrawerContext::LightColormap();
ESPSResult mode = R_SetPatchStyle (parms.style, parms.Alpha, 0, parms.fillcolor); ESPSResult mode = DrawerContext::SetPatchStyle (parms.style, parms.Alpha, 0, parms.fillcolor);
BYTE *destorgsave = dc_destorg;
dc_destorg = screen->GetBuffer();
if (dc_destorg == NULL)
{
I_FatalError("Attempt to write to buffer of hardware canvas");
}
double x0 = parms.x - parms.left * parms.destwidth / parms.texwidth; double x0 = parms.x - parms.left * parms.destwidth / parms.texwidth;
double y0 = parms.y - parms.top * parms.destheight / parms.texheight; double y0 = parms.y - parms.top * parms.destheight / parms.texheight;
@ -220,11 +214,11 @@ void DCanvas::DrawTextureParms(FTexture *img, DrawParms &parms)
assert(spryscale > 0); assert(spryscale > 0);
sprflipvert = false; sprflipvert = false;
//dc_iscale = FLOAT2FIXED(iyscale); //DrawerContext::SetTextureStep(FLOAT2FIXED(iyscale));
//dc_texturemid = (-y0) * iyscale; //DrawerContext::SetTextureMid((-y0) * iyscale);
//dc_iscale = 0xffffffffu / (unsigned)spryscale; //DrawerContext::SetTextureStep(0xffffffffu / (unsigned)spryscale);
dc_iscale = FLOAT2FIXED(1 / spryscale); DrawerContext::SetTextureStep(FLOAT2FIXED(1 / spryscale));
dc_texturemid = (CenterY - 1 - sprtopscreen) * dc_iscale / 65536; DrawerContext::SetTextureMid((CenterY - 1 - sprtopscreen) * DrawerContext::TextureStep() / 65536);
fixed_t frac = 0; fixed_t frac = 0;
double xiscale = img->GetWidth() / parms.destwidth; double xiscale = img->GetWidth() / parms.destwidth;
double x2 = x0 + parms.destwidth; double x2 = x0 + parms.destwidth;
@ -278,14 +272,14 @@ void DCanvas::DrawTextureParms(FTexture *img, DrawParms &parms)
mode = DoDraw0; mode = DoDraw0;
} }
dc_x = int(x0); int x = int(x0);
int x2_i = int(x2); int x2_i = int(x2);
fixed_t xiscale_i = FLOAT2FIXED(xiscale); fixed_t xiscale_i = FLOAT2FIXED(xiscale);
if (mode == DoDraw0) if (mode == DoDraw0)
{ {
// One column at a time // One column at a time
stop4 = dc_x; stop4 = x;
} }
else // DoDraw1` else // DoDraw1`
{ {
@ -293,42 +287,44 @@ void DCanvas::DrawTextureParms(FTexture *img, DrawParms &parms)
stop4 = x2_i & ~3; stop4 = x2_i & ~3;
} }
if (dc_x < x2_i) if (x < x2_i)
{ {
while ((dc_x < stop4) && (dc_x & 3)) DrawerContext::SetMaskedColumnState(mfloorclip, mceilingclip, spryscale, sprtopscreen, sprflipvert);
while ((x < stop4) && (x & 3))
{ {
pixels = img->GetColumn(frac >> FRACBITS, spanptr); pixels = img->GetColumn(frac >> FRACBITS, spanptr);
R_DrawMaskedColumn(pixels, spans); DrawerContext::DrawMaskedColumn(x, pixels, spans);
dc_x++; x++;
frac += xiscale_i; frac += xiscale_i;
} }
while (dc_x < stop4) while (x < stop4)
{ {
rt_initcols(nullptr); DrawerContext::RtInitCols(nullptr);
for (int zz = 4; zz; --zz) for (int zz = 0; zz < 4; ++zz)
{ {
pixels = img->GetColumn(frac >> FRACBITS, spanptr); pixels = img->GetColumn(frac >> FRACBITS, spanptr);
R_DrawMaskedColumnHoriz(pixels, spans); DrawerContext::DrawMaskedColumnHoriz(x + zz, pixels, spans);
dc_x++;
frac += xiscale_i; frac += xiscale_i;
} }
rt_draw4cols(dc_x - 4); DrawerContext::DrawRt4cols(x);
x += 4;
} }
while (dc_x < x2_i) while (x < x2_i)
{ {
pixels = img->GetColumn(frac >> FRACBITS, spanptr); pixels = img->GetColumn(frac >> FRACBITS, spanptr);
R_DrawMaskedColumn(pixels, spans); DrawerContext::DrawMaskedColumn(x, pixels, spans);
dc_x++; x++;
frac += xiscale_i; frac += xiscale_i;
} }
} }
CenterY = centeryback; CenterY = centeryback;
} }
R_FinishSetPatchStyle (); DrawerContext::FinishSetPatchStyle ();
dc_destorg = destorgsave; DrawerContext::SetCanvas(destorgsave);
if (ticdup != 0 && menuactive == MENU_Off) if (ticdup != 0 && menuactive == MENU_Off)
{ {
@ -1024,9 +1020,11 @@ void DCanvas::PUTTRANSDOT (int xx, int yy, int basecolor, int level)
if (IsBgra()) if (IsBgra())
{ {
int inv_level = 64 - level;
uint32_t *spot = (uint32_t*)GetBuffer() + oldyyshifted + xx; uint32_t *spot = (uint32_t*)GetBuffer() + oldyyshifted + xx;
uint32_t fg = shade_pal_index_simple(basecolor, calc_light_multiplier(0)); uint32_t fg = GPalette.BaseColors[basecolor].d;
uint32_t fg_red = (fg >> 16) & 0xff; uint32_t fg_red = (fg >> 16) & 0xff;
uint32_t fg_green = (fg >> 8) & 0xff; uint32_t fg_green = (fg >> 8) & 0xff;
uint32_t fg_blue = fg & 0xff; uint32_t fg_blue = fg & 0xff;
@ -1035,9 +1033,9 @@ void DCanvas::PUTTRANSDOT (int xx, int yy, int basecolor, int level)
uint32_t bg_green = (*spot >> 8) & 0xff; uint32_t bg_green = (*spot >> 8) & 0xff;
uint32_t bg_blue = (*spot) & 0xff; uint32_t bg_blue = (*spot) & 0xff;
uint32_t red = (fg_red + bg_red + 1) / 2; uint32_t red = (fg_red * level + bg_red * inv_level + 1) / 64;
uint32_t green = (fg_green + bg_green + 1) / 2; uint32_t green = (fg_green * level + bg_green * inv_level + 1) / 64;
uint32_t blue = (fg_blue + bg_blue + 1) / 2; uint32_t blue = (fg_blue * level + bg_blue * inv_level + 1) / 64;
*spot = 0xff000000 | (red << 16) | (green << 8) | blue; *spot = 0xff000000 | (red << 16) | (green << 8) | blue;
} }
@ -1399,16 +1397,15 @@ void DCanvas::FillSimplePoly(FTexture *tex, FVector2 *points, int npoints,
sinrot = sin(rotation.Radians()); sinrot = sin(rotation.Radians());
// Setup constant texture mapping parameters. // Setup constant texture mapping parameters.
R_SetupSpanBits(tex);
if (colormap) if (colormap)
R_SetSpanColormap(colormap, clamp(shade >> FRACBITS, 0, NUMCOLORMAPS - 1)); DrawerContext::SetSpanLight(colormap, 0, clamp(shade >> FRACBITS, 0, NUMCOLORMAPS - 1));
else else
R_SetSpanColormap(&identitycolormap, 0); DrawerContext::SetSpanLight(nullptr, 0, 0);
R_SetSpanSource(r_swtruecolor ? (const BYTE*)tex->GetPixelsBgra() : tex->GetPixels()); DrawerContext::SetSpanSource(tex);
scalex = double(1u << (32 - ds_xbits)) / scalex; scalex = double(1u << (32 - DrawerContext::SpanXBits())) / scalex;
scaley = double(1u << (32 - ds_ybits)) / scaley; scaley = double(1u << (32 - DrawerContext::SpanYBits())) / scaley;
ds_xstep = xs_RoundToInt(cosrot * scalex); DrawerContext::SetSpanXStep(xs_RoundToInt(cosrot * scalex));
ds_ystep = xs_RoundToInt(sinrot * scaley); DrawerContext::SetSpanYStep(xs_RoundToInt(sinrot * scaley));
// Travel down the right edge and create an outline of that edge. // Travel down the right edge and create an outline of that edge.
pt1 = toppt; pt1 = toppt;
@ -1472,9 +1469,9 @@ void DCanvas::FillSimplePoly(FTexture *tex, FVector2 *points, int npoints,
#if 0 #if 0
memset(this->Buffer + y * this->Pitch + x1, (int)tex, x2 - x1); memset(this->Buffer + y * this->Pitch + x1, (int)tex, x2 - x1);
#else #else
ds_y = y; DrawerContext::SetSpanY(y);
ds_x1 = x1; DrawerContext::SetSpanX1(x1);
ds_x2 = x2 - 1; DrawerContext::SetSpanX2(x2 - 1);
DVector2 tex(x1 - originx, y - originy); DVector2 tex(x1 - originx, y - originy);
if (dorotate) if (dorotate)
@ -1483,10 +1480,10 @@ void DCanvas::FillSimplePoly(FTexture *tex, FVector2 *points, int npoints,
tex.X = t * cosrot - tex.Y * sinrot; tex.X = t * cosrot - tex.Y * sinrot;
tex.Y = tex.Y * cosrot + t * sinrot; tex.Y = tex.Y * cosrot + t * sinrot;
} }
ds_xfrac = xs_RoundToInt(tex.X * scalex); DrawerContext::SetSpanXFrac(xs_RoundToInt(tex.X * scalex));
ds_yfrac = xs_RoundToInt(tex.Y * scaley); DrawerContext::SetSpanYFrac(xs_RoundToInt(tex.Y * scaley));
R_DrawSpan(); DrawerContext::DrawSimplePolySpan();
#endif #endif
} }
x += xinc; x += xinc;