- implement alpha test

This commit is contained in:
Magnus Norddahl 2019-05-31 06:43:24 +02:00
parent a5608c67b5
commit 80805656ed
4 changed files with 99 additions and 632 deletions

View file

@ -347,7 +347,7 @@ void PolyTriangleThreadData::PushStreamData(const StreamData &data, const PolyPu
auto style = RenderStyle;
if (style.BlendOp == STYLEOP_Add && style.SrcAlpha == STYLEALPHA_One && style.DestAlpha == STYLEALPHA_Zero)
{
drawargs.SetStyle(AlphaTest ? TriBlendMode::Normal : TriBlendMode::Opaque);
drawargs.SetStyle(AlphaTest ? TriBlendMode::AlphaTest : TriBlendMode::Opaque);
}
else if (style.BlendOp == STYLEOP_Add && style.SrcAlpha == STYLEALPHA_Src && style.DestAlpha == STYLEALPHA_InvSrc)
{

View file

@ -205,6 +205,7 @@ public:
uint16_t lightarray[MAXWIDTH];
uint32_t dynlights[MAXWIDTH];
float depthvalues[MAXWIDTH];
uint8_t alphatestbuffer[MAXWIDTH];
static PolyTriangleThreadData *Get(DrawerThread *thread);

View file

@ -189,6 +189,9 @@ void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *threa
uint8_t *stencilLine;
int pitch;
bool alphatest = thread->AlphaTest;
uint8_t *alphatestbuf = thread->alphatestbuffer;
if (OptT::Flags & SWTRI_WriteColor)
{
int bmode = (int)args->uniforms->BlendMode();
@ -261,14 +264,14 @@ void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *threa
stencilLine[x + 2] == stencilTestValue &&
stencilLine[x + 3] == stencilTestValue)
{
if (OptT::Flags & SWTRI_WriteDepth)
if (!alphatest && (OptT::Flags & SWTRI_WriteDepth))
_mm_storeu_ps(zbufferLine + x, mposXW);
x += 4;
}
while (zbufferLine[x] >= depthvalues[x] && stencilLine[x] == stencilTestValue && x < xend)
{
if (OptT::Flags & SWTRI_WriteDepth)
if (!alphatest && (OptT::Flags & SWTRI_WriteDepth))
zbufferLine[x] = depthvalues[x];
x++;
}
@ -279,14 +282,14 @@ void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *threa
__m128 mposXW;
while (x < xendsse && _mm_movemask_ps(_mm_cmpge_ps(_mm_loadu_ps(zbufferLine + x), mposXW = _mm_loadu_ps(depthvalues + x))) == 15)
{
if (OptT::Flags & SWTRI_WriteDepth)
if (!alphatest && (OptT::Flags & SWTRI_WriteDepth))
_mm_storeu_ps(zbufferLine + x, mposXW);
x += 4;
}
while (zbufferLine[x] >= depthvalues[x] && x < xend)
{
if (OptT::Flags & SWTRI_WriteDepth)
if (!alphatest && (OptT::Flags & SWTRI_WriteDepth))
zbufferLine[x] = depthvalues[x];
x++;
}
@ -312,25 +315,48 @@ void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *threa
if (OptT::Flags & SWTRI_WriteColor)
drawfunc(y, xstart, x, args, thread);
if (OptT::Flags & SWTRI_WriteStencil)
if (alphatest)
{
int i = xstart;
int xendsse = xstart + ((x - xstart) / 16);
while (i < xendsse)
if (OptT::Flags & SWTRI_WriteStencil)
{
_mm_storeu_si128((__m128i*)&stencilLine[i], _mm_set1_epi8(stencilWriteValue));
i += 16;
for (int i = xstart; i < x; i++)
{
if (alphatestbuf[i] > 127)
stencilLine[i++] = stencilWriteValue;
}
}
while (i < x)
stencilLine[i++] = stencilWriteValue;
}
if (!(OptT::Flags & SWTRI_DepthTest) && (OptT::Flags & SWTRI_WriteDepth))
{
for (int i = xstart; i < x; i++)
if (OptT::Flags & SWTRI_WriteDepth)
{
zbufferLine[i] = depthvalues[i];
for (int i = xstart; i < x; i++)
{
if (alphatestbuf[i] > 127)
zbufferLine[i] = depthvalues[i];
}
}
}
else
{
if (OptT::Flags & SWTRI_WriteStencil)
{
int i = xstart;
int xendsse = xstart + ((x - xstart) / 16);
while (i < xendsse)
{
_mm_storeu_si128((__m128i*)&stencilLine[i], _mm_set1_epi8(stencilWriteValue));
i += 16;
}
while (i < x)
stencilLine[i++] = stencilWriteValue;
}
if (!(OptT::Flags & SWTRI_DepthTest) && (OptT::Flags & SWTRI_WriteDepth))
{
for (int i = xstart; i < x; i++)
{
zbufferLine[i] = depthvalues[i];
}
}
}
}
@ -391,7 +417,7 @@ void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *threa
{
while (zbufferLine[x] >= depthvalues[x] && stencilLine[x] == stencilTestValue && x < xend)
{
if (OptT::Flags & SWTRI_WriteDepth)
if (!alphatest && (OptT::Flags & SWTRI_WriteDepth))
zbufferLine[x] = depthvalues[x];
x++;
}
@ -400,7 +426,7 @@ void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *threa
{
while (zbufferLine[x] >= depthvalues[x] && x < xend)
{
if (OptT::Flags & SWTRI_WriteDepth)
if (!alphatest && (OptT::Flags & SWTRI_WriteDepth))
zbufferLine[x] = depthvalues[x];
x++;
}
@ -420,17 +446,40 @@ void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *threa
if (OptT::Flags & SWTRI_WriteColor)
drawfunc(y, xstart, x, args, thread);
if (OptT::Flags & SWTRI_WriteStencil)
if (alphatest)
{
for (int i = xstart; i < x; i++)
stencilLine[i] = stencilWriteValue;
}
if (!(OptT::Flags & SWTRI_DepthTest) && (OptT::Flags & SWTRI_WriteDepth))
{
for (int i = xstart; i < x; i++)
if (OptT::Flags & SWTRI_WriteStencil)
{
zbufferLine[i] = depthvalues[i];
for (int i = xstart; i < x; i++)
{
if (alphatestbuf[i] > 127)
stencilLine[i++] = stencilWriteValue;
}
}
if (OptT::Flags & SWTRI_WriteDepth)
{
for (int i = xstart; i < x; i++)
{
if (alphatestbuf[i] > 127)
zbufferLine[i] = depthvalues[i];
}
}
}
else
{
if (OptT::Flags & SWTRI_WriteStencil)
{
for (int i = xstart; i < x; i++)
stencilLine[i] = stencilWriteValue;
}
if (!(OptT::Flags & SWTRI_DepthTest) && (OptT::Flags & SWTRI_WriteDepth))
{
for (int i = xstart; i < x; i++)
{
zbufferLine[i] = depthvalues[i];
}
}
}
}
@ -841,6 +890,7 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyT
const uint32_t *texPixels, *translation;
uint32_t fillcolor;
int actoralpha;
uint8_t *alphatestbuf;
uint32_t *texel = thread->texel;
int32_t *texelV = thread->texelV;
@ -891,6 +941,11 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyT
_fuzzpos = swrenderer::fuzzpos;
}
if (ModeT::SWFlags & SWSTYLEF_AlphaTest)
{
alphatestbuf = thread->alphatestbuffer;
}
uint32_t *dest = (uint32_t*)thread->dest;
uint32_t *destLine = dest + thread->dest_pitch * y;
@ -904,7 +959,8 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyT
!(ModeT::Flags & STYLEF_RedIsAlpha) &&
!(ModeT::SWFlags & SWSTYLEF_Skycap) &&
!(ModeT::SWFlags & SWSTYLEF_FogBoundary) &&
!(ModeT::SWFlags & SWSTYLEF_Fill))
!(ModeT::SWFlags & SWSTYLEF_Fill) &&
!(ModeT::SWFlags & SWSTYLEF_AlphaTest))
{
sseend += (x1 - x0) / 2 * 2;
@ -1064,6 +1120,11 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyT
fgalpha = (fgalpha * actoralpha) >> 8;
}
if (ModeT::SWFlags & SWSTYLEF_AlphaTest)
{
alphatestbuf[x] = fgalpha;
}
uint32_t lightshade;
if (OptT::Flags & SWOPT_FixedLight)
{
@ -1591,536 +1652,6 @@ void DrawSpan8(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTrian
}
}
#if 0
template<typename ModeT>
void DrawRect8(const void *destOrg, int destWidth, int destHeight, int destPitch, const RectDrawArgs *args, PolyTriangleThreadData *thread)
{
using namespace TriScreenDrawerModes;
int x0 = clamp((int)(args->X0() + 0.5f), 0, destWidth);
int x1 = clamp((int)(args->X1() + 0.5f), 0, destWidth);
int y0 = clamp((int)(args->Y0() + 0.5f), 0, destHeight);
int y1 = clamp((int)(args->Y1() + 0.5f), 0, destHeight);
if (x1 <= x0 || y1 <= y0)
return;
const uint8_t *colormaps, *texPixels, *translation;
int texWidth, texHeight;
uint32_t fillcolor;
int alpha;
uint32_t light;
texPixels = args->TexturePixels();
translation = args->Translation();
texWidth = args->TextureWidth();
texHeight = args->TextureHeight();
fillcolor = args->Color();
alpha = args->Alpha();
colormaps = args->BaseColormap();
light = args->Light();
light += light >> 7; // 255 -> 256
light = ((256 - light) * NUMCOLORMAPS) & 0xffffff00;
fixed_t fuzzscale;
int _fuzzpos;
if (ModeT::BlendOp == STYLEOP_Fuzz)
{
fuzzscale = (200 << FRACBITS) / thread->dest_height;
_fuzzpos = swrenderer::fuzzpos;
}
float fstepU = (args->U1() - args->U0()) / (args->X1() - args->X0());
float fstepV = (args->V1() - args->V0()) / (args->Y1() - args->Y0());
uint32_t startU = (int32_t)((args->U0() + (x0 + 0.5f - args->X0()) * fstepU) * 0x1000000);
uint32_t startV = (int32_t)((args->V0() + (y0 + 0.5f - args->Y0()) * fstepV) * 0x1000000);
uint32_t stepU = (int32_t)(fstepU * 0x1000000);
uint32_t stepV = (int32_t)(fstepV * 0x1000000);
uint32_t posV = startV;
y1 = MIN(y1, thread->numa_end_y);
int num_cores = thread->num_cores;
int skip = thread->skipped_by_thread(y0);
posV += skip * stepV;
stepV *= num_cores;
for (int y = y0 + skip; y < y1; y += num_cores, posV += stepV)
{
uint8_t *destLine = ((uint8_t*)destOrg) + y * destPitch;
uint32_t posU = startU;
for (int x = x0; x < x1; x++)
{
if (ModeT::BlendOp == STYLEOP_Fuzz)
{
using namespace swrenderer;
uint32_t texelX = (((posU << 8) >> 16) * texWidth) >> 16;
uint32_t texelY = (((posV << 8) >> 16) * texHeight) >> 16;
unsigned int sampleshadeout = (texPixels[texelX * texHeight + texelY] != 0) ? 256 : 0;
int scaled_x = (x * fuzzscale) >> FRACBITS;
int fuzz_x = fuzz_random_x_offset[scaled_x % FUZZ_RANDOM_X_SIZE] + _fuzzpos;
fixed_t fuzzcount = FUZZTABLE << FRACBITS;
fixed_t fuzz = ((fuzz_x << FRACBITS) + y * fuzzscale) % fuzzcount;
unsigned int alpha = fuzzoffset[fuzz >> FRACBITS];
sampleshadeout = (sampleshadeout * alpha) >> 5;
uint32_t a = 256 - sampleshadeout;
uint32_t dest = GPalette.BaseColors[destLine[x]].d;
uint32_t r = (RPART(dest) * a) >> 8;
uint32_t g = (GPART(dest) * a) >> 8;
uint32_t b = (BPART(dest) * a) >> 8;
destLine[x] = RGB256k.All[((r >> 2) << 12) | ((g >> 2) << 6) | (b >> 2)];
}
else
{
int fg = 0;
if (ModeT::SWFlags & SWSTYLEF_Fill)
{
fg = fillcolor;
}
else
{
uint32_t texelX = (((posU << 8) >> 16) * texWidth) >> 16;
uint32_t texelY = (((posV << 8) >> 16) * texHeight) >> 16;
fg = texPixels[texelX * texHeight + texelY];
}
int fgalpha = 255;
if (ModeT::BlendDest == STYLEALPHA_InvSrc)
{
if (fg == 0)
fgalpha = 0;
}
if ((ModeT::Flags & STYLEF_ColorIsFixed) && !(ModeT::SWFlags & SWSTYLEF_Fill))
{
if (ModeT::Flags & STYLEF_RedIsAlpha)
fgalpha = fg;
fg = fillcolor;
}
if (!(ModeT::Flags & STYLEF_Alpha1))
{
fgalpha = (fgalpha * alpha) >> 8;
}
if (ModeT::SWFlags & SWSTYLEF_Translated)
fg = translation[fg];
uint8_t shadedfg = colormaps[light + fg];
if (ModeT::BlendSrc == STYLEALPHA_One && ModeT::BlendDest == STYLEALPHA_Zero)
{
destLine[x] = shadedfg;
}
else if (ModeT::BlendSrc == STYLEALPHA_One && ModeT::BlendDest == STYLEALPHA_One)
{
uint32_t src = GPalette.BaseColors[shadedfg];
uint32_t dest = GPalette.BaseColors[destLine[x]];
if (ModeT::BlendOp == STYLEOP_Add)
{
uint32_t out_r = MIN<uint32_t>(RPART(dest) + RPART(src), 255);
uint32_t out_g = MIN<uint32_t>(GPART(dest) + GPART(src), 255);
uint32_t out_b = MIN<uint32_t>(BPART(dest) + BPART(src), 255);
destLine[x] = RGB256k.All[((out_r >> 2) << 12) | ((out_g >> 2) << 6) | (out_b >> 2)];
}
else if (ModeT::BlendOp == STYLEOP_RevSub)
{
uint32_t out_r = MAX<uint32_t>(RPART(dest) - RPART(src), 0);
uint32_t out_g = MAX<uint32_t>(GPART(dest) - GPART(src), 0);
uint32_t out_b = MAX<uint32_t>(BPART(dest) - BPART(src), 0);
destLine[x] = RGB256k.All[((out_r >> 2) << 12) | ((out_g >> 2) << 6) | (out_b >> 2)];
}
else //if (ModeT::BlendOp == STYLEOP_Sub)
{
uint32_t out_r = MAX<uint32_t>(RPART(src) - RPART(dest), 0);
uint32_t out_g = MAX<uint32_t>(GPART(src) - GPART(dest), 0);
uint32_t out_b = MAX<uint32_t>(BPART(src) - BPART(dest), 0);
destLine[x] = RGB256k.All[((out_r >> 2) << 12) | ((out_g >> 2) << 6) | (out_b >> 2)];
}
}
else if (ModeT::SWFlags & SWSTYLEF_SrcColorOneMinusSrcColor)
{
uint32_t src = GPalette.BaseColors[shadedfg];
uint32_t dest = GPalette.BaseColors[destLine[x]];
uint32_t sfactor_r = RPART(src); sfactor_r += sfactor_r >> 7; // 255 -> 256
uint32_t sfactor_g = GPART(src); sfactor_g += sfactor_g >> 7; // 255 -> 256
uint32_t sfactor_b = BPART(src); sfactor_b += sfactor_b >> 7; // 255 -> 256
uint32_t sfactor_a = fgalpha; sfactor_a += sfactor_a >> 7; // 255 -> 256
uint32_t dfactor_r = 256 - sfactor_r;
uint32_t dfactor_g = 256 - sfactor_g;
uint32_t dfactor_b = 256 - sfactor_b;
uint32_t out_r = (RPART(dest) * dfactor_r + RPART(src) * sfactor_r + 128) >> 8;
uint32_t out_g = (GPART(dest) * dfactor_g + GPART(src) * sfactor_g + 128) >> 8;
uint32_t out_b = (BPART(dest) * dfactor_b + BPART(src) * sfactor_b + 128) >> 8;
destLine[x] = RGB256k.All[((out_r >> 2) << 12) | ((out_g >> 2) << 6) | (out_b >> 2)];
}
else if (ModeT::BlendSrc == STYLEALPHA_Src && ModeT::BlendDest == STYLEALPHA_InvSrc && fgalpha == 255)
{
destLine[x] = shadedfg;
}
else if (ModeT::BlendSrc != STYLEALPHA_Src || ModeT::BlendDest != STYLEALPHA_InvSrc || fgalpha != 0)
{
uint32_t src = GPalette.BaseColors[shadedfg];
uint32_t dest = GPalette.BaseColors[destLine[x]];
uint32_t sfactor = fgalpha; sfactor += sfactor >> 7; // 255 -> 256
uint32_t dfactor = 256 - sfactor;
uint32_t src_r = RPART(src) * sfactor;
uint32_t src_g = GPART(src) * sfactor;
uint32_t src_b = BPART(src) * sfactor;
uint32_t dest_r = RPART(dest);
uint32_t dest_g = GPART(dest);
uint32_t dest_b = BPART(dest);
if (ModeT::BlendDest == STYLEALPHA_One)
{
dest_r <<= 8;
dest_g <<= 8;
dest_b <<= 8;
}
else
{
uint32_t dfactor = 256 - sfactor;
dest_r *= dfactor;
dest_g *= dfactor;
dest_b *= dfactor;
}
uint32_t out_r, out_g, out_b;
if (ModeT::BlendOp == STYLEOP_Add)
{
if (ModeT::BlendDest == STYLEALPHA_One)
{
out_r = MIN<int32_t>((dest_r + src_r + 128) >> 8, 255);
out_g = MIN<int32_t>((dest_g + src_g + 128) >> 8, 255);
out_b = MIN<int32_t>((dest_b + src_b + 128) >> 8, 255);
}
else
{
out_r = (dest_r + src_r + 128) >> 8;
out_g = (dest_g + src_g + 128) >> 8;
out_b = (dest_b + src_b + 128) >> 8;
}
}
else if (ModeT::BlendOp == STYLEOP_RevSub)
{
out_r = MAX<int32_t>(static_cast<int32_t>(dest_r - src_r + 128) >> 8, 0);
out_g = MAX<int32_t>(static_cast<int32_t>(dest_g - src_g + 128) >> 8, 0);
out_b = MAX<int32_t>(static_cast<int32_t>(dest_b - src_b + 128) >> 8, 0);
}
else //if (ModeT::BlendOp == STYLEOP_Sub)
{
out_r = MAX<int32_t>(static_cast<int32_t>(src_r - dest_r + 128) >> 8, 0);
out_g = MAX<int32_t>(static_cast<int32_t>(src_g - dest_g + 128) >> 8, 0);
out_b = MAX<int32_t>(static_cast<int32_t>(src_b - dest_b + 128) >> 8, 0);
}
destLine[x] = RGB256k.All[((out_r >> 2) << 12) | ((out_g >> 2) << 6) | (out_b >> 2)];
}
}
posU += stepU;
}
}
}
template<typename ModeT, typename OptT>
void DrawRectOpt32(const void *destOrg, int destWidth, int destHeight, int destPitch, const RectDrawArgs *args, PolyTriangleThreadData *thread)
{
using namespace TriScreenDrawerModes;
int x0 = clamp((int)(args->X0() + 0.5f), 0, destWidth);
int x1 = clamp((int)(args->X1() + 0.5f), 0, destWidth);
int y0 = clamp((int)(args->Y0() + 0.5f), 0, destHeight);
int y1 = clamp((int)(args->Y1() + 0.5f), 0, destHeight);
if (x1 <= x0 || y1 <= y0)
return;
const uint32_t *texPixels, *translation;
int texWidth, texHeight;
uint32_t fillcolor;
int alpha;
uint32_t light;
uint32_t shade_fade_r, shade_fade_g, shade_fade_b, shade_light_r, shade_light_g, shade_light_b, desaturate, inv_desaturate;
texPixels = (const uint32_t*)args->TexturePixels();
translation = (const uint32_t*)args->Translation();
texWidth = args->TextureWidth();
texHeight = args->TextureHeight();
fillcolor = args->Color();
alpha = args->Alpha();
light = args->Light();
light += light >> 7; // 255 -> 256
if (OptT::Flags & SWOPT_ColoredFog)
{
shade_fade_r = args->ShadeFadeRed();
shade_fade_g = args->ShadeFadeGreen();
shade_fade_b = args->ShadeFadeBlue();
shade_light_r = args->ShadeLightRed();
shade_light_g = args->ShadeLightGreen();
shade_light_b = args->ShadeLightBlue();
desaturate = args->ShadeDesaturate();
inv_desaturate = 256 - desaturate;
}
fixed_t fuzzscale;
int _fuzzpos;
if (ModeT::BlendOp == STYLEOP_Fuzz)
{
fuzzscale = (200 << FRACBITS) / thread->dest_height;
_fuzzpos = swrenderer::fuzzpos;
}
float fstepU = (args->U1() - args->U0()) / (args->X1() - args->X0());
float fstepV = (args->V1() - args->V0()) / (args->Y1() - args->Y0());
uint32_t startU = (int32_t)((args->U0() + (x0 + 0.5f - args->X0()) * fstepU) * 0x1000000);
uint32_t startV = (int32_t)((args->V0() + (y0 + 0.5f - args->Y0()) * fstepV) * 0x1000000);
uint32_t stepU = (int32_t)(fstepU * 0x1000000);
uint32_t stepV = (int32_t)(fstepV * 0x1000000);
uint32_t posV = startV;
y1 = MIN(y1, thread->numa_end_y);
int num_cores = thread->num_cores;
int skip = thread->skipped_by_thread(y0);
posV += skip * stepV;
stepV *= num_cores;
for (int y = y0 + skip; y < y1; y += num_cores, posV += stepV)
{
uint32_t *destLine = ((uint32_t*)destOrg) + y * destPitch;
uint32_t posU = startU;
for (int x = x0; x < x1; x++)
{
if (ModeT::BlendOp == STYLEOP_Fuzz)
{
using namespace swrenderer;
uint32_t texelX = (((posU << 8) >> 16) * texWidth) >> 16;
uint32_t texelY = (((posV << 8) >> 16) * texHeight) >> 16;
unsigned int sampleshadeout = APART(texPixels[texelX * texHeight + texelY]);
sampleshadeout += sampleshadeout >> 7; // 255 -> 256
int scaled_x = (x * fuzzscale) >> FRACBITS;
int fuzz_x = fuzz_random_x_offset[scaled_x % FUZZ_RANDOM_X_SIZE] + _fuzzpos;
fixed_t fuzzcount = FUZZTABLE << FRACBITS;
fixed_t fuzz = ((fuzz_x << FRACBITS) + y * fuzzscale) % fuzzcount;
unsigned int alpha = fuzzoffset[fuzz >> FRACBITS];
sampleshadeout = (sampleshadeout * alpha) >> 5;
uint32_t a = 256 - sampleshadeout;
uint32_t dest = destLine[x];
uint32_t out_r = (RPART(dest) * a) >> 8;
uint32_t out_g = (GPART(dest) * a) >> 8;
uint32_t out_b = (BPART(dest) * a) >> 8;
destLine[x] = MAKEARGB(255, out_r, out_g, out_b);
}
else
{
uint32_t fg = 0;
if (ModeT::SWFlags & SWSTYLEF_Fill)
{
fg = fillcolor;
}
else if (ModeT::SWFlags & SWSTYLEF_FogBoundary)
{
fg = destLine[x];
}
else
{
uint32_t texelX = (((posU << 8) >> 16) * texWidth) >> 16;
uint32_t texelY = (((posV << 8) >> 16) * texHeight) >> 16;
if (ModeT::SWFlags & SWSTYLEF_Translated)
{
fg = translation[((const uint8_t*)texPixels)[texelX * texHeight + texelY]];
}
else if (ModeT::Flags & STYLEF_RedIsAlpha)
{
fg = ((const uint8_t*)texPixels)[texelX * texHeight + texelY];
}
else
{
fg = texPixels[texelX * texHeight + texelY];
}
}
if ((ModeT::Flags & STYLEF_ColorIsFixed) && !(ModeT::SWFlags & SWSTYLEF_Fill))
{
if (ModeT::Flags & STYLEF_RedIsAlpha)
fg = (fg << 24) | (fillcolor & 0x00ffffff);
else
fg = (fg & 0xff000000) | (fillcolor & 0x00ffffff);
}
uint32_t fgalpha = fg >> 24;
if (!(ModeT::Flags & STYLEF_Alpha1))
{
fgalpha = (fgalpha * alpha) >> 8;
}
int lightshade = light;
uint32_t lit_r = 0, lit_g = 0, lit_b = 0;
uint32_t shadedfg_r, shadedfg_g, shadedfg_b;
if (OptT::Flags & SWOPT_ColoredFog)
{
uint32_t fg_r = RPART(fg);
uint32_t fg_g = GPART(fg);
uint32_t fg_b = BPART(fg);
uint32_t intensity = ((fg_r * 77 + fg_g * 143 + fg_b * 37) >> 8) * desaturate;
shadedfg_r = (((shade_fade_r + ((fg_r * inv_desaturate + intensity) >> 8) * lightshade) >> 8) * shade_light_r) >> 8;
shadedfg_g = (((shade_fade_g + ((fg_g * inv_desaturate + intensity) >> 8) * lightshade) >> 8) * shade_light_g) >> 8;
shadedfg_b = (((shade_fade_b + ((fg_b * inv_desaturate + intensity) >> 8) * lightshade) >> 8) * shade_light_b) >> 8;
}
else
{
shadedfg_r = (RPART(fg) * lightshade) >> 8;
shadedfg_g = (GPART(fg) * lightshade) >> 8;
shadedfg_b = (BPART(fg) * lightshade) >> 8;
}
if (ModeT::BlendSrc == STYLEALPHA_One && ModeT::BlendDest == STYLEALPHA_Zero)
{
destLine[x] = MAKEARGB(255, shadedfg_r, shadedfg_g, shadedfg_b);
}
else if (ModeT::BlendSrc == STYLEALPHA_One && ModeT::BlendDest == STYLEALPHA_One)
{
uint32_t dest = destLine[x];
if (ModeT::BlendOp == STYLEOP_Add)
{
uint32_t out_r = MIN<uint32_t>(RPART(dest) + shadedfg_r, 255);
uint32_t out_g = MIN<uint32_t>(GPART(dest) + shadedfg_g, 255);
uint32_t out_b = MIN<uint32_t>(BPART(dest) + shadedfg_b, 255);
destLine[x] = MAKEARGB(255, out_r, out_g, out_b);
}
else if (ModeT::BlendOp == STYLEOP_RevSub)
{
uint32_t out_r = MAX<uint32_t>(RPART(dest) - shadedfg_r, 0);
uint32_t out_g = MAX<uint32_t>(GPART(dest) - shadedfg_g, 0);
uint32_t out_b = MAX<uint32_t>(BPART(dest) - shadedfg_b, 0);
destLine[x] = MAKEARGB(255, out_r, out_g, out_b);
}
else //if (ModeT::BlendOp == STYLEOP_Sub)
{
uint32_t out_r = MAX<uint32_t>(shadedfg_r - RPART(dest), 0);
uint32_t out_g = MAX<uint32_t>(shadedfg_g - GPART(dest), 0);
uint32_t out_b = MAX<uint32_t>(shadedfg_b - BPART(dest), 0);
destLine[x] = MAKEARGB(255, out_r, out_g, out_b);
}
}
else if (ModeT::SWFlags & SWSTYLEF_SrcColorOneMinusSrcColor)
{
uint32_t dest = destLine[x];
uint32_t sfactor_r = shadedfg_r; sfactor_r += sfactor_r >> 7; // 255 -> 256
uint32_t sfactor_g = shadedfg_g; sfactor_g += sfactor_g >> 7; // 255 -> 256
uint32_t sfactor_b = shadedfg_b; sfactor_b += sfactor_b >> 7; // 255 -> 256
uint32_t sfactor_a = fgalpha; sfactor_a += sfactor_a >> 7; // 255 -> 256
uint32_t dfactor_r = 256 - sfactor_r;
uint32_t dfactor_g = 256 - sfactor_g;
uint32_t dfactor_b = 256 - sfactor_b;
uint32_t out_r = (RPART(dest) * dfactor_r + shadedfg_r * sfactor_r + 128) >> 8;
uint32_t out_g = (GPART(dest) * dfactor_g + shadedfg_g * sfactor_g + 128) >> 8;
uint32_t out_b = (BPART(dest) * dfactor_b + shadedfg_b * sfactor_b + 128) >> 8;
destLine[x] = MAKEARGB(255, out_r, out_g, out_b);
}
else if (ModeT::BlendSrc == STYLEALPHA_Src && ModeT::BlendDest == STYLEALPHA_InvSrc && fgalpha == 255)
{
destLine[x] = MAKEARGB(255, shadedfg_r, shadedfg_g, shadedfg_b);
}
else if (ModeT::BlendSrc != STYLEALPHA_Src || ModeT::BlendDest != STYLEALPHA_InvSrc || fgalpha != 0)
{
uint32_t dest = destLine[x];
uint32_t sfactor = fgalpha; sfactor += sfactor >> 7; // 255 -> 256
uint32_t src_r = shadedfg_r * sfactor;
uint32_t src_g = shadedfg_g * sfactor;
uint32_t src_b = shadedfg_b * sfactor;
uint32_t dest_r = RPART(dest);
uint32_t dest_g = GPART(dest);
uint32_t dest_b = BPART(dest);
if (ModeT::BlendDest == STYLEALPHA_One)
{
dest_r <<= 8;
dest_g <<= 8;
dest_b <<= 8;
}
else
{
uint32_t dfactor = 256 - sfactor;
dest_r *= dfactor;
dest_g *= dfactor;
dest_b *= dfactor;
}
uint32_t out_r, out_g, out_b;
if (ModeT::BlendOp == STYLEOP_Add)
{
if (ModeT::BlendDest == STYLEALPHA_One)
{
out_r = MIN<int32_t>((dest_r + src_r + 128) >> 8, 255);
out_g = MIN<int32_t>((dest_g + src_g + 128) >> 8, 255);
out_b = MIN<int32_t>((dest_b + src_b + 128) >> 8, 255);
}
else
{
out_r = (dest_r + src_r + 128) >> 8;
out_g = (dest_g + src_g + 128) >> 8;
out_b = (dest_b + src_b + 128) >> 8;
}
}
else if (ModeT::BlendOp == STYLEOP_RevSub)
{
out_r = MAX<int32_t>(static_cast<int32_t>(dest_r - src_r + 128) >> 8, 0);
out_g = MAX<int32_t>(static_cast<int32_t>(dest_g - src_g + 128) >> 8, 0);
out_b = MAX<int32_t>(static_cast<int32_t>(dest_b - src_b + 128) >> 8, 0);
}
else //if (ModeT::BlendOp == STYLEOP_Sub)
{
out_r = MAX<int32_t>(static_cast<int32_t>(src_r - dest_r + 128) >> 8, 0);
out_g = MAX<int32_t>(static_cast<int32_t>(src_g - dest_g + 128) >> 8, 0);
out_b = MAX<int32_t>(static_cast<int32_t>(src_b - dest_b + 128) >> 8, 0);
}
destLine[x] = MAKEARGB(255, out_r, out_g, out_b);
}
}
posU += stepU;
}
}
}
template<typename ModeT>
void DrawRect32(const void *destOrg, int destWidth, int destHeight, int destPitch, const RectDrawArgs *args, PolyTriangleThreadData *thread)
{
using namespace TriScreenDrawerModes;
if (args->SimpleShade())
DrawRectOpt32<ModeT, DrawerOptF>(destOrg, destWidth, destHeight, destPitch, args, thread);
else
DrawRectOpt32<ModeT, DrawerOptCF>(destOrg, destWidth, destHeight, destPitch, args, thread);
}
#endif
void(*ScreenTriangle::SpanDrawers8[])(int, int, int, const TriDrawTriangleArgs *, PolyTriangleThreadData *) =
{
&DrawSpan8<TriScreenDrawerModes::StyleOpaque>,
@ -2130,6 +1661,7 @@ void(*ScreenTriangle::SpanDrawers8[])(int, int, int, const TriDrawTriangleArgs *
&DrawSpan8<TriScreenDrawerModes::StyleFill>,
&DrawSpan8<TriScreenDrawerModes::StyleFillTranslucent>,
&DrawSpan8<TriScreenDrawerModes::StyleNormal>,
&DrawSpan8<TriScreenDrawerModes::StyleAlphaTest>,
&DrawSpan8<TriScreenDrawerModes::StyleFuzzy>,
&DrawSpan8<TriScreenDrawerModes::StyleStencil>,
&DrawSpan8<TriScreenDrawerModes::StyleTranslucent>,
@ -2163,6 +1695,7 @@ void(*ScreenTriangle::SpanDrawers32[])(int, int, int, const TriDrawTriangleArgs
&DrawSpan32<TriScreenDrawerModes::StyleFill>,
&DrawSpan32<TriScreenDrawerModes::StyleFillTranslucent>,
&DrawSpan32<TriScreenDrawerModes::StyleNormal>,
&DrawSpan32<TriScreenDrawerModes::StyleAlphaTest>,
&DrawSpan32<TriScreenDrawerModes::StyleFuzzy>,
&DrawSpan32<TriScreenDrawerModes::StyleStencil>,
&DrawSpan32<TriScreenDrawerModes::StyleTranslucent>,
@ -2187,72 +1720,6 @@ void(*ScreenTriangle::SpanDrawers32[])(int, int, int, const TriDrawTriangleArgs
&DrawSpan32<TriScreenDrawerModes::StyleAddShadedTranslated>
};
#if 0
void(*ScreenTriangle::RectDrawers8[])(const void *, int, int, int, const RectDrawArgs *, PolyTriangleThreadData *) =
{
&DrawRect8<TriScreenDrawerModes::StyleOpaque>,
&DrawRect8<TriScreenDrawerModes::StyleSkycap>,
&DrawRect8<TriScreenDrawerModes::StyleFogBoundary>,
&DrawRect8<TriScreenDrawerModes::StyleSrcColor>,
&DrawRect8<TriScreenDrawerModes::StyleFill>,
&DrawRect8<TriScreenDrawerModes::StyleNormal>,
&DrawRect8<TriScreenDrawerModes::StyleFuzzy>,
&DrawRect8<TriScreenDrawerModes::StyleStencil>,
&DrawRect8<TriScreenDrawerModes::StyleTranslucent>,
&DrawRect8<TriScreenDrawerModes::StyleAdd>,
&DrawRect8<TriScreenDrawerModes::StyleShaded>,
&DrawRect8<TriScreenDrawerModes::StyleTranslucentStencil>,
&DrawRect8<TriScreenDrawerModes::StyleShadow>,
&DrawRect8<TriScreenDrawerModes::StyleSubtract>,
&DrawRect8<TriScreenDrawerModes::StyleAddStencil>,
&DrawRect8<TriScreenDrawerModes::StyleAddShaded>,
&DrawRect8<TriScreenDrawerModes::StyleOpaqueTranslated>,
&DrawRect8<TriScreenDrawerModes::StyleSrcColorTranslated>,
&DrawRect8<TriScreenDrawerModes::StyleNormalTranslated>,
&DrawRect8<TriScreenDrawerModes::StyleStencilTranslated>,
&DrawRect8<TriScreenDrawerModes::StyleTranslucentTranslated>,
&DrawRect8<TriScreenDrawerModes::StyleAddTranslated>,
&DrawRect8<TriScreenDrawerModes::StyleShadedTranslated>,
&DrawRect8<TriScreenDrawerModes::StyleTranslucentStencilTranslated>,
&DrawRect8<TriScreenDrawerModes::StyleShadowTranslated>,
&DrawRect8<TriScreenDrawerModes::StyleSubtractTranslated>,
&DrawRect8<TriScreenDrawerModes::StyleAddStencilTranslated>,
&DrawRect8<TriScreenDrawerModes::StyleAddShadedTranslated>
};
void(*ScreenTriangle::RectDrawers32[])(const void *, int, int, int, const RectDrawArgs *, PolyTriangleThreadData *) =
{
&DrawRect32<TriScreenDrawerModes::StyleOpaque>,
&DrawRect32<TriScreenDrawerModes::StyleSkycap>,
&DrawRect32<TriScreenDrawerModes::StyleFogBoundary>,
&DrawRect32<TriScreenDrawerModes::StyleSrcColor>,
&DrawRect32<TriScreenDrawerModes::StyleFill>,
&DrawRect32<TriScreenDrawerModes::StyleNormal>,
&DrawRect32<TriScreenDrawerModes::StyleFuzzy>,
&DrawRect32<TriScreenDrawerModes::StyleStencil>,
&DrawRect32<TriScreenDrawerModes::StyleTranslucent>,
&DrawRect32<TriScreenDrawerModes::StyleAdd>,
&DrawRect32<TriScreenDrawerModes::StyleShaded>,
&DrawRect32<TriScreenDrawerModes::StyleTranslucentStencil>,
&DrawRect32<TriScreenDrawerModes::StyleShadow>,
&DrawRect32<TriScreenDrawerModes::StyleSubtract>,
&DrawRect32<TriScreenDrawerModes::StyleAddStencil>,
&DrawRect32<TriScreenDrawerModes::StyleAddShaded>,
&DrawRect32<TriScreenDrawerModes::StyleOpaqueTranslated>,
&DrawRect32<TriScreenDrawerModes::StyleSrcColorTranslated>,
&DrawRect32<TriScreenDrawerModes::StyleNormalTranslated>,
&DrawRect32<TriScreenDrawerModes::StyleStencilTranslated>,
&DrawRect32<TriScreenDrawerModes::StyleTranslucentTranslated>,
&DrawRect32<TriScreenDrawerModes::StyleAddTranslated>,
&DrawRect32<TriScreenDrawerModes::StyleShadedTranslated>,
&DrawRect32<TriScreenDrawerModes::StyleTranslucentStencilTranslated>,
&DrawRect32<TriScreenDrawerModes::StyleShadowTranslated>,
&DrawRect32<TriScreenDrawerModes::StyleSubtractTranslated>,
&DrawRect32<TriScreenDrawerModes::StyleAddStencilTranslated>,
&DrawRect32<TriScreenDrawerModes::StyleAddShadedTranslated>
};
#endif
void(*ScreenTriangle::TriangleDrawers[])(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread, int16_t *edges, int topY, int bottomY) =
{
&DrawTriangle<TriScreenDrawerModes::TriangleOpt0>,

View file

@ -106,6 +106,7 @@ enum class TriBlendMode
Fill,
FillTranslucent,
Normal,
AlphaTest,
Fuzzy,
Stencil,
Translucent,
@ -139,10 +140,6 @@ public:
static void(*SpanDrawers8[])(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread);
static void(*SpanDrawers32[])(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread);
#if 0
static void(*RectDrawers8[])(const void *, int, int, int, const RectDrawArgs *, PolyTriangleThreadData *);
static void(*RectDrawers32[])(const void *, int, int, int, const RectDrawArgs *, PolyTriangleThreadData *);
#endif
static int FuzzStart;
};
@ -155,7 +152,8 @@ namespace TriScreenDrawerModes
SWSTYLEF_Skycap = 2,
SWSTYLEF_FogBoundary = 4,
SWSTYLEF_Fill = 8,
SWSTYLEF_SrcColorOneMinusSrcColor = 16
SWSTYLEF_SrcColorOneMinusSrcColor = 16,
SWSTYLEF_AlphaTest = 32
};
struct StyleOpaque { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_One, BlendDest = STYLEALPHA_Zero, Flags = STYLEF_Alpha1, SWFlags = 0; };
@ -166,6 +164,7 @@ namespace TriScreenDrawerModes
struct StyleFillTranslucent { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_Alpha1, SWFlags = SWSTYLEF_Fill; };
struct StyleNormal { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_Alpha1, SWFlags = 0; };
struct StyleAlphaTest { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_Alpha1, SWFlags = SWSTYLEF_AlphaTest; };
struct StyleFuzzy { static const int BlendOp = STYLEOP_Fuzz, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = 0, SWFlags = 0; };
struct StyleStencil { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_Alpha1 | STYLEF_ColorIsFixed, SWFlags = 0; };
struct StyleTranslucent { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = 0, SWFlags = 0; };