mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-02-15 16:51:28 +00:00
Merge remote-tracking branch 'gzdoom/master' into newmaster
This commit is contained in:
commit
334f6fc018
25 changed files with 842 additions and 478 deletions
|
@ -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);
|
||||
|
|
|
@ -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<int> (font->StringWidth(cstring) + (spacing * cstring.CharacterCount()));
|
||||
else //monospaced, so just multiply the character size
|
||||
x -= static_cast<int> ((spacing) * cstring.CharacterCount());
|
||||
dx = monospaced
|
||||
? static_cast<int> ((spacing)*cstring.CharacterCount()) //monospaced, so just multiply the character size
|
||||
: static_cast<int> (font->StringWidth(cstring) + (spacing * cstring.CharacterCount()));
|
||||
break;
|
||||
case DI_TEXT_ALIGN_CENTER:
|
||||
if (!monospaced)
|
||||
x -= static_cast<int> (font->StringWidth(cstring) + (spacing * cstring.CharacterCount())) / 2;
|
||||
else //monospaced, so just multiply the character size
|
||||
x -= static_cast<int> ((spacing)* cstring.CharacterCount()) / 2;
|
||||
dx = monospaced
|
||||
? static_cast<int> ((spacing)*cstring.CharacterCount()) / 2 //monospaced, so just multiply the character size
|
||||
: static_cast<int> (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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,11 +217,239 @@ 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>();
|
||||
|
||||
WallColumnDrawerArgs& drawerargs = *thread->columndrawer.get();
|
||||
drawerargs.wallargs = &wallargs;
|
||||
|
||||
bool fixed = wallargs.fixedlight;
|
||||
|
||||
bool haslights = r_dynlights && wallargs.lightlist;
|
||||
if (haslights)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
drawerargs.SetTextureFracBits(wallargs.fracbits);
|
||||
|
||||
float curlight = wallargs.lightpos;
|
||||
float lightstep = wallargs.lightstep;
|
||||
int shade = wallargs.mShade;
|
||||
|
||||
float upos = wallargs.texcoords.upos, ustepX = wallargs.texcoords.ustepX, ustepY = wallargs.texcoords.ustepY;
|
||||
float vpos = wallargs.texcoords.vpos, vstepX = wallargs.texcoords.vstepX, vstepY = wallargs.texcoords.vstepY;
|
||||
float wpos = wallargs.texcoords.wpos, wstepX = wallargs.texcoords.wstepX, wstepY = wallargs.texcoords.wstepY;
|
||||
float startX = wallargs.texcoords.startX;
|
||||
|
||||
int x1 = wallargs.x1;
|
||||
int x2 = wallargs.x2;
|
||||
|
||||
upos += ustepX * (x1 + 0.5f - startX);
|
||||
vpos += vstepX * (x1 + 0.5f - startX);
|
||||
wpos += wstepX * (x1 + 0.5f - startX);
|
||||
|
||||
float centerY = wallargs.CenterY;
|
||||
centerY -= 0.5f;
|
||||
|
||||
auto uwal = wallargs.uwal;
|
||||
auto dwal = wallargs.dwal;
|
||||
for (int x = x1; x < x2; x++)
|
||||
{
|
||||
int y1 = uwal[x];
|
||||
int y2 = dwal[x];
|
||||
if (y2 > y1)
|
||||
{
|
||||
if (!fixed) drawerargs.SetLight(curlight, shade);
|
||||
if (haslights)
|
||||
SetLights(drawerargs, x, y1);
|
||||
else
|
||||
drawerargs.dc_num_lights = 0;
|
||||
|
||||
float dy = (y1 - centerY);
|
||||
float u = upos + ustepY * dy;
|
||||
float v = vpos + vstepY * dy;
|
||||
float w = wpos + wstepY * dy;
|
||||
float scaleU = ustepX;
|
||||
float scaleV = vstepY;
|
||||
w = 1.0f / w;
|
||||
u *= w;
|
||||
v *= w;
|
||||
scaleU *= w;
|
||||
scaleV *= w;
|
||||
|
||||
uint32_t texelX = (uint32_t)(int64_t)((u - std::floor(u)) * 0x1'0000'0000LL);
|
||||
uint32_t texelY = (uint32_t)(int64_t)((v - std::floor(v)) * 0x1'0000'0000LL);
|
||||
uint32_t texelStepX = (uint32_t)(int64_t)(scaleU * 0x1'0000'0000LL);
|
||||
uint32_t texelStepY = (uint32_t)(int64_t)(scaleV * 0x1'0000'0000LL);
|
||||
|
||||
if (wallargs.fracbits != 32)
|
||||
DrawWallColumn8(thread, drawerargs, x, y1, y2, texelX, texelY, texelStepY);
|
||||
else
|
||||
DrawWallColumn32(thread, drawerargs, x, y1, y2, texelX, texelY, texelStepX, texelStepY);
|
||||
}
|
||||
|
||||
upos += ustepX;
|
||||
vpos += vstepX;
|
||||
wpos += wstepX;
|
||||
curlight += lightstep;
|
||||
}
|
||||
|
||||
if (r_modelscene)
|
||||
{
|
||||
for (int x = x1; x < x2; x++)
|
||||
{
|
||||
int y1 = uwal[x];
|
||||
int y2 = dwal[x];
|
||||
if (y2 > y1)
|
||||
{
|
||||
int count = y2 - y1;
|
||||
|
||||
float w1 = 1.0f / wallargs.WallC.sz1;
|
||||
float w2 = 1.0f / wallargs.WallC.sz2;
|
||||
float t = (x - wallargs.WallC.sx1 + 0.5f) / (wallargs.WallC.sx2 - wallargs.WallC.sx1);
|
||||
float wcol = w1 * (1.0f - t) + w2 * t;
|
||||
float zcol = 1.0f / wcol;
|
||||
float zbufferdepth = 1.0f / (zcol / wallargs.FocalTangent);
|
||||
|
||||
drawerargs.SetDest(x, y1);
|
||||
drawerargs.SetCount(count);
|
||||
DrawDepthColumn(thread, drawerargs, zbufferdepth);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DrawWallCommand::DrawWallColumn32(DrawerThread* thread, WallColumnDrawerArgs& drawerargs, int x, int y1, int y2, uint32_t texelX, uint32_t texelY, uint32_t texelStepX, uint32_t texelStepY)
|
||||
{
|
||||
int texwidth = wallargs.texwidth;
|
||||
int texheight = wallargs.texheight;
|
||||
|
||||
double xmagnitude = fabs(static_cast<int32_t>(texelStepX)* (1.0 / 0x1'0000'0000LL));
|
||||
double ymagnitude = fabs(static_cast<int32_t>(texelStepY)* (1.0 / 0x1'0000'0000LL));
|
||||
double magnitude = MAX(ymagnitude, xmagnitude);
|
||||
double min_lod = -1000.0;
|
||||
double lod = MAX(log2(magnitude) + r_lod_bias, min_lod);
|
||||
bool magnifying = lod < 0.0f;
|
||||
|
||||
int mipmap_offset = 0;
|
||||
int mip_width = texwidth;
|
||||
int mip_height = texheight;
|
||||
if (wallargs.mipmapped && mip_width > 1 && mip_height > 1)
|
||||
{
|
||||
int level = (int)lod;
|
||||
while (level > 0 && mip_width > 1 && mip_height > 1)
|
||||
{
|
||||
mipmap_offset += mip_width * mip_height;
|
||||
level--;
|
||||
mip_width = MAX(mip_width >> 1, 1);
|
||||
mip_height = MAX(mip_height >> 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
const uint32_t* pixels = static_cast<const uint32_t*>(wallargs.texpixels) + mipmap_offset;
|
||||
fixed_t xxoffset = (texelX >> 16)* mip_width;
|
||||
|
||||
const uint8_t* source;
|
||||
const uint8_t* source2;
|
||||
uint32_t texturefracx;
|
||||
bool filter_nearest = (magnifying && !r_magfilter) || (!magnifying && !r_minfilter);
|
||||
if (filter_nearest)
|
||||
{
|
||||
int tx = (xxoffset >> FRACBITS) % mip_width;
|
||||
source = (uint8_t*)(pixels + tx * mip_height);
|
||||
source2 = nullptr;
|
||||
texturefracx = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
xxoffset -= FRACUNIT / 2;
|
||||
int tx0 = (xxoffset >> FRACBITS) % mip_width;
|
||||
if (tx0 < 0)
|
||||
tx0 += mip_width;
|
||||
int tx1 = (tx0 + 1) % mip_width;
|
||||
source = (uint8_t*)(pixels + tx0 * mip_height);
|
||||
source2 = (uint8_t*)(pixels + tx1 * mip_height);
|
||||
texturefracx = (xxoffset >> (FRACBITS - 4)) & 15;
|
||||
}
|
||||
|
||||
int count = y2 - y1;
|
||||
drawerargs.SetDest(x, y1);
|
||||
drawerargs.SetCount(count);
|
||||
drawerargs.SetTexture(source, source2, mip_height);
|
||||
drawerargs.SetTextureUPos(texturefracx);
|
||||
drawerargs.SetTextureVPos(texelY);
|
||||
drawerargs.SetTextureVStep(texelStepY);
|
||||
DrawColumn(thread, drawerargs);
|
||||
}
|
||||
|
||||
void DrawWallCommand::DrawWallColumn8(DrawerThread* thread, WallColumnDrawerArgs& drawerargs, int x, int y1, int y2, uint32_t texelX, uint32_t texelY, uint32_t texelStepY)
|
||||
{
|
||||
int texwidth = wallargs.texwidth;
|
||||
int texheight = wallargs.texheight;
|
||||
int fracbits = wallargs.fracbits;
|
||||
uint32_t uv_max = texheight << fracbits;
|
||||
|
||||
const uint8_t* pixels = static_cast<const uint8_t*>(wallargs.texpixels) + (((texelX >> 16)* texwidth) >> 16)* texheight;
|
||||
|
||||
texelY = (static_cast<uint64_t>(texelY)* texheight) >> (32 - fracbits);
|
||||
texelStepY = (static_cast<uint64_t>(texelStepY)* texheight) >> (32 - fracbits);
|
||||
|
||||
drawerargs.SetTexture(pixels, nullptr, texheight);
|
||||
drawerargs.SetTextureVStep(texelStepY);
|
||||
|
||||
if (uv_max == 0 || texelStepY == 0) // power of two
|
||||
{
|
||||
int count = y2 - y1;
|
||||
|
||||
drawerargs.SetDest(x, y1);
|
||||
drawerargs.SetCount(count);
|
||||
drawerargs.SetTextureVPos(texelY);
|
||||
DrawColumn(thread, drawerargs);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t left = y2 - y1;
|
||||
int y = y1;
|
||||
while (left > 0)
|
||||
{
|
||||
uint32_t available = uv_max - texelY;
|
||||
uint32_t next_uv_wrap = available / texelStepY;
|
||||
if (available % texelStepY != 0)
|
||||
next_uv_wrap++;
|
||||
uint32_t count = MIN(left, next_uv_wrap);
|
||||
|
||||
drawerargs.SetDest(x, y);
|
||||
drawerargs.SetCount(count);
|
||||
drawerargs.SetTextureVPos(texelY);
|
||||
DrawColumn(thread, drawerargs);
|
||||
|
||||
y += count;
|
||||
left -= count;
|
||||
texelY += texelStepY * count;
|
||||
if (texelY >= uv_max)
|
||||
texelY -= uv_max;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DrawWallCommand::DrawDepthColumn(DrawerThread* thread, const WallColumnDrawerArgs& args, float idepth)
|
||||
{
|
||||
int x, y, count;
|
||||
|
||||
auto rendertarget = args.Viewport()->RenderTarget;
|
||||
if (rendertarget->IsBgra())
|
||||
{
|
||||
|
@ -241,9 +470,94 @@ namespace swrenderer
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
||||
DepthColumnCommand(const SkyDrawerArgs &args, float idepth) : idepth(idepth)
|
||||
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<DepthColumnCommand>(args, idepth);
|
||||
}
|
||||
|
||||
void SWPixelFormatDrawers::DrawDepthWallColumn(const WallDrawerArgs &args, float idepth)
|
||||
{
|
||||
Queue->Push<DepthColumnCommand>(args, idepth);
|
||||
Queue->Push<DepthSkyColumnCommand>(args, idepth);
|
||||
}
|
||||
|
||||
void SWPixelFormatDrawers::DrawDepthSpan(const SpanDrawerArgs &args, float idepth1, float idepth2)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<DrawWall1PalCommand>(args); }
|
||||
void DrawWallMaskedColumn(const WallDrawerArgs &args) override { Queue->Push<DrawWallMasked1PalCommand>(args); }
|
||||
void DrawWall(const WallDrawerArgs &args) override { Queue->Push<DrawWall1PalCommand>(args); }
|
||||
void DrawWallMasked(const WallDrawerArgs &args) override { Queue->Push<DrawWallMasked1PalCommand>(args); }
|
||||
|
||||
void DrawWallAddColumn(const WallDrawerArgs &args) override
|
||||
void DrawWallAdd(const WallDrawerArgs &args) override
|
||||
{
|
||||
if (args.dc_num_lights == 0)
|
||||
if (!args.lightlist)
|
||||
Queue->Push<DrawWallAdd1PalCommand>(args);
|
||||
else
|
||||
Queue->Push<DrawWallAddClamp1PalCommand>(args);
|
||||
}
|
||||
|
||||
void DrawWallAddClampColumn(const WallDrawerArgs &args) override { Queue->Push<DrawWallAddClamp1PalCommand>(args); }
|
||||
void DrawWallSubClampColumn(const WallDrawerArgs &args) override { Queue->Push<DrawWallSubClamp1PalCommand>(args); }
|
||||
void DrawWallRevSubClampColumn(const WallDrawerArgs &args) override { Queue->Push<DrawWallRevSubClamp1PalCommand>(args); }
|
||||
void DrawWallAddClamp(const WallDrawerArgs &args) override { Queue->Push<DrawWallAddClamp1PalCommand>(args); }
|
||||
void DrawWallSubClamp(const WallDrawerArgs &args) override { Queue->Push<DrawWallSubClamp1PalCommand>(args); }
|
||||
void DrawWallRevSubClamp(const WallDrawerArgs &args) override { Queue->Push<DrawWallRevSubClamp1PalCommand>(args); }
|
||||
void DrawSingleSkyColumn(const SkyDrawerArgs &args) override { Queue->Push<DrawSingleSky1PalCommand>(args); }
|
||||
void DrawDoubleSkyColumn(const SkyDrawerArgs &args) override { Queue->Push<DrawDoubleSky1PalCommand>(args); }
|
||||
void DrawColumn(const SpriteDrawerArgs &args) override { Queue->Push<DrawColumnPalCommand>(args); }
|
||||
|
|
|
@ -80,32 +80,32 @@ CVAR(Float, r_lod_bias, -1.5, 0); // To do: add CVAR_ARCHIVE | CVAR_GLOBALCONFIG
|
|||
|
||||
namespace swrenderer
|
||||
{
|
||||
void SWTruecolorDrawers::DrawWallColumn(const WallDrawerArgs &args)
|
||||
void SWTruecolorDrawers::DrawWall(const WallDrawerArgs &args)
|
||||
{
|
||||
Queue->Push<DrawWall32Command>(args);
|
||||
}
|
||||
|
||||
void SWTruecolorDrawers::DrawWallMaskedColumn(const WallDrawerArgs &args)
|
||||
void SWTruecolorDrawers::DrawWallMasked(const WallDrawerArgs &args)
|
||||
{
|
||||
Queue->Push<DrawWallMasked32Command>(args);
|
||||
}
|
||||
|
||||
void SWTruecolorDrawers::DrawWallAddColumn(const WallDrawerArgs &args)
|
||||
void SWTruecolorDrawers::DrawWallAdd(const WallDrawerArgs &args)
|
||||
{
|
||||
Queue->Push<DrawWallAddClamp32Command>(args);
|
||||
}
|
||||
|
||||
void SWTruecolorDrawers::DrawWallAddClampColumn(const WallDrawerArgs &args)
|
||||
void SWTruecolorDrawers::DrawWallAddClamp(const WallDrawerArgs &args)
|
||||
{
|
||||
Queue->Push<DrawWallAddClamp32Command>(args);
|
||||
}
|
||||
|
||||
void SWTruecolorDrawers::DrawWallSubClampColumn(const WallDrawerArgs &args)
|
||||
void SWTruecolorDrawers::DrawWallSubClamp(const WallDrawerArgs &args)
|
||||
{
|
||||
Queue->Push<DrawWallSubClamp32Command>(args);
|
||||
}
|
||||
|
||||
void SWTruecolorDrawers::DrawWallRevSubClampColumn(const WallDrawerArgs &args)
|
||||
void SWTruecolorDrawers::DrawWallRevSubClamp(const WallDrawerArgs &args)
|
||||
{
|
||||
Queue->Push<DrawWallRevSubClamp32Command>(args);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "swrenderer/drawers/r_draw_pal.h"
|
||||
#include "swrenderer/drawers/r_draw_rgba.h"
|
||||
#include "swrenderer/viewport/r_walldrawer.h"
|
||||
|
||||
|
@ -46,15 +47,12 @@ namespace swrenderer
|
|||
}
|
||||
|
||||
template<typename BlendT>
|
||||
class DrawWall32T : public DrawerCommand
|
||||
class DrawWall32T : public DrawWallCommand
|
||||
{
|
||||
protected:
|
||||
WallDrawerArgs args;
|
||||
|
||||
public:
|
||||
DrawWall32T(const WallDrawerArgs &drawerargs) : args(drawerargs) { }
|
||||
DrawWall32T(const WallDrawerArgs &drawerargs) : DrawWallCommand(drawerargs) { }
|
||||
|
||||
void Execute(DrawerThread *thread) override
|
||||
void DrawColumn(DrawerThread *thread, const WallColumnDrawerArgs& args) override
|
||||
{
|
||||
using namespace DrawWall32TModes;
|
||||
|
||||
|
@ -64,21 +62,21 @@ namespace swrenderer
|
|||
if (shade_constants.simple_shade)
|
||||
{
|
||||
if (is_nearest_filter)
|
||||
Loop<SimpleShade, NearestFilter>(thread, shade_constants);
|
||||
Loop<SimpleShade, NearestFilter>(thread, args, shade_constants);
|
||||
else
|
||||
Loop<SimpleShade, LinearFilter>(thread, shade_constants);
|
||||
Loop<SimpleShade, LinearFilter>(thread, args, shade_constants);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_nearest_filter)
|
||||
Loop<AdvancedShade, NearestFilter>(thread, shade_constants);
|
||||
Loop<AdvancedShade, NearestFilter>(thread, args, shade_constants);
|
||||
else
|
||||
Loop<AdvancedShade, LinearFilter>(thread, shade_constants);
|
||||
Loop<AdvancedShade, LinearFilter>(thread, args, shade_constants);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename ShadeModeT, typename FilterModeT>
|
||||
FORCEINLINE void Loop(DrawerThread *thread, ShadeConstants shade_constants)
|
||||
FORCEINLINE void Loop(DrawerThread *thread, const WallColumnDrawerArgs& args, ShadeConstants shade_constants)
|
||||
{
|
||||
using namespace DrawWall32TModes;
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "swrenderer/drawers/r_draw_pal.h"
|
||||
#include "swrenderer/drawers/r_draw_rgba.h"
|
||||
#include "swrenderer/viewport/r_walldrawer.h"
|
||||
|
||||
|
@ -46,15 +47,12 @@ namespace swrenderer
|
|||
}
|
||||
|
||||
template<typename BlendT>
|
||||
class DrawWall32T : public DrawerCommand
|
||||
class DrawWall32T : public DrawWallCommand
|
||||
{
|
||||
protected:
|
||||
WallDrawerArgs args;
|
||||
|
||||
public:
|
||||
DrawWall32T(const WallDrawerArgs &drawerargs) : args(drawerargs) { }
|
||||
DrawWall32T(const WallDrawerArgs &drawerargs) : DrawWallCommand(drawerargs) { }
|
||||
|
||||
void Execute(DrawerThread *thread) override
|
||||
void DrawColumn(DrawerThread *thread, const WallColumnDrawerArgs& args) override
|
||||
{
|
||||
using namespace DrawWall32TModes;
|
||||
|
||||
|
@ -64,21 +62,21 @@ namespace swrenderer
|
|||
if (shade_constants.simple_shade)
|
||||
{
|
||||
if (is_nearest_filter)
|
||||
Loop<SimpleShade, NearestFilter>(thread, shade_constants);
|
||||
Loop<SimpleShade, NearestFilter>(thread, args, shade_constants);
|
||||
else
|
||||
Loop<SimpleShade, LinearFilter>(thread, shade_constants);
|
||||
Loop<SimpleShade, LinearFilter>(thread, args, shade_constants);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_nearest_filter)
|
||||
Loop<AdvancedShade, NearestFilter>(thread, shade_constants);
|
||||
Loop<AdvancedShade, NearestFilter>(thread, args, shade_constants);
|
||||
else
|
||||
Loop<AdvancedShade, LinearFilter>(thread, shade_constants);
|
||||
Loop<AdvancedShade, LinearFilter>(thread, args, shade_constants);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename ShadeModeT, typename FilterModeT>
|
||||
FORCEINLINE void VECTORCALL Loop(DrawerThread *thread, ShadeConstants shade_constants)
|
||||
FORCEINLINE void VECTORCALL Loop(DrawerThread *thread, const WallColumnDrawerArgs& args, ShadeConstants shade_constants)
|
||||
{
|
||||
using namespace DrawWall32TModes;
|
||||
|
||||
|
|
|
@ -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<PolyTriangleThreadData> poly;
|
||||
std::shared_ptr<swrenderer::WallColumnDrawerArgs> columndrawer;
|
||||
|
||||
size_t debug_draw_pos = 0;
|
||||
|
||||
|
|
|
@ -120,111 +120,6 @@ namespace swrenderer
|
|||
ProcessNormalWall(up, dwal, texcoords);
|
||||
}
|
||||
|
||||
static void DrawWallColumn32(RenderThread* thread, WallDrawerArgs& drawerargs, int x, int y1, int y2, uint32_t texelX, uint32_t texelY, uint32_t texelStepX, uint32_t texelStepY, FSoftwareTexture* pic, int texwidth, int texheight)
|
||||
{
|
||||
double xmagnitude = fabs(static_cast<int32_t>(texelStepX) * (1.0 / 0x1'0000'0000LL));
|
||||
double ymagnitude = fabs(static_cast<int32_t>(texelStepY) * (1.0 / 0x1'0000'0000LL));
|
||||
double magnitude = MAX(ymagnitude, xmagnitude);
|
||||
double min_lod = -1000.0;
|
||||
double lod = MAX(log2(magnitude) + r_lod_bias, min_lod);
|
||||
bool magnifying = lod < 0.0f;
|
||||
|
||||
int mipmap_offset = 0;
|
||||
int mip_width = texwidth;
|
||||
int mip_height = texheight;
|
||||
if (r_mipmap && pic->Mipmapped() && mip_width > 1 && mip_height > 1)
|
||||
{
|
||||
int level = (int)lod;
|
||||
while (level > 0 && mip_width > 1 && mip_height > 1)
|
||||
{
|
||||
mipmap_offset += mip_width * mip_height;
|
||||
level--;
|
||||
mip_width = MAX(mip_width >> 1, 1);
|
||||
mip_height = MAX(mip_height >> 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
const uint32_t* pixels = pic->GetPixelsBgra() + mipmap_offset;
|
||||
fixed_t xxoffset = (texelX >> 16) * mip_width;
|
||||
|
||||
const uint8_t* source;
|
||||
const uint8_t* source2;
|
||||
uint32_t texturefracx;
|
||||
bool filter_nearest = (magnifying && !r_magfilter) || (!magnifying && !r_minfilter);
|
||||
if (filter_nearest)
|
||||
{
|
||||
int tx = (xxoffset >> FRACBITS) % mip_width;
|
||||
source = (uint8_t*)(pixels + tx * mip_height);
|
||||
source2 = nullptr;
|
||||
texturefracx = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
xxoffset -= FRACUNIT / 2;
|
||||
int tx0 = (xxoffset >> FRACBITS) % mip_width;
|
||||
if (tx0 < 0)
|
||||
tx0 += mip_width;
|
||||
int tx1 = (tx0 + 1) % mip_width;
|
||||
source = (uint8_t*)(pixels + tx0 * mip_height);
|
||||
source2 = (uint8_t*)(pixels + tx1 * mip_height);
|
||||
texturefracx = (xxoffset >> (FRACBITS - 4)) & 15;
|
||||
}
|
||||
|
||||
int count = y2 - y1;
|
||||
drawerargs.SetDest(thread->Viewport.get(), x, y1);
|
||||
drawerargs.SetCount(count);
|
||||
drawerargs.SetTexture(source, source2, mip_height);
|
||||
drawerargs.SetTextureUPos(texturefracx);
|
||||
drawerargs.SetTextureVPos(texelY);
|
||||
drawerargs.SetTextureVStep(texelStepY);
|
||||
drawerargs.DrawColumn(thread);
|
||||
}
|
||||
|
||||
static void DrawWallColumn8(RenderThread* thread, WallDrawerArgs& drawerargs, int x, int y1, int y2, uint32_t texelX, uint32_t texelY, uint32_t texelStepY, FSoftwareTexture* pic, int texwidth, int texheight, int fracbits, uint32_t uv_max)
|
||||
{
|
||||
texelY = (static_cast<uint64_t>(texelY)* texheight) >> (32 - fracbits);
|
||||
texelStepY = (static_cast<uint64_t>(texelStepY)* texheight) >> (32 - fracbits);
|
||||
|
||||
const uint8_t* pixels = pic->GetColumn(DefaultRenderStyle(), ((texelX >> 16)* texwidth) >> 16, nullptr);
|
||||
|
||||
drawerargs.SetTexture(pixels, nullptr, texheight);
|
||||
drawerargs.SetTextureVStep(texelStepY);
|
||||
|
||||
if (uv_max == 0 || texelStepY == 0) // power of two
|
||||
{
|
||||
int count = y2 - y1;
|
||||
|
||||
drawerargs.SetDest(thread->Viewport.get(), x, y1);
|
||||
drawerargs.SetCount(count);
|
||||
drawerargs.SetTextureVPos(texelY);
|
||||
drawerargs.DrawColumn(thread);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t left = y2 - y1;
|
||||
int y = y1;
|
||||
while (left > 0)
|
||||
{
|
||||
uint32_t available = uv_max - texelY;
|
||||
uint32_t next_uv_wrap = available / texelStepY;
|
||||
if (available % texelStepY != 0)
|
||||
next_uv_wrap++;
|
||||
uint32_t count = MIN(left, next_uv_wrap);
|
||||
|
||||
drawerargs.SetDest(thread->Viewport.get(), x, y);
|
||||
drawerargs.SetCount(count);
|
||||
drawerargs.SetTextureVPos(texelY);
|
||||
drawerargs.DrawColumn(thread);
|
||||
|
||||
y += count;
|
||||
left -= count;
|
||||
texelY += texelStepY * count;
|
||||
if (texelY >= uv_max)
|
||||
texelY -= uv_max;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RenderWallPart::ProcessNormalWall(const short* uwal, const short* dwal, const ProjectedWallTexcoords& texcoords)
|
||||
{
|
||||
CameraLight* cameraLight = CameraLight::Instance();
|
||||
|
@ -242,185 +137,55 @@ namespace swrenderer
|
|||
drawerargs.SetStyle(mask, additive, alpha, mLight.GetBaseColormap());
|
||||
}
|
||||
|
||||
bool fixed = (cameraLight->FixedColormap() || cameraLight->FixedLightLevel() >= 0);
|
||||
int count = x2 - x1;
|
||||
short* data = Thread->FrameMemory->AllocMemory<short>(count << 1);
|
||||
|
||||
bool haslights = r_dynlights && light_list;
|
||||
if (haslights)
|
||||
drawerargs.x1 = x1;
|
||||
drawerargs.x2 = x2;
|
||||
drawerargs.uwal = data - x1;
|
||||
drawerargs.dwal = data + count - x1; // to avoid calling AllocMemory twice
|
||||
memcpy(drawerargs.uwal + x1, uwal + x1, sizeof(short) * count);
|
||||
memcpy(drawerargs.dwal + x1, dwal + x1, sizeof(short) * count);
|
||||
drawerargs.WallC = WallC;
|
||||
drawerargs.texcoords = texcoords;
|
||||
|
||||
drawerargs.lightpos = mLight.GetLightPos(x1);
|
||||
drawerargs.lightstep = mLight.GetLightStep();
|
||||
drawerargs.mShade = LightVisibility::LightLevelToShade(mLight.GetLightLevel(), mLight.GetFoggy(), viewport);
|
||||
drawerargs.lightlist = light_list;
|
||||
|
||||
drawerargs.texwidth = pic->GetPhysicalWidth();
|
||||
drawerargs.texheight = pic->GetPhysicalHeight();
|
||||
if (viewport->RenderTarget->IsBgra())
|
||||
{
|
||||
float dx = WallC.tright.X - WallC.tleft.X;
|
||||
float dy = WallC.tright.Y - WallC.tleft.Y;
|
||||
float length = sqrt(dx * dx + dy * dy);
|
||||
drawerargs.dc_normal.X = dy / length;
|
||||
drawerargs.dc_normal.Y = -dx / length;
|
||||
drawerargs.dc_normal.Z = 0.0f;
|
||||
drawerargs.texpixels = pic->GetPixelsBgra();
|
||||
drawerargs.fracbits = 32;
|
||||
drawerargs.mipmapped = r_mipmap && pic->Mipmapped();
|
||||
}
|
||||
|
||||
int texwidth = pic->GetPhysicalWidth();
|
||||
int texheight = pic->GetPhysicalHeight();
|
||||
|
||||
else
|
||||
{
|
||||
drawerargs.texpixels = pic->GetPixels(DefaultRenderStyle());
|
||||
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);
|
||||
drawerargs.fracbits = fracbits;
|
||||
drawerargs.mipmapped = false;
|
||||
}
|
||||
|
||||
upos += ustepX;
|
||||
vpos += vstepX;
|
||||
wpos += wstepX;
|
||||
curlight += lightstep;
|
||||
}
|
||||
// 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);
|
||||
|
||||
if (r_modelscene)
|
||||
{
|
||||
for (int x = x1; x < x2; x++)
|
||||
{
|
||||
int y1 = uwal[x];
|
||||
int y2 = dwal[x];
|
||||
if (y2 > y1)
|
||||
{
|
||||
int count = y2 - y1;
|
||||
|
||||
float w1 = 1.0f / WallC.sz1;
|
||||
float w2 = 1.0f / WallC.sz2;
|
||||
float t = (x - WallC.sx1 + 0.5f) / (WallC.sx2 - WallC.sx1);
|
||||
float wcol = w1 * (1.0f - t) + w2 * t;
|
||||
float zcol = 1.0f / wcol;
|
||||
float zbufferdepth = 1.0f / (zcol / viewport->viewwindow.FocalTangent);
|
||||
|
||||
drawerargs.SetDest(viewport, x, y1);
|
||||
drawerargs.SetCount(count);
|
||||
drawerargs.DrawDepthColumn(Thread, zbufferdepth);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RenderWallPart::SetLights(WallDrawerArgs &drawerargs, int x, int y1)
|
||||
{
|
||||
bool mirror = !!(Thread->Portal->MirrorFlags & RF_XFLIP);
|
||||
int tx = x;
|
||||
if (mirror)
|
||||
tx = viewwidth - tx - 1;
|
||||
|
||||
RenderViewport *viewport = Thread->Viewport.get();
|
||||
|
||||
// Find column position in view space
|
||||
float w1 = 1.0f / WallC.sz1;
|
||||
float w2 = 1.0f / WallC.sz2;
|
||||
float t = (x - WallC.sx1 + 0.5f) / (WallC.sx2 - WallC.sx1);
|
||||
float wcol = w1 * (1.0f - t) + w2 * t;
|
||||
float zcol = 1.0f / wcol;
|
||||
|
||||
drawerargs.dc_viewpos.X = (float)((tx + 0.5 - viewport->CenterX) / viewport->CenterX * zcol);
|
||||
drawerargs.dc_viewpos.Y = zcol;
|
||||
drawerargs.dc_viewpos.Z = (float)((viewport->CenterY - y1 - 0.5) / viewport->InvZtoScale * zcol);
|
||||
drawerargs.dc_viewpos_step.Z = (float)(-zcol / viewport->InvZtoScale);
|
||||
|
||||
// Calculate max lights that can touch column so we can allocate memory for the list
|
||||
int max_lights = 0;
|
||||
FLightNode *cur_node = light_list;
|
||||
while (cur_node)
|
||||
{
|
||||
if (cur_node->lightsource->IsActive())
|
||||
max_lights++;
|
||||
cur_node = cur_node->nextLight;
|
||||
}
|
||||
|
||||
drawerargs.dc_num_lights = 0;
|
||||
drawerargs.dc_lights = Thread->FrameMemory->AllocMemory<DrawerLight>(max_lights);
|
||||
|
||||
// Setup lights for column
|
||||
cur_node = light_list;
|
||||
while (cur_node)
|
||||
{
|
||||
if (cur_node->lightsource->IsActive())
|
||||
{
|
||||
double lightX = cur_node->lightsource->X() - viewport->viewpoint.Pos.X;
|
||||
double lightY = cur_node->lightsource->Y() - viewport->viewpoint.Pos.Y;
|
||||
double lightZ = cur_node->lightsource->Z() - viewport->viewpoint.Pos.Z;
|
||||
|
||||
float lx = (float)(lightX * viewport->viewpoint.Sin - lightY * viewport->viewpoint.Cos) - drawerargs.dc_viewpos.X;
|
||||
float ly = (float)(lightX * viewport->viewpoint.TanCos + lightY * viewport->viewpoint.TanSin) - drawerargs.dc_viewpos.Y;
|
||||
float lz = (float)lightZ;
|
||||
|
||||
// Precalculate the constant part of the dot here so the drawer doesn't have to.
|
||||
bool is_point_light = cur_node->lightsource->IsAttenuated();
|
||||
float lconstant = lx * lx + ly * ly;
|
||||
float nlconstant = is_point_light ? lx * drawerargs.dc_normal.X + ly * drawerargs.dc_normal.Y : 0.0f;
|
||||
|
||||
// Include light only if it touches this column
|
||||
float radius = cur_node->lightsource->GetRadius();
|
||||
if (radius * radius >= lconstant && nlconstant >= 0.0f)
|
||||
{
|
||||
uint32_t red = cur_node->lightsource->GetRed();
|
||||
uint32_t green = cur_node->lightsource->GetGreen();
|
||||
uint32_t blue = cur_node->lightsource->GetBlue();
|
||||
|
||||
auto &light = drawerargs.dc_lights[drawerargs.dc_num_lights++];
|
||||
light.x = lconstant;
|
||||
light.y = nlconstant;
|
||||
light.z = lz;
|
||||
light.radius = 256.0f / cur_node->lightsource->GetRadius();
|
||||
light.color = (red << 16) | (green << 8) | blue;
|
||||
}
|
||||
}
|
||||
|
||||
cur_node = cur_node->nextLight;
|
||||
}
|
||||
drawerargs.DrawWall(Thread);
|
||||
}
|
||||
|
||||
FLightNode* RenderWallPart::GetLightList()
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "po_man.h"
|
||||
#include "r_data/colormaps.h"
|
||||
#include "r_memory.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
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<uint8_t*>(Aligned_Alloc(16, BlockSize))), Position(0)
|
||||
{
|
||||
}
|
||||
|
||||
RenderMemory::MemoryBlock::~MemoryBlock()
|
||||
{
|
||||
Aligned_Free(Data);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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); }
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 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; }
|
||||
void SetDest(RenderViewport *viewport);
|
||||
void DrawWall(RenderThread *thread);
|
||||
|
||||
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; }
|
||||
|
||||
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 };
|
||||
DrawerLight *dc_lights = nullptr;
|
||||
int dc_num_lights = 0;
|
||||
|
||||
RenderViewport* Viewport() const { return dc_viewport; }
|
||||
|
||||
private:
|
||||
uint8_t *dc_dest = nullptr;
|
||||
int dc_dest_y = 0;
|
||||
int dc_count = 0;
|
||||
int x1, x2;
|
||||
short* uwal;
|
||||
short* dwal;
|
||||
FWallCoords WallC;
|
||||
ProjectedWallTexcoords texcoords;
|
||||
FLightNode* lightlist = nullptr;
|
||||
|
||||
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 lightpos;
|
||||
float lightstep;
|
||||
int mShade;
|
||||
|
||||
int texwidth;
|
||||
int texheight;
|
||||
int fracbits;
|
||||
bool mipmapped;
|
||||
const void* texpixels;
|
||||
|
||||
// Viewport data
|
||||
uint16_t PortalMirrorFlags;
|
||||
bool fixedlight;
|
||||
float CenterX;
|
||||
float CenterY;
|
||||
float FocalTangent;
|
||||
float InvZtoScale;
|
||||
FVector3 ViewpointPos;
|
||||
float Sin, Cos, TanCos, TanSin;
|
||||
|
||||
private:
|
||||
typedef void(SWPixelFormatDrawers::*WallDrawerFunc)(const WallDrawerArgs &args);
|
||||
WallDrawerFunc wallfunc = nullptr;
|
||||
|
||||
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;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -77,4 +77,6 @@ private:
|
|||
int mTexelsize = 4;
|
||||
|
||||
VkTextureImage mDepthStencil;
|
||||
|
||||
uint8_t* mappedSWFB = nullptr;
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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 = "");
|
||||
|
|
Loading…
Reference in a new issue