diff --git a/src/polyrenderer/drawers/poly_draw_args.cpp b/src/polyrenderer/drawers/poly_draw_args.cpp index 4c526d1ef7..29d32a2fc7 100644 --- a/src/polyrenderer/drawers/poly_draw_args.cpp +++ b/src/polyrenderer/drawers/poly_draw_args.cpp @@ -166,11 +166,12 @@ void PolyDrawArgs::SetStyle(const FRenderStyle &renderstyle, double alpha, uint3 { SetStyle(Translation() ? TriBlendMode::TranslatedAdd : TriBlendMode::TextureAdd, transsouls, 1.0 - transsouls); } - else if (renderstyle == LegacyRenderStyles[STYLE_Fuzzy] || (r_drawfuzz == 2 && renderstyle == LegacyRenderStyles[STYLE_OptFuzzy])) - { // NYI - Fuzzy - for now, just a copy of "Shadow" - SetStyle(Translation() ? TriBlendMode::TranslatedAdd : TriBlendMode::TextureAdd, 0.0, 160 / 255.0); + else if (renderstyle == LegacyRenderStyles[STYLE_Fuzzy] || (r_drawfuzz == 1 && renderstyle == LegacyRenderStyles[STYLE_OptFuzzy])) + { + SetColor(0xff000000, 0); + SetStyle(TriBlendMode::Fuzz); } - else if (renderstyle == LegacyRenderStyles[STYLE_Shadow] || (r_drawfuzz == 1 && renderstyle == LegacyRenderStyles[STYLE_OptFuzzy])) + else if (renderstyle == LegacyRenderStyles[STYLE_Shadow] || (r_drawfuzz == 2 && renderstyle == LegacyRenderStyles[STYLE_OptFuzzy])) { SetStyle(Translation() ? TriBlendMode::TranslatedAdd : TriBlendMode::TextureAdd, 0.0, 160 / 255.0); } @@ -318,11 +319,12 @@ void RectDrawArgs::SetStyle(const FRenderStyle &renderstyle, double alpha, uint3 { SetStyle(Translation() ? TriBlendMode::TranslatedAdd : TriBlendMode::TextureAdd, transsouls, 1.0 - transsouls); } - else if (renderstyle == LegacyRenderStyles[STYLE_Fuzzy] || (r_drawfuzz == 2 && renderstyle == LegacyRenderStyles[STYLE_OptFuzzy])) - { // NYI - Fuzzy - for now, just a copy of "Shadow" - SetStyle(Translation() ? TriBlendMode::TranslatedAdd : TriBlendMode::TextureAdd, 0.0, 160 / 255.0); + else if (renderstyle == LegacyRenderStyles[STYLE_Fuzzy] || (r_drawfuzz == 1 && renderstyle == LegacyRenderStyles[STYLE_OptFuzzy])) + { + SetColor(0xff000000, 0); + SetStyle(TriBlendMode::Fuzz); } - else if (renderstyle == LegacyRenderStyles[STYLE_Shadow] || (r_drawfuzz == 1 && renderstyle == LegacyRenderStyles[STYLE_OptFuzzy])) + else if (renderstyle == LegacyRenderStyles[STYLE_Shadow] || (r_drawfuzz == 2 && renderstyle == LegacyRenderStyles[STYLE_OptFuzzy])) { SetStyle(Translation() ? TriBlendMode::TranslatedAdd : TriBlendMode::TextureAdd, 0.0, 160 / 255.0); } diff --git a/src/polyrenderer/drawers/poly_drawer32_sse2.h b/src/polyrenderer/drawers/poly_drawer32_sse2.h index 119c50746a..4070543379 100644 --- a/src/polyrenderer/drawers/poly_drawer32_sse2.h +++ b/src/polyrenderer/drawers/poly_drawer32_sse2.h @@ -30,7 +30,7 @@ namespace TriScreenDrawerModes FORCEINLINE unsigned int VECTORCALL Sample32(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) { uint32_t texel; - if (SamplerT::Mode == (int)Samplers::Shaded || SamplerT::Mode == (int)Samplers::Stencil || SamplerT::Mode == (int)Samplers::Fill) + if (SamplerT::Mode == (int)Samplers::Shaded || SamplerT::Mode == (int)Samplers::Stencil || SamplerT::Mode == (int)Samplers::Fill || SamplerT::Mode == (int)Samplers::Fuzz) { return color; } @@ -107,7 +107,7 @@ namespace TriScreenDrawerModes } template - FORCEINLINE unsigned int VECTORCALL SampleShade32(int32_t u, int32_t v, const uint32_t *texPixels, int texWidth, int texHeight) + FORCEINLINE unsigned int VECTORCALL SampleShade32(int32_t u, int32_t v, const uint32_t *texPixels, int texWidth, int texHeight, int &fuzzpos) { if (SamplerT::Mode == (int)Samplers::Shaded) { @@ -126,6 +126,16 @@ namespace TriScreenDrawerModes sampleshadeout += sampleshadeout >> 7; // 255 -> 256 return sampleshadeout; } + else if (SamplerT::Mode == (int)Samplers::Fuzz) + { + uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16; + uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; + unsigned int sampleshadeout = APART(texPixels[texelX * texHeight + texelY]); + sampleshadeout += sampleshadeout >> 7; // 255 -> 256 + sampleshadeout = (sampleshadeout * fuzzcolormap[fuzzpos++]) >> 5; + if (fuzzpos >= FUZZTABLE) fuzzpos = 0; + return sampleshadeout; + } else { return 0; @@ -139,7 +149,7 @@ namespace TriScreenDrawerModes { fgcolor = _mm_srli_epi16(_mm_mullo_epi16(fgcolor, mlight), 8); } - else + else if (ShadeModeT::Mode == (int)ShadeMode::Advanced) { int blue0 = BPART(ifgcolor0); int green0 = GPART(ifgcolor0); @@ -293,6 +303,10 @@ public: DrawBlock(x, y, mask0, mask1, args); } } + else if (SamplerT::Mode == (int)Samplers::Fuzz) + { + DrawBlock(x, y, mask0, mask1, args); + } else // no linear filtering for translated, shaded, stencil, fill or skycap { if (is_simple_shade) @@ -317,6 +331,8 @@ private: uint32_t srcalpha = args->uniforms->SrcAlpha(); uint32_t destalpha = args->uniforms->DestAlpha(); + int fuzzpos = (ScreenTriangle::FuzzStart + destX * 123 + destY) % FUZZTABLE; + // Calculate gradients const TriVertex &v1 = *args->v1; ScreenTriangleStepVariables gradientX = args->gradientX; @@ -415,12 +431,12 @@ private: // Sample fgcolor unsigned int ifgcolor[2], ifgshade[2]; ifgcolor[0] = Sample32(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation); - ifgshade[0] = SampleShade32(posU, posV, texPixels, texWidth, texHeight); + ifgshade[0] = SampleShade32(posU, posV, texPixels, texWidth, texHeight, fuzzpos); posU += stepU; posV += stepV; ifgcolor[1] = Sample32(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation); - ifgshade[1] = SampleShade32(posU, posV, texPixels, texWidth, texHeight); + ifgshade[1] = SampleShade32(posU, posV, texPixels, texWidth, texHeight, fuzzpos); posU += stepU; posV += stepV; @@ -501,12 +517,12 @@ private: // Sample fgcolor unsigned int ifgcolor[2], ifgshade[2]; ifgcolor[0] = Sample32(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation); - ifgshade[0] = SampleShade32(posU, posV, texPixels, texWidth, texHeight); + ifgshade[0] = SampleShade32(posU, posV, texPixels, texWidth, texHeight, fuzzpos); posU += stepU; posV += stepV; ifgcolor[1] = Sample32(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation); - ifgshade[1] = SampleShade32(posU, posV, texPixels, texWidth, texHeight); + ifgshade[1] = SampleShade32(posU, posV, texPixels, texWidth, texHeight, fuzzpos); posU += stepU; posV += stepV; @@ -589,12 +605,12 @@ private: // Sample fgcolor unsigned int ifgcolor[2], ifgshade[2]; ifgcolor[0] = Sample32(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation); - ifgshade[0] = SampleShade32(posU, posV, texPixels, texWidth, texHeight); + ifgshade[0] = SampleShade32(posU, posV, texPixels, texWidth, texHeight, fuzzpos); posU += stepU; posV += stepV; ifgcolor[1] = Sample32(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation); - ifgshade[1] = SampleShade32(posU, posV, texPixels, texWidth, texHeight); + ifgshade[1] = SampleShade32(posU, posV, texPixels, texWidth, texHeight, fuzzpos); posU += stepU; posV += stepV; @@ -736,12 +752,17 @@ private: int count = x1 - x0; int sseCount = count / 2; + int fuzzpos = (ScreenTriangle::FuzzStart + x0 * 123 + y0) % FUZZTABLE; + uint32_t posV = startV; for (int y = y0; y < y1; y++, posV += stepV) { int coreBlock = y / 8; if (coreBlock % thread->num_cores != thread->core) + { + fuzzpos = (fuzzpos + count) % FUZZTABLE; continue; + } uint32_t *dest = ((uint32_t*)destOrg) + y * destPitch + x0; @@ -758,11 +779,11 @@ private: // Sample fgcolor unsigned int ifgcolor[2], ifgshade[2]; ifgcolor[0] = Sample32(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation); - ifgshade[0] = SampleShade32(posU, posV, texPixels, texWidth, texHeight); + ifgshade[0] = SampleShade32(posU, posV, texPixels, texWidth, texHeight, fuzzpos); posU += stepU; ifgcolor[1] = Sample32(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation); - ifgshade[1] = SampleShade32(posU, posV, texPixels, texWidth, texHeight); + ifgshade[1] = SampleShade32(posU, posV, texPixels, texWidth, texHeight, fuzzpos); posU += stepU; // Shade and blend @@ -787,7 +808,7 @@ private: // Sample fgcolor unsigned int ifgcolor[2], ifgshade[2]; ifgcolor[0] = Sample32(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation); - ifgshade[0] = SampleShade32(posU, posV, texPixels, texWidth, texHeight); + ifgshade[0] = SampleShade32(posU, posV, texPixels, texWidth, texHeight, fuzzpos); ifgcolor[1] = 0; ifgshade[1] = 0; posU += stepU; diff --git a/src/polyrenderer/drawers/poly_drawer8.h b/src/polyrenderer/drawers/poly_drawer8.h index 8838035be1..a37fa3a119 100644 --- a/src/polyrenderer/drawers/poly_drawer8.h +++ b/src/polyrenderer/drawers/poly_drawer8.h @@ -30,7 +30,7 @@ namespace TriScreenDrawerModes FORCEINLINE unsigned int Sample8(int32_t u, int32_t v, const uint8_t *texPixels, int texWidth, int texHeight, uint32_t color, const uint8_t *translation) { uint8_t texel; - if (SamplerT::Mode == (int)Samplers::Shaded || SamplerT::Mode == (int)Samplers::Stencil || SamplerT::Mode == (int)Samplers::Fill) + if (SamplerT::Mode == (int)Samplers::Shaded || SamplerT::Mode == (int)Samplers::Stencil || SamplerT::Mode == (int)Samplers::Fill || SamplerT::Mode == (int)Samplers::Fuzz) { return color; } @@ -79,7 +79,7 @@ namespace TriScreenDrawerModes } template - FORCEINLINE unsigned int SampleShade8(int32_t u, int32_t v, const uint8_t *texPixels, int texWidth, int texHeight) + FORCEINLINE unsigned int SampleShade8(int32_t u, int32_t v, const uint8_t *texPixels, int texWidth, int texHeight, int &fuzzpos) { if (SamplerT::Mode == (int)Samplers::Shaded) { @@ -95,6 +95,15 @@ namespace TriScreenDrawerModes uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; return texPixels[texelX * texHeight + texelY] != 0 ? 256 : 0; } + else if (SamplerT::Mode == (int)Samplers::Fuzz) + { + uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16; + uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; + unsigned int sampleshadeout = (texPixels[texelX * texHeight + texelY] != 0) ? 256 : 0; + sampleshadeout = (sampleshadeout * fuzzcolormap[fuzzpos++]) >> 5; + if (fuzzpos >= FUZZTABLE) fuzzpos = 0; + return sampleshadeout; + } else { return 0; @@ -219,6 +228,8 @@ public: uint32_t srcalpha = args->uniforms->SrcAlpha(); uint32_t destalpha = args->uniforms->DestAlpha(); + int fuzzpos = (ScreenTriangle::FuzzStart + destX * 123 + destY) % FUZZTABLE; + // Calculate gradients const TriVertex &v1 = *args->v1; ScreenTriangleStepVariables gradientX = args->gradientX; @@ -280,7 +291,8 @@ public: int lightshade = lightpos >> 8; uint8_t bgcolor = dest[ix]; uint8_t fgcolor = Sample8(posU, posV, texPixels, texWidth, texHeight, color, translation); - uint32_t fgshade = SampleShade8(posU, posV, texPixels, texWidth, texHeight); + uint32_t fgshade = SampleShade8(posU, posV, texPixels, texWidth, texHeight, fuzzpos); + if (SamplerT::Mode == (int)Samplers::Fuzz) lightshade = 256; dest[ix] = ShadeAndBlend8(fgcolor, bgcolor, fgshade, lightshade, colormaps, srcalpha, destalpha); posU += stepU; posV += stepV; @@ -328,7 +340,8 @@ public: int lightshade = lightpos >> 8; uint8_t bgcolor = dest[x]; uint8_t fgcolor = Sample8(posU, posV, texPixels, texWidth, texHeight, color, translation); - uint32_t fgshade = SampleShade8(posU, posV, texPixels, texWidth, texHeight); + uint32_t fgshade = SampleShade8(posU, posV, texPixels, texWidth, texHeight, fuzzpos); + if (SamplerT::Mode == (int)Samplers::Fuzz) lightshade = 256; dest[x] = ShadeAndBlend8(fgcolor, bgcolor, fgshade, lightshade, colormaps, srcalpha, destalpha); } @@ -378,7 +391,8 @@ public: int lightshade = lightpos >> 8; uint8_t bgcolor = dest[x]; uint8_t fgcolor = Sample8(posU, posV, texPixels, texWidth, texHeight, color, translation); - uint32_t fgshade = SampleShade8(posU, posV, texPixels, texWidth, texHeight); + uint32_t fgshade = SampleShade8(posU, posV, texPixels, texWidth, texHeight, fuzzpos); + if (SamplerT::Mode == (int)Samplers::Fuzz) lightshade = 256; dest[x] = ShadeAndBlend8(fgcolor, bgcolor, fgshade, lightshade, colormaps, srcalpha, destalpha); } @@ -437,15 +451,21 @@ public: // Setup light uint32_t lightshade = args->Light(); lightshade += lightshade >> 7; // 255 -> 256 + if (SamplerT::Mode == (int)Samplers::Fuzz) lightshade = 256; int count = x1 - x0; + int fuzzpos = (ScreenTriangle::FuzzStart + x0 * 123 + y0) % FUZZTABLE; + uint32_t posV = startV; for (int y = y0; y < y1; y++, posV += stepV) { int coreBlock = y / 8; if (coreBlock % thread->num_cores != thread->core) + { + fuzzpos = (fuzzpos + count) % FUZZTABLE; continue; + } uint8_t *dest = ((uint8_t*)destOrg) + y * destPitch + x0; @@ -454,7 +474,7 @@ public: { uint8_t bgcolor = *dest; uint8_t fgcolor = Sample8(posU, posV, texPixels, texWidth, texHeight, color, translation); - uint32_t fgshade = SampleShade8(posU, posV, texPixels, texWidth, texHeight); + uint32_t fgshade = SampleShade8(posU, posV, texPixels, texWidth, texHeight, fuzzpos); *dest = ShadeAndBlend8(fgcolor, bgcolor, fgshade, lightshade, colormaps, srcalpha, destalpha); posU += stepU; diff --git a/src/polyrenderer/drawers/screen_triangle.cpp b/src/polyrenderer/drawers/screen_triangle.cpp index f8c300dc72..8c5723d8bd 100644 --- a/src/polyrenderer/drawers/screen_triangle.cpp +++ b/src/polyrenderer/drawers/screen_triangle.cpp @@ -914,7 +914,8 @@ void(*ScreenTriangle::TriDrawers8[])(int, int, uint32_t, uint32_t, const TriDraw &TriScreenDrawer8::Execute, // FillSub &TriScreenDrawer8::Execute, // FillRevSub &TriScreenDrawer8::Execute, // FillAddSrcColor - &TriScreenDrawer8::Execute // Skycap + &TriScreenDrawer8::Execute, // Skycap + &TriScreenDrawer8::Execute // Fuzz }; #ifdef NO_SSE @@ -949,7 +950,8 @@ void(*ScreenTriangle::TriDrawers32[])(int, int, uint32_t, uint32_t, const TriDra &TriScreenDrawer32::Execute, // FillSub &TriScreenDrawer32::Execute, // FillRevSub &TriScreenDrawer32::Execute, // FillAddSrcColor - &TriScreenDrawer32::Execute // Skycap + &TriScreenDrawer32::Execute, // Skycap + &TriScreenDrawer32::Execute // Fuzz }; #endif @@ -977,7 +979,8 @@ void(*ScreenTriangle::RectDrawers8[])(const void *, int, int, int, const RectDra &RectScreenDrawer8::Execute, // FillSub &RectScreenDrawer8::Execute, // FillRevSub &RectScreenDrawer8::Execute, // FillAddSrcColor - &RectScreenDrawer8::Execute // Skycap + &RectScreenDrawer8::Execute, // Skycap + &RectScreenDrawer8::Execute // Fuzz }; #ifdef NO_SSE @@ -1012,7 +1015,10 @@ void(*ScreenTriangle::RectDrawers32[])(const void *, int, int, int, const RectDr &RectScreenDrawer32::Execute, // FillSub &RectScreenDrawer32::Execute, // FillRevSub &RectScreenDrawer32::Execute, // FillAddSrcColor - &RectScreenDrawer32::Execute // Skycap + &RectScreenDrawer32::Execute, // Skycap + &RectScreenDrawer32::Execute // Fuzz }; +int ScreenTriangle::FuzzStart = 0; + #endif diff --git a/src/polyrenderer/drawers/screen_triangle.h b/src/polyrenderer/drawers/screen_triangle.h index 3f8d33f73b..3dd4c24eb4 100644 --- a/src/polyrenderer/drawers/screen_triangle.h +++ b/src/polyrenderer/drawers/screen_triangle.h @@ -117,7 +117,8 @@ enum class TriBlendMode FillSub, FillRevSub, FillAddSrcColor, - Skycap + Skycap, + Fuzz }; class ScreenTriangle @@ -129,6 +130,8 @@ public: static void(*TriDrawers32[])(int, int, uint32_t, uint32_t, const TriDrawTriangleArgs *); static void(*RectDrawers8[])(const void *, int, int, int, const RectDrawArgs *, WorkerThreadData *); static void(*RectDrawers32[])(const void *, int, int, int, const RectDrawArgs *, WorkerThreadData *); + + static int FuzzStart; }; namespace TriScreenDrawerModes @@ -147,15 +150,26 @@ namespace TriScreenDrawerModes struct NearestFilter { static const int Mode = (int)FilterModes::Nearest; }; struct LinearFilter { static const int Mode = (int)FilterModes::Linear; }; - enum class ShadeMode { Simple, Advanced }; + enum class ShadeMode { None, Simple, Advanced }; + struct NoShade { static const int Mode = (int)ShadeMode::None; }; struct SimpleShade { static const int Mode = (int)ShadeMode::Simple; }; struct AdvancedShade { static const int Mode = (int)ShadeMode::Advanced; }; - enum class Samplers { Texture, Fill, Shaded, Stencil, Translated, Skycap }; + enum class Samplers { Texture, Fill, Shaded, Stencil, Translated, Skycap, Fuzz }; 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 StencilSampler { static const int Mode = (int)Samplers::Stencil; }; struct TranslatedSampler { static const int Mode = (int)Samplers::Translated; }; struct SkycapSampler { static const int Mode = (int)Samplers::Skycap; }; + struct FuzzSampler { static const int Mode = (int)Samplers::Fuzz; }; + + static const int fuzzcolormap[FUZZTABLE] = + { + 6, 11, 6, 11, 6, 6, 11, 6, 6, 11, + 6, 6, 6, 11, 6, 6, 6, 11, 15, 18, + 21, 6, 11, 15, 6, 6, 6, 6, 11, 6, + 11, 6, 6, 11, 15, 6, 6, 11, 15, 18, + 21, 6, 6, 6, 6, 11, 6, 6, 11, 6, + }; } diff --git a/src/polyrenderer/poly_renderer.cpp b/src/polyrenderer/poly_renderer.cpp index 9cf2824548..33f489cb53 100644 --- a/src/polyrenderer/poly_renderer.cpp +++ b/src/polyrenderer/poly_renderer.cpp @@ -131,6 +131,8 @@ void PolyRenderer::RenderActorView(AActor *actor, bool dontmaplines) if (!Viewpoint.showviewer) Viewpoint.camera->renderflags |= RF_INVISIBLE; + ScreenTriangle::FuzzStart = (ScreenTriangle::FuzzStart + 14) % FUZZTABLE; + ClearBuffers(); SetSceneViewport(); SetupPerspectiveMatrix();