From 8098657cf491da92410163ad0377e683bcdbfc95 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Thu, 24 May 2018 01:39:36 +0200 Subject: [PATCH] - add two-sided culling support in software and poly --- src/polyrenderer/drawers/poly_triangle.cpp | 24 ++++++++++++++++++++++ src/polyrenderer/drawers/poly_triangle.h | 15 ++++++++++++++ src/polyrenderer/scene/poly_model.cpp | 4 ++++ src/swrenderer/things/r_model.cpp | 4 ++++ 4 files changed, 47 insertions(+) diff --git a/src/polyrenderer/drawers/poly_triangle.cpp b/src/polyrenderer/drawers/poly_triangle.cpp index 37052aee7..beefb33d7 100644 --- a/src/polyrenderer/drawers/poly_triangle.cpp +++ b/src/polyrenderer/drawers/poly_triangle.cpp @@ -79,6 +79,11 @@ void PolyTriangleDrawer::SetCullCCW(const DrawerCommandQueuePtr &queue, bool ccw queue->Push(ccw); } +void PolyTriangleDrawer::SetTwoSided(const DrawerCommandQueuePtr &queue, bool twosided) +{ + queue->Push(twosided); +} + void PolyTriangleDrawer::SetWeaponScene(const DrawerCommandQueuePtr &queue, bool enable) { queue->Push(enable); @@ -348,6 +353,14 @@ void PolyTriangleThreadData::DrawShadedTriangle(const ShadedTriVertex *vert, boo } } + if (twosided && numclipvert > 2) + { + args->v1 = &clippedvert[0]; + args->v2 = &clippedvert[1]; + args->v3 = &clippedvert[2]; + ccw = !IsFrontfacing(args); + } + // Draw screen triangles if (ccw) { @@ -588,6 +601,17 @@ void PolySetCullCCWCommand::Execute(DrawerThread *thread) ///////////////////////////////////////////////////////////////////////////// +PolySetTwoSidedCommand::PolySetTwoSidedCommand(bool twosided) : twosided(twosided) +{ +} + +void PolySetTwoSidedCommand::Execute(DrawerThread *thread) +{ + PolyTriangleThreadData::Get(thread)->SetTwoSided(twosided); +} + +///////////////////////////////////////////////////////////////////////////// + PolySetWeaponSceneCommand::PolySetWeaponSceneCommand(bool value) : value(value) { } diff --git a/src/polyrenderer/drawers/poly_triangle.h b/src/polyrenderer/drawers/poly_triangle.h index 3cd88d803..628bdb009 100644 --- a/src/polyrenderer/drawers/poly_triangle.h +++ b/src/polyrenderer/drawers/poly_triangle.h @@ -35,6 +35,7 @@ public: static void ClearBuffers(DCanvas *canvas); static void SetViewport(const DrawerCommandQueuePtr &queue, int x, int y, int width, int height, DCanvas *canvas, bool span_drawers); static void SetCullCCW(const DrawerCommandQueuePtr &queue, bool ccw); + static void SetTwoSided(const DrawerCommandQueuePtr &queue, bool twosided); static void SetWeaponScene(const DrawerCommandQueuePtr &queue, bool enable); static void SetTransform(const DrawerCommandQueuePtr &queue, const Mat4f *objectToClip); }; @@ -47,6 +48,7 @@ public: void SetViewport(int x, int y, int width, int height, uint8_t *dest, int dest_width, int dest_height, int dest_pitch, bool dest_bgra, bool span_drawers); void SetTransform(const Mat4f *objectToClip); void SetCullCCW(bool value) { ccw = value; } + void SetTwoSided(bool value) { twosided = value; } void SetWeaponScene(bool value) { weaponScene = value; } void DrawElements(const PolyDrawArgs &args); @@ -81,6 +83,7 @@ private: bool dest_bgra = false; uint8_t *dest = nullptr; bool ccw = true; + bool twosided = false; bool weaponScene = false; const Mat4f *objectToClip = nullptr; bool span_drawers = false; @@ -112,6 +115,18 @@ private: bool ccw; }; +class PolySetTwoSidedCommand : public DrawerCommand +{ +public: + PolySetTwoSidedCommand(bool twosided); + + void Execute(DrawerThread *thread) override; + FString DebugInfo() override { return "PolySetCullCCWCommand"; } + +private: + bool twosided; +}; + class PolySetWeaponSceneCommand : public DrawerCommand { public: diff --git a/src/polyrenderer/scene/poly_model.cpp b/src/polyrenderer/scene/poly_model.cpp index ac29af9bb..cc8a111ea 100644 --- a/src/polyrenderer/scene/poly_model.cpp +++ b/src/polyrenderer/scene/poly_model.cpp @@ -56,10 +56,12 @@ void PolyModelRenderer::BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, co ModelActor = actor; const_cast(objectToWorldMatrix).copy(ObjectToWorld.Matrix); SetTransform(); + PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, true); } void PolyModelRenderer::EndDrawModel(AActor *actor, FSpriteModelFrame *smf) { + PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, false); ModelActor = nullptr; } @@ -98,12 +100,14 @@ void PolyModelRenderer::BeginDrawHUDModel(AActor *actor, const VSMatrix &objectT const_cast(objectToWorldMatrix).copy(ObjectToWorld.Matrix); SetTransform(); PolyTriangleDrawer::SetWeaponScene(Thread->DrawQueue, true); + PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, true); } void PolyModelRenderer::EndDrawHUDModel(AActor *actor) { ModelActor = nullptr; PolyTriangleDrawer::SetWeaponScene(Thread->DrawQueue, false); + PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, false); } void PolyModelRenderer::SetInterpolation(double interpolation) diff --git a/src/swrenderer/things/r_model.cpp b/src/swrenderer/things/r_model.cpp index fe5769262..2d09ca276 100644 --- a/src/swrenderer/things/r_model.cpp +++ b/src/swrenderer/things/r_model.cpp @@ -120,11 +120,13 @@ namespace swrenderer } SetTransform(); + PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, true); } void SWModelRenderer::EndDrawModel(AActor *actor, FSpriteModelFrame *smf) { ModelActor = nullptr; + PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, false); } IModelVertexBuffer *SWModelRenderer::CreateVertexBuffer(bool needindex, bool singleframe) @@ -183,12 +185,14 @@ namespace swrenderer ClipBottom = {}; SetTransform(); PolyTriangleDrawer::SetWeaponScene(Thread->DrawQueue, true); + PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, true); } void SWModelRenderer::EndDrawHUDModel(AActor *actor) { ModelActor = nullptr; PolyTriangleDrawer::SetWeaponScene(Thread->DrawQueue, false); + PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, false); } void SWModelRenderer::SetInterpolation(double interpolation)