From b17351cda478cbea32810c6e477a2e17c30f7b60 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 5 Aug 2019 08:37:22 +0200 Subject: [PATCH] - implement blend functions --- .../polyrenderer/drawers/poly_draw_args.h | 69 -------------- .../polyrenderer/drawers/screen_triangle.cpp | 93 +++++++++++++++++-- 2 files changed, 84 insertions(+), 78 deletions(-) diff --git a/src/rendering/polyrenderer/drawers/poly_draw_args.h b/src/rendering/polyrenderer/drawers/poly_draw_args.h index 3a15c3a313a..a681b5f37ae 100644 --- a/src/rendering/polyrenderer/drawers/poly_draw_args.h +++ b/src/rendering/polyrenderer/drawers/poly_draw_args.h @@ -168,72 +168,3 @@ class PolyDrawArgs FVector3 mNormal; uint32_t mDynLightColor = 0; }; - -#if 0 -class RectDrawArgs -{ -public: - void SetTexture(FSoftwareTexture *texture, FRenderStyle style); - void SetTexture(FSoftwareTexture *texture, uint32_t translationID, FRenderStyle style); - void SetLight(FSWColormap *basecolormap, uint32_t lightlevel); - void SetStyle(TriBlendMode blendmode, double alpha = 1.0) { mBlendMode = blendmode; mAlpha = (uint32_t)(alpha * 256.0 + 0.5); } - void SetStyle(const FRenderStyle &renderstyle, double alpha, uint32_t fillcolor, uint32_t translationID, FSoftwareTexture *texture, bool fullbright); - void SetColor(uint32_t bgra, uint8_t palindex); - void Draw(PolyRenderThread *thread, double x0, double x1, double y0, double y1, double u0, double u1, double v0, double v1); - - FSoftwareTexture *Texture() const { return mTexture; } - const uint8_t *TexturePixels() const { return mTexturePixels; } - int TextureWidth() const { return mTextureWidth; } - int TextureHeight() const { return mTextureHeight; } - const uint8_t *Translation() const { return mTranslation; } - - TriBlendMode BlendMode() const { return mBlendMode; } - uint32_t Color() const { return mColor; } - uint32_t Alpha() const { return mAlpha; } - - uint32_t Light() const { return mLight; } - const uint8_t *BaseColormap() const { return mColormaps; } - uint16_t ShadeLightAlpha() const { return mLightAlpha; } - uint16_t ShadeLightRed() const { return mLightRed; } - uint16_t ShadeLightGreen() const { return mLightGreen; } - uint16_t ShadeLightBlue() const { return mLightBlue; } - uint16_t ShadeFadeAlpha() const { return mFadeAlpha; } - uint16_t ShadeFadeRed() const { return mFadeRed; } - uint16_t ShadeFadeGreen() const { return mFadeGreen; } - uint16_t ShadeFadeBlue() const { return mFadeBlue; } - uint16_t ShadeDesaturate() const { return mDesaturate; } - bool SimpleShade() const { return mSimpleShade; } - - float X0() const { return mX0; } - float X1() const { return mX1; } - float Y0() const { return mY0; } - float Y1() const { return mY1; } - float U0() const { return mU0; } - float U1() const { return mU1; } - float V0() const { return mV0; } - float V1() const { return mV1; } - -private: - FSoftwareTexture *mTexture = nullptr; - const uint8_t *mTexturePixels = nullptr; - int mTextureWidth = 0; - int mTextureHeight = 0; - const uint8_t *mTranslation = nullptr; - const uint8_t *mColormaps = nullptr; - TriBlendMode mBlendMode = TriBlendMode::Fill; - uint32_t mLight = 0; - uint32_t mColor = 0; - uint32_t mAlpha = 0; - uint16_t mLightAlpha = 0; - uint16_t mLightRed = 0; - uint16_t mLightGreen = 0; - uint16_t mLightBlue = 0; - uint16_t mFadeAlpha = 0; - uint16_t mFadeRed = 0; - uint16_t mFadeGreen = 0; - uint16_t mFadeBlue = 0; - uint16_t mDesaturate = 0; - bool mSimpleShade = true; - float mX0, mX1, mY0, mY1, mU0, mU1, mV0, mV1; -}; -#endif diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.cpp b/src/rendering/polyrenderer/drawers/screen_triangle.cpp index ae189ad8ff6..7d74f564e87 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/screen_triangle.cpp @@ -74,25 +74,100 @@ static void WriteVaryings(int y, int x0, int x1, const TriDrawTriangleArgs* args WriteVarying(args->v1->worldZ * args->v1->w + args->gradientX.WorldZ * startX + args->gradientY.WorldZ * startY, args->gradientX.WorldZ, x0, x1, thread->scanline.W, thread->scanline.WorldZ); } -static void WriteBlend(int y, int x0, int x1, PolyTriangleThreadData* thread) +static uint32_t BlendColor(FRenderStyle style, uint32_t fg, uint32_t bg) +{ + static const int shiftTable[] = { + 0, 0, 0, 0, // STYLEALPHA_Zero + 0, 0, 0, 0, // STYLEALPHA_One + 24, 24, 24, 24, // STYLEALPHA_Src + 24, 24, 24, 24, // STYLEALPHA_InvSrc + 24, 16, 8, 0, // STYLEALPHA_SrcCol + 24, 16, 8, 0, // STYLEALPHA_InvSrcCol + 24, 16, 8, 0, // STYLEALPHA_DstCol + 24, 16, 8, 0 // STYLEALPHA_InvDstCol + }; + + bool invsrc = style.SrcAlpha & 1; + bool invdst = style.DestAlpha & 1; + + int srcinput = style.SrcAlpha <= STYLEALPHA_One ? 0 : (style.SrcAlpha >= STYLEALPHA_DstCol ? bg : fg); + int dstinput = style.DestAlpha <= STYLEALPHA_One ? 0 : (style.DestAlpha >= STYLEALPHA_DstCol ? bg : fg); + + const int* shiftsrc = shiftTable + (style.SrcAlpha << 2); + const int* shiftdst = shiftTable + (style.DestAlpha << 2); + + int32_t src[4], dst[4]; + for (int i = 0; i < 4; i++) + { + // Grab component for scale factors + src[i] = (srcinput >> shiftsrc[i]) & 0xff; + dst[i] = (dstinput >> shiftdst[i]) & 0xff; + + // Inverse if needed + src[i] = invsrc ? 0xff - src[i] : src[i]; + dst[i] = invdst ? 0xff - dst[i] : dst[i]; + + // Rescale 0-255 to 0-256 + src[i] = src[i] + (src[i] >> 7); + dst[i] = dst[i] + (dst[i] >> 7); + + // Multiply with input + src[i] = src[i] * ((fg >> (24 - (i << 3))) & 0xff); + dst[i] = dst[i] * ((bg >> (24 - (i << 3))) & 0xff); + } + + uint32_t out[4]; + switch (style.BlendOp) + { + default: + case STYLEOP_Add: for (int i = 0; i < 4; i++) out[i] = clamp((src[i] + dst[i] + 127) >> 8, 0, 255); break; + case STYLEOP_Sub: for (int i = 0; i < 4; i++) out[i] = clamp((src[i] - dst[i] + 127) >> 8, 0, 255); break; + case STYLEOP_RevSub: for (int i = 0; i < 4; i++) out[i] = clamp((dst[i] - src[i] + 127) >> 8, 0, 255); break; + } + return MAKEARGB(out[0], out[1], out[2], out[3]); +} + +static void WriteColor(int y, int x0, int x1, PolyTriangleThreadData* thread) { uint32_t* dest = (uint32_t*)thread->dest; uint32_t* line = dest + y * (ptrdiff_t)thread->dest_pitch; + FRenderStyle style = thread->RenderStyle; + uint32_t* fragcolor = thread->scanline.FragColor; - if (!thread->AlphaTest) + if (style.BlendOp == STYLEOP_Add && style.SrcAlpha == STYLEALPHA_One && style.DestAlpha == STYLEALPHA_Zero) { - for (int x = x0; x < x1; x++) + if (!thread->AlphaTest) + { + for (int x = x0; x < x1; x++) + { + line[x] = fragcolor[x]; + } + } + else { - line[x] = thread->scanline.FragColor[x]; + for (int x = x0; x < x1; x++) + { + if (fragcolor[x] > 0x7f000000) + line[x] = fragcolor[x]; + } } } else { - uint32_t* fragcolor = thread->scanline.FragColor; - for (int x = x0; x < x1; x++) + if (!thread->AlphaTest) { - if (fragcolor[x] > 0x7f000000) - line[x] = thread->scanline.FragColor[x]; + for (int x = x0; x < x1; x++) + { + line[x] = BlendColor(style, fragcolor[x], line[x]); + } + } + else + { + for (int x = x0; x < x1; x++) + { + if (fragcolor[x] > 0x7f000000) + line[x] = BlendColor(style, fragcolor[x], line[x]); + } } } } @@ -173,7 +248,7 @@ static void DrawSpan(int y, int x0, int x1, const TriDrawTriangleArgs* args, Pol RunShader(x0, x1, thread); if (thread->drawargs.WriteColor()) - WriteBlend(y, x0, x1, thread); + WriteColor(y, x0, x1, thread); if (thread->drawargs.WriteDepth()) WriteDepth(y, x0, x1, thread); if (thread->drawargs.WriteStencil())