diff --git a/src/rendering/swrenderer/drawers/r_draw.cpp b/src/rendering/swrenderer/drawers/r_draw.cpp index 4d20ca682..fe9ebcc8c 100644 --- a/src/rendering/swrenderer/drawers/r_draw.cpp +++ b/src/rendering/swrenderer/drawers/r_draw.cpp @@ -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(texelStepX)* (1.0 / 0x1'0000'0000LL)); + double ymagnitude = fabs(static_cast(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(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(wallargs.texpixels) + (((texelX >> 16)* texwidth) >> 16)* texheight; + + texelY = (static_cast(texelY)* texheight) >> (32 - fracbits); + texelStepY = (static_cast(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(args, idepth); - } - - void SWPixelFormatDrawers::DrawDepthWallColumn(const WallDrawerArgs &args, float idepth) - { - Queue->Push(args, idepth); + Queue->Push(args, idepth); } void SWPixelFormatDrawers::DrawDepthSpan(const SpanDrawerArgs &args, float idepth1, float idepth2) diff --git a/src/rendering/swrenderer/drawers/r_draw.h b/src/rendering/swrenderer/drawers/r_draw.h index 790767ed8..32eba2db0 100644 --- a/src/rendering/swrenderer/drawers/r_draw.h +++ b/src/rendering/swrenderer/drawers/r_draw.h @@ -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; diff --git a/src/rendering/swrenderer/drawers/r_draw_pal.cpp b/src/rendering/swrenderer/drawers/r_draw_pal.cpp index e6280e197..af42a7f35 100644 --- a/src/rendering/swrenderer/drawers/r_draw_pal.cpp +++ b/src/rendering/swrenderer/drawers/r_draw_pal.cpp @@ -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; diff --git a/src/rendering/swrenderer/drawers/r_draw_pal.h b/src/rendering/swrenderer/drawers/r_draw_pal.h index 40349dc44..252a06545 100644 --- a/src/rendering/swrenderer/drawers/r_draw_pal.h +++ b/src/rendering/swrenderer/drawers/r_draw_pal.h @@ -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(args); } - void DrawWallMaskedColumn(const WallDrawerArgs &args) override { Queue->Push(args); } + void DrawWall(const WallDrawerArgs &args) override { Queue->Push(args); } + void DrawWallMasked(const WallDrawerArgs &args) override { Queue->Push(args); } - void DrawWallAddColumn(const WallDrawerArgs &args) override + void DrawWallAdd(const WallDrawerArgs &args) override { - if (args.dc_num_lights == 0) + if (!args.lightlist) Queue->Push(args); else Queue->Push(args); } - void DrawWallAddClampColumn(const WallDrawerArgs &args) override { Queue->Push(args); } - void DrawWallSubClampColumn(const WallDrawerArgs &args) override { Queue->Push(args); } - void DrawWallRevSubClampColumn(const WallDrawerArgs &args) override { Queue->Push(args); } + void DrawWallAddClamp(const WallDrawerArgs &args) override { Queue->Push(args); } + void DrawWallSubClamp(const WallDrawerArgs &args) override { Queue->Push(args); } + void DrawWallRevSubClamp(const WallDrawerArgs &args) override { Queue->Push(args); } void DrawSingleSkyColumn(const SkyDrawerArgs &args) override { Queue->Push(args); } void DrawDoubleSkyColumn(const SkyDrawerArgs &args) override { Queue->Push(args); } void DrawColumn(const SpriteDrawerArgs &args) override { Queue->Push(args); } diff --git a/src/rendering/swrenderer/drawers/r_draw_rgba.cpp b/src/rendering/swrenderer/drawers/r_draw_rgba.cpp index 9c3e328cd..a50221b3d 100644 --- a/src/rendering/swrenderer/drawers/r_draw_rgba.cpp +++ b/src/rendering/swrenderer/drawers/r_draw_rgba.cpp @@ -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(args); } - void SWTruecolorDrawers::DrawWallMaskedColumn(const WallDrawerArgs &args) + void SWTruecolorDrawers::DrawWallMasked(const WallDrawerArgs &args) { Queue->Push(args); } - void SWTruecolorDrawers::DrawWallAddColumn(const WallDrawerArgs &args) + void SWTruecolorDrawers::DrawWallAdd(const WallDrawerArgs &args) { Queue->Push(args); } - void SWTruecolorDrawers::DrawWallAddClampColumn(const WallDrawerArgs &args) + void SWTruecolorDrawers::DrawWallAddClamp(const WallDrawerArgs &args) { Queue->Push(args); } - void SWTruecolorDrawers::DrawWallSubClampColumn(const WallDrawerArgs &args) + void SWTruecolorDrawers::DrawWallSubClamp(const WallDrawerArgs &args) { Queue->Push(args); } - void SWTruecolorDrawers::DrawWallRevSubClampColumn(const WallDrawerArgs &args) + void SWTruecolorDrawers::DrawWallRevSubClamp(const WallDrawerArgs &args) { Queue->Push(args); } diff --git a/src/rendering/swrenderer/drawers/r_draw_rgba.h b/src/rendering/swrenderer/drawers/r_draw_rgba.h index 496564673..2182909ee 100644 --- a/src/rendering/swrenderer/drawers/r_draw_rgba.h +++ b/src/rendering/swrenderer/drawers/r_draw_rgba.h @@ -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; diff --git a/src/rendering/swrenderer/drawers/r_draw_wall32.h b/src/rendering/swrenderer/drawers/r_draw_wall32.h index 864c1f9c6..2f4012901 100644 --- a/src/rendering/swrenderer/drawers/r_draw_wall32.h +++ b/src/rendering/swrenderer/drawers/r_draw_wall32.h @@ -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 - 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(thread, shade_constants); + Loop(thread, args, shade_constants); else - Loop(thread, shade_constants); + Loop(thread, args, shade_constants); } else { if (is_nearest_filter) - Loop(thread, shade_constants); + Loop(thread, args, shade_constants); else - Loop(thread, shade_constants); + Loop(thread, args, shade_constants); } } template - FORCEINLINE void Loop(DrawerThread *thread, ShadeConstants shade_constants) + FORCEINLINE void Loop(DrawerThread *thread, const WallColumnDrawerArgs& args, ShadeConstants shade_constants) { using namespace DrawWall32TModes; diff --git a/src/rendering/swrenderer/drawers/r_draw_wall32_sse2.h b/src/rendering/swrenderer/drawers/r_draw_wall32_sse2.h index 02dfcf90f..5316a9e03 100644 --- a/src/rendering/swrenderer/drawers/r_draw_wall32_sse2.h +++ b/src/rendering/swrenderer/drawers/r_draw_wall32_sse2.h @@ -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 - 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(thread, shade_constants); + Loop(thread, args, shade_constants); else - Loop(thread, shade_constants); + Loop(thread, args, shade_constants); } else { if (is_nearest_filter) - Loop(thread, shade_constants); + Loop(thread, args, shade_constants); else - Loop(thread, shade_constants); + Loop(thread, args, shade_constants); } } template - FORCEINLINE void VECTORCALL Loop(DrawerThread *thread, ShadeConstants shade_constants) + FORCEINLINE void VECTORCALL Loop(DrawerThread *thread, const WallColumnDrawerArgs& args, ShadeConstants shade_constants) { using namespace DrawWall32TModes; diff --git a/src/rendering/swrenderer/line/r_walldraw.cpp b/src/rendering/swrenderer/line/r_walldraw.cpp index bfbdddd3c..77846b53d 100644 --- a/src/rendering/swrenderer/line/r_walldraw.cpp +++ b/src/rendering/swrenderer/line/r_walldraw.cpp @@ -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(texelStepX) * (1.0 / 0x1'0000'0000LL)); - double ymagnitude = fabs(static_cast(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(texelY)* texheight) >> (32 - fracbits); - texelStepY = (static_cast(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(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(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() diff --git a/src/rendering/swrenderer/line/r_walldraw.h b/src/rendering/swrenderer/line/r_walldraw.h index 812908c32..250f0de27 100644 --- a/src/rendering/swrenderer/line/r_walldraw.h +++ b/src/rendering/swrenderer/line/r_walldraw.h @@ -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; diff --git a/src/rendering/swrenderer/viewport/r_drawerargs.h b/src/rendering/swrenderer/viewport/r_drawerargs.h index 8fcb812b4..3c0e2667b 100644 --- a/src/rendering/swrenderer/viewport/r_drawerargs.h +++ b/src/rendering/swrenderer/viewport/r_drawerargs.h @@ -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); } diff --git a/src/rendering/swrenderer/viewport/r_walldrawer.cpp b/src/rendering/swrenderer/viewport/r_walldrawer.cpp index ae9077f4e..e7bdbc112 100644 --- a/src/rendering/swrenderer/viewport/r_walldrawer.cpp +++ b/src/rendering/swrenderer/viewport/r_walldrawer.cpp @@ -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(); diff --git a/src/rendering/swrenderer/viewport/r_walldrawer.h b/src/rendering/swrenderer/viewport/r_walldrawer.h index a657865c2..45ee10610 100644 --- a/src/rendering/swrenderer/viewport/r_walldrawer.h +++ b/src/rendering/swrenderer/viewport/r_walldrawer.h @@ -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; }; }