Queue a full wall as one draw command

This commit is contained in:
Magnus Norddahl 2019-11-23 02:25:42 +01:00
parent 310459b490
commit 62b2039a75
13 changed files with 599 additions and 448 deletions

View file

@ -51,6 +51,7 @@
#include "r_draw_pal.h"
#include "r_thread.h"
#include "swrenderer/scene/r_light.h"
#include "playsim/a_dynlight.h"
CVAR(Bool, r_dynlights, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
CVAR(Bool, r_fuzzscale, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
@ -216,34 +217,343 @@ namespace swrenderer
}
}
class DepthColumnCommand : public DrawerCommand
/////////////////////////////////////////////////////////////////////////
DrawWallCommand::DrawWallCommand(const WallDrawerArgs& args) : wallargs(args)
{
public:
DepthColumnCommand(const WallDrawerArgs &args, float idepth) : idepth(idepth)
}
void DrawWallCommand::Execute(DrawerThread* thread)
{
WallColumnDrawerArgs drawerargs(wallargs);
bool fixed = wallargs.fixedlight;
bool haslights = r_dynlights && wallargs.lightlist;
if (haslights)
{
auto rendertarget = args.Viewport()->RenderTarget;
if (rendertarget->IsBgra())
{
uint32_t *destorg = (uint32_t*)rendertarget->GetPixels();
destorg += viewwindowx + viewwindowy * rendertarget->GetPitch();
uint32_t *dest = (uint32_t*)args.Dest();
int offset = (int)(ptrdiff_t)(dest - destorg);
x = offset % rendertarget->GetPitch();
y = offset / rendertarget->GetPitch();
}
else
{
uint8_t *destorg = rendertarget->GetPixels();
destorg += viewwindowx + viewwindowy * rendertarget->GetPitch();
uint8_t *dest = (uint8_t*)args.Dest();
int offset = (int)(ptrdiff_t)(dest - destorg);
x = offset % rendertarget->GetPitch();
y = offset / rendertarget->GetPitch();
}
count = args.Count();
float dx = wallargs.WallC.tright.X - wallargs.WallC.tleft.X;
float dy = wallargs.WallC.tright.Y - wallargs.WallC.tleft.Y;
float length = sqrt(dx * dx + dy * dy);
drawerargs.dc_normal.X = dy / length;
drawerargs.dc_normal.Y = -dx / length;
drawerargs.dc_normal.Z = 0.0f;
}
DepthColumnCommand(const SkyDrawerArgs &args, float idepth) : idepth(idepth)
drawerargs.SetTextureFracBits(wallargs.fracbits);
float curlight = wallargs.lightpos;
float lightstep = wallargs.lightstep;
int shade = wallargs.mShade;
float upos = wallargs.texcoords.upos, ustepX = wallargs.texcoords.ustepX, ustepY = wallargs.texcoords.ustepY;
float vpos = wallargs.texcoords.vpos, vstepX = wallargs.texcoords.vstepX, vstepY = wallargs.texcoords.vstepY;
float wpos = wallargs.texcoords.wpos, wstepX = wallargs.texcoords.wstepX, wstepY = wallargs.texcoords.wstepY;
float startX = wallargs.texcoords.startX;
int x1 = wallargs.x1;
int x2 = wallargs.x2;
upos += ustepX * (x1 + 0.5f - startX);
vpos += vstepX * (x1 + 0.5f - startX);
wpos += wstepX * (x1 + 0.5f - startX);
float centerY = wallargs.CenterY;
centerY -= 0.5f;
auto uwal = wallargs.uwal;
auto dwal = wallargs.dwal;
for (int x = x1; x < x2; x++)
{
int y1 = uwal[x];
int y2 = dwal[x];
if (y2 > y1)
{
if (!fixed) drawerargs.SetLight(curlight, shade);
if (haslights)
SetLights(drawerargs, x, y1);
else
drawerargs.dc_num_lights = 0;
float dy = (y1 - centerY);
float u = upos + ustepY * dy;
float v = vpos + vstepY * dy;
float w = wpos + wstepY * dy;
float scaleU = ustepX;
float scaleV = vstepY;
w = 1.0f / w;
u *= w;
v *= w;
scaleU *= w;
scaleV *= w;
uint32_t texelX = (uint32_t)(int64_t)((u - std::floor(u)) * 0x1'0000'0000LL);
uint32_t texelY = (uint32_t)(int64_t)((v - std::floor(v)) * 0x1'0000'0000LL);
uint32_t texelStepX = (uint32_t)(int64_t)(scaleU * 0x1'0000'0000LL);
uint32_t texelStepY = (uint32_t)(int64_t)(scaleV * 0x1'0000'0000LL);
if (wallargs.fracbits != 32)
DrawWallColumn8(thread, drawerargs, x, y1, y2, texelX, texelY, texelStepY);
else
DrawWallColumn32(thread, drawerargs, x, y1, y2, texelX, texelY, texelStepX, texelStepY);
}
upos += ustepX;
vpos += vstepX;
wpos += wstepX;
curlight += lightstep;
}
if (r_modelscene)
{
for (int x = x1; x < x2; x++)
{
int y1 = uwal[x];
int y2 = dwal[x];
if (y2 > y1)
{
int count = y2 - y1;
float w1 = 1.0f / wallargs.WallC.sz1;
float w2 = 1.0f / wallargs.WallC.sz2;
float t = (x - wallargs.WallC.sx1 + 0.5f) / (wallargs.WallC.sx2 - wallargs.WallC.sx1);
float wcol = w1 * (1.0f - t) + w2 * t;
float zcol = 1.0f / wcol;
float zbufferdepth = 1.0f / (zcol / wallargs.FocalTangent);
drawerargs.SetDest(x, y1);
drawerargs.SetCount(count);
DrawDepthColumn(thread, drawerargs, zbufferdepth);
}
}
}
}
void DrawWallCommand::DrawWallColumn32(DrawerThread* thread, WallColumnDrawerArgs& drawerargs, int x, int y1, int y2, uint32_t texelX, uint32_t texelY, uint32_t texelStepX, uint32_t texelStepY)
{
int texwidth = wallargs.texwidth;
int texheight = wallargs.texheight;
double xmagnitude = fabs(static_cast<int32_t>(texelStepX)* (1.0 / 0x1'0000'0000LL));
double ymagnitude = fabs(static_cast<int32_t>(texelStepY)* (1.0 / 0x1'0000'0000LL));
double magnitude = MAX(ymagnitude, xmagnitude);
double min_lod = -1000.0;
double lod = MAX(log2(magnitude) + r_lod_bias, min_lod);
bool magnifying = lod < 0.0f;
int mipmap_offset = 0;
int mip_width = texwidth;
int mip_height = texheight;
if (wallargs.mipmapped && mip_width > 1 && mip_height > 1)
{
int level = (int)lod;
while (level > 0 && mip_width > 1 && mip_height > 1)
{
mipmap_offset += mip_width * mip_height;
level--;
mip_width = MAX(mip_width >> 1, 1);
mip_height = MAX(mip_height >> 1, 1);
}
}
const uint32_t* pixels = static_cast<const uint32_t*>(wallargs.texpixels) + mipmap_offset;
fixed_t xxoffset = (texelX >> 16)* mip_width;
const uint8_t* source;
const uint8_t* source2;
uint32_t texturefracx;
bool filter_nearest = (magnifying && !r_magfilter) || (!magnifying && !r_minfilter);
if (filter_nearest)
{
int tx = (xxoffset >> FRACBITS) % mip_width;
source = (uint8_t*)(pixels + tx * mip_height);
source2 = nullptr;
texturefracx = 0;
}
else
{
xxoffset -= FRACUNIT / 2;
int tx0 = (xxoffset >> FRACBITS) % mip_width;
if (tx0 < 0)
tx0 += mip_width;
int tx1 = (tx0 + 1) % mip_width;
source = (uint8_t*)(pixels + tx0 * mip_height);
source2 = (uint8_t*)(pixels + tx1 * mip_height);
texturefracx = (xxoffset >> (FRACBITS - 4)) & 15;
}
int count = y2 - y1;
drawerargs.SetDest(x, y1);
drawerargs.SetCount(count);
drawerargs.SetTexture(source, source2, mip_height);
drawerargs.SetTextureUPos(texturefracx);
drawerargs.SetTextureVPos(texelY);
drawerargs.SetTextureVStep(texelStepY);
DrawColumn(thread, drawerargs);
}
void DrawWallCommand::DrawWallColumn8(DrawerThread* thread, WallColumnDrawerArgs& drawerargs, int x, int y1, int y2, uint32_t texelX, uint32_t texelY, uint32_t texelStepY)
{
int texwidth = wallargs.texwidth;
int texheight = wallargs.texheight;
int fracbits = wallargs.fracbits;
uint32_t uv_max = texheight << fracbits;
const uint8_t* pixels = static_cast<const uint8_t*>(wallargs.texpixels) + (((texelX >> 16)* texwidth) >> 16)* texheight;
texelY = (static_cast<uint64_t>(texelY)* texheight) >> (32 - fracbits);
texelStepY = (static_cast<uint64_t>(texelStepY)* texheight) >> (32 - fracbits);
drawerargs.SetTexture(pixels, nullptr, texheight);
drawerargs.SetTextureVStep(texelStepY);
if (uv_max == 0 || texelStepY == 0) // power of two
{
int count = y2 - y1;
drawerargs.SetDest(x, y1);
drawerargs.SetCount(count);
drawerargs.SetTextureVPos(texelY);
DrawColumn(thread, drawerargs);
}
else
{
uint32_t left = y2 - y1;
int y = y1;
while (left > 0)
{
uint32_t available = uv_max - texelY;
uint32_t next_uv_wrap = available / texelStepY;
if (available % texelStepY != 0)
next_uv_wrap++;
uint32_t count = MIN(left, next_uv_wrap);
drawerargs.SetDest(x, y);
drawerargs.SetCount(count);
drawerargs.SetTextureVPos(texelY);
DrawColumn(thread, drawerargs);
y += count;
left -= count;
texelY += texelStepY * count;
if (texelY >= uv_max)
texelY -= uv_max;
}
}
}
void DrawWallCommand::DrawDepthColumn(DrawerThread* thread, const WallColumnDrawerArgs& args, float idepth)
{
int x, y, count;
auto rendertarget = args.Viewport()->RenderTarget;
if (rendertarget->IsBgra())
{
uint32_t* destorg = (uint32_t*)rendertarget->GetPixels();
destorg += viewwindowx + viewwindowy * rendertarget->GetPitch();
uint32_t* dest = (uint32_t*)args.Dest();
int offset = (int)(ptrdiff_t)(dest - destorg);
x = offset % rendertarget->GetPitch();
y = offset / rendertarget->GetPitch();
}
else
{
uint8_t* destorg = rendertarget->GetPixels();
destorg += viewwindowx + viewwindowy * rendertarget->GetPitch();
uint8_t* dest = (uint8_t*)args.Dest();
int offset = (int)(ptrdiff_t)(dest - destorg);
x = offset % rendertarget->GetPitch();
y = offset / rendertarget->GetPitch();
}
count = args.Count();
auto zbuffer = PolyZBuffer::Instance();
int pitch = PolyStencilBuffer::Instance()->Width();
float* values = zbuffer->Values() + y * pitch + x;
int cnt = count;
values = thread->dest_for_thread(y, pitch, values);
cnt = thread->count_for_thread(y, cnt);
pitch *= thread->num_cores;
float depth = idepth;
for (int i = 0; i < cnt; i++)
{
*values = depth;
values += pitch;
}
}
void DrawWallCommand::SetLights(WallColumnDrawerArgs& drawerargs, int x, int y1)
{
bool mirror = !!(wallargs.PortalMirrorFlags & RF_XFLIP);
int tx = x;
if (mirror)
tx = viewwidth - tx - 1;
// Find column position in view space
float w1 = 1.0f / wallargs.WallC.sz1;
float w2 = 1.0f / wallargs.WallC.sz2;
float t = (x - wallargs.WallC.sx1 + 0.5f) / (wallargs.WallC.sx2 - wallargs.WallC.sx1);
float wcol = w1 * (1.0f - t) + w2 * t;
float zcol = 1.0f / wcol;
drawerargs.dc_viewpos.X = (float)((tx + 0.5 - wallargs.CenterX) / wallargs.CenterX * zcol);
drawerargs.dc_viewpos.Y = zcol;
drawerargs.dc_viewpos.Z = (float)((wallargs.CenterY - y1 - 0.5) / wallargs.InvZtoScale * zcol);
drawerargs.dc_viewpos_step.Z = (float)(-zcol / wallargs.InvZtoScale);
drawerargs.dc_num_lights = 0;
// Setup lights for column
FLightNode* cur_node = drawerargs.LightList();
while (cur_node)
{
if (cur_node->lightsource->IsActive())
{
double lightX = cur_node->lightsource->X() - wallargs.ViewpointPos.X;
double lightY = cur_node->lightsource->Y() - wallargs.ViewpointPos.Y;
double lightZ = cur_node->lightsource->Z() - wallargs.ViewpointPos.Z;
float lx = (float)(lightX * wallargs.Sin - lightY * wallargs.Cos) - drawerargs.dc_viewpos.X;
float ly = (float)(lightX * wallargs.TanCos + lightY * wallargs.TanSin) - drawerargs.dc_viewpos.Y;
float lz = (float)lightZ;
// Precalculate the constant part of the dot here so the drawer doesn't have to.
bool is_point_light = cur_node->lightsource->IsAttenuated();
float lconstant = lx * lx + ly * ly;
float nlconstant = is_point_light ? lx * drawerargs.dc_normal.X + ly * drawerargs.dc_normal.Y : 0.0f;
// Include light only if it touches this column
float radius = cur_node->lightsource->GetRadius();
if (radius * radius >= lconstant && nlconstant >= 0.0f)
{
uint32_t red = cur_node->lightsource->GetRed();
uint32_t green = cur_node->lightsource->GetGreen();
uint32_t blue = cur_node->lightsource->GetBlue();
auto& light = drawerargs.dc_lights[drawerargs.dc_num_lights++];
light.x = lconstant;
light.y = nlconstant;
light.z = lz;
light.radius = 256.0f / cur_node->lightsource->GetRadius();
light.color = (red << 16) | (green << 8) | blue;
if (drawerargs.dc_num_lights == WallColumnDrawerArgs::MAX_DRAWER_LIGHTS)
break;
}
}
cur_node = cur_node->nextLight;
}
}
/////////////////////////////////////////////////////////////////////////
class DepthSkyColumnCommand : public DrawerCommand
{
public:
DepthSkyColumnCommand(const SkyDrawerArgs &args, float idepth) : idepth(idepth)
{
auto rendertarget = args.Viewport()->RenderTarget;
if (rendertarget->IsBgra())
@ -359,12 +669,7 @@ namespace swrenderer
void SWPixelFormatDrawers::DrawDepthSkyColumn(const SkyDrawerArgs &args, float idepth)
{
Queue->Push<DepthColumnCommand>(args, idepth);
}
void SWPixelFormatDrawers::DrawDepthWallColumn(const WallDrawerArgs &args, float idepth)
{
Queue->Push<DepthColumnCommand>(args, idepth);
Queue->Push<DepthSkyColumnCommand>(args, idepth);
}
void SWPixelFormatDrawers::DrawDepthSpan(const SpanDrawerArgs &args, float idepth1, float idepth2)

View file

@ -57,12 +57,12 @@ namespace swrenderer
public:
SWPixelFormatDrawers(DrawerCommandQueuePtr queue) : Queue(queue) { }
virtual ~SWPixelFormatDrawers() { }
virtual void DrawWallColumn(const WallDrawerArgs &args) = 0;
virtual void DrawWallMaskedColumn(const WallDrawerArgs &args) = 0;
virtual void DrawWallAddColumn(const WallDrawerArgs &args) = 0;
virtual void DrawWallAddClampColumn(const WallDrawerArgs &args) = 0;
virtual void DrawWallSubClampColumn(const WallDrawerArgs &args) = 0;
virtual void DrawWallRevSubClampColumn(const WallDrawerArgs &args) = 0;
virtual void DrawWall(const WallDrawerArgs &args) = 0;
virtual void DrawWallMasked(const WallDrawerArgs &args) = 0;
virtual void DrawWallAdd(const WallDrawerArgs &args) = 0;
virtual void DrawWallAddClamp(const WallDrawerArgs &args) = 0;
virtual void DrawWallSubClamp(const WallDrawerArgs &args) = 0;
virtual void DrawWallRevSubClamp(const WallDrawerArgs &args) = 0;
virtual void DrawSingleSkyColumn(const SkyDrawerArgs &args) = 0;
virtual void DrawDoubleSkyColumn(const SkyDrawerArgs &args) = 0;
virtual void DrawColumn(const SpriteDrawerArgs &args) = 0;
@ -96,7 +96,6 @@ namespace swrenderer
virtual void DrawFogBoundaryLine(const SpanDrawerArgs &args) = 0;
void DrawDepthSkyColumn(const SkyDrawerArgs &args, float idepth);
void DrawDepthWallColumn(const WallDrawerArgs &args, float idepth);
void DrawDepthSpan(const SpanDrawerArgs &args, float idepth1, float idepth2);
DrawerCommandQueuePtr Queue;

View file

@ -93,10 +93,6 @@ EXTERN_CVAR(Int, gl_particles_style)
namespace swrenderer
{
PalWall1Command::PalWall1Command(const WallDrawerArgs &args) : args(args)
{
}
uint8_t PalWall1Command::AddLights(const DrawerLight *lights, int num_lights, float viewpos_z, uint8_t fg, uint8_t material)
{
uint32_t lit_r = 0;
@ -150,7 +146,7 @@ namespace swrenderer
return RGB256k.All[((lit_r >> 2) << 12) | ((lit_g >> 2) << 6) | (lit_b >> 2)];
}
void DrawWall1PalCommand::Execute(DrawerThread *thread)
void DrawWall1PalCommand::DrawColumn(DrawerThread *thread, const WallColumnDrawerArgs& args)
{
uint32_t fracstep = args.TextureVStep();
uint32_t frac = args.TextureVPos();
@ -160,7 +156,7 @@ namespace swrenderer
uint8_t *dest = args.Dest();
int bits = args.TextureFracBits();
int pitch = args.Viewport()->RenderTarget->GetPitch();
DrawerLight *dynlights = args.dc_lights;
const DrawerLight *dynlights = args.dc_lights;
int num_dynlights = args.dc_num_lights;
float viewpos_z = args.dc_viewpos.Z;
float step_viewpos_z = args.dc_viewpos_step.Z;
@ -201,7 +197,7 @@ namespace swrenderer
}
}
void DrawWallMasked1PalCommand::Execute(DrawerThread *thread)
void DrawWallMasked1PalCommand::DrawColumn(DrawerThread *thread, const WallColumnDrawerArgs& args)
{
uint32_t fracstep = args.TextureVStep();
uint32_t frac = args.TextureVPos();
@ -211,7 +207,7 @@ namespace swrenderer
uint8_t *dest = args.Dest();
int bits = args.TextureFracBits();
int pitch = args.Viewport()->RenderTarget->GetPitch();
DrawerLight *dynlights = args.dc_lights;
const DrawerLight *dynlights = args.dc_lights;
int num_dynlights = args.dc_num_lights;
float viewpos_z = args.dc_viewpos.Z;
float step_viewpos_z = args.dc_viewpos_step.Z;
@ -260,7 +256,7 @@ namespace swrenderer
}
}
void DrawWallAdd1PalCommand::Execute(DrawerThread *thread)
void DrawWallAdd1PalCommand::DrawColumn(DrawerThread *thread, const WallColumnDrawerArgs& args)
{
uint32_t fracstep = args.TextureVStep();
uint32_t frac = args.TextureVPos();
@ -322,7 +318,7 @@ namespace swrenderer
}
}
void DrawWallAddClamp1PalCommand::Execute(DrawerThread *thread)
void DrawWallAddClamp1PalCommand::DrawColumn(DrawerThread *thread, const WallColumnDrawerArgs& args)
{
uint32_t fracstep = args.TextureVStep();
uint32_t frac = args.TextureVPos();
@ -332,7 +328,7 @@ namespace swrenderer
uint8_t *dest = args.Dest();
int bits = args.TextureFracBits();
int pitch = args.Viewport()->RenderTarget->GetPitch();
DrawerLight *dynlights = args.dc_lights;
const DrawerLight *dynlights = args.dc_lights;
int num_dynlights = args.dc_num_lights;
float viewpos_z = args.dc_viewpos.Z;
float step_viewpos_z = args.dc_viewpos_step.Z;
@ -396,7 +392,7 @@ namespace swrenderer
}
}
void DrawWallSubClamp1PalCommand::Execute(DrawerThread *thread)
void DrawWallSubClamp1PalCommand::DrawColumn(DrawerThread *thread, const WallColumnDrawerArgs& args)
{
uint32_t fracstep = args.TextureVStep();
uint32_t frac = args.TextureVPos();
@ -406,7 +402,7 @@ namespace swrenderer
uint8_t *dest = args.Dest();
int bits = args.TextureFracBits();
int pitch = args.Viewport()->RenderTarget->GetPitch();
DrawerLight *dynlights = args.dc_lights;
const DrawerLight *dynlights = args.dc_lights;
int num_dynlights = args.dc_num_lights;
float viewpos_z = args.dc_viewpos.Z;
float step_viewpos_z = args.dc_viewpos_step.Z;
@ -469,7 +465,7 @@ namespace swrenderer
}
}
void DrawWallRevSubClamp1PalCommand::Execute(DrawerThread *thread)
void DrawWallRevSubClamp1PalCommand::DrawColumn(DrawerThread *thread, const WallColumnDrawerArgs& args)
{
uint32_t fracstep = args.TextureVStep();
uint32_t frac = args.TextureVPos();
@ -479,7 +475,7 @@ namespace swrenderer
uint8_t *dest = args.Dest();
int bits = args.TextureFracBits();
int pitch = args.Viewport()->RenderTarget->GetPitch();
DrawerLight *dynlights = args.dc_lights;
const DrawerLight *dynlights = args.dc_lights;
int num_dynlights = args.dc_num_lights;
float viewpos_z = args.dc_viewpos.Z;
float step_viewpos_z = args.dc_viewpos_step.Z;

View file

@ -8,26 +8,140 @@
#include "swrenderer/viewport/r_spandrawer.h"
#include "swrenderer/viewport/r_walldrawer.h"
#include "swrenderer/viewport/r_spritedrawer.h"
#include "swrenderer/r_swcolormaps.h"
struct FSWColormap;
namespace swrenderer
{
class PalWall1Command : public DrawerCommand
class WallColumnDrawerArgs
{
public:
PalWall1Command(const WallDrawerArgs &args);
WallColumnDrawerArgs(const WallDrawerArgs& wallargs) : wallargs(wallargs) { }
void SetDest(int x, int y)
{
dc_dest = Viewport()->GetDest(x, y);
dc_dest_y = y;
}
void SetCount(int count) { dc_count = count; }
void SetTexture(const uint8_t* pixels, const uint8_t* pixels2, int height)
{
dc_source = pixels;
dc_source2 = pixels2;
dc_textureheight = height;
}
void SetTextureFracBits(int bits) { dc_wall_fracbits = bits; }
void SetTextureUPos(uint32_t pos) { dc_texturefracx = pos; }
void SetTextureVPos(fixed_t pos) { dc_texturefrac = pos; }
void SetTextureVStep(fixed_t step) { dc_iscale = step; }
void SetLight(float light, int shade) { mLight = light; mShade = shade; }
uint8_t* Dest() const { return dc_dest; }
int DestY() const { return dc_dest_y; }
int Count() const { return dc_count; }
uint32_t* SrcBlend() const { return wallargs.SrcBlend(); }
uint32_t* DestBlend() const { return wallargs.DestBlend(); }
fixed_t SrcAlpha() const { return wallargs.SrcAlpha(); }
fixed_t DestAlpha() const { return wallargs.DestAlpha(); }
uint32_t TextureUPos() const { return dc_texturefracx; }
fixed_t TextureVPos() const { return dc_texturefrac; }
fixed_t TextureVStep() const { return dc_iscale; }
const uint8_t* TexturePixels() const { return dc_source; }
const uint8_t* TexturePixels2() const { return dc_source2; }
uint32_t TextureHeight() const { return dc_textureheight; }
int TextureFracBits() const { return dc_wall_fracbits; }
FVector3 dc_normal = { 0,0,0 };
FVector3 dc_viewpos = { 0,0,0 };
FVector3 dc_viewpos_step = { 0,0,0 };
enum { MAX_DRAWER_LIGHTS = 16 };
DrawerLight dc_lights[MAX_DRAWER_LIGHTS];
int dc_num_lights = 0;
RenderViewport* Viewport() const { return wallargs.Viewport(); }
uint8_t* Colormap(RenderViewport* viewport) const
{
auto basecolormap = wallargs.BaseColormap();
if (basecolormap)
{
if (viewport->RenderTarget->IsBgra())
return basecolormap->Maps;
else
return basecolormap->Maps + (GETPALOOKUP(mLight, mShade) << COLORMAPSHIFT);
}
else
{
return wallargs.TranslationMap();
}
}
uint8_t* TranslationMap() const { return wallargs.TranslationMap(); }
ShadeConstants ColormapConstants() const { return wallargs.ColormapConstants(); }
fixed_t Light() const { return LIGHTSCALE(mLight, mShade); }
FLightNode* LightList() const { return wallargs.lightlist; }
private:
const WallDrawerArgs& wallargs;
uint8_t* dc_dest = nullptr;
int dc_dest_y = 0;
int dc_count = 0;
fixed_t dc_iscale = 0;
fixed_t dc_texturefrac = 0;
uint32_t dc_texturefracx = 0;
uint32_t dc_textureheight = 0;
const uint8_t* dc_source = nullptr;
const uint8_t* dc_source2 = nullptr;
int dc_wall_fracbits = 0;
float mLight = 0.0f;
int mShade = 0;
};
class DrawWallCommand : public DrawerCommand
{
public:
DrawWallCommand(const WallDrawerArgs& args);
void Execute(DrawerThread* thread) override;
protected:
virtual void DrawColumn(DrawerThread* thread, const WallColumnDrawerArgs& args) = 0;
private:
void DrawWallColumn32(DrawerThread* thread, WallColumnDrawerArgs& drawerargs, int x, int y1, int y2, uint32_t texelX, uint32_t texelY, uint32_t texelStepX, uint32_t texelStepY);
void DrawWallColumn8(DrawerThread* thread, WallColumnDrawerArgs& drawerargs, int x, int y1, int y2, uint32_t texelX, uint32_t texelY, uint32_t texelStepY);
void DrawDepthColumn(DrawerThread* thread, const WallColumnDrawerArgs& args, float idepth);
void SetLights(WallColumnDrawerArgs& drawerargs, int x, int y1);
WallDrawerArgs wallargs;
};
class PalWall1Command : public DrawWallCommand
{
public:
PalWall1Command(const WallDrawerArgs &args) : DrawWallCommand(args) { }
protected:
inline static uint8_t AddLights(const DrawerLight *lights, int num_lights, float viewpos_z, uint8_t fg, uint8_t material);
WallDrawerArgs args;
};
class DrawWall1PalCommand : public PalWall1Command { public: using PalWall1Command::PalWall1Command; void Execute(DrawerThread *thread) override; };
class DrawWallMasked1PalCommand : public PalWall1Command { public: using PalWall1Command::PalWall1Command; void Execute(DrawerThread *thread) override; };
class DrawWallAdd1PalCommand : public PalWall1Command { public: using PalWall1Command::PalWall1Command; void Execute(DrawerThread *thread) override; };
class DrawWallAddClamp1PalCommand : public PalWall1Command { public: using PalWall1Command::PalWall1Command; void Execute(DrawerThread *thread) override; };
class DrawWallSubClamp1PalCommand : public PalWall1Command { public: using PalWall1Command::PalWall1Command; void Execute(DrawerThread *thread) override; };
class DrawWallRevSubClamp1PalCommand : public PalWall1Command { public: using PalWall1Command::PalWall1Command; void Execute(DrawerThread *thread) override; };
class DrawWall1PalCommand : public PalWall1Command { public: using PalWall1Command::PalWall1Command; void DrawColumn(DrawerThread *thread, const WallColumnDrawerArgs& args) override; };
class DrawWallMasked1PalCommand : public PalWall1Command { public: using PalWall1Command::PalWall1Command; void DrawColumn(DrawerThread *thread, const WallColumnDrawerArgs& args) override; };
class DrawWallAdd1PalCommand : public PalWall1Command { public: using PalWall1Command::PalWall1Command; void DrawColumn(DrawerThread *thread, const WallColumnDrawerArgs& args) override; };
class DrawWallAddClamp1PalCommand : public PalWall1Command { public: using PalWall1Command::PalWall1Command; void DrawColumn(DrawerThread *thread, const WallColumnDrawerArgs& args) override; };
class DrawWallSubClamp1PalCommand : public PalWall1Command { public: using PalWall1Command::PalWall1Command; void DrawColumn(DrawerThread *thread, const WallColumnDrawerArgs& args) override; };
class DrawWallRevSubClamp1PalCommand : public PalWall1Command { public: using PalWall1Command::PalWall1Command; void DrawColumn(DrawerThread *thread, const WallColumnDrawerArgs& args) override; };
class PalSkyCommand : public DrawerCommand
{
@ -230,20 +344,20 @@ namespace swrenderer
public:
using SWPixelFormatDrawers::SWPixelFormatDrawers;
void DrawWallColumn(const WallDrawerArgs &args) override { Queue->Push<DrawWall1PalCommand>(args); }
void DrawWallMaskedColumn(const WallDrawerArgs &args) override { Queue->Push<DrawWallMasked1PalCommand>(args); }
void DrawWall(const WallDrawerArgs &args) override { Queue->Push<DrawWall1PalCommand>(args); }
void DrawWallMasked(const WallDrawerArgs &args) override { Queue->Push<DrawWallMasked1PalCommand>(args); }
void DrawWallAddColumn(const WallDrawerArgs &args) override
void DrawWallAdd(const WallDrawerArgs &args) override
{
if (args.dc_num_lights == 0)
if (!args.lightlist)
Queue->Push<DrawWallAdd1PalCommand>(args);
else
Queue->Push<DrawWallAddClamp1PalCommand>(args);
}
void DrawWallAddClampColumn(const WallDrawerArgs &args) override { Queue->Push<DrawWallAddClamp1PalCommand>(args); }
void DrawWallSubClampColumn(const WallDrawerArgs &args) override { Queue->Push<DrawWallSubClamp1PalCommand>(args); }
void DrawWallRevSubClampColumn(const WallDrawerArgs &args) override { Queue->Push<DrawWallRevSubClamp1PalCommand>(args); }
void DrawWallAddClamp(const WallDrawerArgs &args) override { Queue->Push<DrawWallAddClamp1PalCommand>(args); }
void DrawWallSubClamp(const WallDrawerArgs &args) override { Queue->Push<DrawWallSubClamp1PalCommand>(args); }
void DrawWallRevSubClamp(const WallDrawerArgs &args) override { Queue->Push<DrawWallRevSubClamp1PalCommand>(args); }
void DrawSingleSkyColumn(const SkyDrawerArgs &args) override { Queue->Push<DrawSingleSky1PalCommand>(args); }
void DrawDoubleSkyColumn(const SkyDrawerArgs &args) override { Queue->Push<DrawDoubleSky1PalCommand>(args); }
void DrawColumn(const SpriteDrawerArgs &args) override { Queue->Push<DrawColumnPalCommand>(args); }

View file

@ -80,32 +80,32 @@ CVAR(Float, r_lod_bias, -1.5, 0); // To do: add CVAR_ARCHIVE | CVAR_GLOBALCONFIG
namespace swrenderer
{
void SWTruecolorDrawers::DrawWallColumn(const WallDrawerArgs &args)
void SWTruecolorDrawers::DrawWall(const WallDrawerArgs &args)
{
Queue->Push<DrawWall32Command>(args);
}
void SWTruecolorDrawers::DrawWallMaskedColumn(const WallDrawerArgs &args)
void SWTruecolorDrawers::DrawWallMasked(const WallDrawerArgs &args)
{
Queue->Push<DrawWallMasked32Command>(args);
}
void SWTruecolorDrawers::DrawWallAddColumn(const WallDrawerArgs &args)
void SWTruecolorDrawers::DrawWallAdd(const WallDrawerArgs &args)
{
Queue->Push<DrawWallAddClamp32Command>(args);
}
void SWTruecolorDrawers::DrawWallAddClampColumn(const WallDrawerArgs &args)
void SWTruecolorDrawers::DrawWallAddClamp(const WallDrawerArgs &args)
{
Queue->Push<DrawWallAddClamp32Command>(args);
}
void SWTruecolorDrawers::DrawWallSubClampColumn(const WallDrawerArgs &args)
void SWTruecolorDrawers::DrawWallSubClamp(const WallDrawerArgs &args)
{
Queue->Push<DrawWallSubClamp32Command>(args);
}
void SWTruecolorDrawers::DrawWallRevSubClampColumn(const WallDrawerArgs &args)
void SWTruecolorDrawers::DrawWallRevSubClamp(const WallDrawerArgs &args)
{
Queue->Push<DrawWallRevSubClamp32Command>(args);
}

View file

@ -244,12 +244,12 @@ namespace swrenderer
public:
using SWPixelFormatDrawers::SWPixelFormatDrawers;
void DrawWallColumn(const WallDrawerArgs &args) override;
void DrawWallMaskedColumn(const WallDrawerArgs &args) override;
void DrawWallAddColumn(const WallDrawerArgs &args) override;
void DrawWallAddClampColumn(const WallDrawerArgs &args) override;
void DrawWallSubClampColumn(const WallDrawerArgs &args) override;
void DrawWallRevSubClampColumn(const WallDrawerArgs &args) override;
void DrawWall(const WallDrawerArgs &args) override;
void DrawWallMasked(const WallDrawerArgs &args) override;
void DrawWallAdd(const WallDrawerArgs &args) override;
void DrawWallAddClamp(const WallDrawerArgs &args) override;
void DrawWallSubClamp(const WallDrawerArgs &args) override;
void DrawWallRevSubClamp(const WallDrawerArgs &args) override;
void DrawSingleSkyColumn(const SkyDrawerArgs &args) override;
void DrawDoubleSkyColumn(const SkyDrawerArgs &args) override;
void DrawColumn(const SpriteDrawerArgs &args) override;

View file

@ -22,6 +22,7 @@
#pragma once
#include "swrenderer/drawers/r_draw_pal.h"
#include "swrenderer/drawers/r_draw_rgba.h"
#include "swrenderer/viewport/r_walldrawer.h"
@ -46,15 +47,12 @@ namespace swrenderer
}
template<typename BlendT>
class DrawWall32T : public DrawerCommand
class DrawWall32T : public DrawWallCommand
{
protected:
WallDrawerArgs args;
public:
DrawWall32T(const WallDrawerArgs &drawerargs) : args(drawerargs) { }
DrawWall32T(const WallDrawerArgs &drawerargs) : DrawWallCommand(drawerargs) { }
void Execute(DrawerThread *thread) override
void DrawColumn(DrawerThread *thread, const WallColumnDrawerArgs& args) override
{
using namespace DrawWall32TModes;
@ -64,21 +62,21 @@ namespace swrenderer
if (shade_constants.simple_shade)
{
if (is_nearest_filter)
Loop<SimpleShade, NearestFilter>(thread, shade_constants);
Loop<SimpleShade, NearestFilter>(thread, args, shade_constants);
else
Loop<SimpleShade, LinearFilter>(thread, shade_constants);
Loop<SimpleShade, LinearFilter>(thread, args, shade_constants);
}
else
{
if (is_nearest_filter)
Loop<AdvancedShade, NearestFilter>(thread, shade_constants);
Loop<AdvancedShade, NearestFilter>(thread, args, shade_constants);
else
Loop<AdvancedShade, LinearFilter>(thread, shade_constants);
Loop<AdvancedShade, LinearFilter>(thread, args, shade_constants);
}
}
template<typename ShadeModeT, typename FilterModeT>
FORCEINLINE void Loop(DrawerThread *thread, ShadeConstants shade_constants)
FORCEINLINE void Loop(DrawerThread *thread, const WallColumnDrawerArgs& args, ShadeConstants shade_constants)
{
using namespace DrawWall32TModes;

View file

@ -22,6 +22,7 @@
#pragma once
#include "swrenderer/drawers/r_draw_pal.h"
#include "swrenderer/drawers/r_draw_rgba.h"
#include "swrenderer/viewport/r_walldrawer.h"
@ -46,15 +47,12 @@ namespace swrenderer
}
template<typename BlendT>
class DrawWall32T : public DrawerCommand
class DrawWall32T : public DrawWallCommand
{
protected:
WallDrawerArgs args;
public:
DrawWall32T(const WallDrawerArgs &drawerargs) : args(drawerargs) { }
DrawWall32T(const WallDrawerArgs &drawerargs) : DrawWallCommand(drawerargs) { }
void Execute(DrawerThread *thread) override
void DrawColumn(DrawerThread *thread, const WallColumnDrawerArgs& args) override
{
using namespace DrawWall32TModes;
@ -64,21 +62,21 @@ namespace swrenderer
if (shade_constants.simple_shade)
{
if (is_nearest_filter)
Loop<SimpleShade, NearestFilter>(thread, shade_constants);
Loop<SimpleShade, NearestFilter>(thread, args, shade_constants);
else
Loop<SimpleShade, LinearFilter>(thread, shade_constants);
Loop<SimpleShade, LinearFilter>(thread, args, shade_constants);
}
else
{
if (is_nearest_filter)
Loop<AdvancedShade, NearestFilter>(thread, shade_constants);
Loop<AdvancedShade, NearestFilter>(thread, args, shade_constants);
else
Loop<AdvancedShade, LinearFilter>(thread, shade_constants);
Loop<AdvancedShade, LinearFilter>(thread, args, shade_constants);
}
}
template<typename ShadeModeT, typename FilterModeT>
FORCEINLINE void VECTORCALL Loop(DrawerThread *thread, ShadeConstants shade_constants)
FORCEINLINE void VECTORCALL Loop(DrawerThread *thread, const WallColumnDrawerArgs& args, ShadeConstants shade_constants)
{
using namespace DrawWall32TModes;

View file

@ -120,111 +120,6 @@ namespace swrenderer
ProcessNormalWall(up, dwal, texcoords);
}
static void DrawWallColumn32(RenderThread* thread, WallDrawerArgs& drawerargs, int x, int y1, int y2, uint32_t texelX, uint32_t texelY, uint32_t texelStepX, uint32_t texelStepY, FSoftwareTexture* pic, int texwidth, int texheight)
{
double xmagnitude = fabs(static_cast<int32_t>(texelStepX) * (1.0 / 0x1'0000'0000LL));
double ymagnitude = fabs(static_cast<int32_t>(texelStepY) * (1.0 / 0x1'0000'0000LL));
double magnitude = MAX(ymagnitude, xmagnitude);
double min_lod = -1000.0;
double lod = MAX(log2(magnitude) + r_lod_bias, min_lod);
bool magnifying = lod < 0.0f;
int mipmap_offset = 0;
int mip_width = texwidth;
int mip_height = texheight;
if (r_mipmap && pic->Mipmapped() && mip_width > 1 && mip_height > 1)
{
int level = (int)lod;
while (level > 0 && mip_width > 1 && mip_height > 1)
{
mipmap_offset += mip_width * mip_height;
level--;
mip_width = MAX(mip_width >> 1, 1);
mip_height = MAX(mip_height >> 1, 1);
}
}
const uint32_t* pixels = pic->GetPixelsBgra() + mipmap_offset;
fixed_t xxoffset = (texelX >> 16) * mip_width;
const uint8_t* source;
const uint8_t* source2;
uint32_t texturefracx;
bool filter_nearest = (magnifying && !r_magfilter) || (!magnifying && !r_minfilter);
if (filter_nearest)
{
int tx = (xxoffset >> FRACBITS) % mip_width;
source = (uint8_t*)(pixels + tx * mip_height);
source2 = nullptr;
texturefracx = 0;
}
else
{
xxoffset -= FRACUNIT / 2;
int tx0 = (xxoffset >> FRACBITS) % mip_width;
if (tx0 < 0)
tx0 += mip_width;
int tx1 = (tx0 + 1) % mip_width;
source = (uint8_t*)(pixels + tx0 * mip_height);
source2 = (uint8_t*)(pixels + tx1 * mip_height);
texturefracx = (xxoffset >> (FRACBITS - 4)) & 15;
}
int count = y2 - y1;
drawerargs.SetDest(thread->Viewport.get(), x, y1);
drawerargs.SetCount(count);
drawerargs.SetTexture(source, source2, mip_height);
drawerargs.SetTextureUPos(texturefracx);
drawerargs.SetTextureVPos(texelY);
drawerargs.SetTextureVStep(texelStepY);
drawerargs.DrawColumn(thread);
}
static void DrawWallColumn8(RenderThread* thread, WallDrawerArgs& drawerargs, int x, int y1, int y2, uint32_t texelX, uint32_t texelY, uint32_t texelStepY, FSoftwareTexture* pic, int texwidth, int texheight, int fracbits, uint32_t uv_max)
{
texelY = (static_cast<uint64_t>(texelY)* texheight) >> (32 - fracbits);
texelStepY = (static_cast<uint64_t>(texelStepY)* texheight) >> (32 - fracbits);
const uint8_t* pixels = pic->GetColumn(DefaultRenderStyle(), ((texelX >> 16)* texwidth) >> 16, nullptr);
drawerargs.SetTexture(pixels, nullptr, texheight);
drawerargs.SetTextureVStep(texelStepY);
if (uv_max == 0 || texelStepY == 0) // power of two
{
int count = y2 - y1;
drawerargs.SetDest(thread->Viewport.get(), x, y1);
drawerargs.SetCount(count);
drawerargs.SetTextureVPos(texelY);
drawerargs.DrawColumn(thread);
}
else
{
uint32_t left = y2 - y1;
int y = y1;
while (left > 0)
{
uint32_t available = uv_max - texelY;
uint32_t next_uv_wrap = available / texelStepY;
if (available % texelStepY != 0)
next_uv_wrap++;
uint32_t count = MIN(left, next_uv_wrap);
drawerargs.SetDest(thread->Viewport.get(), x, y);
drawerargs.SetCount(count);
drawerargs.SetTextureVPos(texelY);
drawerargs.DrawColumn(thread);
y += count;
left -= count;
texelY += texelStepY * count;
if (texelY >= uv_max)
texelY -= uv_max;
}
}
}
void RenderWallPart::ProcessNormalWall(const short* uwal, const short* dwal, const ProjectedWallTexcoords& texcoords)
{
CameraLight* cameraLight = CameraLight::Instance();
@ -242,185 +137,55 @@ namespace swrenderer
drawerargs.SetStyle(mask, additive, alpha, mLight.GetBaseColormap());
}
bool fixed = (cameraLight->FixedColormap() || cameraLight->FixedLightLevel() >= 0);
int count = x2 - x1;
short* data = Thread->FrameMemory->AllocMemory<short>(count << 1);
bool haslights = r_dynlights && light_list;
if (haslights)
drawerargs.x1 = x1;
drawerargs.x2 = x2;
drawerargs.uwal = data - x1;
drawerargs.dwal = data + count - x1; // to avoid calling AllocMemory twice
memcpy(drawerargs.uwal + x1, uwal + x1, sizeof(short) * count);
memcpy(drawerargs.dwal + x1, dwal + x1, sizeof(short) * count);
drawerargs.WallC = WallC;
drawerargs.texcoords = texcoords;
drawerargs.lightpos = mLight.GetLightPos(x1);
drawerargs.lightstep = mLight.GetLightStep();
drawerargs.mShade = LightVisibility::LightLevelToShade(mLight.GetLightLevel(), mLight.GetFoggy(), viewport);
drawerargs.lightlist = light_list;
drawerargs.texwidth = pic->GetPhysicalWidth();
drawerargs.texheight = pic->GetPhysicalHeight();
if (viewport->RenderTarget->IsBgra())
{
float dx = WallC.tright.X - WallC.tleft.X;
float dy = WallC.tright.Y - WallC.tleft.Y;
float length = sqrt(dx * dx + dy * dy);
drawerargs.dc_normal.X = dy / length;
drawerargs.dc_normal.Y = -dx / length;
drawerargs.dc_normal.Z = 0.0f;
drawerargs.texpixels = pic->GetPixelsBgra();
drawerargs.fracbits = 32;
drawerargs.mipmapped = r_mipmap && pic->Mipmapped();
}
else
{
drawerargs.texpixels = pic->GetPixels(DefaultRenderStyle());
int fracbits = 32 - pic->GetHeightBits();
if (fracbits == 32) fracbits = 0; // One pixel tall textures
drawerargs.fracbits = fracbits;
drawerargs.mipmapped = false;
}
int texwidth = pic->GetPhysicalWidth();
int texheight = pic->GetPhysicalHeight();
// This data really should be its own command as it rarely changes
drawerargs.SetDest(viewport);
drawerargs.CenterX = Thread->Viewport->CenterX;
drawerargs.CenterY = Thread->Viewport->CenterY;
drawerargs.FocalTangent = Thread->Viewport->viewwindow.FocalTangent;
drawerargs.InvZtoScale = Thread->Viewport->InvZtoScale;
drawerargs.ViewpointPos = { (float)Thread->Viewport->viewpoint.Pos.X, (float)Thread->Viewport->viewpoint.Pos.Y, (float)Thread->Viewport->viewpoint.Pos.Z };
drawerargs.Sin = Thread->Viewport->viewpoint.Sin;
drawerargs.Cos = Thread->Viewport->viewpoint.Cos;
drawerargs.TanCos = Thread->Viewport->viewpoint.TanCos;
drawerargs.TanSin = Thread->Viewport->viewpoint.TanSin;
drawerargs.PortalMirrorFlags = Thread->Portal->MirrorFlags;
drawerargs.fixedlight = (cameraLight->FixedColormap() || cameraLight->FixedLightLevel() >= 0);
int fracbits = 32 - pic->GetHeightBits();
if (fracbits == 32) fracbits = 0; // One pixel tall textures
if (viewport->RenderTarget->IsBgra()) fracbits = 32;
drawerargs.SetTextureFracBits(fracbits);
uint32_t uv_max;
int uv_fracbits = 32 - pic->GetHeightBits();
if (uv_fracbits != 32)
uv_max = texheight << uv_fracbits;
float curlight = mLight.GetLightPos(x1);
float lightstep = mLight.GetLightStep();
float upos = texcoords.upos, ustepX = texcoords.ustepX, ustepY = texcoords.ustepY;
float vpos = texcoords.vpos, vstepX = texcoords.vstepX, vstepY = texcoords.vstepY;
float wpos = texcoords.wpos, wstepX = texcoords.wstepX, wstepY = texcoords.wstepY;
float startX = texcoords.startX;
upos += ustepX * (x1 + 0.5f - startX);
vpos += vstepX * (x1 + 0.5f - startX);
wpos += wstepX * (x1 + 0.5f - startX);
float centerY = Thread->Viewport->CenterY;
centerY -= 0.5f;
for (int x = x1; x < x2; x++)
{
int y1 = uwal[x];
int y2 = dwal[x];
if (y2 > y1)
{
if (!fixed) drawerargs.SetLight(curlight, mLight.GetLightLevel(), mLight.GetFoggy(), viewport);
if (haslights)
SetLights(drawerargs, x, y1);
else
drawerargs.dc_num_lights = 0;
float dy = (y1 - centerY);
float u = upos + ustepY * dy;
float v = vpos + vstepY * dy;
float w = wpos + wstepY * dy;
float scaleU = ustepX;
float scaleV = vstepY;
w = 1.0f / w;
u *= w;
v *= w;
scaleU *= w;
scaleV *= w;
uint32_t texelX = (uint32_t)(int64_t)((u - std::floor(u)) * 0x1'0000'0000LL);
uint32_t texelY = (uint32_t)(int64_t)((v - std::floor(v)) * 0x1'0000'0000LL);
uint32_t texelStepX = (uint32_t)(int64_t)(scaleU * 0x1'0000'0000LL);
uint32_t texelStepY = (uint32_t)(int64_t)(scaleV * 0x1'0000'0000LL);
if (fracbits != 32)
DrawWallColumn8(Thread, drawerargs, x, y1, y2, texelX, texelY, texelStepY, pic, texwidth, texheight, fracbits, uv_max);
else
DrawWallColumn32(Thread, drawerargs, x, y1, y2, texelX, texelY, texelStepX, texelStepY, pic, texwidth, texheight);
}
upos += ustepX;
vpos += vstepX;
wpos += wstepX;
curlight += lightstep;
}
if (r_modelscene)
{
for (int x = x1; x < x2; x++)
{
int y1 = uwal[x];
int y2 = dwal[x];
if (y2 > y1)
{
int count = y2 - y1;
float w1 = 1.0f / WallC.sz1;
float w2 = 1.0f / WallC.sz2;
float t = (x - WallC.sx1 + 0.5f) / (WallC.sx2 - WallC.sx1);
float wcol = w1 * (1.0f - t) + w2 * t;
float zcol = 1.0f / wcol;
float zbufferdepth = 1.0f / (zcol / viewport->viewwindow.FocalTangent);
drawerargs.SetDest(viewport, x, y1);
drawerargs.SetCount(count);
drawerargs.DrawDepthColumn(Thread, zbufferdepth);
}
}
}
}
void RenderWallPart::SetLights(WallDrawerArgs &drawerargs, int x, int y1)
{
bool mirror = !!(Thread->Portal->MirrorFlags & RF_XFLIP);
int tx = x;
if (mirror)
tx = viewwidth - tx - 1;
RenderViewport *viewport = Thread->Viewport.get();
// Find column position in view space
float w1 = 1.0f / WallC.sz1;
float w2 = 1.0f / WallC.sz2;
float t = (x - WallC.sx1 + 0.5f) / (WallC.sx2 - WallC.sx1);
float wcol = w1 * (1.0f - t) + w2 * t;
float zcol = 1.0f / wcol;
drawerargs.dc_viewpos.X = (float)((tx + 0.5 - viewport->CenterX) / viewport->CenterX * zcol);
drawerargs.dc_viewpos.Y = zcol;
drawerargs.dc_viewpos.Z = (float)((viewport->CenterY - y1 - 0.5) / viewport->InvZtoScale * zcol);
drawerargs.dc_viewpos_step.Z = (float)(-zcol / viewport->InvZtoScale);
// Calculate max lights that can touch column so we can allocate memory for the list
int max_lights = 0;
FLightNode *cur_node = light_list;
while (cur_node)
{
if (cur_node->lightsource->IsActive())
max_lights++;
cur_node = cur_node->nextLight;
}
drawerargs.dc_num_lights = 0;
drawerargs.dc_lights = Thread->FrameMemory->AllocMemory<DrawerLight>(max_lights);
// Setup lights for column
cur_node = light_list;
while (cur_node)
{
if (cur_node->lightsource->IsActive())
{
double lightX = cur_node->lightsource->X() - viewport->viewpoint.Pos.X;
double lightY = cur_node->lightsource->Y() - viewport->viewpoint.Pos.Y;
double lightZ = cur_node->lightsource->Z() - viewport->viewpoint.Pos.Z;
float lx = (float)(lightX * viewport->viewpoint.Sin - lightY * viewport->viewpoint.Cos) - drawerargs.dc_viewpos.X;
float ly = (float)(lightX * viewport->viewpoint.TanCos + lightY * viewport->viewpoint.TanSin) - drawerargs.dc_viewpos.Y;
float lz = (float)lightZ;
// Precalculate the constant part of the dot here so the drawer doesn't have to.
bool is_point_light = cur_node->lightsource->IsAttenuated();
float lconstant = lx * lx + ly * ly;
float nlconstant = is_point_light ? lx * drawerargs.dc_normal.X + ly * drawerargs.dc_normal.Y : 0.0f;
// Include light only if it touches this column
float radius = cur_node->lightsource->GetRadius();
if (radius * radius >= lconstant && nlconstant >= 0.0f)
{
uint32_t red = cur_node->lightsource->GetRed();
uint32_t green = cur_node->lightsource->GetGreen();
uint32_t blue = cur_node->lightsource->GetBlue();
auto &light = drawerargs.dc_lights[drawerargs.dc_num_lights++];
light.x = lconstant;
light.y = nlconstant;
light.z = lz;
light.radius = 256.0f / cur_node->lightsource->GetRadius();
light.color = (red << 16) | (green << 8) | blue;
}
}
cur_node = cur_node->nextLight;
}
drawerargs.DrawWall(Thread);
}
FLightNode* RenderWallPart::GetLightList()

View file

@ -62,7 +62,6 @@ namespace swrenderer
private:
void ProcessStripedWall(const short *uwal, const short *dwal, const ProjectedWallTexcoords& texcoords);
void ProcessNormalWall(const short *uwal, const short *dwal, const ProjectedWallTexcoords& texcoords);
void SetLights(WallDrawerArgs &drawerargs, int x, int y1);
FLightNode* GetLightList();
RenderThread* Thread = nullptr;

View file

@ -38,6 +38,7 @@ namespace swrenderer
uint8_t *Colormap(RenderViewport *viewport) const;
uint8_t *TranslationMap() const { return mTranslation; }
FSWColormap* BaseColormap() const { return mBaseColormap; }
ShadeConstants ColormapConstants() const;
fixed_t Light() const { return LIGHTSCALE(mLight, mShade); }

View file

@ -25,19 +25,12 @@
namespace swrenderer
{
void WallDrawerArgs::SetDest(RenderViewport *viewport, int x, int y)
void WallDrawerArgs::SetDest(RenderViewport *viewport)
{
dc_viewport = viewport;
dc_dest = viewport->GetDest(x, y);
dc_dest_y = y;
}
void WallDrawerArgs::DrawDepthColumn(RenderThread *thread, float idepth)
{
thread->Drawers(dc_viewport)->DrawDepthWallColumn(*this, idepth);
}
void WallDrawerArgs::DrawColumn(RenderThread *thread)
void WallDrawerArgs::DrawWall(RenderThread *thread)
{
(thread->Drawers(dc_viewport)->*wallfunc)(*this);
}
@ -48,7 +41,7 @@ namespace swrenderer
{
if (!additive)
{
wallfunc = &SWPixelFormatDrawers::DrawWallAddColumn;
wallfunc = &SWPixelFormatDrawers::DrawWallAdd;
dc_srcblend = Col2RGB8[alpha >> 10];
dc_destblend = Col2RGB8[(OPAQUE - alpha) >> 10];
dc_srcalpha = alpha;
@ -56,7 +49,7 @@ namespace swrenderer
}
else
{
wallfunc = &SWPixelFormatDrawers::DrawWallAddClampColumn;
wallfunc = &SWPixelFormatDrawers::DrawWallAddClamp;
dc_srcblend = Col2RGB8_LessPrecision[alpha >> 10];
dc_destblend = Col2RGB8_LessPrecision[FRACUNIT >> 10];
dc_srcalpha = alpha;
@ -65,11 +58,11 @@ namespace swrenderer
}
else if (masked)
{
wallfunc = &SWPixelFormatDrawers::DrawWallMaskedColumn;
wallfunc = &SWPixelFormatDrawers::DrawWallMasked;
}
else
{
wallfunc = &SWPixelFormatDrawers::DrawWallColumn;
wallfunc = &SWPixelFormatDrawers::DrawWall;
}
CameraLight *cameraLight = CameraLight::Instance();

View file

@ -2,6 +2,7 @@
#pragma once
#include "r_drawerargs.h"
#include "swrenderer/line/r_wallsetup.h"
struct FSWColormap;
struct FLightNode;
@ -15,70 +16,52 @@ namespace swrenderer
{
public:
void SetStyle(bool masked, bool additive, fixed_t alpha, FDynamicColormap *basecolormap);
void SetDest(RenderViewport *viewport, int x, int y);
void SetCount(int count) { dc_count = count; }
void SetTexture(const uint8_t *pixels, const uint8_t *pixels2, int height)
{
dc_source = pixels;
dc_source2 = pixels2;
dc_textureheight = height;
}
void SetTextureFracBits(int bits) { dc_wall_fracbits = bits; }
void SetTextureUPos(uint32_t pos) { dc_texturefracx = pos; }
void SetTextureVPos(fixed_t pos) { dc_texturefrac = pos; }
void SetTextureVStep(fixed_t step) { dc_iscale = step; }
void SetDest(RenderViewport *viewport);
void DrawWall(RenderThread *thread);
void DrawDepthColumn(RenderThread *thread, float idepth);
void DrawColumn(RenderThread *thread);
uint8_t *Dest() const { return dc_dest; }
int DestY() const { return dc_dest_y; }
int Count() const { return dc_count; }
uint32_t *SrcBlend() const { return dc_srcblend; }
uint32_t *DestBlend() const { return dc_destblend; }
uint32_t* SrcBlend() const { return dc_srcblend; }
uint32_t* DestBlend() const { return dc_destblend; }
fixed_t SrcAlpha() const { return dc_srcalpha; }
fixed_t DestAlpha() const { return dc_destalpha; }
uint32_t TextureUPos() const { return dc_texturefracx; }
fixed_t TextureVPos() const { return dc_texturefrac; }
fixed_t TextureVStep() const { return dc_iscale; }
RenderViewport* Viewport() const { return dc_viewport; }
const uint8_t *TexturePixels() const { return dc_source; }
const uint8_t *TexturePixels2() const { return dc_source2; }
uint32_t TextureHeight() const { return dc_textureheight; }
int x1, x2;
short* uwal;
short* dwal;
FWallCoords WallC;
ProjectedWallTexcoords texcoords;
FLightNode* lightlist = nullptr;
int TextureFracBits() const { return dc_wall_fracbits; }
float lightpos;
float lightstep;
int mShade;
FVector3 dc_normal = { 0,0,0 };
FVector3 dc_viewpos = { 0,0,0 };
FVector3 dc_viewpos_step = { 0,0,0 };
DrawerLight *dc_lights = nullptr;
int dc_num_lights = 0;
int texwidth;
int texheight;
int fracbits;
bool mipmapped;
const void* texpixels;
RenderViewport *Viewport() const { return dc_viewport; }
// Viewport data
uint16_t PortalMirrorFlags;
bool fixedlight;
float CenterX;
float CenterY;
float FocalTangent;
float InvZtoScale;
FVector3 ViewpointPos;
float Sin, Cos, TanCos, TanSin;
private:
uint8_t *dc_dest = nullptr;
int dc_dest_y = 0;
int dc_count = 0;
fixed_t dc_iscale = 0;
fixed_t dc_texturefrac = 0;
uint32_t dc_texturefracx = 0;
uint32_t dc_textureheight = 0;
const uint8_t *dc_source = nullptr;
const uint8_t *dc_source2 = nullptr;
int dc_wall_fracbits = 0;
uint32_t *dc_srcblend = nullptr;
uint32_t *dc_destblend = nullptr;
fixed_t dc_srcalpha = 0;
fixed_t dc_destalpha = 0;
typedef void(SWPixelFormatDrawers::*WallDrawerFunc)(const WallDrawerArgs &args);
WallDrawerFunc wallfunc = nullptr;
RenderViewport *dc_viewport = nullptr;
uint32_t* dc_srcblend = nullptr;
uint32_t* dc_destblend = nullptr;
fixed_t dc_srcalpha = 0;
fixed_t dc_destalpha = 0;
RenderViewport* dc_viewport = nullptr;
};
}