From d437b342dbb81a3b4efcfb9a9f194e40ee6d1c21 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Tue, 21 Mar 2017 14:12:19 +0100 Subject: [PATCH] - replaced the softpoly drawers with templated versions --- src/CMakeLists.txt | 1 - src/polyrenderer/drawers/poly_drawer32_sse2.h | 649 + src/polyrenderer/drawers/poly_drawer8.h | 366 + src/polyrenderer/drawers/poly_drawers.h | 15414 ---------------- src/polyrenderer/drawers/poly_drawers.php | 449 - src/polyrenderer/drawers/screen_triangle.cpp | 335 +- src/polyrenderer/drawers/screen_triangle.h | 26 + src/polyrenderer/scene/poly_decal.cpp | 2 +- src/polyrenderer/scene/poly_particle.cpp | 4 +- src/polyrenderer/scene/poly_plane.cpp | 4 +- src/polyrenderer/scene/poly_sky.cpp | 2 +- src/polyrenderer/scene/poly_sprite.cpp | 2 +- src/polyrenderer/scene/poly_wall.cpp | 2 +- src/polyrenderer/scene/poly_wallsprite.cpp | 4 +- 14 files changed, 1131 insertions(+), 16129 deletions(-) create mode 100644 src/polyrenderer/drawers/poly_drawer32_sse2.h create mode 100644 src/polyrenderer/drawers/poly_drawer8.h delete mode 100644 src/polyrenderer/drawers/poly_drawers.h delete mode 100644 src/polyrenderer/drawers/poly_drawers.php diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index eaa22b716..1896c3ab8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -784,7 +784,6 @@ file( GLOB HEADER_FILES polyrenderer/*.h polyrenderer/math/*.h polyrenderer/drawers/*.h - polyrenderer/drawers/*.php polyrenderer/scene/*.h gl/*.h gl/api/*.h diff --git a/src/polyrenderer/drawers/poly_drawer32_sse2.h b/src/polyrenderer/drawers/poly_drawer32_sse2.h new file mode 100644 index 000000000..b15b5e47b --- /dev/null +++ b/src/polyrenderer/drawers/poly_drawer32_sse2.h @@ -0,0 +1,649 @@ +/* +** Projected triangle drawer +** Copyright (c) 2016 Magnus Norddahl +** +** This software is provided 'as-is', without any express or implied +** warranty. In no event will the authors be held liable for any damages +** arising from the use of this software. +** +** Permission is granted to anyone to use this software for any purpose, +** including commercial applications, and to alter it and redistribute it +** freely, subject to the following restrictions: +** +** 1. The origin of this software must not be misrepresented; you must not +** claim that you wrote the original software. If you use this software +** in a product, an acknowledgment in the product documentation would be +** appreciated but is not required. +** 2. Altered source versions must be plainly marked as such, and must not be +** misrepresented as being the original software. +** 3. This notice may not be removed or altered from any source distribution. +** +*/ + +#pragma once + +#include "screen_triangle.h" + +template +class TriScreenDrawer32 +{ +public: + static void Execute(const TriDrawTriangleArgs *args, WorkerThreadData *thread) + { + using namespace TriScreenDrawerModes; + + auto flags = args->uniforms->flags; + bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; + + if (SamplerT::Mode == (int)Samplers::Texture) + { + bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; + + if (is_simple_shade) + { + if (is_nearest_filter) + Loop(args, thread); + else + Loop(args, thread); + } + else + { + if (is_nearest_filter) + Loop(args, thread); + else + Loop(args, thread); + } + } + else // no linear filtering for translated, shaded, fill or skycap + { + if (is_simple_shade) + { + Loop(args, thread); + } + else + { + Loop(args, thread); + } + } + } + + template + FORCEINLINE static void VECTORCALL Loop(const TriDrawTriangleArgs *args, WorkerThreadData *thread) + { + using namespace TriScreenDrawerModes; + + int numSpans = thread->NumFullSpans; + auto fullSpans = thread->FullSpans; + int numBlocks = thread->NumPartialBlocks; + auto partialBlocks = thread->PartialBlocks; + int startX = thread->StartX; + int startY = thread->StartY; + + auto flags = args->uniforms->flags; + bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; + uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; + auto colormaps = args->colormaps; + uint32_t srcalpha = args->uniforms->srcalpha; + uint32_t destalpha = args->uniforms->destalpha; + + // Calculate gradients + const TriVertex &v1 = *args->v1; + const TriVertex &v2 = *args->v2; + const TriVertex &v3 = *args->v3; + ScreenTriangleStepVariables gradientX; + ScreenTriangleStepVariables gradientY; + ScreenTriangleStepVariables start; + gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); + gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); + start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); + for (int i = 0; i < TriVertex::NumVarying; i++) + { + gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); + gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); + start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); + } + + // Output + uint32_t * RESTRICT destOrg = (uint32_t*)args->dest; + int pitch = args->pitch; + + // Light + uint32_t light = args->uniforms->light; + float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; + float globVis = args->uniforms->globvis * (1.0f / 32.0f); + + // Sampling stuff + uint32_t color = args->uniforms->color; + const uint32_t * RESTRICT translation = (const uint32_t *)args->translation; + const uint32_t * RESTRICT texPixels = (const uint32_t *)args->texturePixels; + uint32_t texWidth = args->textureWidth; + uint32_t texHeight = args->textureHeight; + uint32_t oneU, oneV; + if (SamplerT::Mode != (int)Samplers::Fill) + { + oneU = ((0x800000 + texWidth - 1) / texWidth) * 2 + 1; + oneV = ((0x800000 + texHeight - 1) / texHeight) * 2 + 1; + } + else + { + oneU = 0; + oneV = 0; + } + + // Shade constants + __m128i inv_desaturate, shade_fade, shade_light; + int desaturate; + if (ShadeModeT::Mode == (int)ShadeMode::Advanced) + { + inv_desaturate = _mm_setr_epi16(256, 256 - args->uniforms->desaturate, 256 - args->uniforms->desaturate, 256 - args->uniforms->desaturate, 256, 256 - args->uniforms->desaturate, 256 - args->uniforms->desaturate, 256 - args->uniforms->desaturate); + shade_fade = _mm_set_epi16(args->uniforms->fade_alpha, args->uniforms->fade_red, args->uniforms->fade_green, args->uniforms->fade_blue, args->uniforms->fade_alpha, args->uniforms->fade_red, args->uniforms->fade_green, args->uniforms->fade_blue); + shade_light = _mm_set_epi16(args->uniforms->light_alpha, args->uniforms->light_red, args->uniforms->light_green, args->uniforms->light_blue, args->uniforms->light_alpha, args->uniforms->light_red, args->uniforms->light_green, args->uniforms->light_blue); + desaturate = args->uniforms->desaturate; + } + else + { + inv_desaturate = _mm_setzero_si128(); + shade_fade = _mm_setzero_si128(); + shade_fade = _mm_setzero_si128(); + shade_light = _mm_setzero_si128(); + desaturate = 0; + } + + for (int i = 0; i < numSpans; i++) + { + const auto &span = fullSpans[i]; + + uint32_t *dest = destOrg + span.X + span.Y * pitch; + int width = span.Length; + int height = 8; + + ScreenTriangleStepVariables blockPosY; + blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); + for (int j = 0; j < TriVertex::NumVarying; j++) + blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); + + for (int y = 0; y < height; y++) + { + ScreenTriangleStepVariables blockPosX = blockPosY; + + float rcpW = 0x01000000 / blockPosX.W; + int32_t varyingPos[TriVertex::NumVarying]; + for (int j = 0; j < TriVertex::NumVarying; j++) + varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); + + fixed_t lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); + lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); + + for (int x = 0; x < width; x++) + { + blockPosX.W += gradientX.W * 8; + for (int j = 0; j < TriVertex::NumVarying; j++) + blockPosX.Varying[j] += gradientX.Varying[j] * 8; + + rcpW = 0x01000000 / blockPosX.W; + int32_t varyingStep[TriVertex::NumVarying]; + for (int j = 0; j < TriVertex::NumVarying; j++) + { + int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); + varyingStep[j] = (nextPos - varyingPos[j]) / 8; + } + + fixed_t lightnext = FRACUNIT - (fixed_t)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); + fixed_t lightstep = (lightnext - lightpos) / 8; + lightstep = lightstep & lightmask; + + for (int ix = 0; ix < 4; ix++) + { + // Load bgcolor + __m128i bgcolor; + if (BlendT::Mode != (int)BlendModes::Opaque) + bgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(dest + x * 8 + ix * 2)), _mm_setzero_si128()); + else + bgcolor = _mm_setzero_si128(); + + // Sample fgcolor + unsigned int ifgcolor[2]; + ifgcolor[0] = Sample(varyingPos[0], varyingPos[1], texPixels, texWidth, texHeight, oneU, oneV, color, translation); + for (int j = 0; j < TriVertex::NumVarying; j++) + varyingPos[j] += varyingStep[j]; + + ifgcolor[1] = Sample(varyingPos[0], varyingPos[1], texPixels, texWidth, texHeight, oneU, oneV, color, translation); + for (int j = 0; j < TriVertex::NumVarying; j++) + varyingPos[j] += varyingStep[j]; + + // Setup light + int lightpos0 = lightpos >> 8; + lightpos += lightstep; + int lightpos1 = lightpos >> 8; + lightpos += lightstep; + __m128i mlight = _mm_set_epi16(256, lightpos1, lightpos1, lightpos1, 256, lightpos0, lightpos0, lightpos0); + + __m128i shade_fade_lit; + if (ShadeModeT::Mode == (int)ShadeMode::Advanced) + { + __m128i inv_light = _mm_sub_epi16(_mm_set_epi16(0, 256, 256, 256, 0, 256, 256, 256), mlight); + shade_fade_lit = _mm_mullo_epi16(shade_fade, inv_light); + } + else + { + shade_fade_lit = _mm_setzero_si128(); + } + + // Shade and blend + __m128i fgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)ifgcolor), _mm_setzero_si128()); + fgcolor = Shade(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light); + __m128i outcolor = Blend(fgcolor, bgcolor, ifgcolor[0], ifgcolor[1], srcalpha, destalpha); + + // Store result + _mm_storel_epi64((__m128i*)(dest + x * 8 + ix * 2), outcolor); + } + } + + blockPosY.W += gradientY.W; + for (int j = 0; j < TriVertex::NumVarying; j++) + blockPosY.Varying[j] += gradientY.Varying[j]; + + dest += pitch; + } + } + + for (int i = 0; i < numBlocks; i++) + { + const auto &block = partialBlocks[i]; + + ScreenTriangleStepVariables blockPosY; + blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); + for (int j = 0; j < TriVertex::NumVarying; j++) + blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); + + uint32_t *dest = destOrg + block.X + block.Y * pitch; + uint32_t mask0 = block.Mask0; + uint32_t mask1 = block.Mask1; + + // mask0 loop: + for (int y = 0; y < 4; y++) + { + ScreenTriangleStepVariables blockPosX = blockPosY; + + float rcpW = 0x01000000 / blockPosX.W; + int32_t varyingPos[TriVertex::NumVarying]; + for (int j = 0; j < TriVertex::NumVarying; j++) + varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); + + fixed_t lightpos = FRACUNIT - (fixed_t)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); + lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); + + blockPosX.W += gradientX.W * 8; + for (int j = 0; j < TriVertex::NumVarying; j++) + blockPosX.Varying[j] += gradientX.Varying[j] * 8; + + rcpW = 0x01000000 / blockPosX.W; + int32_t varyingStep[TriVertex::NumVarying]; + for (int j = 0; j < TriVertex::NumVarying; j++) + { + int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); + varyingStep[j] = (nextPos - varyingPos[j]) / 8; + } + + fixed_t lightnext = FRACUNIT - (fixed_t)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); + fixed_t lightstep = (lightnext - lightpos) / 8; + lightstep = lightstep & lightmask; + + for (int x = 0; x < 4; x++) + { + // Load bgcolor + uint32_t desttmp[2]; + if (mask0 & (1 << 31)) desttmp[0] = dest[x * 2]; + if (mask0 & (1 << 30)) desttmp[1] = dest[x * 2 + 1]; + + __m128i bgcolor; + if (BlendT::Mode != (int)BlendModes::Opaque) + bgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)desttmp), _mm_setzero_si128()); + else + bgcolor = _mm_setzero_si128(); + + // Sample fgcolor + unsigned int ifgcolor[2]; + ifgcolor[0] = Sample(varyingPos[0], varyingPos[1], texPixels, texWidth, texHeight, oneU, oneV, color, translation); + for (int j = 0; j < TriVertex::NumVarying; j++) + varyingPos[j] += varyingStep[j]; + + ifgcolor[1] = Sample(varyingPos[0], varyingPos[1], texPixels, texWidth, texHeight, oneU, oneV, color, translation); + for (int j = 0; j < TriVertex::NumVarying; j++) + varyingPos[j] += varyingStep[j]; + + // Setup light + int lightpos0 = lightpos >> 8; + lightpos += lightstep; + int lightpos1 = lightpos >> 8; + lightpos += lightstep; + __m128i mlight = _mm_set_epi16(256, lightpos1, lightpos1, lightpos1, 256, lightpos0, lightpos0, lightpos0); + + __m128i shade_fade_lit; + if (ShadeModeT::Mode == (int)ShadeMode::Advanced) + { + __m128i inv_light = _mm_sub_epi16(_mm_set_epi16(0, 256, 256, 256, 0, 256, 256, 256), mlight); + shade_fade_lit = _mm_mullo_epi16(shade_fade, inv_light); + } + else + { + shade_fade_lit = _mm_setzero_si128(); + } + + // Shade and blend + __m128i fgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)ifgcolor), _mm_setzero_si128()); + fgcolor = Shade(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light); + __m128i outcolor = Blend(fgcolor, bgcolor, ifgcolor[0], ifgcolor[1], srcalpha, destalpha); + + // Store result + _mm_storel_epi64((__m128i*)desttmp, outcolor); + if (mask0 & (1 << 31)) dest[x * 2] = desttmp[0]; + if (mask0 & (1 << 30)) dest[x * 2 + 1] = desttmp[1]; + + mask0 <<= 2; + } + + blockPosY.W += gradientY.W; + for (int j = 0; j < TriVertex::NumVarying; j++) + blockPosY.Varying[j] += gradientY.Varying[j]; + + dest += pitch; + } + + // mask1 loop: + for (int y = 0; y < 4; y++) + { + ScreenTriangleStepVariables blockPosX = blockPosY; + + float rcpW = 0x01000000 / blockPosX.W; + int32_t varyingPos[TriVertex::NumVarying]; + for (int j = 0; j < TriVertex::NumVarying; j++) + varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); + + fixed_t lightpos = FRACUNIT - (fixed_t)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); + lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); + + blockPosX.W += gradientX.W * 8; + for (int j = 0; j < TriVertex::NumVarying; j++) + blockPosX.Varying[j] += gradientX.Varying[j] * 8; + + rcpW = 0x01000000 / blockPosX.W; + int32_t varyingStep[TriVertex::NumVarying]; + for (int j = 0; j < TriVertex::NumVarying; j++) + { + int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); + varyingStep[j] = (nextPos - varyingPos[j]) / 8; + } + + fixed_t lightnext = FRACUNIT - (fixed_t)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); + fixed_t lightstep = (lightnext - lightpos) / 8; + lightstep = lightstep & lightmask; + + for (int x = 0; x < 4; x++) + { + // Load bgcolor + uint32_t desttmp[2]; + if (mask1 & (1 << 31)) desttmp[0] = dest[x * 2]; + if (mask1 & (1 << 30)) desttmp[1] = dest[x * 2 + 1]; + + __m128i bgcolor; + if (BlendT::Mode != (int)BlendModes::Opaque) + bgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)desttmp), _mm_setzero_si128()); + else + bgcolor = _mm_setzero_si128(); + + // Sample fgcolor + unsigned int ifgcolor[2]; + ifgcolor[0] = Sample(varyingPos[0], varyingPos[1], texPixels, texWidth, texHeight, oneU, oneV, color, translation); + for (int j = 0; j < TriVertex::NumVarying; j++) + varyingPos[j] += varyingStep[j]; + + ifgcolor[1] = Sample(varyingPos[0], varyingPos[1], texPixels, texWidth, texHeight, oneU, oneV, color, translation); + for (int j = 0; j < TriVertex::NumVarying; j++) + varyingPos[j] += varyingStep[j]; + + // Setup light + int lightpos0 = lightpos >> 8; + lightpos += lightstep; + int lightpos1 = lightpos >> 8; + lightpos += lightstep; + __m128i mlight = _mm_set_epi16(256, lightpos1, lightpos1, lightpos1, 256, lightpos0, lightpos0, lightpos0); + + __m128i shade_fade_lit; + if (ShadeModeT::Mode == (int)ShadeMode::Advanced) + { + __m128i inv_light = _mm_sub_epi16(_mm_set_epi16(0, 256, 256, 256, 0, 256, 256, 256), mlight); + shade_fade_lit = _mm_mullo_epi16(shade_fade, inv_light); + } + else + { + shade_fade_lit = _mm_setzero_si128(); + } + + // Shade and blend + __m128i fgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)ifgcolor), _mm_setzero_si128()); + fgcolor = Shade(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light); + __m128i outcolor = Blend(fgcolor, bgcolor, ifgcolor[0], ifgcolor[1], srcalpha, destalpha); + + // Store result + _mm_storel_epi64((__m128i*)desttmp, outcolor); + if (mask1 & (1 << 31)) dest[x * 2] = desttmp[0]; + if (mask1 & (1 << 30)) dest[x * 2 + 1] = desttmp[1]; + + mask1 <<= 2; + } + + blockPosY.W += gradientY.W; + for (int j = 0; j < TriVertex::NumVarying; j++) + blockPosY.Varying[j] += gradientY.Varying[j]; + + dest += pitch; + } + } + } + +private: + template + FORCEINLINE static unsigned int VECTORCALL Sample(int32_t u, int32_t v, const uint32_t *texPixels, int texWidth, int texHeight, uint32_t oneU, uint32_t oneV, uint32_t color, const uint32_t *translation) + { + using namespace TriScreenDrawerModes; + + uint32_t texel; + if (SamplerT::Mode == (int)Samplers::Shaded || SamplerT::Mode == (int)Samplers::Fill) + { + return color; + } + else if (SamplerT::Mode == (int)Samplers::Translated) + { + const uint8_t *texpal = (const uint8_t *)texPixels; + uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16; + uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; + return translation[texpal[texelX * texHeight + texelY]]; + } + else if (FilterModeT::Mode == (int)FilterModes::Nearest) + { + uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16; + uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; + texel = texPixels[texelX * texHeight + texelY]; + } + else + { + u -= oneU >> 1; + v -= oneV >> 1; + + unsigned int frac_x0 = (((uint32_t)u << 8) >> FRACBITS) * texWidth; + unsigned int frac_x1 = ((((uint32_t)u << 8) + oneU) >> FRACBITS) * texWidth; + unsigned int frac_y0 = (((uint32_t)v << 8) >> FRACBITS) * texHeight; + unsigned int frac_y1 = ((((uint32_t)v << 8) + oneV) >> FRACBITS) * texHeight; + unsigned int x0 = frac_x0 >> FRACBITS; + unsigned int x1 = frac_x1 >> FRACBITS; + unsigned int y0 = frac_y0 >> FRACBITS; + unsigned int y1 = frac_y1 >> FRACBITS; + + unsigned int p00 = texPixels[x0 * texHeight + y0]; + unsigned int p01 = texPixels[x0 * texHeight + y1]; + unsigned int p10 = texPixels[x1 * texHeight + y0]; + unsigned int p11 = texPixels[x1 * texHeight + y1]; + + unsigned int inv_a = (frac_x1 >> (FRACBITS - 4)) & 15; + unsigned int inv_b = (frac_y1 >> (FRACBITS - 4)) & 15; + unsigned int a = 16 - inv_a; + unsigned int b = 16 - inv_b; + + unsigned int sred = (RPART(p00) * (a * b) + RPART(p01) * (inv_a * b) + RPART(p10) * (a * inv_b) + RPART(p11) * (inv_a * inv_b) + 127) >> 8; + unsigned int sgreen = (GPART(p00) * (a * b) + GPART(p01) * (inv_a * b) + GPART(p10) * (a * inv_b) + GPART(p11) * (inv_a * inv_b) + 127) >> 8; + unsigned int sblue = (BPART(p00) * (a * b) + BPART(p01) * (inv_a * b) + BPART(p10) * (a * inv_b) + BPART(p11) * (inv_a * inv_b) + 127) >> 8; + unsigned int salpha = (APART(p00) * (a * b) + APART(p01) * (inv_a * b) + APART(p10) * (a * inv_b) + APART(p11) * (inv_a * inv_b) + 127) >> 8; + + texel = (salpha << 24) | (sred << 16) | (sgreen << 8) | sblue; + } + + if (SamplerT::Mode == (int)Samplers::Skycap) + { + int start_fade = 2; // How fast it should fade out + + int alpha_top = clamp(v >> (16 - start_fade), 0, 256); + int alpha_bottom = clamp(((2 << 24) - v) >> (16 - start_fade), 0, 256); + int a = MIN(alpha_top, alpha_bottom); + int inv_a = 256 - a; + + uint32_t r = RPART(texel); + uint32_t g = GPART(texel); + uint32_t b = BPART(texel); + uint32_t fg_a = APART(texel); + uint32_t bg_red = RPART(color); + uint32_t bg_green = GPART(color); + uint32_t bg_blue = BPART(color); + r = (r * a + bg_red * inv_a + 127) >> 8; + g = (g * a + bg_green * inv_a + 127) >> 8; + b = (b * a + bg_blue * inv_a + 127) >> 8; + return MAKEARGB(fg_a, r, g, b); + } + else + { + return texel; + } + } + + template + FORCEINLINE static __m128i VECTORCALL Shade(__m128i fgcolor, __m128i mlight, unsigned int ifgcolor0, unsigned int ifgcolor1, int desaturate, __m128i inv_desaturate, __m128i shade_fade, __m128i shade_light) + { + using namespace TriScreenDrawerModes; + + if (ShadeModeT::Mode == (int)ShadeMode::Simple) + { + fgcolor = _mm_srli_epi16(_mm_mullo_epi16(fgcolor, mlight), 8); + } + else + { + int blue0 = BPART(ifgcolor0); + int green0 = GPART(ifgcolor0); + int red0 = RPART(ifgcolor0); + int intensity0 = ((red0 * 77 + green0 * 143 + blue0 * 37) >> 8) * desaturate; + + int blue1 = BPART(ifgcolor1); + int green1 = GPART(ifgcolor1); + int red1 = RPART(ifgcolor1); + int intensity1 = ((red1 * 77 + green1 * 143 + blue1 * 37) >> 8) * desaturate; + + __m128i intensity = _mm_set_epi16(0, intensity1, intensity1, intensity1, 0, intensity0, intensity0, intensity0); + + fgcolor = _mm_srli_epi16(_mm_add_epi16(_mm_mullo_epi16(fgcolor, inv_desaturate), intensity), 8); + fgcolor = _mm_mullo_epi16(fgcolor, mlight); + fgcolor = _mm_srli_epi16(_mm_add_epi16(shade_fade, fgcolor), 8); + fgcolor = _mm_srli_epi16(_mm_mullo_epi16(fgcolor, shade_light), 8); + } + return fgcolor; + } + + FORCEINLINE static __m128i VECTORCALL Blend(__m128i fgcolor, __m128i bgcolor, unsigned int ifgcolor0, unsigned int ifgcolor1, uint32_t srcalpha, uint32_t destalpha) + { + using namespace TriScreenDrawerModes; + + if (BlendT::Mode == (int)BlendModes::Opaque) + { + __m128i outcolor = fgcolor; + outcolor = _mm_packus_epi16(outcolor, _mm_setzero_si128()); + return outcolor; + } + else if (BlendT::Mode == (int)BlendModes::Masked) + { + __m128i mask = _mm_cmpeq_epi32(_mm_packus_epi16(fgcolor, _mm_setzero_si128()), _mm_setzero_si128()); + mask = _mm_unpacklo_epi8(mask, _mm_setzero_si128()); + __m128i outcolor = _mm_or_si128(_mm_and_si128(mask, bgcolor), _mm_andnot_si128(mask, fgcolor)); + outcolor = _mm_packus_epi16(outcolor, _mm_setzero_si128()); + outcolor = _mm_or_si128(outcolor, _mm_set1_epi32(0xff000000)); + return outcolor; + } + else if (BlendT::Mode == (int)BlendModes::AddSrcColorOneMinusSrcColor) + { + __m128i inv_srccolor = _mm_sub_epi16(_mm_set1_epi16(256), _mm_add_epi16(fgcolor, _mm_srli_epi16(fgcolor, 7))); + __m128i outcolor = _mm_add_epi16(fgcolor, _mm_srli_epi16(_mm_mullo_epi16(bgcolor, inv_srccolor), 8)); + outcolor = _mm_packus_epi16(outcolor, _mm_setzero_si128()); + return outcolor; + } + else + { + uint32_t alpha0 = APART(ifgcolor0); + uint32_t alpha1 = APART(ifgcolor1); + alpha0 += alpha0 >> 7; // 255->256 + alpha1 += alpha1 >> 7; // 255->256 + uint32_t inv_alpha0 = 256 - alpha0; + uint32_t inv_alpha1 = 256 - alpha1; + + uint32_t bgalpha0 = (destalpha * alpha0 + (inv_alpha0 << 8) + 128) >> 8; + uint32_t bgalpha1 = (destalpha * alpha1 + (inv_alpha1 << 8) + 128) >> 8; + uint32_t fgalpha0 = (srcalpha * alpha0 + 128) >> 8; + uint32_t fgalpha1 = (srcalpha * alpha1 + 128) >> 8; + + __m128i bgalpha = _mm_set_epi16(bgalpha1, bgalpha1, bgalpha1, bgalpha1, bgalpha0, bgalpha0, bgalpha0, bgalpha0); + __m128i fgalpha = _mm_set_epi16(fgalpha1, fgalpha1, fgalpha1, fgalpha1, fgalpha0, fgalpha0, fgalpha0, fgalpha0); + + fgcolor = _mm_mullo_epi16(fgcolor, fgalpha); + bgcolor = _mm_mullo_epi16(bgcolor, bgalpha); + + __m128i fg_lo = _mm_unpacklo_epi16(fgcolor, _mm_setzero_si128()); + __m128i bg_lo = _mm_unpacklo_epi16(bgcolor, _mm_setzero_si128()); + __m128i fg_hi = _mm_unpackhi_epi16(fgcolor, _mm_setzero_si128()); + __m128i bg_hi = _mm_unpackhi_epi16(bgcolor, _mm_setzero_si128()); + + __m128i out_lo, out_hi; + if (BlendT::Mode == (int)BlendModes::AddClamp) + { + out_lo = _mm_add_epi32(fg_lo, bg_lo); + out_hi = _mm_add_epi32(fg_hi, bg_hi); + } + else if (BlendT::Mode == (int)BlendModes::SubClamp) + { + out_lo = _mm_sub_epi32(fg_lo, bg_lo); + out_hi = _mm_sub_epi32(fg_hi, bg_hi); + } + else if (BlendT::Mode == (int)BlendModes::RevSubClamp) + { + out_lo = _mm_sub_epi32(bg_lo, fg_lo); + out_hi = _mm_sub_epi32(bg_hi, fg_hi); + } + + out_lo = _mm_srai_epi32(out_lo, 8); + out_hi = _mm_srai_epi32(out_hi, 8); + __m128i outcolor = _mm_packs_epi32(out_lo, out_hi); + outcolor = _mm_packus_epi16(outcolor, _mm_setzero_si128()); + outcolor = _mm_or_si128(outcolor, _mm_set1_epi32(0xff000000)); + return outcolor; + } + } + + static float FindGradientX(float x0, float y0, float x1, float y1, float x2, float y2, float c0, float c1, float c2) + { + float top = (c1 - c2) * (y0 - y2) - (c0 - c2) * (y1 - y2); + float bottom = (x1 - x2) * (y0 - y2) - (x0 - x2) * (y1 - y2); + return top / bottom; + } + + static float FindGradientY(float x0, float y0, float x1, float y1, float x2, float y2, float c0, float c1, float c2) + { + float top = (c1 - c2) * (x0 - x2) - (c0 - c2) * (x1 - x2); + float bottom = (x0 - x2) * (y1 - y2) - (x1 - x2) * (y0 - y2); + return top / bottom; + } +}; diff --git a/src/polyrenderer/drawers/poly_drawer8.h b/src/polyrenderer/drawers/poly_drawer8.h new file mode 100644 index 000000000..f9c412c4f --- /dev/null +++ b/src/polyrenderer/drawers/poly_drawer8.h @@ -0,0 +1,366 @@ +/* +** Projected triangle drawer +** Copyright (c) 2016 Magnus Norddahl +** +** This software is provided 'as-is', without any express or implied +** warranty. In no event will the authors be held liable for any damages +** arising from the use of this software. +** +** Permission is granted to anyone to use this software for any purpose, +** including commercial applications, and to alter it and redistribute it +** freely, subject to the following restrictions: +** +** 1. The origin of this software must not be misrepresented; you must not +** claim that you wrote the original software. If you use this software +** in a product, an acknowledgment in the product documentation would be +** appreciated but is not required. +** 2. Altered source versions must be plainly marked as such, and must not be +** misrepresented as being the original software. +** 3. This notice may not be removed or altered from any source distribution. +** +*/ + +#pragma once + +#include "screen_triangle.h" + +template +class TriScreenDrawer8 +{ +public: + static void Execute(const TriDrawTriangleArgs *args, WorkerThreadData *thread) + { + using namespace TriScreenDrawerModes; + + int numSpans = thread->NumFullSpans; + auto fullSpans = thread->FullSpans; + int numBlocks = thread->NumPartialBlocks; + auto partialBlocks = thread->PartialBlocks; + int startX = thread->StartX; + int startY = thread->StartY; + + auto flags = args->uniforms->flags; + bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; + uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; + auto colormaps = args->colormaps; + uint32_t srcalpha = args->uniforms->srcalpha; + uint32_t destalpha = args->uniforms->destalpha; + + // Calculate gradients + const TriVertex &v1 = *args->v1; + const TriVertex &v2 = *args->v2; + const TriVertex &v3 = *args->v3; + ScreenTriangleStepVariables gradientX; + ScreenTriangleStepVariables gradientY; + ScreenTriangleStepVariables start; + gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); + gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); + start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); + for (int i = 0; i < TriVertex::NumVarying; i++) + { + gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); + gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); + start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); + } + + // Output + uint8_t * RESTRICT destOrg = args->dest; + int pitch = args->pitch; + + // Light + uint32_t light = args->uniforms->light; + float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; + float globVis = args->uniforms->globvis * (1.0f / 32.0f); + + // Sampling stuff + uint32_t color = args->uniforms->color; + const uint8_t * RESTRICT translation = args->translation; + const uint8_t * RESTRICT texPixels = args->texturePixels; + uint32_t texWidth = args->textureWidth; + uint32_t texHeight = args->textureHeight; + + for (int i = 0; i < numSpans; i++) + { + const auto &span = fullSpans[i]; + + uint8_t *dest = destOrg + span.X + span.Y * pitch; + int width = span.Length; + int height = 8; + + ScreenTriangleStepVariables blockPosY; + blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); + for (int j = 0; j < TriVertex::NumVarying; j++) + blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); + + for (int y = 0; y < height; y++) + { + ScreenTriangleStepVariables blockPosX = blockPosY; + + float rcpW = 0x01000000 / blockPosX.W; + int32_t varyingPos[TriVertex::NumVarying]; + for (int j = 0; j < TriVertex::NumVarying; j++) + varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); + + fixed_t lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); + lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); + + for (int x = 0; x < width; x++) + { + blockPosX.W += gradientX.W * 8; + for (int j = 0; j < TriVertex::NumVarying; j++) + blockPosX.Varying[j] += gradientX.Varying[j] * 8; + + rcpW = 0x01000000 / blockPosX.W; + int32_t varyingStep[TriVertex::NumVarying]; + for (int j = 0; j < TriVertex::NumVarying; j++) + { + int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); + varyingStep[j] = (nextPos - varyingPos[j]) / 8; + } + + fixed_t lightnext = FRACUNIT - (fixed_t)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); + fixed_t lightstep = (lightnext - lightpos) / 8; + lightstep = lightstep & lightmask; + + for (int ix = 0; ix < 8; ix++) + { + int lightshade = lightpos >> 8; + uint8_t bgcolor = dest[x * 8 + ix]; + uint8_t fgcolor = Sample(varyingPos[0], varyingPos[1], texPixels, texWidth, texHeight, color, translation); + dest[x * 8 + ix] = ShadeAndBlend(fgcolor, bgcolor, lightshade, colormaps, srcalpha, destalpha); + for (int j = 0; j < TriVertex::NumVarying; j++) + varyingPos[j] += varyingStep[j]; + lightpos += lightstep; + } + } + + blockPosY.W += gradientY.W; + for (int j = 0; j < TriVertex::NumVarying; j++) + blockPosY.Varying[j] += gradientY.Varying[j]; + + dest += pitch; + } + } + + for (int i = 0; i < numBlocks; i++) + { + const auto &block = partialBlocks[i]; + + ScreenTriangleStepVariables blockPosY; + blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); + for (int j = 0; j < TriVertex::NumVarying; j++) + blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); + + uint8_t *dest = destOrg + block.X + block.Y * pitch; + uint32_t mask0 = block.Mask0; + uint32_t mask1 = block.Mask1; + + // mask0 loop: + for (int y = 0; y < 4; y++) + { + ScreenTriangleStepVariables blockPosX = blockPosY; + + float rcpW = 0x01000000 / blockPosX.W; + int32_t varyingPos[TriVertex::NumVarying]; + for (int j = 0; j < TriVertex::NumVarying; j++) + varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); + + fixed_t lightpos = FRACUNIT - (fixed_t)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); + lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); + + blockPosX.W += gradientX.W * 8; + for (int j = 0; j < TriVertex::NumVarying; j++) + blockPosX.Varying[j] += gradientX.Varying[j] * 8; + + rcpW = 0x01000000 / blockPosX.W; + int32_t varyingStep[TriVertex::NumVarying]; + for (int j = 0; j < TriVertex::NumVarying; j++) + { + int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); + varyingStep[j] = (nextPos - varyingPos[j]) / 8; + } + + fixed_t lightnext = FRACUNIT - (fixed_t)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); + fixed_t lightstep = (lightnext - lightpos) / 8; + lightstep = lightstep & lightmask; + + for (int x = 0; x < 8; x++) + { + if (mask0 & (1 << 31)) + { + int lightshade = lightpos >> 8; + uint8_t bgcolor = dest[x]; + uint8_t fgcolor = Sample(varyingPos[0], varyingPos[1], texPixels, texWidth, texHeight, color, translation); + dest[x] = ShadeAndBlend(fgcolor, bgcolor, lightshade, colormaps, srcalpha, destalpha); + } + + for (int j = 0; j < TriVertex::NumVarying; j++) + varyingPos[j] += varyingStep[j]; + lightpos += lightstep; + + mask0 <<= 1; + } + + blockPosY.W += gradientY.W; + for (int j = 0; j < TriVertex::NumVarying; j++) + blockPosY.Varying[j] += gradientY.Varying[j]; + + dest += pitch; + } + + // mask1 loop: + for (int y = 0; y < 4; y++) + { + ScreenTriangleStepVariables blockPosX = blockPosY; + + float rcpW = 0x01000000 / blockPosX.W; + int32_t varyingPos[TriVertex::NumVarying]; + for (int j = 0; j < TriVertex::NumVarying; j++) + varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); + + fixed_t lightpos = FRACUNIT - (fixed_t)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); + lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); + + blockPosX.W += gradientX.W * 8; + for (int j = 0; j < TriVertex::NumVarying; j++) + blockPosX.Varying[j] += gradientX.Varying[j] * 8; + + rcpW = 0x01000000 / blockPosX.W; + int32_t varyingStep[TriVertex::NumVarying]; + for (int j = 0; j < TriVertex::NumVarying; j++) + { + int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); + varyingStep[j] = (nextPos - varyingPos[j]) / 8; + } + + fixed_t lightnext = FRACUNIT - (fixed_t)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); + fixed_t lightstep = (lightnext - lightpos) / 8; + lightstep = lightstep & lightmask; + + for (int x = 0; x < 8; x++) + { + if (mask1 & (1 << 31)) + { + int lightshade = lightpos >> 8; + uint8_t bgcolor = dest[x]; + uint8_t fgcolor = Sample(varyingPos[0], varyingPos[1], texPixels, texWidth, texHeight, color, translation); + dest[x] = ShadeAndBlend(fgcolor, bgcolor, lightshade, colormaps, srcalpha, destalpha); + } + + for (int j = 0; j < TriVertex::NumVarying; j++) + varyingPos[j] += varyingStep[j]; + lightpos += lightstep; + + mask1 <<= 1; + } + + blockPosY.W += gradientY.W; + for (int j = 0; j < TriVertex::NumVarying; j++) + blockPosY.Varying[j] += gradientY.Varying[j]; + + dest += pitch; + } + } + } + +private: + FORCEINLINE static unsigned int VECTORCALL Sample(int32_t u, int32_t v, const uint8_t *texPixels, int texWidth, int texHeight, uint32_t color, const uint8_t *translation) + { + using namespace TriScreenDrawerModes; + + uint8_t texel; + if (SamplerT::Mode == (int)Samplers::Shaded || SamplerT::Mode == (int)Samplers::Fill) + { + return color; + } + else if (SamplerT::Mode == (int)Samplers::Translated) + { + uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16; + uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; + return translation[texPixels[texelX * texHeight + texelY]]; + } + else + { + uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16; + uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; + texel = texPixels[texelX * texHeight + texelY]; + } + + if (SamplerT::Mode == (int)Samplers::Skycap) + { + /* + int start_fade = 2; // How fast it should fade out + + int alpha_top = clamp(v >> (16 - start_fade), 0, 256); + int alpha_bottom = clamp(((2 << 24) - v) >> (16 - start_fade), 0, 256); + int a = MIN(alpha_top, alpha_bottom); + int inv_a = 256 - a; + + uint32_t r = RPART(texel); + uint32_t g = GPART(texel); + uint32_t b = BPART(texel); + uint32_t fg_a = APART(texel); + uint32_t bg_red = RPART(color); + uint32_t bg_green = GPART(color); + uint32_t bg_blue = BPART(color); + r = (r * a + bg_red * inv_a + 127) >> 8; + g = (g * a + bg_green * inv_a + 127) >> 8; + b = (b * a + bg_blue * inv_a + 127) >> 8; + return MAKEARGB(fg_a, r, g, b); + */ + return texel; + } + else + { + return texel; + } + } + + FORCEINLINE static uint8_t ShadeAndBlend(uint8_t fgcolor, uint8_t bgcolor, uint32_t lightshade, const uint8_t *colormaps, uint32_t srcalpha, uint32_t destalpha) + { + using namespace TriScreenDrawerModes; + + lightshade = ((256 - lightshade) * (NUMCOLORMAPS - 1) + (NUMCOLORMAPS - 1) / 2) / 256; + uint8_t shadedfg = colormaps[lightshade * 256 + fgcolor]; + + if (BlendT::Mode == (int)BlendModes::Opaque) + { + return shadedfg; + } + else if (BlendT::Mode == (int)BlendModes::Masked) + { + return (fgcolor != 0) ? shadedfg : bgcolor; + } + else if (BlendT::Mode == (int)BlendModes::AddSrcColorOneMinusSrcColor) + { + return (fgcolor != 0) ? shadedfg : bgcolor; + } + else + { + if (BlendT::Mode == (int)BlendModes::AddClamp) + { + } + else if (BlendT::Mode == (int)BlendModes::SubClamp) + { + } + else if (BlendT::Mode == (int)BlendModes::RevSubClamp) + { + } + return (fgcolor != 0) ? shadedfg : bgcolor; + } + } + + static float FindGradientX(float x0, float y0, float x1, float y1, float x2, float y2, float c0, float c1, float c2) + { + float top = (c1 - c2) * (y0 - y2) - (c0 - c2) * (y1 - y2); + float bottom = (x1 - x2) * (y0 - y2) - (x0 - x2) * (y1 - y2); + return top / bottom; + } + + static float FindGradientY(float x0, float y0, float x1, float y1, float x2, float y2, float c0, float c1, float c2) + { + float top = (c1 - c2) * (x0 - x2) - (c0 - c2) * (x1 - x2); + float bottom = (x0 - x2) * (y1 - y2) - (x1 - x2) * (y0 - y2); + return top / bottom; + } +}; diff --git a/src/polyrenderer/drawers/poly_drawers.h b/src/polyrenderer/drawers/poly_drawers.h deleted file mode 100644 index d17d570f2..000000000 --- a/src/polyrenderer/drawers/poly_drawers.h +++ /dev/null @@ -1,15414 +0,0 @@ -/* -** Projected triangle drawer -** Copyright (c) 2016 Magnus Norddahl -** -** This software is provided 'as-is', without any express or implied -** warranty. In no event will the authors be held liable for any damages -** arising from the use of this software. -** -** Permission is granted to anyone to use this software for any purpose, -** including commercial applications, and to alter it and redistribute it -** freely, subject to the following restrictions: -** -** 1. The origin of this software must not be misrepresented; you must not -** claim that you wrote the original software. If you use this software -** in a product, an acknowledgment in the product documentation would be -** appreciated but is not required. -** 2. Altered source versions must be plainly marked as such, and must not be -** misrepresented as being the original software. -** 3. This notice may not be removed or altered from any source distribution. -** -*/ - -/* - Warning: this C++ source file has been auto-generated. Please modify the original php script that generated it. -*/ - -#pragma once - -#include "screen_triangle.h" - -static float FindGradientX(float x0, float y0, float x1, float y1, float x2, float y2, float c0, float c1, float c2) -{ - float top = (c1 - c2) * (y0 - y2) - (c0 - c2) * (y1 - y2); - float bottom = (x1 - x2) * (y0 - y2) - (x0 - x2) * (y1 - y2); - return top / bottom; -} - -static float FindGradientY(float x0, float y0, float x1, float y1, float x2, float y2, float c0, float c1, float c2) -{ - float top = (c1 - c2) * (x0 - x2) - (c0 - c2) * (x1 - x2); - float bottom = (x0 - x2) * (y1 - y2) - (x1 - x2) * (y0 - y2); - return top / bottom; -} - -static void TriFill32Copy(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint32_t * RESTRICT texPixels = (const uint32_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint32_t * RESTRICT destOrg = (uint32_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint32_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint32_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint32_t *destptr = dest + x * 8 + ix; - uint32_t fg = color; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint32_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint32_t *destptr = dest + x; - uint32_t fg = color; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint32_t *destptr = dest + x; - uint32_t fg = color; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriFill32AlphaBlend(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint32_t * RESTRICT texPixels = (const uint32_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint32_t * RESTRICT destOrg = (uint32_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint32_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint32_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint32_t *destptr = dest + x * 8 + ix; - uint32_t fg = color; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint32_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint32_t *destptr = dest + x; - uint32_t fg = color; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint32_t *destptr = dest + x; - uint32_t fg = color; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriFill32AddSolid(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint32_t * RESTRICT texPixels = (const uint32_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint32_t * RESTRICT destOrg = (uint32_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint32_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint32_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint32_t *destptr = dest + x * 8 + ix; - uint32_t fg = color; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint32_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint32_t *destptr = dest + x; - uint32_t fg = color; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint32_t *destptr = dest + x; - uint32_t fg = color; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriFill32Add(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint32_t * RESTRICT texPixels = (const uint32_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint32_t * RESTRICT destOrg = (uint32_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint32_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint32_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint32_t *destptr = dest + x * 8 + ix; - uint32_t fg = color; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint32_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint32_t *destptr = dest + x; - uint32_t fg = color; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint32_t *destptr = dest + x; - uint32_t fg = color; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriFill32Sub(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint32_t * RESTRICT texPixels = (const uint32_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint32_t * RESTRICT destOrg = (uint32_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint32_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint32_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint32_t *destptr = dest + x * 8 + ix; - uint32_t fg = color; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint32_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint32_t *destptr = dest + x; - uint32_t fg = color; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint32_t *destptr = dest + x; - uint32_t fg = color; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriFill32RevSub(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint32_t * RESTRICT texPixels = (const uint32_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint32_t * RESTRICT destOrg = (uint32_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint32_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint32_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint32_t *destptr = dest + x * 8 + ix; - uint32_t fg = color; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint32_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint32_t *destptr = dest + x; - uint32_t fg = color; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint32_t *destptr = dest + x; - uint32_t fg = color; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriFill32Stencil(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint32_t * RESTRICT texPixels = (const uint32_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint32_t * RESTRICT destOrg = (uint32_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint32_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint32_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint32_t *destptr = dest + x * 8 + ix; - uint32_t fg = color; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t fgalpha = APART(fg); - uint32_t inv_fgalpha = 256 - fgalpha; - int a = (fgalpha * srcalpha + 128) >> 8; - int inv_a = (destalpha * fgalpha + 256 * inv_fgalpha + 128) >> 8; - - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint32_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint32_t *destptr = dest + x; - uint32_t fg = color; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t fgalpha = APART(fg); - uint32_t inv_fgalpha = 256 - fgalpha; - int a = (fgalpha * srcalpha + 128) >> 8; - int inv_a = (destalpha * fgalpha + 256 * inv_fgalpha + 128) >> 8; - - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint32_t *destptr = dest + x; - uint32_t fg = color; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t fgalpha = APART(fg); - uint32_t inv_fgalpha = 256 - fgalpha; - int a = (fgalpha * srcalpha + 128) >> 8; - int inv_a = (destalpha * fgalpha + 256 * inv_fgalpha + 128) >> 8; - - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriFill32Shaded(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = args->texturePixels; - const uint32_t * RESTRICT translation = (const uint32_t *)args->translation; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint32_t * RESTRICT destOrg = (uint32_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint32_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint32_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint32_t *destptr = dest + x * 8 + ix; - uint32_t fg = color; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - int sample = texPixels[texelX * texHeight + texelY]; - - uint32_t fgalpha = sample;//clamp(sample, 0, 64) * 4; - uint32_t inv_fgalpha = 256 - fgalpha; - int a = (fgalpha * srcalpha + 128) >> 8; - int inv_a = (destalpha * fgalpha + 256 * inv_fgalpha + 128) >> 8; - - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint32_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint32_t *destptr = dest + x; - uint32_t fg = color; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - int sample = texPixels[texelX * texHeight + texelY]; - - uint32_t fgalpha = sample;//clamp(sample, 0, 64) * 4; - uint32_t inv_fgalpha = 256 - fgalpha; - int a = (fgalpha * srcalpha + 128) >> 8; - int inv_a = (destalpha * fgalpha + 256 * inv_fgalpha + 128) >> 8; - - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint32_t *destptr = dest + x; - uint32_t fg = color; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - int sample = texPixels[texelX * texHeight + texelY]; - - uint32_t fgalpha = sample;//clamp(sample, 0, 64) * 4; - uint32_t inv_fgalpha = 256 - fgalpha; - int a = (fgalpha * srcalpha + 128) >> 8; - int inv_a = (destalpha * fgalpha + 256 * inv_fgalpha + 128) >> 8; - - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriFill32TranslateCopy(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = args->texturePixels; - const uint32_t * RESTRICT translation = (const uint32_t *)args->translation; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint32_t * RESTRICT destOrg = (uint32_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint32_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint32_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint32_t *destptr = dest + x * 8 + ix; - uint32_t fg = color; - fg = translation[fg]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint32_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint32_t *destptr = dest + x; - uint32_t fg = color; - fg = translation[fg]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint32_t *destptr = dest + x; - uint32_t fg = color; - fg = translation[fg]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriFill32TranslateAlphaBlend(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = args->texturePixels; - const uint32_t * RESTRICT translation = (const uint32_t *)args->translation; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint32_t * RESTRICT destOrg = (uint32_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint32_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint32_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint32_t *destptr = dest + x * 8 + ix; - uint32_t fg = color; - fg = translation[fg]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint32_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint32_t *destptr = dest + x; - uint32_t fg = color; - fg = translation[fg]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint32_t *destptr = dest + x; - uint32_t fg = color; - fg = translation[fg]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriFill32TranslateAdd(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = args->texturePixels; - const uint32_t * RESTRICT translation = (const uint32_t *)args->translation; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint32_t * RESTRICT destOrg = (uint32_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint32_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint32_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint32_t *destptr = dest + x * 8 + ix; - uint32_t fg = color; - fg = translation[fg]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint32_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint32_t *destptr = dest + x; - uint32_t fg = color; - fg = translation[fg]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint32_t *destptr = dest + x; - uint32_t fg = color; - fg = translation[fg]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriFill32TranslateSub(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = args->texturePixels; - const uint32_t * RESTRICT translation = (const uint32_t *)args->translation; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint32_t * RESTRICT destOrg = (uint32_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint32_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint32_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint32_t *destptr = dest + x * 8 + ix; - uint32_t fg = color; - fg = translation[fg]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint32_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint32_t *destptr = dest + x; - uint32_t fg = color; - fg = translation[fg]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint32_t *destptr = dest + x; - uint32_t fg = color; - fg = translation[fg]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriFill32TranslateRevSub(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = args->texturePixels; - const uint32_t * RESTRICT translation = (const uint32_t *)args->translation; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint32_t * RESTRICT destOrg = (uint32_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint32_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint32_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint32_t *destptr = dest + x * 8 + ix; - uint32_t fg = color; - fg = translation[fg]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint32_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint32_t *destptr = dest + x; - uint32_t fg = color; - fg = translation[fg]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint32_t *destptr = dest + x; - uint32_t fg = color; - fg = translation[fg]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriFill32AddSrcColorOneMinusSrcColor(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint32_t * RESTRICT texPixels = (const uint32_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint32_t * RESTRICT destOrg = (uint32_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint32_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint32_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint32_t *destptr = dest + x * 8 + ix; - uint32_t fg = color; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t inv_r = 256 - (r + (r >> 7)); - uint32_t inv_g = 256 - (g + (r >> 7)); - uint32_t inv_b = 256 - (b + (r >> 7)); - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = r + ((bg_red * inv_r + 127) >> 8); - g = g + ((bg_green * inv_g + 127) >> 8); - b = b + ((bg_blue * inv_b + 127) >> 8); - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint32_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint32_t *destptr = dest + x; - uint32_t fg = color; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t inv_r = 256 - (r + (r >> 7)); - uint32_t inv_g = 256 - (g + (r >> 7)); - uint32_t inv_b = 256 - (b + (r >> 7)); - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = r + ((bg_red * inv_r + 127) >> 8); - g = g + ((bg_green * inv_g + 127) >> 8); - b = b + ((bg_blue * inv_b + 127) >> 8); - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint32_t *destptr = dest + x; - uint32_t fg = color; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t inv_r = 256 - (r + (r >> 7)); - uint32_t inv_g = 256 - (g + (r >> 7)); - uint32_t inv_b = 256 - (b + (r >> 7)); - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = r + ((bg_red * inv_r + 127) >> 8); - g = g + ((bg_green * inv_g + 127) >> 8); - b = b + ((bg_blue * inv_b + 127) >> 8); - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriFill32Skycap(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint32_t * RESTRICT texPixels = (const uint32_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint32_t * RESTRICT destOrg = (uint32_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint32_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint32_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint32_t *destptr = dest + x * 8 + ix; - uint32_t fg = color; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - int start_fade = 2; // How fast it should fade out - - int alpha_top = clamp(varyingPos[1] >> (16 - start_fade), 0, 256); - int alpha_bottom = clamp(((2 << 24) - varyingPos[1]) >> (16 - start_fade), 0, 256); - int a = MIN(alpha_top, alpha_bottom); - int inv_a = 256 - a; - - uint32_t bg_red = RPART(color); - uint32_t bg_green = GPART(color); - uint32_t bg_blue = BPART(color); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint32_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint32_t *destptr = dest + x; - uint32_t fg = color; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - int start_fade = 2; // How fast it should fade out - - int alpha_top = clamp(varyingPos[1] >> (16 - start_fade), 0, 256); - int alpha_bottom = clamp(((2 << 24) - varyingPos[1]) >> (16 - start_fade), 0, 256); - int a = MIN(alpha_top, alpha_bottom); - int inv_a = 256 - a; - - uint32_t bg_red = RPART(color); - uint32_t bg_green = GPART(color); - uint32_t bg_blue = BPART(color); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint32_t *destptr = dest + x; - uint32_t fg = color; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - int start_fade = 2; // How fast it should fade out - - int alpha_top = clamp(varyingPos[1] >> (16 - start_fade), 0, 256); - int alpha_bottom = clamp(((2 << 24) - varyingPos[1]) >> (16 - start_fade), 0, 256); - int a = MIN(alpha_top, alpha_bottom); - int inv_a = 256 - a; - - uint32_t bg_red = RPART(color); - uint32_t bg_green = GPART(color); - uint32_t bg_blue = BPART(color); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriDraw32Copy(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint32_t * RESTRICT texPixels = (const uint32_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint32_t * RESTRICT destOrg = (uint32_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint32_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint32_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint32_t *destptr = dest + x * 8 + ix; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint32_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint32_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint32_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriDraw32AlphaBlend(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint32_t * RESTRICT texPixels = (const uint32_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint32_t * RESTRICT destOrg = (uint32_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint32_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint32_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint32_t *destptr = dest + x * 8 + ix; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint32_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint32_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint32_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriDraw32AddSolid(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint32_t * RESTRICT texPixels = (const uint32_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint32_t * RESTRICT destOrg = (uint32_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint32_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint32_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint32_t *destptr = dest + x * 8 + ix; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint32_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint32_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint32_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriDraw32Add(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint32_t * RESTRICT texPixels = (const uint32_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint32_t * RESTRICT destOrg = (uint32_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint32_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint32_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint32_t *destptr = dest + x * 8 + ix; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint32_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint32_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint32_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriDraw32Sub(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint32_t * RESTRICT texPixels = (const uint32_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint32_t * RESTRICT destOrg = (uint32_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint32_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint32_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint32_t *destptr = dest + x * 8 + ix; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint32_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint32_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint32_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriDraw32RevSub(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint32_t * RESTRICT texPixels = (const uint32_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint32_t * RESTRICT destOrg = (uint32_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint32_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint32_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint32_t *destptr = dest + x * 8 + ix; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint32_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint32_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint32_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriDraw32Stencil(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint32_t * RESTRICT texPixels = (const uint32_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint32_t * RESTRICT destOrg = (uint32_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint32_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint32_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint32_t *destptr = dest + x * 8 + ix; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t fgalpha = APART(fg); - uint32_t inv_fgalpha = 256 - fgalpha; - int a = (fgalpha * srcalpha + 128) >> 8; - int inv_a = (destalpha * fgalpha + 256 * inv_fgalpha + 128) >> 8; - - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint32_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint32_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t fgalpha = APART(fg); - uint32_t inv_fgalpha = 256 - fgalpha; - int a = (fgalpha * srcalpha + 128) >> 8; - int inv_a = (destalpha * fgalpha + 256 * inv_fgalpha + 128) >> 8; - - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint32_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t fgalpha = APART(fg); - uint32_t inv_fgalpha = 256 - fgalpha; - int a = (fgalpha * srcalpha + 128) >> 8; - int inv_a = (destalpha * fgalpha + 256 * inv_fgalpha + 128) >> 8; - - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriDraw32Shaded(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = args->texturePixels; - const uint32_t * RESTRICT translation = (const uint32_t *)args->translation; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint32_t * RESTRICT destOrg = (uint32_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint32_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint32_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint32_t *destptr = dest + x * 8 + ix; - uint32_t fg = color; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - int sample = texPixels[texelX * texHeight + texelY]; - - uint32_t fgalpha = sample;//clamp(sample, 0, 64) * 4; - uint32_t inv_fgalpha = 256 - fgalpha; - int a = (fgalpha * srcalpha + 128) >> 8; - int inv_a = (destalpha * fgalpha + 256 * inv_fgalpha + 128) >> 8; - - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint32_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint32_t *destptr = dest + x; - uint32_t fg = color; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - int sample = texPixels[texelX * texHeight + texelY]; - - uint32_t fgalpha = sample;//clamp(sample, 0, 64) * 4; - uint32_t inv_fgalpha = 256 - fgalpha; - int a = (fgalpha * srcalpha + 128) >> 8; - int inv_a = (destalpha * fgalpha + 256 * inv_fgalpha + 128) >> 8; - - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint32_t *destptr = dest + x; - uint32_t fg = color; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - int sample = texPixels[texelX * texHeight + texelY]; - - uint32_t fgalpha = sample;//clamp(sample, 0, 64) * 4; - uint32_t inv_fgalpha = 256 - fgalpha; - int a = (fgalpha * srcalpha + 128) >> 8; - int inv_a = (destalpha * fgalpha + 256 * inv_fgalpha + 128) >> 8; - - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriDraw32TranslateCopy(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = args->texturePixels; - const uint32_t * RESTRICT translation = (const uint32_t *)args->translation; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint32_t * RESTRICT destOrg = (uint32_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint32_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint32_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint32_t *destptr = dest + x * 8 + ix; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - fg = translation[fg]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint32_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint32_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - fg = translation[fg]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint32_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - fg = translation[fg]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriDraw32TranslateAlphaBlend(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = args->texturePixels; - const uint32_t * RESTRICT translation = (const uint32_t *)args->translation; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint32_t * RESTRICT destOrg = (uint32_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint32_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint32_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint32_t *destptr = dest + x * 8 + ix; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - fg = translation[fg]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint32_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint32_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - fg = translation[fg]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint32_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - fg = translation[fg]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriDraw32TranslateAdd(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = args->texturePixels; - const uint32_t * RESTRICT translation = (const uint32_t *)args->translation; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint32_t * RESTRICT destOrg = (uint32_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint32_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint32_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint32_t *destptr = dest + x * 8 + ix; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - fg = translation[fg]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint32_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint32_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - fg = translation[fg]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint32_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - fg = translation[fg]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriDraw32TranslateSub(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = args->texturePixels; - const uint32_t * RESTRICT translation = (const uint32_t *)args->translation; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint32_t * RESTRICT destOrg = (uint32_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint32_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint32_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint32_t *destptr = dest + x * 8 + ix; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - fg = translation[fg]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint32_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint32_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - fg = translation[fg]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint32_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - fg = translation[fg]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriDraw32TranslateRevSub(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = args->texturePixels; - const uint32_t * RESTRICT translation = (const uint32_t *)args->translation; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint32_t * RESTRICT destOrg = (uint32_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint32_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint32_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint32_t *destptr = dest + x * 8 + ix; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - fg = translation[fg]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint32_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint32_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - fg = translation[fg]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint32_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - fg = translation[fg]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriDraw32AddSrcColorOneMinusSrcColor(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint32_t * RESTRICT texPixels = (const uint32_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint32_t * RESTRICT destOrg = (uint32_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint32_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint32_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint32_t *destptr = dest + x * 8 + ix; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t inv_r = 256 - (r + (r >> 7)); - uint32_t inv_g = 256 - (g + (r >> 7)); - uint32_t inv_b = 256 - (b + (r >> 7)); - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = r + ((bg_red * inv_r + 127) >> 8); - g = g + ((bg_green * inv_g + 127) >> 8); - b = b + ((bg_blue * inv_b + 127) >> 8); - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint32_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint32_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t inv_r = 256 - (r + (r >> 7)); - uint32_t inv_g = 256 - (g + (r >> 7)); - uint32_t inv_b = 256 - (b + (r >> 7)); - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = r + ((bg_red * inv_r + 127) >> 8); - g = g + ((bg_green * inv_g + 127) >> 8); - b = b + ((bg_blue * inv_b + 127) >> 8); - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint32_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - uint32_t inv_r = 256 - (r + (r >> 7)); - uint32_t inv_g = 256 - (g + (r >> 7)); - uint32_t inv_b = 256 - (b + (r >> 7)); - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = r + ((bg_red * inv_r + 127) >> 8); - g = g + ((bg_green * inv_g + 127) >> 8); - b = b + ((bg_blue * inv_b + 127) >> 8); - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriDraw32Skycap(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint32_t * RESTRICT texPixels = (const uint32_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint32_t * RESTRICT destOrg = (uint32_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint32_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint32_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint32_t *destptr = dest + x * 8 + ix; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - int start_fade = 2; // How fast it should fade out - - int alpha_top = clamp(varyingPos[1] >> (16 - start_fade), 0, 256); - int alpha_bottom = clamp(((2 << 24) - varyingPos[1]) >> (16 - start_fade), 0, 256); - int a = MIN(alpha_top, alpha_bottom); - int inv_a = 256 - a; - - uint32_t bg_red = RPART(color); - uint32_t bg_green = GPART(color); - uint32_t bg_blue = BPART(color); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint32_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint32_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - int start_fade = 2; // How fast it should fade out - - int alpha_top = clamp(varyingPos[1] >> (16 - start_fade), 0, 256); - int alpha_bottom = clamp(((2 << 24) - varyingPos[1]) >> (16 - start_fade), 0, 256); - int a = MIN(alpha_top, alpha_bottom); - int inv_a = 256 - a; - - uint32_t bg_red = RPART(color); - uint32_t bg_green = GPART(color); - uint32_t bg_blue = BPART(color); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint32_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - int start_fade = 2; // How fast it should fade out - - int alpha_top = clamp(varyingPos[1] >> (16 - start_fade), 0, 256); - int alpha_bottom = clamp(((2 << 24) - varyingPos[1]) >> (16 - start_fade), 0, 256); - int a = MIN(alpha_top, alpha_bottom); - int inv_a = 256 - a; - - uint32_t bg_red = RPART(color); - uint32_t bg_green = GPART(color); - uint32_t bg_blue = BPART(color); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriFill8Copy(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = (const uint8_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint8_t * RESTRICT destOrg = (uint8_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint8_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint8_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint8_t *destptr = dest + x * 8 + ix; - uint8_t fg = color; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint8_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint8_t *destptr = dest + x; - uint8_t fg = color; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint8_t *destptr = dest + x; - uint8_t fg = color; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriFill8AlphaBlend(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = (const uint8_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint8_t * RESTRICT destOrg = (uint8_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint8_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint8_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint8_t *destptr = dest + x * 8 + ix; - uint8_t fg = color; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint8_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint8_t *destptr = dest + x; - uint8_t fg = color; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint8_t *destptr = dest + x; - uint8_t fg = color; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriFill8AddSolid(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = (const uint8_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint8_t * RESTRICT destOrg = (uint8_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint8_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint8_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint8_t *destptr = dest + x * 8 + ix; - uint8_t fg = color; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint8_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint8_t *destptr = dest + x; - uint8_t fg = color; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint8_t *destptr = dest + x; - uint8_t fg = color; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriFill8Add(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = (const uint8_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint8_t * RESTRICT destOrg = (uint8_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint8_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint8_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint8_t *destptr = dest + x * 8 + ix; - uint8_t fg = color; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint8_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint8_t *destptr = dest + x; - uint8_t fg = color; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint8_t *destptr = dest + x; - uint8_t fg = color; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriFill8Sub(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = (const uint8_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint8_t * RESTRICT destOrg = (uint8_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint8_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint8_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint8_t *destptr = dest + x * 8 + ix; - uint8_t fg = color; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint8_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint8_t *destptr = dest + x; - uint8_t fg = color; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint8_t *destptr = dest + x; - uint8_t fg = color; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriFill8RevSub(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = (const uint8_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint8_t * RESTRICT destOrg = (uint8_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint8_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint8_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint8_t *destptr = dest + x * 8 + ix; - uint8_t fg = color; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint8_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint8_t *destptr = dest + x; - uint8_t fg = color; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint8_t *destptr = dest + x; - uint8_t fg = color; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriFill8Stencil(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = (const uint8_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint8_t * RESTRICT destOrg = (uint8_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint8_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint8_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint8_t *destptr = dest + x * 8 + ix; - uint8_t fg = color; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint8_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint8_t *destptr = dest + x; - uint8_t fg = color; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint8_t *destptr = dest + x; - uint8_t fg = color; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriFill8Shaded(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = args->texturePixels; - const uint8_t * RESTRICT translation = (const uint8_t *)args->translation; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint8_t * RESTRICT destOrg = (uint8_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint8_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint8_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint8_t *destptr = dest + x * 8 + ix; - uint8_t fg = color; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint8_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint8_t *destptr = dest + x; - uint8_t fg = color; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint8_t *destptr = dest + x; - uint8_t fg = color; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriFill8TranslateCopy(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = args->texturePixels; - const uint8_t * RESTRICT translation = (const uint8_t *)args->translation; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint8_t * RESTRICT destOrg = (uint8_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint8_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint8_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint8_t *destptr = dest + x * 8 + ix; - uint8_t fg = color; - fg = translation[fg]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint8_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint8_t *destptr = dest + x; - uint8_t fg = color; - fg = translation[fg]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint8_t *destptr = dest + x; - uint8_t fg = color; - fg = translation[fg]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriFill8TranslateAlphaBlend(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = args->texturePixels; - const uint8_t * RESTRICT translation = (const uint8_t *)args->translation; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint8_t * RESTRICT destOrg = (uint8_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint8_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint8_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint8_t *destptr = dest + x * 8 + ix; - uint8_t fg = color; - fg = translation[fg]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint8_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint8_t *destptr = dest + x; - uint8_t fg = color; - fg = translation[fg]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint8_t *destptr = dest + x; - uint8_t fg = color; - fg = translation[fg]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriFill8TranslateAdd(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = args->texturePixels; - const uint8_t * RESTRICT translation = (const uint8_t *)args->translation; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint8_t * RESTRICT destOrg = (uint8_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint8_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint8_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint8_t *destptr = dest + x * 8 + ix; - uint8_t fg = color; - fg = translation[fg]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint8_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint8_t *destptr = dest + x; - uint8_t fg = color; - fg = translation[fg]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint8_t *destptr = dest + x; - uint8_t fg = color; - fg = translation[fg]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriFill8TranslateSub(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = args->texturePixels; - const uint8_t * RESTRICT translation = (const uint8_t *)args->translation; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint8_t * RESTRICT destOrg = (uint8_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint8_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint8_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint8_t *destptr = dest + x * 8 + ix; - uint8_t fg = color; - fg = translation[fg]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint8_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint8_t *destptr = dest + x; - uint8_t fg = color; - fg = translation[fg]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint8_t *destptr = dest + x; - uint8_t fg = color; - fg = translation[fg]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriFill8TranslateRevSub(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = args->texturePixels; - const uint8_t * RESTRICT translation = (const uint8_t *)args->translation; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint8_t * RESTRICT destOrg = (uint8_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint8_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint8_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint8_t *destptr = dest + x * 8 + ix; - uint8_t fg = color; - fg = translation[fg]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint8_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint8_t *destptr = dest + x; - uint8_t fg = color; - fg = translation[fg]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint8_t *destptr = dest + x; - uint8_t fg = color; - fg = translation[fg]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriFill8AddSrcColorOneMinusSrcColor(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = (const uint8_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint8_t * RESTRICT destOrg = (uint8_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint8_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint8_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint8_t *destptr = dest + x * 8 + ix; - uint8_t fg = color; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint8_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint8_t *destptr = dest + x; - uint8_t fg = color; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint8_t *destptr = dest + x; - uint8_t fg = color; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriFill8Skycap(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = (const uint8_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint8_t * RESTRICT destOrg = (uint8_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint8_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint8_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint8_t *destptr = dest + x * 8 + ix; - uint8_t fg = color; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint8_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint8_t *destptr = dest + x; - uint8_t fg = color; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint8_t *destptr = dest + x; - uint8_t fg = color; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriDraw8Copy(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = (const uint8_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint8_t * RESTRICT destOrg = (uint8_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint8_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint8_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint8_t *destptr = dest + x * 8 + ix; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint8_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint8_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint8_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriDraw8AlphaBlend(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = (const uint8_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint8_t * RESTRICT destOrg = (uint8_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint8_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint8_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint8_t *destptr = dest + x * 8 + ix; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint8_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint8_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint8_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriDraw8AddSolid(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = (const uint8_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint8_t * RESTRICT destOrg = (uint8_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint8_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint8_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint8_t *destptr = dest + x * 8 + ix; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint8_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint8_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint8_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriDraw8Add(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = (const uint8_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint8_t * RESTRICT destOrg = (uint8_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint8_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint8_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint8_t *destptr = dest + x * 8 + ix; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint8_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint8_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint8_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriDraw8Sub(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = (const uint8_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint8_t * RESTRICT destOrg = (uint8_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint8_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint8_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint8_t *destptr = dest + x * 8 + ix; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint8_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint8_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint8_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriDraw8RevSub(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = (const uint8_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint8_t * RESTRICT destOrg = (uint8_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint8_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint8_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint8_t *destptr = dest + x * 8 + ix; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint8_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint8_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint8_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriDraw8Stencil(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = (const uint8_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint8_t * RESTRICT destOrg = (uint8_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint8_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint8_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint8_t *destptr = dest + x * 8 + ix; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint8_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint8_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint8_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriDraw8Shaded(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = args->texturePixels; - const uint8_t * RESTRICT translation = (const uint8_t *)args->translation; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint8_t * RESTRICT destOrg = (uint8_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint8_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint8_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint8_t *destptr = dest + x * 8 + ix; - uint8_t fg = color; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint8_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint8_t *destptr = dest + x; - uint8_t fg = color; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint8_t *destptr = dest + x; - uint8_t fg = color; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriDraw8TranslateCopy(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = args->texturePixels; - const uint8_t * RESTRICT translation = (const uint8_t *)args->translation; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint8_t * RESTRICT destOrg = (uint8_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint8_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint8_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint8_t *destptr = dest + x * 8 + ix; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - fg = translation[fg]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint8_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint8_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - fg = translation[fg]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint8_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - fg = translation[fg]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriDraw8TranslateAlphaBlend(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = args->texturePixels; - const uint8_t * RESTRICT translation = (const uint8_t *)args->translation; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint8_t * RESTRICT destOrg = (uint8_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint8_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint8_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint8_t *destptr = dest + x * 8 + ix; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - fg = translation[fg]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint8_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint8_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - fg = translation[fg]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint8_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - fg = translation[fg]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriDraw8TranslateAdd(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = args->texturePixels; - const uint8_t * RESTRICT translation = (const uint8_t *)args->translation; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint8_t * RESTRICT destOrg = (uint8_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint8_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint8_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint8_t *destptr = dest + x * 8 + ix; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - fg = translation[fg]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint8_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint8_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - fg = translation[fg]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint8_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - fg = translation[fg]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriDraw8TranslateSub(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = args->texturePixels; - const uint8_t * RESTRICT translation = (const uint8_t *)args->translation; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint8_t * RESTRICT destOrg = (uint8_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint8_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint8_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint8_t *destptr = dest + x * 8 + ix; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - fg = translation[fg]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint8_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint8_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - fg = translation[fg]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint8_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - fg = translation[fg]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriDraw8TranslateRevSub(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = args->texturePixels; - const uint8_t * RESTRICT translation = (const uint8_t *)args->translation; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint8_t * RESTRICT destOrg = (uint8_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint8_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint8_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint8_t *destptr = dest + x * 8 + ix; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - fg = translation[fg]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint8_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint8_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - fg = translation[fg]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint8_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - fg = translation[fg]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriDraw8AddSrcColorOneMinusSrcColor(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = (const uint8_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint8_t * RESTRICT destOrg = (uint8_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint8_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint8_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint8_t *destptr = dest + x * 8 + ix; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint8_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint8_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint8_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -static void TriDraw8Skycap(const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - const uint8_t * RESTRICT texPixels = (const uint8_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint8_t * RESTRICT destOrg = (uint8_t*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - uint8_t color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint8_t *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - uint8_t *destptr = dest + x * 8 + ix; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint8_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - uint8_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - uint8_t *destptr = dest + x; - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint8_t fg = texPixels[texelX * texHeight + texelY]; - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - *destptr = fg; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } -} - -std::vector ScreenTriangle::TriFill32 = -{ - &TriFill32Copy, - &TriFill32AlphaBlend, - &TriFill32AddSolid, - &TriFill32Add, - &TriFill32Sub, - &TriFill32RevSub, - &TriFill32Stencil, - &TriFill32Shaded, - &TriFill32TranslateCopy, - &TriFill32TranslateAlphaBlend, - &TriFill32TranslateAdd, - &TriFill32TranslateSub, - &TriFill32TranslateRevSub, - &TriFill32AddSrcColorOneMinusSrcColor, - &TriFill32Skycap, -}; - -std::vector ScreenTriangle::TriDraw32 = -{ - &TriDraw32Copy, - &TriDraw32AlphaBlend, - &TriDraw32AddSolid, - &TriDraw32Add, - &TriDraw32Sub, - &TriDraw32RevSub, - &TriDraw32Stencil, - &TriDraw32Shaded, - &TriDraw32TranslateCopy, - &TriDraw32TranslateAlphaBlend, - &TriDraw32TranslateAdd, - &TriDraw32TranslateSub, - &TriDraw32TranslateRevSub, - &TriDraw32AddSrcColorOneMinusSrcColor, - &TriDraw32Skycap, -}; - -std::vector ScreenTriangle::TriFill8 = -{ - &TriFill8Copy, - &TriFill8AlphaBlend, - &TriFill8AddSolid, - &TriFill8Add, - &TriFill8Sub, - &TriFill8RevSub, - &TriFill8Stencil, - &TriFill8Shaded, - &TriFill8TranslateCopy, - &TriFill8TranslateAlphaBlend, - &TriFill8TranslateAdd, - &TriFill8TranslateSub, - &TriFill8TranslateRevSub, - &TriFill8AddSrcColorOneMinusSrcColor, - &TriFill8Skycap, -}; - -std::vector ScreenTriangle::TriDraw8 = -{ - &TriDraw8Copy, - &TriDraw8AlphaBlend, - &TriDraw8AddSolid, - &TriDraw8Add, - &TriDraw8Sub, - &TriDraw8RevSub, - &TriDraw8Stencil, - &TriDraw8Shaded, - &TriDraw8TranslateCopy, - &TriDraw8TranslateAlphaBlend, - &TriDraw8TranslateAdd, - &TriDraw8TranslateSub, - &TriDraw8TranslateRevSub, - &TriDraw8AddSrcColorOneMinusSrcColor, - &TriDraw8Skycap, -}; - diff --git a/src/polyrenderer/drawers/poly_drawers.php b/src/polyrenderer/drawers/poly_drawers.php deleted file mode 100644 index 741fcf3c7..000000000 --- a/src/polyrenderer/drawers/poly_drawers.php +++ /dev/null @@ -1,449 +0,0 @@ -/* -** Projected triangle drawer -** Copyright (c) 2016 Magnus Norddahl -** -** This software is provided 'as-is', without any express or implied -** warranty. In no event will the authors be held liable for any damages -** arising from the use of this software. -** -** Permission is granted to anyone to use this software for any purpose, -** including commercial applications, and to alter it and redistribute it -** freely, subject to the following restrictions: -** -** 1. The origin of this software must not be misrepresented; you must not -** claim that you wrote the original software. If you use this software -** in a product, an acknowledgment in the product documentation would be -** appreciated but is not required. -** 2. Altered source versions must be plainly marked as such, and must not be -** misrepresented as being the original software. -** 3. This notice may not be removed or altered from any source distribution. -** -*/ - -/* - Warning: this C++ source file has been auto-generated. Please modify the original php script that generated it. -*/ - -#pragma once - -#include "screen_triangle.h" - -static float FindGradientX(float x0, float y0, float x1, float y1, float x2, float y2, float c0, float c1, float c2) -{ - float top = (c1 - c2) * (y0 - y2) - (c0 - c2) * (y1 - y2); - float bottom = (x1 - x2) * (y0 - y2) - (x0 - x2) * (y1 - y2); - return top / bottom; -} - -static float FindGradientY(float x0, float y0, float x1, float y1, float x2, float y2, float c0, float c1, float c2) -{ - float top = (c1 - c2) * (x0 - x2) - (c0 - c2) * (x1 - x2); - float bottom = (x0 - x2) * (y1 - y2) - (x1 - x2) * (y0 - y2); - return top / bottom; -} - - -std::vector ScreenTriangle:: = -{ - -}; - - - &, - -static void (const TriDrawTriangleArgs *args, WorkerThreadData *thread) -{ - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; - - auto flags = args->uniforms->flags; - bool is_simple_shade = (flags & TriUniforms::simple_shade) == TriUniforms::simple_shade; - bool is_nearest_filter = (flags & TriUniforms::nearest_filter) == TriUniforms::nearest_filter; - bool is_fixed_light = (flags & TriUniforms::fixed_light) == TriUniforms::fixed_light; - uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff; - auto colormaps = args->colormaps; - uint32_t srcalpha = args->uniforms->srcalpha; - uint32_t destalpha = args->uniforms->destalpha; - - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } - - - const uint8_t * RESTRICT texPixels = args->texturePixels; - const * RESTRICT translation = (const *)args->translation; - - const * RESTRICT texPixels = (const *)args->texturePixels; - - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - * RESTRICT destOrg = (*)args->dest; - int pitch = args->pitch; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = args->uniforms->globvis * (1.0f / 32.0f); - - color = args->uniforms->color; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - *dest = destOrg + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int ix = 0; ix < 8; ix++) - { - *destptr = dest + x * 8 + ix; - - *destptr = fg; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - *dest = destOrg + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); - int lightstep = (lightnext - lightpos) / 8; - lightstep = lightstep & lightmask; - - for (int x = 0; x < 8; x++) - { - if ( & (1 << 31)) - { - *destptr = dest + x; - - *destptr = fg; - } - <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - } - - } -} - - - fg = color; - - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - fg = texPixels[texelX * texHeight + texelY]; - - fg = translation[fg]; - - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = (r * lightpos) >> 16; - g = (g * lightpos) >> 16; - b = (b * lightpos) >> 16; - - fg = 0xff000000 | (r << 16) | (g << 8) | b; - - int colormapindex = MIN(((256 - (lightpos >> 8)) * 32) >> 8, 31) << 8; - fg = colormaps[colormapindex + fg]; - - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - - - - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - int sample = texPixels[texelX * texHeight + texelY]; - - uint32_t fgalpha = sample;//clamp(sample, 0, 64) * 4; - uint32_t inv_fgalpha = 256 - fgalpha; - int a = (fgalpha * srcalpha + 128) >> 8; - int inv_a = (destalpha * fgalpha + 256 * inv_fgalpha + 128) >> 8; - - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - - uint32_t fgalpha = APART(fg); - uint32_t inv_fgalpha = 256 - fgalpha; - int a = (fgalpha * srcalpha + 128) >> 8; - int inv_a = (destalpha * fgalpha + 256 * inv_fgalpha + 128) >> 8; - - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - - uint32_t inv_r = 256 - (r + (r >> 7)); - uint32_t inv_g = 256 - (g + (r >> 7)); - uint32_t inv_b = 256 - (b + (r >> 7)); - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = r + ((bg_red * inv_r + 127) >> 8); - g = g + ((bg_green * inv_g + 127) >> 8); - b = b + ((bg_blue * inv_b + 127) >> 8); - - int start_fade = 2; // How fast it should fade out - - int alpha_top = clamp(varyingPos[1] >> (16 - start_fade), 0, 256); - int alpha_bottom = clamp(((2 << 24) - varyingPos[1]) >> (16 - start_fade), 0, 256); - int a = MIN(alpha_top, alpha_bottom); - int inv_a = 256 - a; - - uint32_t bg_red = RPART(color); - uint32_t bg_green = GPART(color); - uint32_t bg_blue = BPART(color); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - - uint32_t a = APART(fg); - a += a >> 7; - uint32_t inv_a = 256 - a; - uint32_t bg = *destptr; - uint32_t bg_red = RPART(bg); - uint32_t bg_green = GPART(bg); - uint32_t bg_blue = BPART(bg); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - \ No newline at end of file diff --git a/src/polyrenderer/drawers/screen_triangle.cpp b/src/polyrenderer/drawers/screen_triangle.cpp index 54af97f2c..b6a737a01 100644 --- a/src/polyrenderer/drawers/screen_triangle.cpp +++ b/src/polyrenderer/drawers/screen_triangle.cpp @@ -36,7 +36,10 @@ #include "poly_triangle.h" #include "swrenderer/drawers/r_draw_rgba.h" #include "screen_triangle.h" -#include "poly_drawers.h" +#ifndef NO_SSE +#include "poly_drawer32_sse2.h" +#endif +#include "poly_drawer8.h" void ScreenTriangle::SetupNormal(const TriDrawTriangleArgs *args, WorkerThreadData *thread) { @@ -702,265 +705,87 @@ void ScreenTriangle::SubsectorWrite(const TriDrawTriangleArgs *args, WorkerThrea } } -#if 0 -float ScreenTriangle::FindGradientX(float x0, float y0, float x1, float y1, float x2, float y2, float c0, float c1, float c2) +std::vector ScreenTriangle::TriDraw8 = { - float top = (c1 - c2) * (y0 - y2) - (c0 - c2) * (y1 - y2); - float bottom = (x1 - x2) * (y0 - y2) - (x0 - x2) * (y1 - y2); - return top / bottom; -} + &TriScreenDrawer8::Execute, // "Copy", "opaque", false + &TriScreenDrawer8::Execute, // "AlphaBlend", "masked", false + &TriScreenDrawer8::Execute, // "AddSolid", "translucent", false + &TriScreenDrawer8::Execute, // "Add", "add", false + &TriScreenDrawer8::Execute, // "Sub", "sub", false + &TriScreenDrawer8::Execute, // "RevSub", "revsub", false + &TriScreenDrawer8::Execute, // "Stencil", "stencil", false + &TriScreenDrawer8::Execute, // "Shaded", "shaded", false + &TriScreenDrawer8::Execute, // "TranslateCopy", "opaque", true + &TriScreenDrawer8::Execute, // "TranslateAlphaBlend", "masked", true + &TriScreenDrawer8::Execute, // "TranslateAdd", "add", true + &TriScreenDrawer8::Execute, // "TranslateSub", "sub", true + &TriScreenDrawer8::Execute, // "TranslateRevSub", "revsub", true + &TriScreenDrawer8::Execute, // "AddSrcColorOneMinusSrcColor", "addsrccolor", false + &TriScreenDrawer8::Execute // "Skycap", "skycap", false +}; -float ScreenTriangle::FindGradientY(float x0, float y0, float x1, float y1, float x2, float y2, float c0, float c1, float c2) +std::vector ScreenTriangle::TriFill8 = { - float top = (c1 - c2) * (x0 - x2) - (c0 - c2) * (x1 - x2); - float bottom = (x0 - x2) * (y1 - y2) - (x1 - x2) * (y0 - y2); - return top / bottom; -} + &TriScreenDrawer8::Execute, // "Copy", "opaque", false + &TriScreenDrawer8::Execute, // "AlphaBlend", "masked", false + &TriScreenDrawer8::Execute, // "AddSolid", "translucent", false + &TriScreenDrawer8::Execute, // "Add", "add", false + &TriScreenDrawer8::Execute, // "Sub", "sub", false + &TriScreenDrawer8::Execute, // "RevSub", "revsub", false + &TriScreenDrawer8::Execute, // "Stencil", "stencil", false + &TriScreenDrawer8::Execute, // "Shaded", "shaded", false + &TriScreenDrawer8::Execute, // "TranslateCopy", "opaque", true + &TriScreenDrawer8::Execute, // "TranslateAlphaBlend", "masked", true + &TriScreenDrawer8::Execute, // "TranslateAdd", "add", true + &TriScreenDrawer8::Execute, // "TranslateSub", "sub", true + &TriScreenDrawer8::Execute, // "TranslateRevSub", "revsub", true + &TriScreenDrawer8::Execute, // "AddSrcColorOneMinusSrcColor", "addsrccolor", false + &TriScreenDrawer8::Execute // "Skycap", "skycap", false +}; -void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, WorkerThreadData *thread) +#ifdef NO_SSE + +std::vector ScreenTriangle::TriDraw32; +std::vector ScreenTriangle::TriFill32; + +#else + +std::vector ScreenTriangle::TriDraw32 = { - int numSpans = thread->NumFullSpans; - auto fullSpans = thread->FullSpans; - int numBlocks = thread->NumPartialBlocks; - auto partialBlocks = thread->PartialBlocks; - int startX = thread->StartX; - int startY = thread->StartY; + &TriScreenDrawer32::Execute, // "Copy", "opaque", false + &TriScreenDrawer32::Execute, // "AlphaBlend", "masked", false + &TriScreenDrawer32::Execute, // "AddSolid", "translucent", false + &TriScreenDrawer32::Execute, // "Add", "add", false + &TriScreenDrawer32::Execute, // "Sub", "sub", false + &TriScreenDrawer32::Execute, // "RevSub", "revsub", false + &TriScreenDrawer32::Execute, // "Stencil", "stencil", false + &TriScreenDrawer32::Execute, // "Shaded", "shaded", false + &TriScreenDrawer32::Execute, // "TranslateCopy", "opaque", true + &TriScreenDrawer32::Execute, // "TranslateAlphaBlend", "masked", true + &TriScreenDrawer32::Execute, // "TranslateAdd", "add", true + &TriScreenDrawer32::Execute, // "TranslateSub", "sub", true + &TriScreenDrawer32::Execute, // "TranslateRevSub", "revsub", true + &TriScreenDrawer32::Execute, // "AddSrcColorOneMinusSrcColor", "addsrccolor", false + &TriScreenDrawer32::Execute // "Skycap", "skycap", false +}; - // Calculate gradients - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - ScreenTriangleStepVariables start; - gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); - start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } +std::vector ScreenTriangle::TriFill32 = +{ + &TriScreenDrawer32::Execute, // "Copy", "opaque", false + &TriScreenDrawer32::Execute, // "AlphaBlend", "masked", false + &TriScreenDrawer32::Execute, // "AddSolid", "translucent", false + &TriScreenDrawer32::Execute, // "Add", "add", false + &TriScreenDrawer32::Execute, // "Sub", "sub", false + &TriScreenDrawer32::Execute, // "RevSub", "revsub", false + &TriScreenDrawer32::Execute, // "Stencil", "stencil", false + &TriScreenDrawer32::Execute, // "Shaded", "shaded", false + &TriScreenDrawer32::Execute, // "TranslateCopy", "opaque", true + &TriScreenDrawer32::Execute, // "TranslateAlphaBlend", "masked", true + &TriScreenDrawer32::Execute, // "TranslateAdd", "add", true + &TriScreenDrawer32::Execute, // "TranslateSub", "sub", true + &TriScreenDrawer32::Execute, // "TranslateRevSub", "revsub", true + &TriScreenDrawer32::Execute, // "AddSrcColorOneMinusSrcColor", "addsrccolor", false + &TriScreenDrawer32::Execute // "Skycap", "skycap", false +}; - const uint32_t * RESTRICT texPixels = (const uint32_t *)args->texturePixels; - uint32_t texWidth = args->textureWidth; - uint32_t texHeight = args->textureHeight; - - uint32_t * RESTRICT destOrg = (uint32_t*)args->dest; - uint32_t * RESTRICT subsectorGBuffer = (uint32_t*)args->subsectorGBuffer; - int pitch = args->pitch; - - uint32_t subsectorDepth = args->uniforms->subsectorDepth; - - uint32_t light = args->uniforms->light; - float shade = (64.0f - (light * 255 / 256 + 12.0f) * 32.0f / 128.0f) / 32.0f; - float globVis = 1706.0f; - - for (int i = 0; i < numSpans; i++) - { - const auto &span = fullSpans[i]; - - uint32_t *dest = destOrg + span.X + span.Y * pitch; - uint32_t *subsector = subsectorGBuffer + span.X + span.Y * pitch; - int width = span.Length; - int height = 8; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); - - for (int y = 0; y < height; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - int lightpos = 256 - (int)(clamp(shade - MIN(24.0f, globVis * blockPosX.W) / 32.0f, 0.0f, 31.0f / 32.0f) * 256.0f); - - for (int x = 0; x < width; x++) - { - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = 256 - (int)(clamp(shade - MIN(24.0f, globVis * blockPosX.W) / 32.0f, 0.0f, 31.0f / 32.0f) * 256.0f); - int lightstep = (lightnext - lightpos) / 8; - - for (int ix = 0; ix < 8; ix++) - { - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = r * lightpos / 256; - g = g * lightpos / 256; - b = b * lightpos / 256; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - - dest[x * 8 + ix] = fg; - subsector[x * 8 + ix] = subsectorDepth; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - subsector += pitch; - } - } - - for (int i = 0; i < numBlocks; i++) - { - const auto &block = partialBlocks[i]; - - ScreenTriangleStepVariables blockPosY; - blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); - - uint32_t *dest = destOrg + block.X + block.Y * pitch; - uint32_t *subsector = subsectorGBuffer + block.X + block.Y * pitch; - uint32_t mask0 = block.Mask0; - uint32_t mask1 = block.Mask1; - for (int y = 0; y < 4; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = 256 - (int)(clamp(shade - MIN(24.0f, globVis * blockPosX.W) / 32.0f, 0.0f, 31.0f / 32.0f) * 256.0f); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = 256 - (int)(clamp(shade - MIN(24.0f, globVis * blockPosX.W) / 32.0f, 0.0f, 31.0f / 32.0f) * 256.0f); - int lightstep = (lightnext - lightpos) / 8; - - for (int x = 0; x < 8; x++) - { - if (mask0 & (1 << 31)) - { - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = r * lightpos / 256; - g = g * lightpos / 256; - b = b * lightpos / 256; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - - dest[x] = fg; - subsector[x] = subsectorDepth; - } - mask0 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - subsector += pitch; - } - for (int y = 4; y < 8; y++) - { - ScreenTriangleStepVariables blockPosX = blockPosY; - - float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); - - int lightpos = 256 - (int)(clamp(shade - MIN(24.0f, globVis * blockPosX.W) / 32.0f, 0.0f, 31.0f / 32.0f) * 256.0f); - - blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; - - rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } - - int lightnext = 256 - (int)(clamp(shade - MIN(24.0f, globVis * blockPosX.W) / 32.0f, 0.0f, 31.0f / 32.0f) * 256.0f); - int lightstep = (lightnext - lightpos) / 8; - - for (int x = 0; x < 8; x++) - { - if (mask1 & (1 << 31)) - { - int texelX = ((((uint32_t)varyingPos[0] << 8) >> 16) * texWidth) >> 16; - int texelY = ((((uint32_t)varyingPos[1] << 8) >> 16) * texHeight) >> 16; - uint32_t fg = texPixels[texelX * texHeight + texelY]; - - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - r = r * lightpos / 256; - g = g * lightpos / 256; - b = b * lightpos / 256; - fg = 0xff000000 | (r << 16) | (g << 8) | b; - - dest[x] = fg; - subsector[x] = subsectorDepth; - } - mask1 <<= 1; - - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; - lightpos += lightstep; - } - - blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; - - dest += pitch; - subsector += pitch; - } - } -} #endif diff --git a/src/polyrenderer/drawers/screen_triangle.h b/src/polyrenderer/drawers/screen_triangle.h index 5539be305..3e539f2c6 100644 --- a/src/polyrenderer/drawers/screen_triangle.h +++ b/src/polyrenderer/drawers/screen_triangle.h @@ -160,3 +160,29 @@ struct ScreenTriangleStepVariables float W; float Varying[TriVertex::NumVarying]; }; + +namespace TriScreenDrawerModes +{ + enum class BlendModes { Opaque, Masked, AddClamp, SubClamp, RevSubClamp, AddSrcColorOneMinusSrcColor }; + struct OpaqueBlend { static const int Mode = (int)BlendModes::Opaque; }; + struct MaskedBlend { static const int Mode = (int)BlendModes::Masked; }; + struct AddClampBlend { static const int Mode = (int)BlendModes::AddClamp; }; + struct SubClampBlend { static const int Mode = (int)BlendModes::SubClamp; }; + struct RevSubClampBlend { static const int Mode = (int)BlendModes::RevSubClamp; }; + struct AddSrcColorBlend { static const int Mode = (int)BlendModes::AddSrcColorOneMinusSrcColor; }; + + enum class FilterModes { Nearest, Linear }; + struct NearestFilter { static const int Mode = (int)FilterModes::Nearest; }; + struct LinearFilter { static const int Mode = (int)FilterModes::Linear; }; + + enum class ShadeMode { Simple, Advanced }; + struct SimpleShade { static const int Mode = (int)ShadeMode::Simple; }; + struct AdvancedShade { static const int Mode = (int)ShadeMode::Advanced; }; + + enum class Samplers { Texture, Fill, Shaded, Translated, Skycap }; + struct TextureSampler { static const int Mode = (int)Samplers::Texture; }; + struct FillSampler { static const int Mode = (int)Samplers::Fill; }; + struct ShadedSampler { static const int Mode = (int)Samplers::Shaded; }; + struct TranslatedSampler { static const int Mode = (int)Samplers::Translated; }; + struct SkycapSampler { static const int Mode = (int)Samplers::Skycap; }; +} diff --git a/src/polyrenderer/scene/poly_decal.cpp b/src/polyrenderer/scene/poly_decal.cpp index 65a1bb767..c77d6a040 100644 --- a/src/polyrenderer/scene/poly_decal.cpp +++ b/src/polyrenderer/scene/poly_decal.cpp @@ -136,7 +136,7 @@ void RenderPolyDecal::Render(const TriMatrix &worldToClip, const Vec4f &clipPlan PolyCameraLight *cameraLight = PolyCameraLight::Instance(); PolyDrawArgs args; - args.uniforms.flags = 0; + args.uniforms.flags = TriUniforms::nearest_filter; args.SetColormap(GetColorTable(front->Colormap)); args.SetTexture(tex, decal->Translation, true); args.uniforms.globvis = (float)PolyRenderer::Instance()->Light.WallGlobVis(foggy); diff --git a/src/polyrenderer/scene/poly_particle.cpp b/src/polyrenderer/scene/poly_particle.cpp index 6fd47021e..94618ef38 100644 --- a/src/polyrenderer/scene/poly_particle.cpp +++ b/src/polyrenderer/scene/poly_particle.cpp @@ -81,12 +81,12 @@ void RenderPolyParticle::Render(const TriMatrix &worldToClip, const Vec4f &clipP if (fullbrightSprite || cameraLight->FixedLightLevel() >= 0 || cameraLight->FixedColormap()) { args.uniforms.light = 256; - args.uniforms.flags = TriUniforms::fixed_light; + args.uniforms.flags = TriUniforms::fixed_light | TriUniforms::nearest_filter; } else { args.uniforms.light = (uint32_t)((sub->sector->lightlevel + actualextralight) / 255.0f * 256.0f); - args.uniforms.flags = 0; + args.uniforms.flags = TriUniforms::nearest_filter; } args.uniforms.subsectorDepth = subsectorDepth; diff --git a/src/polyrenderer/scene/poly_plane.cpp b/src/polyrenderer/scene/poly_plane.cpp index dd6fb1936..a885f778a 100644 --- a/src/polyrenderer/scene/poly_plane.cpp +++ b/src/polyrenderer/scene/poly_plane.cpp @@ -116,7 +116,7 @@ void RenderPolyPlane::Render3DFloor(const TriMatrix &worldToClip, const Vec4f &c args.uniforms.light = (uint32_t)(lightlevel / 255.0f * 256.0f); if (cameraLight->FixedLightLevel() >= 0 || cameraLight->FixedColormap()) args.uniforms.light = 256; - args.uniforms.flags = 0; + args.uniforms.flags = TriUniforms::nearest_filter; args.uniforms.subsectorDepth = subsectorDepth; TriVertex *vertices = PolyVertexBuffer::GetVertices(sub->numlines); @@ -314,7 +314,7 @@ void RenderPolyPlane::Render(const TriMatrix &worldToClip, const Vec4f &clipPlan args.uniforms.light = (uint32_t)(frontsector->lightlevel / 255.0f * 256.0f); if (cameraLight->FixedLightLevel() >= 0 || cameraLight->FixedColormap()) args.uniforms.light = 256; - args.uniforms.flags = 0; + args.uniforms.flags = TriUniforms::nearest_filter; args.uniforms.subsectorDepth = isSky ? RenderPolyScene::SkySubsectorDepth : subsectorDepth; TriVertex *vertices = PolyVertexBuffer::GetVertices(sub->numlines); diff --git a/src/polyrenderer/scene/poly_sky.cpp b/src/polyrenderer/scene/poly_sky.cpp index 0c1c0ae14..3be38e481 100644 --- a/src/polyrenderer/scene/poly_sky.cpp +++ b/src/polyrenderer/scene/poly_sky.cpp @@ -59,7 +59,7 @@ void PolySkyDome::Render(const TriMatrix &worldToClip) PolyDrawArgs args; args.uniforms.globvis = (float)PolyRenderer::Instance()->Light.WallGlobVis(foggy); args.uniforms.light = 256; - args.uniforms.flags = 0; + args.uniforms.flags = TriUniforms::nearest_filter; args.uniforms.subsectorDepth = RenderPolyScene::SkySubsectorDepth; args.objectToClip = &objectToClip; args.stenciltestvalue = 255; diff --git a/src/polyrenderer/scene/poly_sprite.cpp b/src/polyrenderer/scene/poly_sprite.cpp index 37cc5dbd5..fa197eb89 100644 --- a/src/polyrenderer/scene/poly_sprite.cpp +++ b/src/polyrenderer/scene/poly_sprite.cpp @@ -142,7 +142,7 @@ void RenderPolySprite::Render(const TriMatrix &worldToClip, const Vec4f &clipPla PolyDrawArgs args; args.uniforms.globvis = (float)PolyRenderer::Instance()->Light.SpriteGlobVis(foggy); - args.uniforms.flags = 0; + args.uniforms.flags = TriUniforms::nearest_filter; if (fullbrightSprite || cameraLight->FixedLightLevel() >= 0 || cameraLight->FixedColormap()) { args.uniforms.light = 256; diff --git a/src/polyrenderer/scene/poly_wall.cpp b/src/polyrenderer/scene/poly_wall.cpp index 5c1b6988b..996e51094 100644 --- a/src/polyrenderer/scene/poly_wall.cpp +++ b/src/polyrenderer/scene/poly_wall.cpp @@ -251,7 +251,7 @@ void RenderPolyWall::Render(const TriMatrix &worldToClip, const Vec4f &clipPlane PolyDrawArgs args; args.uniforms.globvis = (float)PolyRenderer::Instance()->Light.WallGlobVis(foggy); args.uniforms.light = (uint32_t)(GetLightLevel() / 255.0f * 256.0f); - args.uniforms.flags = 0; + args.uniforms.flags = TriUniforms::nearest_filter; args.uniforms.subsectorDepth = SubsectorDepth; args.objectToClip = &worldToClip; args.vinput = vertices; diff --git a/src/polyrenderer/scene/poly_wallsprite.cpp b/src/polyrenderer/scene/poly_wallsprite.cpp index fb8c75318..bbefbe91e 100644 --- a/src/polyrenderer/scene/poly_wallsprite.cpp +++ b/src/polyrenderer/scene/poly_wallsprite.cpp @@ -106,12 +106,12 @@ void RenderPolyWallSprite::Render(const TriMatrix &worldToClip, const Vec4f &cli if (fullbrightSprite || cameraLight->FixedLightLevel() >= 0 || cameraLight->FixedColormap()) { args.uniforms.light = 256; - args.uniforms.flags = TriUniforms::fixed_light; + args.uniforms.flags = TriUniforms::fixed_light | TriUniforms::nearest_filter; } else { args.uniforms.light = (uint32_t)((thing->Sector->lightlevel + actualextralight) / 255.0f * 256.0f); - args.uniforms.flags = 0; + args.uniforms.flags = TriUniforms::nearest_filter; } args.uniforms.subsectorDepth = subsectorDepth;