From 1b9479ea45ae8e349523a5a7a9e7e1341ed079f3 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 1 Dec 2019 21:44:44 +0100 Subject: [PATCH 1/2] Implement burn.fp and second texture binding --- .../polyrenderer/backend/poly_renderstate.cpp | 12 ++++++- .../polyrenderer/drawers/poly_draw_args.cpp | 7 ++++ .../polyrenderer/drawers/poly_draw_args.h | 8 +++++ .../polyrenderer/drawers/poly_triangle.cpp | 11 ++++--- .../polyrenderer/drawers/poly_triangle.h | 9 ++--- .../polyrenderer/drawers/screen_triangle.cpp | 33 ++++++++++++++++--- 6 files changed, 67 insertions(+), 13 deletions(-) diff --git a/src/rendering/polyrenderer/backend/poly_renderstate.cpp b/src/rendering/polyrenderer/backend/poly_renderstate.cpp index 4adf4a59b..046a5c467 100644 --- a/src/rendering/polyrenderer/backend/poly_renderstate.cpp +++ b/src/rendering/polyrenderer/backend/poly_renderstate.cpp @@ -233,7 +233,17 @@ void PolyRenderState::ApplyMaterial() if (base) { DCanvas *texcanvas = base->GetImage(mMaterial); - PolyTriangleDrawer::SetTexture(GetPolyFrameBuffer()->GetDrawCommands(), texcanvas->GetPixels(), texcanvas->GetHeight(), texcanvas->GetWidth()); + PolyTriangleDrawer::SetTexture(GetPolyFrameBuffer()->GetDrawCommands(), 0, texcanvas->GetPixels(), texcanvas->GetHeight(), texcanvas->GetWidth()); + + int numLayers = mMaterial.mMaterial->GetLayers(); + for (int i = 1; i < numLayers; i++) + { + FTexture* layer; + auto systex = static_cast(mMaterial.mMaterial->GetLayer(i, 0, &layer)); + + texcanvas = systex->GetImage(mMaterial); + PolyTriangleDrawer::SetTexture(GetPolyFrameBuffer()->GetDrawCommands(), i, texcanvas->GetPixels(), texcanvas->GetHeight(), texcanvas->GetWidth()); + } } mMaterial.mChanged = false; diff --git a/src/rendering/polyrenderer/drawers/poly_draw_args.cpp b/src/rendering/polyrenderer/drawers/poly_draw_args.cpp index 50e8a82ae..b18619b74 100644 --- a/src/rendering/polyrenderer/drawers/poly_draw_args.cpp +++ b/src/rendering/polyrenderer/drawers/poly_draw_args.cpp @@ -59,6 +59,13 @@ void PolyDrawArgs::SetTexture(FSoftwareTexture *texture, FRenderStyle style) mTranslation = nullptr; } +void PolyDrawArgs::SetTexture2(const uint8_t* texels, int width, int height) +{ + mTexture2Pixels = texels; + mTexture2Width = width; + mTexture2Height = height; +} + void PolyDrawArgs::SetTexture(FSoftwareTexture *texture, uint32_t translationID, FRenderStyle style) { // Alphatexture overrides translations. diff --git a/src/rendering/polyrenderer/drawers/poly_draw_args.h b/src/rendering/polyrenderer/drawers/poly_draw_args.h index a681b5f37..2b89f9d1e 100644 --- a/src/rendering/polyrenderer/drawers/poly_draw_args.h +++ b/src/rendering/polyrenderer/drawers/poly_draw_args.h @@ -71,6 +71,7 @@ public: void SetTexture(const uint8_t *texels, int width, int height); void SetTexture(FSoftwareTexture *texture, FRenderStyle style); void SetTexture(FSoftwareTexture *texture, uint32_t translationID, FRenderStyle style); + void SetTexture2(const uint8_t* texels, int width, int height); void SetLight(FSWColormap *basecolormap, uint32_t lightlevel, double globVis, bool fixed); void SetNoColormap() { mLight = 255; mFixedLight = true; mLightRed = 256; mLightGreen = 256; mLightBlue = 256; mLightAlpha = 256; mFadeRed = 0; mFadeGreen = 0; mFadeBlue = 0; mFadeAlpha = 0; mDesaturate = 0; mSimpleShade = true; mColormaps = nullptr; } void SetDepthTest(bool enable) { mDepthTest = enable; } @@ -95,6 +96,10 @@ public: int TextureHeight() const { return mTextureHeight; } const uint8_t *Translation() const { return mTranslation; } + const uint8_t* Texture2Pixels() const { return mTexture2Pixels; } + int Texture2Width() const { return mTexture2Width; } + int Texture2Height() const { return mTexture2Height; } + bool WriteStencil() const { return mWriteStencil; } bool StencilTest() const { return mStencilTest; } uint8_t StencilTestValue() const { return mStencilTestValue; } @@ -142,6 +147,9 @@ private: int mTextureWidth = 0; int mTextureHeight = 0; const uint8_t *mTranslation = nullptr; + const uint8_t* mTexture2Pixels = nullptr; + int mTexture2Width = 0; + int mTexture2Height = 0; uint8_t mStencilTestValue = 0; uint8_t mStencilWriteValue = 0; const uint8_t *mColormaps = nullptr; diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/rendering/polyrenderer/drawers/poly_triangle.cpp index 650784485..0afe496a5 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/poly_triangle.cpp @@ -183,9 +183,9 @@ void PolyTriangleDrawer::SetRenderStyle(const DrawerCommandQueuePtr &queue, FRen queue->Push(style); } -void PolyTriangleDrawer::SetTexture(const DrawerCommandQueuePtr &queue, void *pixels, int width, int height) +void PolyTriangleDrawer::SetTexture(const DrawerCommandQueuePtr &queue, int unit, void *pixels, int width, int height) { - queue->Push(pixels, width, height); + queue->Push(unit, pixels, width, height); } void PolyTriangleDrawer::SetShader(const DrawerCommandQueuePtr &queue, int specialEffect, int effectState, bool alphaTest) @@ -446,9 +446,12 @@ void PolyTriangleThreadData::SetShader(int specialEffect, int effectState, bool AlphaTest = alphaTest; } -void PolyTriangleThreadData::SetTexture(void *pixels, int width, int height) +void PolyTriangleThreadData::SetTexture(int unit, void *pixels, int width, int height) { - drawargs.SetTexture((uint8_t*)pixels, width, height); + if (unit == 0) + drawargs.SetTexture((uint8_t*)pixels, width, height); + else if (unit == 1) + drawargs.SetTexture2((uint8_t*)pixels, width, height); } void PolyTriangleThreadData::DrawIndexed(int index, int vcount, PolyDrawMode drawmode) diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.h b/src/rendering/polyrenderer/drawers/poly_triangle.h index 619cf6c16..1e3cb1467 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.h +++ b/src/rendering/polyrenderer/drawers/poly_triangle.h @@ -57,7 +57,7 @@ public: static void SetScissor(const DrawerCommandQueuePtr &queue, int x, int y, int w, int h); static void EnableDepthTest(const DrawerCommandQueuePtr &queue, bool on); static void SetRenderStyle(const DrawerCommandQueuePtr &queue, FRenderStyle style); - static void SetTexture(const DrawerCommandQueuePtr &queue, void *pixels, int width, int height); + static void SetTexture(const DrawerCommandQueuePtr &queue, int unit, void *pixels, int width, int height); static void SetShader(const DrawerCommandQueuePtr &queue, int specialEffect, int effectState, bool alphaTest); static void PushStreamData(const DrawerCommandQueuePtr &queue, const StreamData &data, const PolyPushConstants &constants); static void PushMatrices(const DrawerCommandQueuePtr &queue, const VSMatrix &modelMatrix, const VSMatrix &normalModelMatrix, const VSMatrix &textureMatrix); @@ -159,7 +159,7 @@ public: void SetScissor(int x, int y, int w, int h); void EnableDepthTest(bool on); void SetRenderStyle(FRenderStyle style); - void SetTexture(void *pixels, int width, int height); + void SetTexture(int unit, void *pixels, int width, int height); void SetShader(int specialEffect, int effectState, bool alphaTest); void UpdateClip(); @@ -423,10 +423,11 @@ private: class PolySetTextureCommand : public PolyDrawerCommand { public: - PolySetTextureCommand(void *pixels, int width, int height) : pixels(pixels), width(width), height(height) { } - void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetTexture(pixels, width, height); } + PolySetTextureCommand(int unit, void *pixels, int width, int height) : unit(unit), pixels(pixels), width(width), height(height) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetTexture(unit, pixels, width, height); } private: + int unit; void *pixels; int width; int height; diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.cpp b/src/rendering/polyrenderer/drawers/screen_triangle.cpp index 8faf2af63..66f3c9869 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/screen_triangle.cpp @@ -375,10 +375,35 @@ static void RunShader(int x0, int x1, PolyTriangleThreadData* thread) } else if (thread->SpecialEffect == EFF_BURN) // burn.fp { - /*vec4 frag = vColor; - vec4 t1 = texture(tex, vTexCoord.xy); - vec4 t2 = texture(texture2, vec2(vTexCoord.x, 1.0-vTexCoord.y)); - FragColor = frag * vec4(t1.rgb, t2.a);*/ + int texWidth = thread->drawargs.TextureWidth(); + int texHeight = thread->drawargs.TextureHeight(); + const uint32_t* texPixels = (const uint32_t*)thread->drawargs.TexturePixels(); + + int tex2Width = thread->drawargs.Texture2Width(); + int tex2Height = thread->drawargs.Texture2Height(); + const uint32_t* tex2Pixels = (const uint32_t*)thread->drawargs.Texture2Pixels(); + + uint32_t frag = thread->mainVertexShader.vColor; + uint32_t frag_r = RPART(frag); + uint32_t frag_g = GPART(frag); + uint32_t frag_b = BPART(frag); + uint32_t frag_a = APART(frag); + frag_r += frag_r >> 7; // 255 -> 256 + frag_g += frag_g >> 7; // 255 -> 256 + frag_b += frag_b >> 7; // 255 -> 256 + frag_a += frag_a >> 7; // 255 -> 256 + for (int x = x0; x < x1; x++) + { + uint32_t t1 = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight); + uint32_t t2 = sampleTexture(u[x], 1.0f - v[x], tex2Pixels, tex2Width, tex2Height); + + uint32_t r = (frag_r * RPART(t1)) >> 8; + uint32_t g = (frag_g * GPART(t1)) >> 8; + uint32_t b = (frag_b * BPART(t1)) >> 8; + uint32_t a = (frag_a * APART(t2)) >> 8; + + fragcolor[x] = MAKEARGB(a, r, g, b); + } return; } else if (thread->SpecialEffect == EFF_STENCIL) // stencil.fp From 8ca05fe30ab9a3313e6b1016dc673cc76548fdc3 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 1 Dec 2019 22:05:10 +0100 Subject: [PATCH 2/2] Implement crossfade --- .../polyrenderer/backend/poly_hwtexture.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/rendering/polyrenderer/backend/poly_hwtexture.cpp b/src/rendering/polyrenderer/backend/poly_hwtexture.cpp index cd3102b53..a16b58287 100644 --- a/src/rendering/polyrenderer/backend/poly_hwtexture.cpp +++ b/src/rendering/polyrenderer/backend/poly_hwtexture.cpp @@ -121,6 +121,22 @@ void PolyHardwareTexture::CreateWipeTexture(int w, int h, const char *name) mCanvas.reset(new DCanvas(0, 0, true)); mCanvas->Resize(w, h, false); } + + auto fb = static_cast(screen); + + fb->FlushDrawCommands(); + DrawerThreads::WaitForWorkers(); + + uint32_t* dest = (uint32_t*)mCanvas->GetPixels(); + uint32_t* src = (uint32_t*)fb->GetCanvas()->GetPixels(); + int dpitch = mCanvas->GetPitch(); + int spitch = fb->GetCanvas()->GetPitch(); + int pixelsize = 4; + + for (int y = 0; y < h; y++) + { + memcpy(dest + dpitch * (h - 1 - y), src + spitch * y, w * pixelsize); + } } void PolyHardwareTexture::CreateImage(FTexture *tex, int translation, int flags)