diff --git a/src/g_statusbar/sbar.h b/src/g_statusbar/sbar.h index f7faee70b..1f53859c0 100644 --- a/src/g_statusbar/sbar.h +++ b/src/g_statusbar/sbar.h @@ -437,7 +437,7 @@ public: void DrawAltHUD(); void DrawGraphic(FTextureID texture, double x, double y, int flags, double Alpha, double boxwidth, double boxheight, double scaleX, double scaleY); - void DrawString(FFont *font, const FString &cstring, double x, double y, int flags, double Alpha, int translation, int spacing, EMonospacing monospacing, int shadowX, int shadowY); + void DrawString(FFont *font, const FString &cstring, double x, double y, int flags, double Alpha, int translation, int spacing, EMonospacing monospacing, int shadowX, int shadowY, double scaleX, double scaleY); void TransformRect(double &x, double &y, double &w, double &h, int flags = 0); void Fill(PalEntry color, double x, double y, double w, double h, int flags = 0); void SetClipRect(double x, double y, double w, double h, int flags = 0); diff --git a/src/g_statusbar/shared_sbar.cpp b/src/g_statusbar/shared_sbar.cpp index dc836d032..aa0967080 100644 --- a/src/g_statusbar/shared_sbar.cpp +++ b/src/g_statusbar/shared_sbar.cpp @@ -1675,28 +1675,30 @@ void DBaseStatusBar::DrawGraphic(FTextureID texture, double x, double y, int fla // //============================================================================ -void DBaseStatusBar::DrawString(FFont *font, const FString &cstring, double x, double y, int flags, double Alpha, int translation, int spacing, EMonospacing monospacing, int shadowX, int shadowY) +void DBaseStatusBar::DrawString(FFont *font, const FString &cstring, double x, double y, int flags, double Alpha, int translation, int spacing, EMonospacing monospacing, int shadowX, int shadowY, double scaleX, double scaleY) { bool monospaced = monospacing != EMonospacing::Off; + double dx = 0; switch (flags & DI_TEXT_ALIGN) { default: break; case DI_TEXT_ALIGN_RIGHT: - if (!monospaced) - x -= static_cast (font->StringWidth(cstring) + (spacing * cstring.CharacterCount())); - else //monospaced, so just multiply the character size - x -= static_cast ((spacing) * cstring.CharacterCount()); + dx = monospaced + ? static_cast ((spacing)*cstring.CharacterCount()) //monospaced, so just multiply the character size + : static_cast (font->StringWidth(cstring) + (spacing * cstring.CharacterCount())); break; case DI_TEXT_ALIGN_CENTER: - if (!monospaced) - x -= static_cast (font->StringWidth(cstring) + (spacing * cstring.CharacterCount())) / 2; - else //monospaced, so just multiply the character size - x -= static_cast ((spacing)* cstring.CharacterCount()) / 2; + dx = monospaced + ? static_cast ((spacing)*cstring.CharacterCount()) / 2 //monospaced, so just multiply the character size + : static_cast (font->StringWidth(cstring) + (spacing * cstring.CharacterCount())) / 2; break; } + // Take text scale into account + x -= dx * scaleX; + const uint8_t* str = (const uint8_t*)cstring.GetChars(); const EColorRange boldTranslation = EColorRange(translation ? translation - 1 : NumTextColors - 1); int fontcolor = translation; @@ -1781,6 +1783,11 @@ void DBaseStatusBar::DrawString(FFont *font, const FString &cstring, double x, d rx += orgx; ry += orgy; } + + // Apply text scale + rw *= scaleX; + rh *= scaleY; + // This is not really such a great way to draw shadows because they can overlap with previously drawn characters. // This may have to be changed to draw the shadow text up front separately. if ((shadowX != 0 || shadowY != 0) && !(flags & DI_NOSHADOW)) @@ -1798,14 +1805,16 @@ void DBaseStatusBar::DrawString(FFont *font, const FString &cstring, double x, d DTA_Alpha, Alpha, TAG_DONE); - if (!monospaced) - x += width + spacing - (c->GetDisplayLeftOffsetDouble() + 1); - else - x += spacing; + dx = monospaced + ? spacing + : width + spacing - (c->GetDisplayLeftOffsetDouble() + 1); + + // Take text scale into account + x += dx * scaleX; } } -void SBar_DrawString(DBaseStatusBar *self, DHUDFont *font, const FString &string, double x, double y, int flags, int trans, double alpha, int wrapwidth, int linespacing) +void SBar_DrawString(DBaseStatusBar *self, DHUDFont *font, const FString &string, double x, double y, int flags, int trans, double alpha, int wrapwidth, int linespacing, double scaleX, double scaleY) { if (font == nullptr) ThrowAbortException(X_READ_NIL, nullptr); if (!screen->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); @@ -1821,16 +1830,16 @@ void SBar_DrawString(DBaseStatusBar *self, DHUDFont *font, const FString &string if (wrapwidth > 0) { - auto brk = V_BreakLines(font->mFont, wrapwidth, string, true); + auto brk = V_BreakLines(font->mFont, int(wrapwidth * scaleX), string, true); for (auto &line : brk) { - self->DrawString(font->mFont, line.Text, x, y, flags, alpha, trans, font->mSpacing, font->mMonospacing, font->mShadowX, font->mShadowY); - y += font->mFont->GetHeight() + linespacing; + self->DrawString(font->mFont, line.Text, x, y, flags, alpha, trans, font->mSpacing, font->mMonospacing, font->mShadowX, font->mShadowY, scaleX, scaleY); + y += (font->mFont->GetHeight() + linespacing) * scaleY; } } else { - self->DrawString(font->mFont, string, x, y, flags, alpha, trans, font->mSpacing, font->mMonospacing, font->mShadowX, font->mShadowY); + self->DrawString(font->mFont, string, x, y, flags, alpha, trans, font->mSpacing, font->mMonospacing, font->mShadowX, font->mShadowY, scaleX, scaleY); } } diff --git a/src/rendering/swrenderer/drawers/r_draw.cpp b/src/rendering/swrenderer/drawers/r_draw.cpp index 4d20ca682..ef4289a14 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,347 @@ 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) + { + if (!thread->columndrawer) + thread->columndrawer = std::make_shared(); + + WallColumnDrawerArgs& drawerargs = *thread->columndrawer.get(); + drawerargs.wallargs = &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 +673,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..cb2af1bcb 100644 --- a/src/rendering/swrenderer/drawers/r_draw_pal.h +++ b/src/rendering/swrenderer/drawers/r_draw_pal.h @@ -8,26 +8,138 @@ #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); + 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; } + + const WallDrawerArgs* wallargs; + + 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; + + 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 +342,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/drawers/r_thread.h b/src/rendering/swrenderer/drawers/r_thread.h index eb804ac76..0d45b2cac 100644 --- a/src/rendering/swrenderer/drawers/r_thread.h +++ b/src/rendering/swrenderer/drawers/r_thread.h @@ -34,6 +34,8 @@ EXTERN_CVAR(Int, r_multithreaded) class PolyTriangleThreadData; +namespace swrenderer { class WallColumnDrawerArgs; } + // Worker data for each thread executing drawer commands class DrawerThread { @@ -61,6 +63,7 @@ public: const uint8_t *tiltlighting[MAXWIDTH]; std::shared_ptr poly; + std::shared_ptr columndrawer; size_t debug_draw_pos = 0; 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/r_memory.cpp b/src/rendering/swrenderer/r_memory.cpp index 6e0556edb..492beb03f 100644 --- a/src/rendering/swrenderer/r_memory.cpp +++ b/src/rendering/swrenderer/r_memory.cpp @@ -37,6 +37,7 @@ #include "po_man.h" #include "r_data/colormaps.h" #include "r_memory.h" +#include void *RenderMemory::AllocBytes(int size) { @@ -73,3 +74,42 @@ void RenderMemory::Clear() FreeBlocks.push_back(std::move(block)); } } + +static void* Aligned_Alloc(size_t alignment, size_t size) +{ + void* ptr; +#if defined _MSC_VER + ptr = _aligned_malloc(size, alignment); + if (!ptr) + throw std::bad_alloc(); +#else + // posix_memalign required alignment to be a min of sizeof(void *) + if (alignment < sizeof(void*)) + alignment = sizeof(void*); + + if (posix_memalign((void**)&ptr, alignment, size)) + throw std::bad_alloc(); +#endif + return ptr; +} + +static void Aligned_Free(void* ptr) +{ + if (ptr) + { +#if defined _MSC_VER + _aligned_free(ptr); +#else + free(ptr); +#endif + } +} + +RenderMemory::MemoryBlock::MemoryBlock() : Data(static_cast(Aligned_Alloc(16, BlockSize))), Position(0) +{ +} + +RenderMemory::MemoryBlock::~MemoryBlock() +{ + Aligned_Free(Data); +} diff --git a/src/rendering/swrenderer/r_memory.h b/src/rendering/swrenderer/r_memory.h index 67ade026e..8007b6cc1 100644 --- a/src/rendering/swrenderer/r_memory.h +++ b/src/rendering/swrenderer/r_memory.h @@ -29,8 +29,8 @@ private: struct MemoryBlock { - MemoryBlock() : Data(new uint8_t[BlockSize]), Position(0) { } - ~MemoryBlock() { delete[] Data; } + MemoryBlock(); + ~MemoryBlock(); MemoryBlock(const MemoryBlock &) = delete; MemoryBlock &operator=(const MemoryBlock &) = delete; 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; }; } diff --git a/src/rendering/vulkan/textures/vk_hwtexture.cpp b/src/rendering/vulkan/textures/vk_hwtexture.cpp index 93a1cc92d..d43abaf6a 100644 --- a/src/rendering/vulkan/textures/vk_hwtexture.cpp +++ b/src/rendering/vulkan/textures/vk_hwtexture.cpp @@ -69,6 +69,12 @@ void VkHardwareTexture::Reset() { ResetDescriptors(); + if (mappedSWFB) + { + mImage.Image->Unmap(); + mappedSWFB = nullptr; + } + auto &deleteList = fb->FrameDeleteList; if (mImage.Image) deleteList.Images.push_back(std::move(mImage.Image)); if (mImage.View) deleteList.ImageViews.push_back(std::move(mImage.View)); @@ -348,12 +354,13 @@ void VkHardwareTexture::AllocateBuffer(int w, int h, int texelsize) uint8_t *VkHardwareTexture::MapBuffer() { - return (uint8_t*)mImage.Image->Map(0, mImage.Image->width * mImage.Image->height * mTexelsize); + if (!mappedSWFB) + mappedSWFB = (uint8_t*)mImage.Image->Map(0, mImage.Image->width * mImage.Image->height * mTexelsize); + return mappedSWFB; } unsigned int VkHardwareTexture::CreateTexture(unsigned char * buffer, int w, int h, int texunit, bool mipmap, int translation, const char *name) { - mImage.Image->Unmap(); return 0; } diff --git a/src/rendering/vulkan/textures/vk_hwtexture.h b/src/rendering/vulkan/textures/vk_hwtexture.h index 6d461184f..9770cb1c0 100644 --- a/src/rendering/vulkan/textures/vk_hwtexture.h +++ b/src/rendering/vulkan/textures/vk_hwtexture.h @@ -77,4 +77,6 @@ private: int mTexelsize = 4; VkTextureImage mDepthStencil; + + uint8_t* mappedSWFB = nullptr; }; diff --git a/src/scripting/decorate/thingdef_exp.cpp b/src/scripting/decorate/thingdef_exp.cpp index 4a1a82922..9b78a5f28 100644 --- a/src/scripting/decorate/thingdef_exp.cpp +++ b/src/scripting/decorate/thingdef_exp.cpp @@ -510,7 +510,8 @@ static FxExpression *ParseExpression0 (FScanner &sc, PClassActor *cls) sc.UnGet(); ParseFunctionParameters(sc, cls, args, func, "", nullptr); } - return new FxVMFunctionCall(new FxSelf(sc), func, args, sc, false); + // FxVMFunctionCall cannot be used here as it lacks some important checks + return new FxFunctionCall(identifier, NAME_None, args, sc); } } diff --git a/src/scripting/vmthunks.cpp b/src/scripting/vmthunks.cpp index d21fe0394..4f0d2fb32 100644 --- a/src/scripting/vmthunks.cpp +++ b/src/scripting/vmthunks.cpp @@ -2541,7 +2541,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(DBaseStatusBar, DrawImage, SBar_DrawImage) return 0; } -void SBar_DrawString(DBaseStatusBar *self, DHUDFont *font, const FString &string, double x, double y, int flags, int trans, double alpha, int wrapwidth, int linespacing); +void SBar_DrawString(DBaseStatusBar *self, DHUDFont *font, const FString &string, double x, double y, int flags, int trans, double alpha, int wrapwidth, int linespacing, double scaleX, double scaleY); DEFINE_ACTION_FUNCTION_NATIVE(DBaseStatusBar, DrawString, SBar_DrawString) { @@ -2555,7 +2555,9 @@ DEFINE_ACTION_FUNCTION_NATIVE(DBaseStatusBar, DrawString, SBar_DrawString) PARAM_FLOAT(alpha); PARAM_INT(wrapwidth); PARAM_INT(linespacing); - SBar_DrawString(self, font, string, x, y, flags, trans, alpha, wrapwidth, linespacing); + PARAM_FLOAT(scaleX); + PARAM_FLOAT(scaleY); + SBar_DrawString(self, font, string, x, y, flags, trans, alpha, wrapwidth, linespacing, scaleX, scaleY); return 0; } diff --git a/wadsrc/static/zscript/level_compatibility.zs b/wadsrc/static/zscript/level_compatibility.zs index 6d891602b..20356935b 100644 --- a/wadsrc/static/zscript/level_compatibility.zs +++ b/wadsrc/static/zscript/level_compatibility.zs @@ -1514,12 +1514,153 @@ class LevelCompatibility : LevelPostProcessor case 'BA1288DF7A7AD637948825EA87E18728': // Valletta's Doom Nightmare (vltnight.wad) map02 { //This door's backside had a backwards linedef so it wouldn't work - FlipLine(306); - FlipLineSideRefs(306); + FlipLineCompletely(306); //Set the exit to point to Position 0, since that's the only one on the next map SetLineSpecial(564, Exit_Normal, 0); break; } + + case '9B966DA88265AC8972B7E15C86928AFB': // Clavicula Nox: Revised Edition map01 + { + // All swimmable water in Clavicula Nox is Vavoom-style, and doesn't work. + // Change it to ZDoom-style and extend the control sector heights to fill. + // Lava also sometimes needs the damage effect added manually. + SetLineSpecial(698, 160, 4, 2, 0, 128); + OffsetSectorPlane(121, Sector.floor, -32); + break; + } + + case '9FD0C47C2E132F64B48CA5BFBDE47F1D': // clavnoxr map02 + { + SetLineSpecial(953, 160, 12, 2, 0, 128); + OffsetSectorPlane(139, Sector.floor, -24); + SetLineSpecial(989, 160, 13, 2, 0, 128); + OffsetSectorPlane(143, Sector.floor, -24); + SetLineSpecial(1601, 160, 19, 2, 0, 128); + SetLineSpecial(1640, 160, 20, 2, 0, 128); + SetLineSpecial(1641, 160, 21, 2, 0, 128); + OffsetSectorPlane(236, Sector.floor, -96); + break; + } + + case '969B9691007490CF022B632B2729CA49': // clavnoxr map03 + { + SetLineSpecial(96, 160, 1, 2, 0, 128); + OffsetSectorPlane(11, Sector.floor, -80); + SetLineSpecial(955, 160, 13, 2, 0, 128); + OffsetSectorPlane(173, Sector.floor, -16); + SetLineSpecial(1082, 160, 14, 2, 0, 128); + OffsetSectorPlane(195, Sector.floor, -16); + SetLineSpecial(1111, 160, 15, 2, 0, 128); + OffsetSectorPlane(203, Sector.floor, -16); + SetLineSpecial(1115, 160, 16, 2, 0, 128); + OffsetSectorPlane(204, Sector.floor, -16); + SetLineSpecial(1163, 160, 17, 2, 0, 128); + OffsetSectorPlane(216, Sector.floor, -56); + SetLineSpecial(1169, 160, 18, 2, 0, 128); + OffsetSectorPlane(217, Sector.floor, -16); + break; + } + + case '748EDAEB3990F13B22C13C593631B2E6': // clavnoxr map04 + { + SetLineSpecial(859, 160, 22, 2, 0, 128); + SetLineSpecial(861, 160, 23, 2, 0, 128); + OffsetSectorPlane(172, Sector.floor, -168); + break; + } + + case 'A066B0B432FAE8ED20B83383F9E03E12': // clavnoxr map05 + { + SetLineSpecial(1020, 160, 2, 2, 0, 128); + SetSectorSpecial(190, 69); + OffsetSectorPlane(190, Sector.floor, -24); + break; + } + + case '5F36D758ED26CAE907FA79902330877D': // clavnoxr map06 + { + SetLineSpecial(1086, 160, 1, 2, 0, 128); + SetLineSpecial(60, 160, 4, 2, 0, 128); + SetLineSpecial(561, 160, 2, 2, 0, 128); + SetLineSpecial(280, 160, 3, 2, 0, 128); + SetLineSpecial(692, 160, 5, 2, 0, 128); + SetLineSpecial(1090, 160, 7, 2, 0, 128); + SetLineSpecial(1091, 160, 8, 2, 0, 128); + SetLineSpecial(1094, 160, 9, 2, 0, 128); + SetLineSpecial(1139, 160, 12, 2, 0, 128); + SetLineSpecial(1595, 160, 16, 2, 0, 128); + SetLineSpecial(1681, 160, 17, 2, 0, 128); + SetLineSpecial(1878, 160, 20, 2, 0, 128); + SetLineSpecial(1882, 160, 22, 2, 0, 128); + OffsetSectorPlane(8, Sector.floor, -64); + OffsetSectorPlane(34, Sector.floor, -24); + OffsetSectorPlane(64, Sector.floor, -16); + OffsetSectorPlane(102, Sector.floor, -16); + OffsetSectorPlane(170, Sector.floor, -64); + OffsetSectorPlane(171, Sector.floor, -64); + OffsetSectorPlane(178, Sector.floor, -16); + OffsetSectorPlane(236, Sector.floor, -16); + OffsetSectorPlane(250, Sector.floor, -16); + OffsetSectorPlane(283, Sector.floor, -64); + OffsetSectorPlane(284, Sector.floor, -56); + break; + } + + case 'B7E98C1EA1B38B707ADA8097C25CFA75': // clavnoxr map07 + { + SetLineSpecial(1307, 160, 22, 2, 0, 128); + SetLineSpecial(1305, 160, 23, 2, 0, 128); + OffsetSectorPlane(218, Sector.floor, -64); + break; + } + + case '7DAB2E8BB5759D742211505A3E5054D1': // clavnoxr map08 + { + SetLineSpecial(185, 160, 1, 2, 0, 128); + SetLineSpecial(735, 160, 13, 2, 0, 128); + OffsetSectorPlane(20, Sector.floor, -16); + SetSectorSpecial(20, 69); + OffsetSectorPlane(102, Sector.floor, -64); + break; + } + + case 'C17A9D1350399E251C70711EB22856AE': // clavnoxr map09 + { + SetLineSpecial(63, 160, 1, 2, 0, 128); + SetLineSpecial(84, 160, 2, 2, 0, 128); + SetLineSpecial(208, 160, 4, 2, 0, 128); + SetLineSpecial(326, 160, 6, 2, 0, 128); + SetLineSpecial(433, 160, 10, 2, 0, 128); + OffsetSectorPlane(6, Sector.floor, -64); + OffsetSectorPlane(9, Sector.floor, -64); + OffsetSectorPlane(34, Sector.floor, -64); + OffsetSectorPlane(59, Sector.floor, -64); + SetSectorSpecial(75, 69); + OffsetSectorPlane(75, Sector.floor, -64); + break; + } + + case 'B6BB8A1792FE51C773E6770CD91DB618': // clavnoxr map11 + { + SetLineSpecial(1235, 160, 23, 2, 0, 128); + SetLineSpecial(1238, 160, 24, 2, 0, 128); + OffsetSectorPlane(240, Sector.floor, -80); + break; + } + + case 'ADDF57B80E389F86D324571D43F3CAB7': // clavnoxr map12 + { + SetLineSpecial(1619, 160, 19, 2, 0, 128); + SetLineSpecial(1658, 160, 20, 2, 0, 128); + SetLineSpecial(1659, 160, 21, 2, 0, 128); + OffsetSectorPlane(254, Sector.floor, -160); + // Raising platforms in MAP12 didn't work, so this will redo them. + SetLineSpecial(1469, 160, 6, 1, 0, 255); + OffsetSectorPlane(65, Sector.floor, -8); + OffsetSectorPlane(65, Sector.ceiling, 8); + break; + } } } } diff --git a/wadsrc/static/zscript/level_postprocessor.zs b/wadsrc/static/zscript/level_postprocessor.zs index 9b3b7b750..93ee8343d 100644 --- a/wadsrc/static/zscript/level_postprocessor.zs +++ b/wadsrc/static/zscript/level_postprocessor.zs @@ -52,13 +52,19 @@ class LevelPostProcessor native play protected native void SetLineSectorRef(uint line, uint side, uint sector); protected native Actor GetDefaultActor(Name actorclass); - protected void FlipLine(uint Line) + protected void FlipLineVertexes(uint Line) { uint v1 = level.lines[Line].v1.Index(); uint v2 = level.lines[Line].v2.Index(); SetLineVertexes(Line, v2, v1); } + protected void FlipLineCompletely(uint Line) + { + FlipLineVertexes(Line); + FlipLineSideRefs(Line); + } + protected void SetWallTexture(int line, int side, int texpart, String texture) { SetWallTextureID(line, side, texpart, TexMan.CheckForTexture(texture, TexMan.Type_Wall)); diff --git a/wadsrc/static/zscript/ui/statusbar/statusbar.zs b/wadsrc/static/zscript/ui/statusbar/statusbar.zs index 4f84fad3a..85cf54475 100644 --- a/wadsrc/static/zscript/ui/statusbar/statusbar.zs +++ b/wadsrc/static/zscript/ui/statusbar/statusbar.zs @@ -349,7 +349,7 @@ class BaseStatusBar native ui native static TextureID, bool GetInventoryIcon(Inventory item, int flags); native void DrawTexture(TextureID texture, Vector2 pos, int flags = 0, double Alpha = 1., Vector2 box = (-1, -1), Vector2 scale = (1, 1)); native void DrawImage(String texture, Vector2 pos, int flags = 0, double Alpha = 1., Vector2 box = (-1, -1), Vector2 scale = (1, 1)); - native void DrawString(HUDFont font, String string, Vector2 pos, int flags = 0, int translation = Font.CR_UNTRANSLATED, double Alpha = 1., int wrapwidth = -1, int linespacing = 4); + native void DrawString(HUDFont font, String string, Vector2 pos, int flags = 0, int translation = Font.CR_UNTRANSLATED, double Alpha = 1., int wrapwidth = -1, int linespacing = 4, Vector2 scale = (1, 1)); native double, double, double, double TransformRect(double x, double y, double w, double h, int flags = 0); native void Fill(Color col, double x, double y, double w, double h, int flags = 0); native static String FormatNumber(int number, int minsize = 0, int maxsize = 0, int format = 0, String prefix = "");