diff --git a/src/polyrenderer/drawers/poly_draw_args.cpp b/src/polyrenderer/drawers/poly_draw_args.cpp index 3a921ae0aa..1ca30ea538 100644 --- a/src/polyrenderer/drawers/poly_draw_args.cpp +++ b/src/polyrenderer/drawers/poly_draw_args.cpp @@ -140,7 +140,7 @@ void PolyDrawArgs::SetColor(uint32_t bgra, uint8_t palindex) } } -void PolyDrawArgs::DrawArray(const DrawerCommandQueuePtr &queue, const TriVertex *vertices, int vcount, PolyDrawMode mode) +void PolyDrawArgs::DrawArray(const DrawerCommandQueuePtr &queue, const void *vertices, int vcount, PolyDrawMode mode) { mVertices = vertices; mVertexCount = vcount; @@ -149,7 +149,7 @@ void PolyDrawArgs::DrawArray(const DrawerCommandQueuePtr &queue, const TriVertex queue->Push(*this); } -void PolyDrawArgs::DrawElements(const DrawerCommandQueuePtr &queue, const TriVertex *vertices, const unsigned int *elements, int count, PolyDrawMode mode) +void PolyDrawArgs::DrawElements(const DrawerCommandQueuePtr &queue, const void *vertices, const unsigned int *elements, int count, PolyDrawMode mode) { mVertices = vertices; mElements = elements; diff --git a/src/polyrenderer/drawers/poly_draw_args.h b/src/polyrenderer/drawers/poly_draw_args.h index 2d43ae64fa..12ca5a662d 100644 --- a/src/polyrenderer/drawers/poly_draw_args.h +++ b/src/polyrenderer/drawers/poly_draw_args.h @@ -80,12 +80,12 @@ public: void SetColor(uint32_t bgra, uint8_t palindex); void SetLights(PolyLight *lights, int numLights) { mLights = lights; mNumLights = numLights; } void SetDynLightColor(uint32_t color) { mDynLightColor = color; } - void DrawArray(const DrawerCommandQueuePtr &queue, const TriVertex *vertices, int vcount, PolyDrawMode mode = PolyDrawMode::Triangles); - void DrawElements(const DrawerCommandQueuePtr &queue, const TriVertex *vertices, const unsigned int *elements, int count, PolyDrawMode mode = PolyDrawMode::Triangles); + void DrawArray(const DrawerCommandQueuePtr &queue, const void *vertices, int vcount, PolyDrawMode mode = PolyDrawMode::Triangles); + void DrawElements(const DrawerCommandQueuePtr &queue, const void *vertices, const unsigned int *elements, int count, PolyDrawMode mode = PolyDrawMode::Triangles); const PolyClipPlane &ClipPlane(int index) const { return mClipPlane[index]; } - const TriVertex *Vertices() const { return mVertices; } + const void *Vertices() const { return mVertices; } int VertexCount() const { return mVertexCount; } const unsigned int *Elements() const { return mElements; } PolyDrawMode DrawMode() const { return mDrawMode; } @@ -134,7 +134,7 @@ public: void SetNormal(const FVector3 &normal) { mNormal = normal; } private: - const TriVertex *mVertices = nullptr; + const void *mVertices = nullptr; int mVertexCount = 0; const unsigned int *mElements = nullptr; PolyDrawMode mDrawMode = PolyDrawMode::Triangles; diff --git a/src/polyrenderer/drawers/poly_triangle.cpp b/src/polyrenderer/drawers/poly_triangle.cpp index 5b380da8d6..0600e3a039 100644 --- a/src/polyrenderer/drawers/poly_triangle.cpp +++ b/src/polyrenderer/drawers/poly_triangle.cpp @@ -31,6 +31,7 @@ #include "g_game.h" #include "g_level.h" #include "r_data/r_translate.h" +#include "r_data/models/models.h" #include "v_palette.h" #include "r_data/colormaps.h" #include "poly_triangle.h" @@ -102,6 +103,11 @@ void PolyTriangleDrawer::SetWeaponScene(const DrawerCommandQueuePtr &queue, bool queue->Push(enable); } +void PolyTriangleDrawer::SetModelVertexShader(const DrawerCommandQueuePtr &queue, int frame1, int frame2, float interpolationFactor) +{ + queue->Push(frame1, frame2, interpolationFactor); +} + ///////////////////////////////////////////////////////////////////////////// void PolyTriangleThreadData::ClearStencil(uint8_t value) @@ -156,7 +162,6 @@ void PolyTriangleThreadData::DrawElements(const PolyDrawArgs &drawargs) args.zbuffer = PolyZBuffer::Instance()->Values(); args.depthOffset = weaponScene ? 1.0f : 0.0f; - const TriVertex *vinput = drawargs.Vertices(); const unsigned int *elements = drawargs.Elements(); int vcount = drawargs.VertexCount(); @@ -166,17 +171,17 @@ void PolyTriangleThreadData::DrawElements(const PolyDrawArgs &drawargs) for (int i = 0; i < vcount / 3; i++) { for (int j = 0; j < 3; j++) - vert[j] = ShadeVertex(drawargs, vinput[*(elements++)]); + vert[j] = ShadeVertex(drawargs, *(elements++)); DrawShadedTriangle(vert, ccw, &args); } } else if (drawargs.DrawMode() == PolyDrawMode::TriangleFan) { - vert[0] = ShadeVertex(drawargs, vinput[*(elements++)]); - vert[1] = ShadeVertex(drawargs, vinput[*(elements++)]); + vert[0] = ShadeVertex(drawargs, *(elements++)); + vert[1] = ShadeVertex(drawargs, *(elements++)); for (int i = 2; i < vcount; i++) { - vert[2] = ShadeVertex(drawargs, vinput[*(elements++)]); + vert[2] = ShadeVertex(drawargs, *(elements++)); DrawShadedTriangle(vert, ccw, &args); vert[1] = vert[2]; } @@ -184,11 +189,11 @@ void PolyTriangleThreadData::DrawElements(const PolyDrawArgs &drawargs) else // TriangleDrawMode::TriangleStrip { bool toggleccw = ccw; - vert[0] = ShadeVertex(drawargs, vinput[*(elements++)]); - vert[1] = ShadeVertex(drawargs, vinput[*(elements++)]); + vert[0] = ShadeVertex(drawargs, *(elements++)); + vert[1] = ShadeVertex(drawargs, *(elements++)); for (int i = 2; i < vcount; i++) { - vert[2] = ShadeVertex(drawargs, vinput[*(elements++)]); + vert[2] = ShadeVertex(drawargs, *(elements++)); DrawShadedTriangle(vert, toggleccw, &args); vert[0] = vert[1]; vert[1] = vert[2]; @@ -213,7 +218,7 @@ void PolyTriangleThreadData::DrawArrays(const PolyDrawArgs &drawargs) args.zbuffer = PolyZBuffer::Instance()->Values(); args.depthOffset = weaponScene ? 1.0f : 0.0f; - const TriVertex *vinput = drawargs.Vertices(); + int vinput = 0; int vcount = drawargs.VertexCount(); ShadedTriVertex vert[3]; @@ -222,17 +227,17 @@ void PolyTriangleThreadData::DrawArrays(const PolyDrawArgs &drawargs) for (int i = 0; i < vcount / 3; i++) { for (int j = 0; j < 3; j++) - vert[j] = ShadeVertex(drawargs, *(vinput++)); + vert[j] = ShadeVertex(drawargs, vinput++); DrawShadedTriangle(vert, ccw, &args); } } else if (drawargs.DrawMode() == PolyDrawMode::TriangleFan) { - vert[0] = ShadeVertex(drawargs, *(vinput++)); - vert[1] = ShadeVertex(drawargs, *(vinput++)); + vert[0] = ShadeVertex(drawargs, vinput++); + vert[1] = ShadeVertex(drawargs, vinput++); for (int i = 2; i < vcount; i++) { - vert[2] = ShadeVertex(drawargs, *(vinput++)); + vert[2] = ShadeVertex(drawargs, vinput++); DrawShadedTriangle(vert, ccw, &args); vert[1] = vert[2]; } @@ -240,11 +245,11 @@ void PolyTriangleThreadData::DrawArrays(const PolyDrawArgs &drawargs) else // TriangleDrawMode::TriangleStrip { bool toggleccw = ccw; - vert[0] = ShadeVertex(drawargs, *(vinput++)); - vert[1] = ShadeVertex(drawargs, *(vinput++)); + vert[0] = ShadeVertex(drawargs, vinput++); + vert[1] = ShadeVertex(drawargs, vinput++); for (int i = 2; i < vcount; i++) { - vert[2] = ShadeVertex(drawargs, *(vinput++)); + vert[2] = ShadeVertex(drawargs, vinput++); DrawShadedTriangle(vert, toggleccw, &args); vert[0] = vert[1]; vert[1] = vert[2]; @@ -253,25 +258,51 @@ void PolyTriangleThreadData::DrawArrays(const PolyDrawArgs &drawargs) } } -ShadedTriVertex PolyTriangleThreadData::ShadeVertex(const PolyDrawArgs &drawargs, const TriVertex &v) +ShadedTriVertex PolyTriangleThreadData::ShadeVertex(const PolyDrawArgs &drawargs, int index) { + ShadedTriVertex sv; + Vec4f objpos; + + if (modelFrame1 == -1) + { + const TriVertex &v = ((TriVertex*)drawargs.Vertices())[index]; + objpos = Vec4f(v.x, v.y, v.z, v.w); + sv.u = v.u; + sv.v = v.v; + } + else if (modelFrame1 == modelFrame2 || modelInterpolationFactor == 0.f) + { + const FModelVertex &v = ((FModelVertex*)drawargs.Vertices())[modelFrame1 + index]; + objpos = Vec4f(v.x, v.y, v.z, 1.0f); + sv.u = v.u; + sv.v = v.v; + } + else + { + const FModelVertex &v1 = ((FModelVertex*)drawargs.Vertices())[modelFrame1 + index]; + const FModelVertex &v2 = ((FModelVertex*)drawargs.Vertices())[modelFrame2 + index]; + + float frac = modelInterpolationFactor; + float inv_frac = 1.0f - frac; + + objpos = Vec4f(v1.x * inv_frac + v2.x * frac, v1.y * inv_frac + v2.y * frac, v1.z * inv_frac + v2.z * frac, 1.0f); + sv.u = v1.u; + sv.v = v1.v; + } + // Apply transform to get clip coordinates: - Vec4f objpos = Vec4f(v.x, v.y, v.z, v.w); Vec4f clippos = (*objectToClip) * objpos; - ShadedTriVertex sv; sv.x = clippos.X; sv.y = clippos.Y; sv.z = clippos.Z; sv.w = clippos.W; - sv.u = v.u; - sv.v = v.v; if (!objectToWorld) // Identity matrix { - sv.worldX = v.x; - sv.worldY = v.y; - sv.worldZ = v.z; + sv.worldX = objpos.X; + sv.worldY = objpos.Y; + sv.worldZ = objpos.Z; } else { @@ -285,7 +316,7 @@ ShadedTriVertex PolyTriangleThreadData::ShadeVertex(const PolyDrawArgs &drawargs for (int i = 0; i < 3; i++) { const auto &clipPlane = drawargs.ClipPlane(i); - sv.clipDistance[i] = v.x * clipPlane.A + v.y * clipPlane.B + v.z * clipPlane.C + v.w * clipPlane.D; + sv.clipDistance[i] = objpos.X * clipPlane.A + objpos.Y * clipPlane.B + objpos.Z * clipPlane.C + objpos.W * clipPlane.D; } return sv; @@ -653,6 +684,17 @@ void PolySetWeaponSceneCommand::Execute(DrawerThread *thread) ///////////////////////////////////////////////////////////////////////////// +PolySetModelVertexShaderCommand::PolySetModelVertexShaderCommand(int frame1, int frame2, float interpolationFactor) : frame1(frame1), frame2(frame2), interpolationFactor(interpolationFactor) +{ +} + +void PolySetModelVertexShaderCommand::Execute(DrawerThread *thread) +{ + PolyTriangleThreadData::Get(thread)->SetModelVertexShader(frame1, frame2, interpolationFactor); +} + +///////////////////////////////////////////////////////////////////////////// + PolyClearStencilCommand::PolyClearStencilCommand(uint8_t value) : value(value) { } diff --git a/src/polyrenderer/drawers/poly_triangle.h b/src/polyrenderer/drawers/poly_triangle.h index a92011c717..b4aa09c2c4 100644 --- a/src/polyrenderer/drawers/poly_triangle.h +++ b/src/polyrenderer/drawers/poly_triangle.h @@ -38,6 +38,7 @@ public: 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 SetModelVertexShader(const DrawerCommandQueuePtr &queue, int frame1, int frame2, float interpolationFactor); static void SetTransform(const DrawerCommandQueuePtr &queue, const Mat4f *objectToClip, const Mat4f *objectToWorld); static bool IsBgra(); @@ -54,6 +55,7 @@ public: void SetCullCCW(bool value) { ccw = value; } void SetTwoSided(bool value) { twosided = value; } void SetWeaponScene(bool value) { weaponScene = value; } + void SetModelVertexShader(int frame1, int frame2, float interpolationFactor) { modelFrame1 = frame1; modelFrame2 = frame2; modelInterpolationFactor = interpolationFactor; } void DrawElements(const PolyDrawArgs &args); void DrawArrays(const PolyDrawArgs &args); @@ -71,7 +73,7 @@ public: static PolyTriangleThreadData *Get(DrawerThread *thread); private: - ShadedTriVertex ShadeVertex(const PolyDrawArgs &drawargs, const TriVertex &v); + ShadedTriVertex ShadeVertex(const PolyDrawArgs &drawargs, int index); void DrawShadedTriangle(const ShadedTriVertex *vertices, bool ccw, TriDrawTriangleArgs *args); static bool IsDegenerate(const ShadedTriVertex *vertices); static bool IsFrontfacing(TriDrawTriangleArgs *args); @@ -91,6 +93,9 @@ private: bool weaponScene = false; const Mat4f *objectToClip = nullptr; const Mat4f *objectToWorld = nullptr; + int modelFrame1 = -1; + int modelFrame2 = -1; + float modelInterpolationFactor = 0.0f; enum { max_additional_vertices = 16 }; }; @@ -140,6 +145,19 @@ private: bool value; }; +class PolySetModelVertexShaderCommand : public DrawerCommand +{ +public: + PolySetModelVertexShaderCommand(int frame1, int frame2, float interpolationFactor); + + void Execute(DrawerThread *thread) override; + +private: + int frame1; + int frame2; + float interpolationFactor; +}; + class PolyClearStencilCommand : public DrawerCommand { public: diff --git a/src/polyrenderer/scene/poly_model.cpp b/src/polyrenderer/scene/poly_model.cpp index 3db3509431..8109868e8f 100644 --- a/src/polyrenderer/scene/poly_model.cpp +++ b/src/polyrenderer/scene/poly_model.cpp @@ -38,12 +38,14 @@ void PolyRenderModel(PolyRenderThread *thread, const Mat4f &worldToClip, uint32_ PolyModelRenderer renderer(thread, worldToClip, stencilValue); renderer.AddLights(actor); renderer.RenderModel(x, y, z, smf, actor); + PolyTriangleDrawer::SetModelVertexShader(thread->DrawQueue, -1, -1, 0.0f); } void PolyRenderHUDModel(PolyRenderThread *thread, const Mat4f &worldToClip, uint32_t stencilValue, DPSprite *psp, float ofsx, float ofsy) { PolyModelRenderer renderer(thread, worldToClip, stencilValue); renderer.RenderHUDModel(psp, ofsx, ofsy); + PolyTriangleDrawer::SetModelVertexShader(thread->DrawQueue, -1, -1, 0.0f); } ///////////////////////////////////////////////////////////////////////////// @@ -288,44 +290,7 @@ void PolyModelVertexBuffer::UnlockIndexBuffer() void PolyModelVertexBuffer::SetupFrame(FModelRenderer *renderer, unsigned int frame1, unsigned int frame2, unsigned int size) { PolyModelRenderer *polyrenderer = (PolyModelRenderer *)renderer; - - if (frame1 == frame2 || size == 0 || polyrenderer->InterpolationFactor == 0.f) - { - TriVertex *vertices = polyrenderer->Thread->FrameMemory->AllocMemory(size); - - for (unsigned int i = 0; i < size; i++) - { - vertices[i] = - { - mVertexBuffer[frame1 + i].x, - mVertexBuffer[frame1 + i].y, - mVertexBuffer[frame1 + i].z, - 1.0f, - mVertexBuffer[frame1 + i].u, - mVertexBuffer[frame1 + i].v - }; - } - - polyrenderer->VertexBuffer = vertices; - polyrenderer->IndexBuffer = &mIndexBuffer[0]; - } - else - { - TriVertex *vertices = polyrenderer->Thread->FrameMemory->AllocMemory(size); - - float frac = polyrenderer->InterpolationFactor; - float inv_frac = 1.0f - frac; - for (unsigned int i = 0; i < size; i++) - { - vertices[i].x = mVertexBuffer[frame1 + i].x * inv_frac + mVertexBuffer[frame2 + i].x * frac; - vertices[i].y = mVertexBuffer[frame1 + i].y * inv_frac + mVertexBuffer[frame2 + i].y * frac; - vertices[i].z = mVertexBuffer[frame1 + i].z * inv_frac + mVertexBuffer[frame2 + i].z * frac; - vertices[i].w = 1.0f; - vertices[i].u = mVertexBuffer[frame1 + i].u; - vertices[i].v = mVertexBuffer[frame1 + i].v; - } - - polyrenderer->VertexBuffer = vertices; - polyrenderer->IndexBuffer = &mIndexBuffer[0]; - } + polyrenderer->VertexBuffer = mVertexBuffer.Size() ? &mVertexBuffer[0] : nullptr; + polyrenderer->IndexBuffer = mIndexBuffer.Size() ? &mIndexBuffer[0] : nullptr; + PolyTriangleDrawer::SetModelVertexShader(polyrenderer->Thread->DrawQueue, frame1, frame2, polyrenderer->InterpolationFactor); } diff --git a/src/polyrenderer/scene/poly_model.h b/src/polyrenderer/scene/poly_model.h index 9d2519e817..bb3008a191 100644 --- a/src/polyrenderer/scene/poly_model.h +++ b/src/polyrenderer/scene/poly_model.h @@ -61,7 +61,7 @@ public: Mat4f ObjectToWorld; FTexture *SkinTexture = nullptr; unsigned int *IndexBuffer = nullptr; - TriVertex *VertexBuffer = nullptr; + FModelVertex *VertexBuffer = nullptr; float InterpolationFactor = 0.0; PolyLight *Lights = nullptr; int NumLights = 0; @@ -82,7 +82,6 @@ public: void SetupFrame(FModelRenderer *renderer, unsigned int frame1, unsigned int frame2, unsigned int size) override; private: - int mIndexFrame[2]; TArray mVertexBuffer; TArray mIndexBuffer; }; diff --git a/src/swrenderer/things/r_model.cpp b/src/swrenderer/things/r_model.cpp index a7e8553a67..40db26882a 100644 --- a/src/swrenderer/things/r_model.cpp +++ b/src/swrenderer/things/r_model.cpp @@ -77,6 +77,7 @@ namespace swrenderer SWModelRenderer renderer(thread, clip3DFloor, &WorldToClip, MirrorWorldToClip); renderer.AddLights(actor); renderer.RenderModel(x, y, z, smf, actor); + PolyTriangleDrawer::SetModelVertexShader(thread->DrawQueue, -1, -1, 0.0f); } ///////////////////////////////////////////////////////////////////////////// @@ -85,6 +86,7 @@ namespace swrenderer { SWModelRenderer renderer(thread, Fake3DTranslucent(), &thread->Viewport->WorldToClip, false); renderer.RenderHUDModel(psp, ofsx, ofsy); + PolyTriangleDrawer::SetModelVertexShader(thread->DrawQueue, -1, -1, 0.0f); } ///////////////////////////////////////////////////////////////////////////// @@ -390,45 +392,8 @@ namespace swrenderer void SWModelVertexBuffer::SetupFrame(FModelRenderer *renderer, unsigned int frame1, unsigned int frame2, unsigned int size) { SWModelRenderer *swrenderer = (SWModelRenderer *)renderer; - - if (frame1 == frame2 || size == 0 || swrenderer->InterpolationFactor == 0.f) - { - TriVertex *vertices = swrenderer->Thread->FrameMemory->AllocMemory(size); - - for (unsigned int i = 0; i < size; i++) - { - vertices[i] = - { - mVertexBuffer[frame1 + i].x, - mVertexBuffer[frame1 + i].y, - mVertexBuffer[frame1 + i].z, - 1.0f, - mVertexBuffer[frame1 + i].u, - mVertexBuffer[frame1 + i].v - }; - } - - swrenderer->VertexBuffer = vertices; - swrenderer->IndexBuffer = &mIndexBuffer[0]; - } - else - { - TriVertex *vertices = swrenderer->Thread->FrameMemory->AllocMemory(size); - - float frac = swrenderer->InterpolationFactor; - float inv_frac = 1.0f - frac; - for (unsigned int i = 0; i < size; i++) - { - vertices[i].x = mVertexBuffer[frame1 + i].x * inv_frac + mVertexBuffer[frame2 + i].x * frac; - vertices[i].y = mVertexBuffer[frame1 + i].y * inv_frac + mVertexBuffer[frame2 + i].y * frac; - vertices[i].z = mVertexBuffer[frame1 + i].z * inv_frac + mVertexBuffer[frame2 + i].z * frac; - vertices[i].w = 1.0f; - vertices[i].u = mVertexBuffer[frame1 + i].u; - vertices[i].v = mVertexBuffer[frame1 + i].v; - } - - swrenderer->VertexBuffer = vertices; - swrenderer->IndexBuffer = &mIndexBuffer[0]; - } + swrenderer->VertexBuffer = mVertexBuffer.Size() ? &mVertexBuffer[0] : nullptr; + swrenderer->IndexBuffer = mIndexBuffer.Size() ? &mIndexBuffer[0] : nullptr; + PolyTriangleDrawer::SetModelVertexShader(swrenderer->Thread->DrawQueue, frame1, frame2, swrenderer->InterpolationFactor); } } diff --git a/src/swrenderer/things/r_model.h b/src/swrenderer/things/r_model.h index b2db91c07e..bd9b868dcd 100644 --- a/src/swrenderer/things/r_model.h +++ b/src/swrenderer/things/r_model.h @@ -85,7 +85,7 @@ namespace swrenderer PolyClipPlane ClipTop, ClipBottom; FTexture *SkinTexture = nullptr; unsigned int *IndexBuffer = nullptr; - TriVertex *VertexBuffer = nullptr; + FModelVertex *VertexBuffer = nullptr; float InterpolationFactor = 0.0; Mat4f *WorldToClip = nullptr; bool MirrorWorldToClip = false; @@ -108,7 +108,6 @@ namespace swrenderer void SetupFrame(FModelRenderer *renderer, unsigned int frame1, unsigned int frame2, unsigned int size) override; private: - int mIndexFrame[2]; TArray mVertexBuffer; TArray mIndexBuffer; };