diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bbc6c0f22..198384a5a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -801,7 +801,7 @@ set( POLYRENDER_SOURCES polyrenderer/drawers/poly_triangle.cpp polyrenderer/drawers/poly_draw_args.cpp polyrenderer/drawers/screen_triangle.cpp - polyrenderer/math/tri_matrix.cpp + polyrenderer/math/gpu_types.cpp ) # These files will be flagged as "headers" so that they appear in project files diff --git a/src/polyrenderer/drawers/poly_draw_args.cpp b/src/polyrenderer/drawers/poly_draw_args.cpp index 312cb3e32..532bd93d9 100644 --- a/src/polyrenderer/drawers/poly_draw_args.cpp +++ b/src/polyrenderer/drawers/poly_draw_args.cpp @@ -40,6 +40,7 @@ void PolyDrawArgs::SetTexture(const uint8_t *texels, int width, int height) { + mTexture = nullptr; mTexturePixels = texels; mTextureWidth = width; mTextureHeight = height; @@ -48,6 +49,7 @@ void PolyDrawArgs::SetTexture(const uint8_t *texels, int width, int height) void PolyDrawArgs::SetTexture(FTexture *texture, FRenderStyle style) { + mTexture = texture; mTextureWidth = texture->GetWidth(); mTextureHeight = texture->GetHeight(); if (PolyRenderer::Instance()->RenderTarget->IsBgra()) @@ -70,6 +72,7 @@ void PolyDrawArgs::SetTexture(FTexture *texture, uint32_t translationID, FRender else mTranslation = table->Remap; + mTexture = texture; mTextureWidth = texture->GetWidth(); mTextureHeight = texture->GetHeight(); mTexturePixels = texture->GetPixels(style); @@ -79,6 +82,7 @@ void PolyDrawArgs::SetTexture(FTexture *texture, uint32_t translationID, FRender if (style.Flags & STYLEF_RedIsAlpha) { + mTexture = texture; mTextureWidth = texture->GetWidth(); mTextureHeight = texture->GetHeight(); mTexturePixels = texture->GetPixels(style); @@ -133,7 +137,7 @@ void PolyDrawArgs::DrawArray(const DrawerCommandQueuePtr &queue, const TriVertex mVertexCount = vcount; mElements = nullptr; mDrawMode = mode; - queue->Push(*this, PolyTriangleDrawer::is_mirror()); + queue->Push(*this); } void PolyDrawArgs::DrawElements(const DrawerCommandQueuePtr &queue, const TriVertex *vertices, const unsigned int *elements, int count, PolyDrawMode mode) @@ -142,25 +146,7 @@ void PolyDrawArgs::DrawElements(const DrawerCommandQueuePtr &queue, const TriVer mElements = elements; mVertexCount = count; mDrawMode = mode; - queue->Push(*this, PolyTriangleDrawer::is_mirror()); -} - -void PolyDrawArgs::DrawArray(PolyRenderThread *thread, const TriVertex *vertices, int vcount, PolyDrawMode mode) -{ - mVertices = vertices; - mVertexCount = vcount; - mElements = nullptr; - mDrawMode = mode; - thread->DrawQueue->Push(*this, PolyTriangleDrawer::is_mirror()); -} - -void PolyDrawArgs::DrawElements(PolyRenderThread *thread, const TriVertex *vertices, const unsigned int *elements, int count, PolyDrawMode mode) -{ - mVertices = vertices; - mElements = elements; - mVertexCount = count; - mDrawMode = mode; - thread->DrawQueue->Push(*this, PolyTriangleDrawer::is_mirror()); + queue->Push(*this); } void PolyDrawArgs::SetStyle(const FRenderStyle &renderstyle, double alpha, uint32_t fillcolor, uint32_t translationID, FTexture *tex, bool fullbright) @@ -224,16 +210,9 @@ void PolyDrawArgs::SetStyle(const FRenderStyle &renderstyle, double alpha, uint3 ///////////////////////////////////////////////////////////////////////////// -void RectDrawArgs::SetTexture(const uint8_t *texels, int width, int height) -{ - mTexturePixels = texels; - mTextureWidth = width; - mTextureHeight = height; - mTranslation = nullptr; -} - void RectDrawArgs::SetTexture(FTexture *texture, FRenderStyle style) { + mTexture = texture; mTextureWidth = texture->GetWidth(); mTextureHeight = texture->GetHeight(); if (PolyRenderer::Instance()->RenderTarget->IsBgra()) @@ -255,6 +234,7 @@ void RectDrawArgs::SetTexture(FTexture *texture, uint32_t translationID, FRender else mTranslation = table->Remap; + mTexture = texture; mTextureWidth = texture->GetWidth(); mTextureHeight = texture->GetHeight(); mTexturePixels = texture->GetPixels(style); @@ -264,6 +244,7 @@ void RectDrawArgs::SetTexture(FTexture *texture, uint32_t translationID, FRender if (style.Flags & STYLEF_RedIsAlpha) { + mTexture = texture; mTextureWidth = texture->GetWidth(); mTextureHeight = texture->GetHeight(); mTexturePixels = texture->GetPixels(style); @@ -312,6 +293,7 @@ void RectDrawArgs::Draw(PolyRenderThread *thread, double x0, double x1, double y mU1 = (float)u1; mV0 = (float)v0; mV1 = (float)v1; + thread->DrawQueue->Push(*this); } diff --git a/src/polyrenderer/drawers/poly_draw_args.h b/src/polyrenderer/drawers/poly_draw_args.h index 05ad0862d..0c10be6b8 100644 --- a/src/polyrenderer/drawers/poly_draw_args.h +++ b/src/polyrenderer/drawers/poly_draw_args.h @@ -28,7 +28,7 @@ class PolyRenderThread; class FTexture; -struct TriMatrix; +class Mat4f; enum class PolyDrawMode { @@ -75,19 +75,14 @@ public: void SetWriteColor(bool enable) { mWriteColor = enable; } void SetWriteStencil(bool enable, uint8_t stencilWriteValue = 0) { mWriteStencil = enable; mStencilWriteValue = stencilWriteValue; } void SetWriteDepth(bool enable) { mWriteDepth = enable; } - void SetFaceCullCCW(bool counterclockwise) { mFaceCullCCW = counterclockwise; } void SetStyle(TriBlendMode blendmode, double srcalpha = 1.0, double destalpha = 1.0) { mBlendMode = blendmode; mSrcAlpha = (uint32_t)(srcalpha * 256.0 + 0.5); mDestAlpha = (uint32_t)(destalpha * 256.0 + 0.5); } void SetStyle(const FRenderStyle &renderstyle, double alpha, uint32_t fillcolor, uint32_t translationID, FTexture *texture, bool fullbright); - void SetTransform(const TriMatrix *objectToClip) { mObjectToClip = objectToClip; } 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(PolyRenderThread *thread, const TriVertex *vertices, int vcount, PolyDrawMode mode = PolyDrawMode::Triangles); - void DrawElements(PolyRenderThread *thread, const TriVertex *vertices, const unsigned int *elements, int count, PolyDrawMode mode = PolyDrawMode::Triangles); 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); - const TriMatrix *ObjectToClip() const { return mObjectToClip; } const PolyClipPlane &ClipPlane(int index) const { return mClipPlane[index]; } const TriVertex *Vertices() const { return mVertices; } @@ -95,9 +90,9 @@ public: const unsigned int *Elements() const { return mElements; } PolyDrawMode DrawMode() const { return mDrawMode; } - bool FaceCullCCW() const { return mFaceCullCCW; } bool WriteColor() const { return mWriteColor; } + FTexture *Texture() const { return mTexture; } const uint8_t *TexturePixels() const { return mTexturePixels; } int TextureWidth() const { return mTextureWidth; } int TextureHeight() const { return mTextureHeight; } @@ -140,16 +135,15 @@ public: void SetNormal(const FVector3 &normal) { mNormal = normal; } private: - const TriMatrix *mObjectToClip = nullptr; const TriVertex *mVertices = nullptr; int mVertexCount = 0; const unsigned int *mElements = nullptr; PolyDrawMode mDrawMode = PolyDrawMode::Triangles; - bool mFaceCullCCW = false; bool mDepthTest = false; bool mWriteStencil = true; bool mWriteColor = true; bool mWriteDepth = true; + FTexture *mTexture = nullptr; const uint8_t *mTexturePixels = nullptr; int mTextureWidth = 0; int mTextureHeight = 0; @@ -185,7 +179,6 @@ private: class RectDrawArgs { public: - void SetTexture(const uint8_t *texels, int width, int height); void SetTexture(FTexture *texture, FRenderStyle style); void SetTexture(FTexture *texture, uint32_t translationID, FRenderStyle style); void SetLight(FSWColormap *basecolormap, uint32_t lightlevel); @@ -194,6 +187,7 @@ public: 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); + FTexture *Texture() const { return mTexture; } const uint8_t *TexturePixels() const { return mTexturePixels; } int TextureWidth() const { return mTextureWidth; } int TextureHeight() const { return mTextureHeight; } @@ -227,6 +221,7 @@ public: float V1() const { return mV1; } private: + FTexture *mTexture = nullptr; const uint8_t *mTexturePixels = nullptr; int mTextureWidth = 0; int mTextureHeight = 0; diff --git a/src/polyrenderer/drawers/poly_drawer32.h b/src/polyrenderer/drawers/poly_drawer32.h index 1acb3de1b..579330ad1 100644 --- a/src/polyrenderer/drawers/poly_drawer32.h +++ b/src/polyrenderer/drawers/poly_drawer32.h @@ -778,7 +778,7 @@ template class RectScreenDrawer32 { public: - static void Execute(const void *destOrg, int destWidth, int destHeight, int destPitch, const RectDrawArgs *args, WorkerThreadData *thread) + static void Execute(const void *destOrg, int destWidth, int destHeight, int destPitch, const RectDrawArgs *args, PolyTriangleThreadData *thread) { using namespace TriScreenDrawerModes; @@ -798,7 +798,7 @@ public: private: template - FORCEINLINE static void Loop(const void *destOrg, int destWidth, int destHeight, int destPitch, const RectDrawArgs *args, WorkerThreadData *thread) + FORCEINLINE static void Loop(const void *destOrg, int destWidth, int destHeight, int destPitch, const RectDrawArgs *args, PolyTriangleThreadData *thread) { using namespace TriScreenDrawerModes; diff --git a/src/polyrenderer/drawers/poly_drawer32_sse2.h b/src/polyrenderer/drawers/poly_drawer32_sse2.h index 3826d063d..33af938dc 100644 --- a/src/polyrenderer/drawers/poly_drawer32_sse2.h +++ b/src/polyrenderer/drawers/poly_drawer32_sse2.h @@ -805,7 +805,7 @@ template class RectScreenDrawer32 { public: - static void Execute(const void *destOrg, int destWidth, int destHeight, int destPitch, const RectDrawArgs *args, WorkerThreadData *thread) + static void Execute(const void *destOrg, int destWidth, int destHeight, int destPitch, const RectDrawArgs *args, PolyTriangleThreadData *thread) { using namespace TriScreenDrawerModes; @@ -821,7 +821,7 @@ public: private: template - FORCEINLINE static void VECTORCALL Loop(const void *destOrg, int destWidth, int destHeight, int destPitch, const RectDrawArgs *args, WorkerThreadData *thread) + FORCEINLINE static void VECTORCALL Loop(const void *destOrg, int destWidth, int destHeight, int destPitch, const RectDrawArgs *args, PolyTriangleThreadData *thread) { using namespace TriScreenDrawerModes; diff --git a/src/polyrenderer/drawers/poly_drawer8.h b/src/polyrenderer/drawers/poly_drawer8.h index fb7169186..d87b16194 100644 --- a/src/polyrenderer/drawers/poly_drawer8.h +++ b/src/polyrenderer/drawers/poly_drawer8.h @@ -429,7 +429,7 @@ template class RectScreenDrawer8 { public: - static void Execute(const void *destOrg, int destWidth, int destHeight, int destPitch, const RectDrawArgs *args, WorkerThreadData *thread) + static void Execute(const void *destOrg, int destWidth, int destHeight, int destPitch, const RectDrawArgs *args, PolyTriangleThreadData *thread) { using namespace TriScreenDrawerModes; diff --git a/src/polyrenderer/drawers/poly_triangle.cpp b/src/polyrenderer/drawers/poly_triangle.cpp index 83a6f9ed7..df8b2896a 100644 --- a/src/polyrenderer/drawers/poly_triangle.cpp +++ b/src/polyrenderer/drawers/poly_triangle.cpp @@ -39,52 +39,69 @@ #include "screen_triangle.h" #include "x86.h" -int PolyTriangleDrawer::viewport_x; -int PolyTriangleDrawer::viewport_y; -int PolyTriangleDrawer::viewport_width; -int PolyTriangleDrawer::viewport_height; -int PolyTriangleDrawer::dest_pitch; -int PolyTriangleDrawer::dest_width; -int PolyTriangleDrawer::dest_height; -uint8_t *PolyTriangleDrawer::dest; -bool PolyTriangleDrawer::dest_bgra; -bool PolyTriangleDrawer::mirror; - -void PolyTriangleDrawer::set_viewport(int x, int y, int width, int height, DCanvas *canvas) +void PolyTriangleDrawer::ClearBuffers(DCanvas *canvas) { - dest = (uint8_t*)canvas->GetBuffer(); - dest_width = canvas->GetWidth(); - dest_height = canvas->GetHeight(); - dest_pitch = canvas->GetPitch(); - dest_bgra = canvas->IsBgra(); + PolyStencilBuffer::Instance()->Clear(canvas->GetWidth(), canvas->GetHeight(), 0); + PolyZBuffer::Instance()->Resize(canvas->GetPitch(), canvas->GetHeight()); +} + +void PolyTriangleDrawer::SetViewport(const DrawerCommandQueuePtr &queue, int x, int y, int width, int height, DCanvas *canvas, bool span_drawers) +{ + uint8_t *dest = (uint8_t*)canvas->GetBuffer(); + int dest_width = canvas->GetWidth(); + int dest_height = canvas->GetHeight(); + int dest_pitch = canvas->GetPitch(); + bool dest_bgra = canvas->IsBgra(); int offsetx = clamp(x, 0, dest_width); int offsety = clamp(y, 0, dest_height); int pixelsize = dest_bgra ? 4 : 1; - viewport_x = x - offsetx; - viewport_y = y - offsety; - viewport_width = width; - viewport_height = height; + int viewport_x = x - offsetx; + int viewport_y = y - offsety; + int viewport_width = width; + int viewport_height = height; dest += (offsetx + offsety * dest_pitch) * pixelsize; dest_width = clamp(viewport_x + viewport_width, 0, dest_width - offsetx); dest_height = clamp(viewport_y + viewport_height, 0, dest_height - offsety); + queue->Push(viewport_x, viewport_y, viewport_width, viewport_height, dest, dest_width, dest_height, dest_pitch, dest_bgra, span_drawers); +} + +void PolyTriangleDrawer::SetTransform(const DrawerCommandQueuePtr &queue, const Mat4f *objectToClip) +{ + queue->Push(objectToClip); +} + +void PolyTriangleDrawer::ToggleMirror(const DrawerCommandQueuePtr &queue) +{ + queue->Push(); +} + +///////////////////////////////////////////////////////////////////////////// + +void PolyTriangleThreadData::SetViewport(int x, int y, int width, int height, uint8_t *new_dest, int new_dest_width, int new_dest_height, int new_dest_pitch, bool new_dest_bgra, bool new_span_drawers) +{ + viewport_x = x; + viewport_y = y; + viewport_width = width; + viewport_height = height; + dest = new_dest; + dest_width = new_dest_width; + dest_height = new_dest_height; + dest_pitch = new_dest_pitch; + dest_bgra = new_dest_bgra; + span_drawers = new_span_drawers; mirror = false; } -void PolyTriangleDrawer::toggle_mirror() +void PolyTriangleThreadData::SetTransform(const Mat4f *newObjectToClip) { - mirror = !mirror; + objectToClip = newObjectToClip; } -bool PolyTriangleDrawer::is_mirror() -{ - return mirror; -} - -void PolyTriangleDrawer::draw_elements(const PolyDrawArgs &drawargs, WorkerThreadData *thread) +void PolyTriangleThreadData::DrawElements(const PolyDrawArgs &drawargs) { if (drawargs.VertexCount() < 3) return; @@ -101,7 +118,7 @@ void PolyTriangleDrawer::draw_elements(const PolyDrawArgs &drawargs, WorkerThrea args.stencilMasks = PolyStencilBuffer::Instance()->Masks(); args.zbuffer = PolyZBuffer::Instance()->Values(); - bool ccw = drawargs.FaceCullCCW(); + bool ccw = !mirror; const TriVertex *vinput = drawargs.Vertices(); const unsigned int *elements = drawargs.Elements(); int vcount = drawargs.VertexCount(); @@ -112,29 +129,29 @@ void PolyTriangleDrawer::draw_elements(const PolyDrawArgs &drawargs, WorkerThrea for (int i = 0; i < vcount / 3; i++) { for (int j = 0; j < 3; j++) - vert[j] = shade_vertex(drawargs, vinput[*(elements++)]); - draw_shaded_triangle(vert, ccw, &args, thread); + vert[j] = ShadeVertex(drawargs, vinput[*(elements++)]); + DrawShadedTriangle(vert, ccw, &args); } } else if (drawargs.DrawMode() == PolyDrawMode::TriangleFan) { - vert[0] = shade_vertex(drawargs, vinput[*(elements++)]); - vert[1] = shade_vertex(drawargs, vinput[*(elements++)]); + vert[0] = ShadeVertex(drawargs, vinput[*(elements++)]); + vert[1] = ShadeVertex(drawargs, vinput[*(elements++)]); for (int i = 2; i < vcount; i++) { - vert[2] = shade_vertex(drawargs, vinput[*(elements++)]); - draw_shaded_triangle(vert, ccw, &args, thread); + vert[2] = ShadeVertex(drawargs, vinput[*(elements++)]); + DrawShadedTriangle(vert, ccw, &args); vert[1] = vert[2]; } } else // TriangleDrawMode::TriangleStrip { - vert[0] = shade_vertex(drawargs, vinput[*(elements++)]); - vert[1] = shade_vertex(drawargs, vinput[*(elements++)]); + vert[0] = ShadeVertex(drawargs, vinput[*(elements++)]); + vert[1] = ShadeVertex(drawargs, vinput[*(elements++)]); for (int i = 2; i < vcount; i++) { - vert[2] = shade_vertex(drawargs, vinput[*(elements++)]); - draw_shaded_triangle(vert, ccw, &args, thread); + vert[2] = ShadeVertex(drawargs, vinput[*(elements++)]); + DrawShadedTriangle(vert, ccw, &args); vert[0] = vert[1]; vert[1] = vert[2]; ccw = !ccw; @@ -142,7 +159,7 @@ void PolyTriangleDrawer::draw_elements(const PolyDrawArgs &drawargs, WorkerThrea } } -void PolyTriangleDrawer::draw_arrays(const PolyDrawArgs &drawargs, WorkerThreadData *thread) +void PolyTriangleThreadData::DrawArrays(const PolyDrawArgs &drawargs) { if (drawargs.VertexCount() < 3) return; @@ -159,7 +176,7 @@ void PolyTriangleDrawer::draw_arrays(const PolyDrawArgs &drawargs, WorkerThreadD args.stencilMasks = PolyStencilBuffer::Instance()->Masks(); args.zbuffer = PolyZBuffer::Instance()->Values(); - bool ccw = drawargs.FaceCullCCW(); + bool ccw = !mirror; const TriVertex *vinput = drawargs.Vertices(); int vcount = drawargs.VertexCount(); @@ -169,29 +186,29 @@ void PolyTriangleDrawer::draw_arrays(const PolyDrawArgs &drawargs, WorkerThreadD for (int i = 0; i < vcount / 3; i++) { for (int j = 0; j < 3; j++) - vert[j] = shade_vertex(drawargs, *(vinput++)); - draw_shaded_triangle(vert, ccw, &args, thread); + vert[j] = ShadeVertex(drawargs, *(vinput++)); + DrawShadedTriangle(vert, ccw, &args); } } else if (drawargs.DrawMode() == PolyDrawMode::TriangleFan) { - vert[0] = shade_vertex(drawargs, *(vinput++)); - vert[1] = shade_vertex(drawargs, *(vinput++)); + vert[0] = ShadeVertex(drawargs, *(vinput++)); + vert[1] = ShadeVertex(drawargs, *(vinput++)); for (int i = 2; i < vcount; i++) { - vert[2] = shade_vertex(drawargs, *(vinput++)); - draw_shaded_triangle(vert, ccw, &args, thread); + vert[2] = ShadeVertex(drawargs, *(vinput++)); + DrawShadedTriangle(vert, ccw, &args); vert[1] = vert[2]; } } else // TriangleDrawMode::TriangleStrip { - vert[0] = shade_vertex(drawargs, *(vinput++)); - vert[1] = shade_vertex(drawargs, *(vinput++)); + vert[0] = ShadeVertex(drawargs, *(vinput++)); + vert[1] = ShadeVertex(drawargs, *(vinput++)); for (int i = 2; i < vcount; i++) { - vert[2] = shade_vertex(drawargs, *(vinput++)); - draw_shaded_triangle(vert, ccw, &args, thread); + vert[2] = ShadeVertex(drawargs, *(vinput++)); + DrawShadedTriangle(vert, ccw, &args); vert[0] = vert[1]; vert[1] = vert[2]; ccw = !ccw; @@ -199,12 +216,10 @@ void PolyTriangleDrawer::draw_arrays(const PolyDrawArgs &drawargs, WorkerThreadD } } -ShadedTriVertex PolyTriangleDrawer::shade_vertex(const PolyDrawArgs &drawargs, const TriVertex &v) +ShadedTriVertex PolyTriangleThreadData::ShadeVertex(const PolyDrawArgs &drawargs, const TriVertex &v) { - const TriMatrix &objectToClip = *drawargs.ObjectToClip(); - // Apply transform to get clip coordinates: - FVector4 position = objectToClip * FVector4(v.x, v.y, v.z, v.w); + Vec4f position = (*objectToClip) * Vec4f(v.x, v.y, v.z, v.w); ShadedTriVertex sv; sv.x = position.X; @@ -227,7 +242,7 @@ ShadedTriVertex PolyTriangleDrawer::shade_vertex(const PolyDrawArgs &drawargs, c return sv; } -bool PolyTriangleDrawer::is_degenerate(const ShadedTriVertex *vert) +bool PolyTriangleThreadData::IsDegenerate(const ShadedTriVertex *vert) { // A degenerate triangle has a zero cross product for two of its sides. float ax = vert[1].x - vert[0].x; @@ -243,7 +258,7 @@ bool PolyTriangleDrawer::is_degenerate(const ShadedTriVertex *vert) return crosslengthsqr <= 1.e-6f; } -bool PolyTriangleDrawer::is_frontfacing(TriDrawTriangleArgs *args) +bool PolyTriangleThreadData::IsFrontfacing(TriDrawTriangleArgs *args) { float a = args->v1->x * args->v2->y - args->v2->x * args->v1->y + @@ -252,15 +267,15 @@ bool PolyTriangleDrawer::is_frontfacing(TriDrawTriangleArgs *args) return a <= 0.0f; } -void PolyTriangleDrawer::draw_shaded_triangle(const ShadedTriVertex *vert, bool ccw, TriDrawTriangleArgs *args, WorkerThreadData *thread) +void PolyTriangleThreadData::DrawShadedTriangle(const ShadedTriVertex *vert, bool ccw, TriDrawTriangleArgs *args) { // Reject triangle if degenerate - if (is_degenerate(vert)) + if (IsDegenerate(vert)) return; // Cull, clip and generate additional vertices as needed ShadedTriVertex clippedvert[max_additional_vertices]; - int numclipvert = clipedge(vert, clippedvert); + int numclipvert = ClipEdge(vert, clippedvert); #ifdef NO_SSE // Map to 2D viewport: @@ -333,8 +348,13 @@ void PolyTriangleDrawer::draw_shaded_triangle(const ShadedTriVertex *vert, bool args->v1 = &clippedvert[numclipvert - 1]; args->v2 = &clippedvert[i - 1]; args->v3 = &clippedvert[i - 2]; - if (is_frontfacing(args) == ccw && args->CalculateGradients()) - ScreenTriangle::Draw(args, thread); + if (IsFrontfacing(args) == ccw && args->CalculateGradients()) + { + if (!span_drawers) + ScreenTriangle::Draw(args, this); + else + ScreenTriangle::DrawSWRender(args, this); + } } } else @@ -344,13 +364,18 @@ void PolyTriangleDrawer::draw_shaded_triangle(const ShadedTriVertex *vert, bool args->v1 = &clippedvert[0]; args->v2 = &clippedvert[i - 1]; args->v3 = &clippedvert[i]; - if (is_frontfacing(args) != ccw && args->CalculateGradients()) - ScreenTriangle::Draw(args, thread); + if (IsFrontfacing(args) != ccw && args->CalculateGradients()) + { + if (!span_drawers) + ScreenTriangle::Draw(args, this); + else + ScreenTriangle::DrawSWRender(args, this); + } } } } -int PolyTriangleDrawer::clipedge(const ShadedTriVertex *verts, ShadedTriVertex *clippedvert) +int PolyTriangleThreadData::ClipEdge(const ShadedTriVertex *verts, ShadedTriVertex *clippedvert) { // Clip and cull so that the following is true for all vertices: // -v.w <= v.x <= v.w @@ -524,35 +549,61 @@ int PolyTriangleDrawer::clipedge(const ShadedTriVertex *verts, ShadedTriVertex * return inputverts; } +PolyTriangleThreadData *PolyTriangleThreadData::Get(DrawerThread *thread) +{ + if (!thread->poly) + thread->poly = std::make_shared(thread->core, thread->num_cores); + return thread->poly.get(); +} + ///////////////////////////////////////////////////////////////////////////// -DrawPolyTrianglesCommand::DrawPolyTrianglesCommand(const PolyDrawArgs &args, bool mirror) - : args(args) +PolySetTransformCommand::PolySetTransformCommand(const Mat4f *objectToClip) : objectToClip(objectToClip) +{ +} + +void PolySetTransformCommand::Execute(DrawerThread *thread) +{ + PolyTriangleThreadData::Get(thread)->SetTransform(objectToClip); +} + +///////////////////////////////////////////////////////////////////////////// + +void PolyToggleMirrorCommand::Execute(DrawerThread *thread) +{ + PolyTriangleThreadData::Get(thread)->ToggleMirror(); +} + +///////////////////////////////////////////////////////////////////////////// + +PolySetViewportCommand::PolySetViewportCommand(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) + : x(x), y(y), width(width), height(height), dest(dest), dest_width(dest_width), dest_height(dest_height), dest_pitch(dest_pitch), dest_bgra(dest_bgra), span_drawers(span_drawers) +{ +} + +void PolySetViewportCommand::Execute(DrawerThread *thread) +{ + PolyTriangleThreadData::Get(thread)->SetViewport(x, y, width, height, dest, dest_width, dest_height, dest_pitch, dest_bgra, span_drawers); +} + +///////////////////////////////////////////////////////////////////////////// + +DrawPolyTrianglesCommand::DrawPolyTrianglesCommand(const PolyDrawArgs &args) : args(args) { - if (mirror) - this->args.SetFaceCullCCW(!this->args.FaceCullCCW()); } void DrawPolyTrianglesCommand::Execute(DrawerThread *thread) { - WorkerThreadData thread_data; - thread_data.core = thread->core; - thread_data.num_cores = thread->num_cores; - if (!args.Elements()) - PolyTriangleDrawer::draw_arrays(args, &thread_data); + PolyTriangleThreadData::Get(thread)->DrawArrays(args); else - PolyTriangleDrawer::draw_elements(args, &thread_data); + PolyTriangleThreadData::Get(thread)->DrawElements(args); } ///////////////////////////////////////////////////////////////////////////// void DrawRectCommand::Execute(DrawerThread *thread) { - WorkerThreadData thread_data; - thread_data.core = thread->core; - thread_data.num_cores = thread->num_cores; - auto renderTarget = PolyRenderer::Instance()->RenderTarget; const void *destOrg = renderTarget->GetBuffer(); int destWidth = renderTarget->GetWidth(); @@ -560,7 +611,7 @@ void DrawRectCommand::Execute(DrawerThread *thread) int destPitch = renderTarget->GetPitch(); int blendmode = (int)args.BlendMode(); if (renderTarget->IsBgra()) - ScreenTriangle::RectDrawers32[blendmode](destOrg, destWidth, destHeight, destPitch, &args, &thread_data); + ScreenTriangle::RectDrawers32[blendmode](destOrg, destWidth, destHeight, destPitch, &args, PolyTriangleThreadData::Get(thread)); else - ScreenTriangle::RectDrawers8[blendmode](destOrg, destWidth, destHeight, destPitch, &args, &thread_data); + ScreenTriangle::RectDrawers8[blendmode](destOrg, destWidth, destHeight, destPitch, &args, PolyTriangleThreadData::Get(thread)); } diff --git a/src/polyrenderer/drawers/poly_triangle.h b/src/polyrenderer/drawers/poly_triangle.h index 7ddfbed19..7c520ed6f 100644 --- a/src/polyrenderer/drawers/poly_triangle.h +++ b/src/polyrenderer/drawers/poly_triangle.h @@ -25,43 +25,110 @@ #include "swrenderer/drawers/r_draw.h" #include "swrenderer/drawers/r_thread.h" #include "polyrenderer/drawers/screen_triangle.h" -#include "polyrenderer/math/tri_matrix.h" +#include "polyrenderer/math/gpu_types.h" #include "polyrenderer/drawers/poly_buffer.h" #include "polyrenderer/drawers/poly_draw_args.h" -typedef void(*PolyDrawFuncPtr)(const TriDrawTriangleArgs *, WorkerThreadData *); - class PolyTriangleDrawer { public: - static void set_viewport(int x, int y, int width, int height, DCanvas *canvas); - static void toggle_mirror(); - static bool is_mirror(); + 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 ToggleMirror(const DrawerCommandQueuePtr &queue); + static void SetTransform(const DrawerCommandQueuePtr &queue, const Mat4f *objectToClip); +}; + +class PolyTriangleThreadData +{ +public: + PolyTriangleThreadData(int32_t core, int32_t num_cores) : core(core), num_cores(num_cores) { } + + 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 ToggleMirror() { mirror = !mirror; } + + void DrawElements(const PolyDrawArgs &args); + void DrawArrays(const PolyDrawArgs &args); + + int32_t core; + int32_t num_cores; + + // The number of lines to skip to reach the first line to be rendered by this thread + int skipped_by_thread(int first_line) + { + int core_skip = (num_cores - (first_line - core) % num_cores) % num_cores; + return core_skip; + } + + static PolyTriangleThreadData *Get(DrawerThread *thread); private: - static ShadedTriVertex shade_vertex(const PolyDrawArgs &drawargs, const TriVertex &v); - static void draw_elements(const PolyDrawArgs &args, WorkerThreadData *thread); - static void draw_arrays(const PolyDrawArgs &args, WorkerThreadData *thread); - static void draw_shaded_triangle(const ShadedTriVertex *vertices, bool ccw, TriDrawTriangleArgs *args, WorkerThreadData *thread); - static bool is_degenerate(const ShadedTriVertex *vertices); - static bool is_frontfacing(TriDrawTriangleArgs *args); + ShadedTriVertex ShadeVertex(const PolyDrawArgs &drawargs, const TriVertex &v); + void DrawShadedTriangle(const ShadedTriVertex *vertices, bool ccw, TriDrawTriangleArgs *args); + static bool IsDegenerate(const ShadedTriVertex *vertices); + static bool IsFrontfacing(TriDrawTriangleArgs *args); + static int ClipEdge(const ShadedTriVertex *verts, ShadedTriVertex *clippedvert); - static int clipedge(const ShadedTriVertex *verts, ShadedTriVertex *clippedvert); - - static int viewport_x, viewport_y, viewport_width, viewport_height, dest_pitch, dest_width, dest_height; - static bool dest_bgra; - static uint8_t *dest; - static bool mirror; + int viewport_x = 0; + int viewport_y = 0; + int viewport_width = 0; + int viewport_height = 0; + int dest_pitch = 0; + int dest_width = 0; + int dest_height = 0; + bool dest_bgra = false; + uint8_t *dest = nullptr; + bool mirror = false; + const Mat4f *objectToClip = nullptr; + bool span_drawers = false; enum { max_additional_vertices = 16 }; +}; - friend class DrawPolyTrianglesCommand; +class PolySetTransformCommand : public DrawerCommand +{ +public: + PolySetTransformCommand(const Mat4f *objectToClip); + + void Execute(DrawerThread *thread) override; + FString DebugInfo() override { return "PolySetTransform"; } + +private: + const Mat4f *objectToClip; +}; + +class PolyToggleMirrorCommand : public DrawerCommand +{ +public: + void Execute(DrawerThread *thread) override; + FString DebugInfo() override { return "PolyToggleMirror"; } +}; + +class PolySetViewportCommand : public DrawerCommand +{ +public: + PolySetViewportCommand(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 Execute(DrawerThread *thread) override; + FString DebugInfo() override { return "PolySetViewport"; } + +private: + 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; }; class DrawPolyTrianglesCommand : public DrawerCommand { public: - DrawPolyTrianglesCommand(const PolyDrawArgs &args, bool mirror); + DrawPolyTrianglesCommand(const PolyDrawArgs &args); void Execute(DrawerThread *thread) override; FString DebugInfo() override { return "DrawPolyTriangles"; } diff --git a/src/polyrenderer/drawers/screen_triangle.cpp b/src/polyrenderer/drawers/screen_triangle.cpp index 37a7f843b..9e1afdc71 100644 --- a/src/polyrenderer/drawers/screen_triangle.cpp +++ b/src/polyrenderer/drawers/screen_triangle.cpp @@ -47,7 +47,7 @@ class TriangleBlock { public: - TriangleBlock(const TriDrawTriangleArgs *args, WorkerThreadData *thread); + TriangleBlock(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread); void Render(); private: @@ -61,7 +61,7 @@ private: void RenderBlock(int x0, int y0, int x1, int y1); const TriDrawTriangleArgs *args; - WorkerThreadData *thread; + PolyTriangleThreadData *thread; // Block size, standard 8x8 (must be power of two) static const int q = 8; @@ -138,7 +138,7 @@ private: void DepthWrite(const TriDrawTriangleArgs *args); }; -TriangleBlock::TriangleBlock(const TriDrawTriangleArgs *args, WorkerThreadData *thread) : args(args), thread(thread) +TriangleBlock::TriangleBlock(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread) : args(args), thread(thread) { const ShadedTriVertex &v1 = *args->v1; const ShadedTriVertex &v2 = *args->v2; @@ -1071,19 +1071,10 @@ void TriangleBlock::DepthWrite(const TriDrawTriangleArgs *args) #endif -EXTERN_CVAR(Bool, r_polyrenderer) - -void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, WorkerThreadData *thread) +void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread) { - if (r_polyrenderer) - { - TriangleBlock block(args, thread); - block.Render(); - } - else - { - DrawSWRender(args, thread); - } + TriangleBlock block(args, thread); + block.Render(); } static void SortVertices(const TriDrawTriangleArgs *args, ShadedTriVertex **sortedVertices) @@ -1100,7 +1091,7 @@ static void SortVertices(const TriDrawTriangleArgs *args, ShadedTriVertex **sort std::swap(sortedVertices[1], sortedVertices[2]); } -void ScreenTriangle::DrawSWRender(const TriDrawTriangleArgs *args, WorkerThreadData *thread) +void ScreenTriangle::DrawSWRender(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread) { // Sort vertices by Y position ShadedTriVertex *sortedVertices[3]; @@ -1568,7 +1559,7 @@ void(*ScreenTriangle::TriDrawers32[])(int, int, uint32_t, uint32_t, const TriDra &TriScreenDrawer32::Execute // FogBoundary }; -void(*ScreenTriangle::RectDrawers8[])(const void *, int, int, int, const RectDrawArgs *, WorkerThreadData *) = +void(*ScreenTriangle::RectDrawers8[])(const void *, int, int, int, const RectDrawArgs *, PolyTriangleThreadData *) = { &RectScreenDrawer8::Execute, // TextureOpaque &RectScreenDrawer8::Execute, // TextureMasked @@ -1596,7 +1587,7 @@ void(*ScreenTriangle::RectDrawers8[])(const void *, int, int, int, const RectDra &RectScreenDrawer8::Execute // FogBoundary }; -void(*ScreenTriangle::RectDrawers32[])(const void *, int, int, int, const RectDrawArgs *, WorkerThreadData *) = +void(*ScreenTriangle::RectDrawers32[])(const void *, int, int, int, const RectDrawArgs *, PolyTriangleThreadData *) = { &RectScreenDrawer32::Execute, // TextureOpaque &RectScreenDrawer32::Execute, // TextureMasked diff --git a/src/polyrenderer/drawers/screen_triangle.h b/src/polyrenderer/drawers/screen_triangle.h index 62f59ba44..9480952a4 100644 --- a/src/polyrenderer/drawers/screen_triangle.h +++ b/src/polyrenderer/drawers/screen_triangle.h @@ -27,19 +27,7 @@ class FString; class PolyDrawArgs; - -struct WorkerThreadData -{ - int32_t core; - int32_t num_cores; - - // The number of lines to skip to reach the first line to be rendered by this thread - int skipped_by_thread(int first_line) - { - int core_skip = (num_cores - (first_line - core) % num_cores) % num_cores; - return core_skip; - } -}; +class PolyTriangleThreadData; struct ShadedTriVertex { @@ -148,15 +136,15 @@ enum class TriBlendMode class ScreenTriangle { public: - static void Draw(const TriDrawTriangleArgs *args, WorkerThreadData *thread); - static void DrawSWRender(const TriDrawTriangleArgs *args, WorkerThreadData *thread); + static void Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread); + static void DrawSWRender(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread); static void DrawSpan8(int y, int x0, int x1, const TriDrawTriangleArgs *args); static void DrawSpan32(int y, int x0, int x1, const TriDrawTriangleArgs *args); static void(*TriDrawers8[])(int, int, uint32_t, uint32_t, const TriDrawTriangleArgs *); 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 void(*RectDrawers8[])(const void *, int, int, int, const RectDrawArgs *, PolyTriangleThreadData *); + static void(*RectDrawers32[])(const void *, int, int, int, const RectDrawArgs *, PolyTriangleThreadData *); static int FuzzStart; }; diff --git a/src/polyrenderer/math/gpu_types.cpp b/src/polyrenderer/math/gpu_types.cpp new file mode 100644 index 000000000..3e3d8182a --- /dev/null +++ b/src/polyrenderer/math/gpu_types.cpp @@ -0,0 +1,271 @@ +/* +** Hardpoly renderer +** Copyright (c) 2016 Magnus Norddahl +** +** This software is provided 'as-is', without any express or implied +** warranty. In no event will the authors be held liable for any damages +** arising from the use of this software. +** +** Permission is granted to anyone to use this software for any purpose, +** including commercial applications, and to alter it and redistribute it +** freely, subject to the following restrictions: +** +** 1. The origin of this software must not be misrepresented; you must not +** claim that you wrote the original software. If you use this software +** in a product, an acknowledgment in the product documentation would be +** appreciated but is not required. +** 2. Altered source versions must be plainly marked as such, and must not be +** misrepresented as being the original software. +** 3. This notice may not be removed or altered from any source distribution. +** +*/ + +#include +#include "gpu_types.h" +#include "doomtype.h" +#include + +Mat4f Mat4f::Null() +{ + Mat4f m; + memset(m.Matrix, 0, sizeof(m.Matrix)); + return m; +} + +Mat4f Mat4f::Identity() +{ + Mat4f m = Null(); + m.Matrix[0] = 1.0f; + m.Matrix[5] = 1.0f; + m.Matrix[10] = 1.0f; + m.Matrix[15] = 1.0f; + return m; +} + +Mat4f Mat4f::FromValues(float *matrix) +{ + Mat4f m; + memcpy(m.Matrix, matrix, sizeof(m.Matrix)); + return m; +} + +Mat4f Mat4f::Transpose(const Mat4f &matrix) +{ + Mat4f m; + for (int y = 0; y < 4; y++) + for (int x = 0; x < 4; x++) + m.Matrix[x + y * 4] = matrix.Matrix[y + x * 4]; + return m; +} + +Mat4f Mat4f::Translate(float x, float y, float z) +{ + Mat4f m = Identity(); + m.Matrix[0 + 3 * 4] = x; + m.Matrix[1 + 3 * 4] = y; + m.Matrix[2 + 3 * 4] = z; + return m; +} + +Mat4f Mat4f::Scale(float x, float y, float z) +{ + Mat4f m = Null(); + m.Matrix[0 + 0 * 4] = x; + m.Matrix[1 + 1 * 4] = y; + m.Matrix[2 + 2 * 4] = z; + m.Matrix[3 + 3 * 4] = 1; + return m; +} + +Mat4f Mat4f::Rotate(float angle, float x, float y, float z) +{ + float c = cosf(angle); + float s = sinf(angle); + Mat4f m = Null(); + m.Matrix[0 + 0 * 4] = (x*x*(1.0f - c) + c); + m.Matrix[0 + 1 * 4] = (x*y*(1.0f - c) - z*s); + m.Matrix[0 + 2 * 4] = (x*z*(1.0f - c) + y*s); + m.Matrix[1 + 0 * 4] = (y*x*(1.0f - c) + z*s); + m.Matrix[1 + 1 * 4] = (y*y*(1.0f - c) + c); + m.Matrix[1 + 2 * 4] = (y*z*(1.0f - c) - x*s); + m.Matrix[2 + 0 * 4] = (x*z*(1.0f - c) - y*s); + m.Matrix[2 + 1 * 4] = (y*z*(1.0f - c) + x*s); + m.Matrix[2 + 2 * 4] = (z*z*(1.0f - c) + c); + m.Matrix[3 + 3 * 4] = 1.0f; + return m; +} + +Mat4f Mat4f::SwapYZ() +{ + Mat4f m = Null(); + m.Matrix[0 + 0 * 4] = 1.0f; + m.Matrix[1 + 2 * 4] = 1.0f; + m.Matrix[2 + 1 * 4] = -1.0f; + m.Matrix[3 + 3 * 4] = 1.0f; + return m; +} + +Mat4f Mat4f::Perspective(float fovy, float aspect, float z_near, float z_far, Handedness handedness, ClipZRange clipZ) +{ + float f = (float)(1.0 / tan(fovy * M_PI / 360.0)); + Mat4f m = Null(); + m.Matrix[0 + 0 * 4] = f / aspect; + m.Matrix[1 + 1 * 4] = f; + m.Matrix[2 + 2 * 4] = (z_far + z_near) / (z_near - z_far); + m.Matrix[2 + 3 * 4] = (2.0f * z_far * z_near) / (z_near - z_far); + m.Matrix[3 + 2 * 4] = -1.0f; + + if (handedness == Handedness::Left) + { + m = m * Mat4f::Scale(1.0f, 1.0f, -1.0f); + } + + if (clipZ == ClipZRange::ZeroPositiveW) + { + Mat4f scale_translate = Identity(); + scale_translate.Matrix[2 + 2 * 4] = 0.5f; + scale_translate.Matrix[2 + 3 * 4] = 0.5f; + m = scale_translate * m; + } + + return m; +} + +Mat4f Mat4f::Frustum(float left, float right, float bottom, float top, float near, float far, Handedness handedness, ClipZRange clipZ) +{ + float a = (right + left) / (right - left); + float b = (top + bottom) / (top - bottom); + float c = -(far + near) / (far - near); + float d = -(2.0f * far) / (far - near); + Mat4f m = Null(); + m.Matrix[0 + 0 * 4] = 2.0f * near / (right - left); + m.Matrix[1 + 1 * 4] = 2.0f * near / (top - bottom); + m.Matrix[0 + 2 * 4] = a; + m.Matrix[1 + 2 * 4] = b; + m.Matrix[2 + 2 * 4] = c; + m.Matrix[2 + 3 * 4] = d; + m.Matrix[3 + 2 * 4] = -1; + + if (handedness == Handedness::Left) + { + m = m * Mat4f::Scale(1.0f, 1.0f, -1.0f); + } + + if (clipZ == ClipZRange::ZeroPositiveW) + { + Mat4f scale_translate = Identity(); + scale_translate.Matrix[2 + 2 * 4] = 0.5f; + scale_translate.Matrix[2 + 3 * 4] = 0.5f; + m = scale_translate * m; + } + + return m; +} + +Mat4f Mat4f::operator*(const Mat4f &mult) const +{ + Mat4f result; + for (int x = 0; x < 4; x++) + { + for (int y = 0; y < 4; y++) + { + result.Matrix[x + y * 4] = + Matrix[0 * 4 + x] * mult.Matrix[y * 4 + 0] + + Matrix[1 * 4 + x] * mult.Matrix[y * 4 + 1] + + Matrix[2 * 4 + x] * mult.Matrix[y * 4 + 2] + + Matrix[3 * 4 + x] * mult.Matrix[y * 4 + 3]; + } + } + return result; +} + +Vec4f Mat4f::operator*(const Vec4f &v) const +{ + Vec4f result; +#ifdef NO_SSE + result.X = Matrix[0 * 4 + 0] * v.X + Matrix[1 * 4 + 0] * v.Y + Matrix[2 * 4 + 0] * v.Z + Matrix[3 * 4 + 0] * v.W; + result.Y = Matrix[0 * 4 + 1] * v.X + Matrix[1 * 4 + 1] * v.Y + Matrix[2 * 4 + 1] * v.Z + Matrix[3 * 4 + 1] * v.W; + result.Z = Matrix[0 * 4 + 2] * v.X + Matrix[1 * 4 + 2] * v.Y + Matrix[2 * 4 + 2] * v.Z + Matrix[3 * 4 + 2] * v.W; + result.W = Matrix[0 * 4 + 3] * v.X + Matrix[1 * 4 + 3] * v.Y + Matrix[2 * 4 + 3] * v.Z + Matrix[3 * 4 + 3] * v.W; +#else + __m128 m0 = _mm_loadu_ps(Matrix); + __m128 m1 = _mm_loadu_ps(Matrix + 4); + __m128 m2 = _mm_loadu_ps(Matrix + 8); + __m128 m3 = _mm_loadu_ps(Matrix + 12); + __m128 mv = _mm_loadu_ps(&v.X); + m0 = _mm_mul_ps(m0, _mm_shuffle_ps(mv, mv, _MM_SHUFFLE(0, 0, 0, 0))); + m1 = _mm_mul_ps(m1, _mm_shuffle_ps(mv, mv, _MM_SHUFFLE(1, 1, 1, 1))); + m2 = _mm_mul_ps(m2, _mm_shuffle_ps(mv, mv, _MM_SHUFFLE(2, 2, 2, 2))); + m3 = _mm_mul_ps(m3, _mm_shuffle_ps(mv, mv, _MM_SHUFFLE(3, 3, 3, 3))); + mv = _mm_add_ps(_mm_add_ps(_mm_add_ps(m0, m1), m2), m3); + Vec4f sv; + _mm_storeu_ps(&result.X, mv); +#endif + return result; +} + +///////////////////////////////////////////////////////////////////////////// + +Mat3f::Mat3f(const Mat4f &matrix) +{ + for (int y = 0; y < 3; y++) + for (int x = 0; x < 3; x++) + Matrix[x + y * 3] = matrix.Matrix[x + y * 4]; +} + +Mat3f Mat3f::Null() +{ + Mat3f m; + memset(m.Matrix, 0, sizeof(m.Matrix)); + return m; +} + +Mat3f Mat3f::Identity() +{ + Mat3f m = Null(); + m.Matrix[0] = 1.0f; + m.Matrix[4] = 1.0f; + m.Matrix[8] = 1.0f; + return m; +} + +Mat3f Mat3f::FromValues(float *matrix) +{ + Mat3f m; + memcpy(m.Matrix, matrix, sizeof(m.Matrix)); + return m; +} + +Mat3f Mat3f::Transpose(const Mat3f &matrix) +{ + Mat3f m; + for (int y = 0; y < 3; y++) + for (int x = 0; x < 3; x++) + m.Matrix[x + y * 3] = matrix.Matrix[y + x * 3]; + return m; +} + +Mat3f Mat3f::operator*(const Mat3f &mult) const +{ + Mat3f result; + for (int x = 0; x < 3; x++) + { + for (int y = 0; y < 3; y++) + { + result.Matrix[x + y * 3] = + Matrix[0 * 3 + x] * mult.Matrix[y * 3 + 0] + + Matrix[1 * 3 + x] * mult.Matrix[y * 3 + 1] + + Matrix[2 * 3 + x] * mult.Matrix[y * 3 + 2]; + } + } + return result; +} + +Vec3f Mat3f::operator*(const Vec3f &v) const +{ + Vec3f result; + result.X = Matrix[0 * 3 + 0] * v.X + Matrix[1 * 3 + 0] * v.Y + Matrix[2 * 3 + 0] * v.Z; + result.Y = Matrix[0 * 3 + 1] * v.X + Matrix[1 * 3 + 1] * v.Y + Matrix[2 * 3 + 1] * v.Z; + result.Z = Matrix[0 * 3 + 2] * v.X + Matrix[1 * 3 + 2] * v.Y + Matrix[2 * 3 + 2] * v.Z; + return result; +} diff --git a/src/polyrenderer/math/gpu_types.h b/src/polyrenderer/math/gpu_types.h new file mode 100644 index 000000000..0a0c261dd --- /dev/null +++ b/src/polyrenderer/math/gpu_types.h @@ -0,0 +1,148 @@ +/* +** Hardpoly renderer +** Copyright (c) 2016 Magnus Norddahl +** +** This software is provided 'as-is', without any express or implied +** warranty. In no event will the authors be held liable for any damages +** arising from the use of this software. +** +** Permission is granted to anyone to use this software for any purpose, +** including commercial applications, and to alter it and redistribute it +** freely, subject to the following restrictions: +** +** 1. The origin of this software must not be misrepresented; you must not +** claim that you wrote the original software. If you use this software +** in a product, an acknowledgment in the product documentation would be +** appreciated but is not required. +** 2. Altered source versions must be plainly marked as such, and must not be +** misrepresented as being the original software. +** 3. This notice may not be removed or altered from any source distribution. +** +*/ + +#pragma once + +#include + +template class Vec4; +template class Vec3; + +template +class Vec2 +{ +public: + Vec2() : X(Type(0)), Y(Type(0)) { } + Vec2(float v) : X(v), Y(v) { } + Vec2(float x, float y) : X(x), Y(y) { } + + float X, Y; + + bool operator==(const Vec2 &other) const { return X == other.X && Y == other.Y; } + bool operator!=(const Vec2 &other) const { return X != other.X || Y != other.Y; } +}; + +template +class Vec3 +{ +public: + Vec3() : X(Type(0)), Y(Type(0)), Z(Type(0)) { } + Vec3(float v) : X(v), Y(v), Z(v) { } + Vec3(float x, float y, float z) : X(x), Y(y), Z(z) { } + Vec3(const Vec2 &v, float z) : X(v.X), Y(v.Y), Z(z) { } + + float X, Y, Z; + + bool operator==(const Vec3 &other) const { return X == other.X && Y == other.Y && Z == other.Z; } + bool operator!=(const Vec3 &other) const { return X != other.X || Y != other.Y || Z != other.Z; } +}; + +template +class Vec4 +{ +public: + Vec4() : X(Type(0)), Y(Type(0)), Z(Type(0)), W(Type(0)) { } + Vec4(Type v) : X(v), Y(v), Z(v), W(v) { } + Vec4(Type x, Type y, Type z, Type w = 1.0f) : X(x), Y(y), Z(z), W(w) { } + + Vec4(const Vec2 &v, Type z, Type w) : X(v.X), Y(v.Y), Z(z), W(w) { } + Vec4(const Vec3 &v, Type w) : X(v.X), Y(v.Y), Z(v.Z), W(w) { } + + Type X, Y, Z, W; + + bool operator==(const Vec4 &other) const { return X == other.X && Y == other.Y && Z == other.Z && W == other.W; } + bool operator!=(const Vec4 &other) const { return X != other.X || Y != other.Y || Z != other.Z || W != other.W; } +}; + +typedef Vec4 Vec4d; +typedef Vec3 Vec3d; +typedef Vec2 Vec2d; +typedef Vec4 Vec4f; +typedef Vec3 Vec3f; +typedef Vec2 Vec2f; +typedef Vec4 Vec4i; +typedef Vec3 Vec3i; +typedef Vec2 Vec2i; +typedef Vec4 Vec4s; +typedef Vec3 Vec3s; +typedef Vec2 Vec2s; +typedef Vec4 Vec4b; +typedef Vec3 Vec3b; +typedef Vec2 Vec2b; +typedef Vec4 Vec4ui; +typedef Vec3 Vec3ui; +typedef Vec2 Vec2ui; +typedef Vec4 Vec4us; +typedef Vec3 Vec3us; +typedef Vec2 Vec2us; +typedef Vec4 Vec4ub; +typedef Vec3 Vec3ub; +typedef Vec2 Vec2ub; + +enum class Handedness +{ + Left, + Right +}; + +enum class ClipZRange +{ + NegativePositiveW, // OpenGL, -wclip <= zclip <= wclip + ZeroPositiveW // Direct3D, 0 <= zclip <= wclip +}; + +class Mat4f +{ +public: + static Mat4f Null(); + static Mat4f Identity(); + static Mat4f FromValues(float *matrix); + static Mat4f Transpose(const Mat4f &matrix); + static Mat4f Translate(float x, float y, float z); + static Mat4f Scale(float x, float y, float z); + static Mat4f Rotate(float angle, float x, float y, float z); + static Mat4f SwapYZ(); + static Mat4f Perspective(float fovy, float aspect, float near, float far, Handedness handedness, ClipZRange clipZ); + static Mat4f Frustum(float left, float right, float bottom, float top, float near, float far, Handedness handedness, ClipZRange clipZ); + + Vec4f operator*(const Vec4f &v) const; + Mat4f operator*(const Mat4f &m) const; + + float Matrix[16]; +}; + +class Mat3f +{ +public: + Mat3f() { } + Mat3f(const Mat4f &matrix); + + static Mat3f Null(); + static Mat3f Identity(); + static Mat3f FromValues(float *matrix); + static Mat3f Transpose(const Mat3f &matrix); + + Vec3f operator*(const Vec3f &v) const; + Mat3f operator*(const Mat3f &m) const; + + float Matrix[9]; +}; diff --git a/src/polyrenderer/math/tri_matrix.cpp b/src/polyrenderer/math/tri_matrix.cpp deleted file mode 100644 index ed606d793..000000000 --- a/src/polyrenderer/math/tri_matrix.cpp +++ /dev/null @@ -1,197 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 Magnus Norddahl -** -** This software is provided 'as-is', without any express or implied -** warranty. In no event will the authors be held liable for any damages -** arising from the use of this software. -** -** Permission is granted to anyone to use this software for any purpose, -** including commercial applications, and to alter it and redistribute it -** freely, subject to the following restrictions: -** -** 1. The origin of this software must not be misrepresented; you must not -** claim that you wrote the original software. If you use this software -** in a product, an acknowledgment in the product documentation would be -** appreciated but is not required. -** 2. Altered source versions must be plainly marked as such, and must not be -** misrepresented as being the original software. -** 3. This notice may not be removed or altered from any source distribution. -** -*/ - -#include -#include "templates.h" -#include "doomdef.h" -#include "i_system.h" -#include "w_wad.h" -#include "v_video.h" -#include "doomstat.h" -#include "st_stuff.h" -#include "g_game.h" -#include "g_level.h" -#include "r_data/r_translate.h" -#include "v_palette.h" -#include "r_data/colormaps.h" -#include "r_utility.h" -#include "tri_matrix.h" -#include "polyrenderer/drawers/poly_triangle.h" -#include "swrenderer/drawers/r_draw_rgba.h" -#include "swrenderer/viewport/r_viewport.h" - -TriMatrix TriMatrix::null() -{ - TriMatrix m; - memset(m.matrix, 0, sizeof(m.matrix)); - return m; -} - -TriMatrix TriMatrix::identity() -{ - TriMatrix m = null(); - m.matrix[0] = 1.0f; - m.matrix[5] = 1.0f; - m.matrix[10] = 1.0f; - m.matrix[15] = 1.0f; - return m; -} - -TriMatrix TriMatrix::translate(float x, float y, float z) -{ - TriMatrix m = identity(); - m.matrix[0 + 3 * 4] = x; - m.matrix[1 + 3 * 4] = y; - m.matrix[2 + 3 * 4] = z; - return m; -} - -TriMatrix TriMatrix::scale(float x, float y, float z) -{ - TriMatrix m = null(); - m.matrix[0 + 0 * 4] = x; - m.matrix[1 + 1 * 4] = y; - m.matrix[2 + 2 * 4] = z; - m.matrix[3 + 3 * 4] = 1; - return m; -} - -TriMatrix TriMatrix::rotate(float angle, float x, float y, float z) -{ - float c = cosf(angle); - float s = sinf(angle); - TriMatrix m = null(); - m.matrix[0 + 0 * 4] = (x*x*(1.0f - c) + c); - m.matrix[0 + 1 * 4] = (x*y*(1.0f - c) - z*s); - m.matrix[0 + 2 * 4] = (x*z*(1.0f - c) + y*s); - m.matrix[1 + 0 * 4] = (y*x*(1.0f - c) + z*s); - m.matrix[1 + 1 * 4] = (y*y*(1.0f - c) + c); - m.matrix[1 + 2 * 4] = (y*z*(1.0f - c) - x*s); - m.matrix[2 + 0 * 4] = (x*z*(1.0f - c) - y*s); - m.matrix[2 + 1 * 4] = (y*z*(1.0f - c) + x*s); - m.matrix[2 + 2 * 4] = (z*z*(1.0f - c) + c); - m.matrix[3 + 3 * 4] = 1.0f; - return m; -} - -TriMatrix TriMatrix::swapYZ() -{ - TriMatrix m = null(); - m.matrix[0 + 0 * 4] = 1.0f; - m.matrix[1 + 2 * 4] = 1.0f; - m.matrix[2 + 1 * 4] = -1.0f; - m.matrix[3 + 3 * 4] = 1.0f; - return m; -} - -TriMatrix TriMatrix::perspective(float fovy, float aspect, float z_near, float z_far) -{ - float f = (float)(1.0 / tan(fovy * M_PI / 360.0)); - TriMatrix m = null(); - m.matrix[0 + 0 * 4] = f / aspect; - m.matrix[1 + 1 * 4] = f; - m.matrix[2 + 2 * 4] = (z_far + z_near) / (z_near - z_far); - m.matrix[2 + 3 * 4] = (2.0f * z_far * z_near) / (z_near - z_far); - m.matrix[3 + 2 * 4] = -1.0f; - return m; -} - -TriMatrix TriMatrix::frustum(float left, float right, float bottom, float top, float near, float far) -{ - float a = (right + left) / (right - left); - float b = (top + bottom) / (top - bottom); - float c = -(far + near) / (far - near); - float d = -(2.0f * far) / (far - near); - TriMatrix m = null(); - m.matrix[0 + 0 * 4] = 2.0f * near / (right - left); - m.matrix[1 + 1 * 4] = 2.0f * near / (top - bottom); - m.matrix[0 + 2 * 4] = a; - m.matrix[1 + 2 * 4] = b; - m.matrix[2 + 2 * 4] = c; - m.matrix[2 + 3 * 4] = d; - m.matrix[3 + 2 * 4] = -1; - return m; -} - -TriMatrix TriMatrix::worldToView(const FRenderViewpoint &viewpoint) -{ - TriMatrix m = null(); - m.matrix[0 + 0 * 4] = (float)viewpoint.Sin; - m.matrix[0 + 1 * 4] = (float)-viewpoint.Cos; - m.matrix[1 + 2 * 4] = 1.0f; - m.matrix[2 + 0 * 4] = (float)-viewpoint.Cos; - m.matrix[2 + 1 * 4] = (float)-viewpoint.Sin; - m.matrix[3 + 3 * 4] = 1.0f; - return m * translate((float)-viewpoint.Pos.X, (float)-viewpoint.Pos.Y, (float)-viewpoint.Pos.Z); -} - -TriMatrix TriMatrix::viewToClip(double focalTangent, double centerY, double YaspectMul) -{ - float near = 5.0f; - float far = 65536.0f; - float width = (float)(focalTangent * near); - float top = (float)(centerY / viewheight * YaspectMul * near); - float bottom = (float)(top - YaspectMul * near); - return frustum(-width, width, bottom, top, near, far); -} - -TriMatrix TriMatrix::operator*(const TriMatrix &mult) const -{ - TriMatrix result; - for (int x = 0; x < 4; x++) - { - for (int y = 0; y < 4; y++) - { - result.matrix[x + y * 4] = - matrix[0 * 4 + x] * mult.matrix[y * 4 + 0] + - matrix[1 * 4 + x] * mult.matrix[y * 4 + 1] + - matrix[2 * 4 + x] * mult.matrix[y * 4 + 2] + - matrix[3 * 4 + x] * mult.matrix[y * 4 + 3]; - } - } - return result; -} - -FVector4 TriMatrix::operator*(const FVector4 &v) const -{ -#ifdef NO_SSE - float vx = matrix[0 * 4 + 0] * v.X + matrix[1 * 4 + 0] * v.Y + matrix[2 * 4 + 0] * v.Z + matrix[3 * 4 + 0] * v.W; - float vy = matrix[0 * 4 + 1] * v.X + matrix[1 * 4 + 1] * v.Y + matrix[2 * 4 + 1] * v.Z + matrix[3 * 4 + 1] * v.W; - float vz = matrix[0 * 4 + 2] * v.X + matrix[1 * 4 + 2] * v.Y + matrix[2 * 4 + 2] * v.Z + matrix[3 * 4 + 2] * v.W; - float vw = matrix[0 * 4 + 3] * v.X + matrix[1 * 4 + 3] * v.Y + matrix[2 * 4 + 3] * v.Z + matrix[3 * 4 + 3] * v.W; - return{ vx, vy, vz, vw }; -#else - __m128 m0 = _mm_loadu_ps(matrix); - __m128 m1 = _mm_loadu_ps(matrix + 4); - __m128 m2 = _mm_loadu_ps(matrix + 8); - __m128 m3 = _mm_loadu_ps(matrix + 12); - __m128 mv = _mm_loadu_ps(&v.X); - m0 = _mm_mul_ps(m0, _mm_shuffle_ps(mv, mv, _MM_SHUFFLE(0, 0, 0, 0))); - m1 = _mm_mul_ps(m1, _mm_shuffle_ps(mv, mv, _MM_SHUFFLE(1, 1, 1, 1))); - m2 = _mm_mul_ps(m2, _mm_shuffle_ps(mv, mv, _MM_SHUFFLE(2, 2, 2, 2))); - m3 = _mm_mul_ps(m3, _mm_shuffle_ps(mv, mv, _MM_SHUFFLE(3, 3, 3, 3))); - mv = _mm_add_ps(_mm_add_ps(_mm_add_ps(m0, m1), m2), m3); - FVector4 sv; - _mm_storeu_ps(&sv.X, mv); - return sv; -#endif -} diff --git a/src/polyrenderer/math/tri_matrix.h b/src/polyrenderer/math/tri_matrix.h deleted file mode 100644 index 592825c20..000000000 --- a/src/polyrenderer/math/tri_matrix.h +++ /dev/null @@ -1,46 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 Magnus Norddahl -** -** This software is provided 'as-is', without any express or implied -** warranty. In no event will the authors be held liable for any damages -** arising from the use of this software. -** -** Permission is granted to anyone to use this software for any purpose, -** including commercial applications, and to alter it and redistribute it -** freely, subject to the following restrictions: -** -** 1. The origin of this software must not be misrepresented; you must not -** claim that you wrote the original software. If you use this software -** in a product, an acknowledgment in the product documentation would be -** appreciated but is not required. -** 2. Altered source versions must be plainly marked as such, and must not be -** misrepresented as being the original software. -** 3. This notice may not be removed or altered from any source distribution. -** -*/ - -#pragma once - -struct TriVertex; -struct FRenderViewpoint; - -struct TriMatrix -{ - static TriMatrix null(); - static TriMatrix identity(); - static TriMatrix translate(float x, float y, float z); - static TriMatrix scale(float x, float y, float z); - static TriMatrix rotate(float angle, float x, float y, float z); - static TriMatrix swapYZ(); - static TriMatrix perspective(float fovy, float aspect, float near, float far); - static TriMatrix frustum(float left, float right, float bottom, float top, float near, float far); - - static TriMatrix worldToView(const FRenderViewpoint &viewpoint); // Software renderer world to view space transform - static TriMatrix viewToClip(double focalTangent, double centerY, double YaspectMul); // Software renderer shearing projection - - FVector4 operator*(const FVector4 &v) const; - TriMatrix operator*(const TriMatrix &m) const; - - float matrix[16]; -}; diff --git a/src/polyrenderer/poly_all.cpp b/src/polyrenderer/poly_all.cpp index 216dd88e1..1a777fbb1 100644 --- a/src/polyrenderer/poly_all.cpp +++ b/src/polyrenderer/poly_all.cpp @@ -4,7 +4,7 @@ #include "drawers/poly_draw_args.cpp" #include "drawers/poly_triangle.cpp" #include "drawers/screen_triangle.cpp" -#include "math/tri_matrix.cpp" +#include "math/gpu_types.cpp" #include "scene/poly_cull.cpp" #include "scene/poly_decal.cpp" #include "scene/poly_particle.cpp" diff --git a/src/polyrenderer/poly_renderer.cpp b/src/polyrenderer/poly_renderer.cpp index 7517083c5..d012c1bc9 100644 --- a/src/polyrenderer/poly_renderer.cpp +++ b/src/polyrenderer/poly_renderer.cpp @@ -38,10 +38,12 @@ #include "swrenderer/drawers/r_draw_rgba.h" #include "swrenderer/viewport/r_viewport.h" #include "swrenderer/r_swcolormaps.h" +#include "gl/system/gl_swframebuffer.h" EXTERN_CVAR(Bool, r_shadercolormaps) EXTERN_CVAR(Int, screenblocks) EXTERN_CVAR(Float, r_visibility) + void InitGLRMapinfoData(); ///////////////////////////////////////////////////////////////////////////// @@ -76,9 +78,11 @@ void PolyRenderer::RenderView(player_t *player) { Threads.MainThread()->DrawQueue->Push(cameraLight->ShaderColormap(), screen); } - + Threads.MainThread()->FlushDrawQueue(); + PolyDrawerWaitCycles.Clock(); DrawerThreads::WaitForWorkers(); + PolyDrawerWaitCycles.Unclock(); } void PolyRenderer::RenderViewToCanvas(AActor *actor, DCanvas *canvas, int x, int y, int width, int height, bool dontmaplines) @@ -98,9 +102,9 @@ void PolyRenderer::RenderViewToCanvas(AActor *actor, DCanvas *canvas, int x, int RenderActorView(actor, dontmaplines); Threads.MainThread()->FlushDrawQueue(); DrawerThreads::WaitForWorkers(); - - canvas->Unlock(); + canvas->Unlock(); + RenderTarget = screen; R_ExecuteSetViewSize(Viewpoint, Viewwindow); float trueratio; @@ -111,6 +115,14 @@ void PolyRenderer::RenderViewToCanvas(AActor *actor, DCanvas *canvas, int x, int void PolyRenderer::RenderActorView(AActor *actor, bool dontmaplines) { + PolyTotalBatches = 0; + PolyTotalTriangles = 0; + PolyTotalDrawCalls = 0; + PolyCullCycles.Reset(); + PolyOpaqueCycles.Reset(); + PolyMaskedCycles.Reset(); + PolyDrawerWaitCycles.Reset(); + NetUpdate(); DontMapLines = dontmaplines; @@ -139,10 +151,15 @@ void PolyRenderer::RenderActorView(AActor *actor, bool dontmaplines) ClearBuffers(); SetSceneViewport(); SetupPerspectiveMatrix(); - MainPortal.SetViewpoint(WorldToClip, PolyClipPlane(0.0f, 0.0f, 0.0f, 1.0f), GetNextStencilValue()); - MainPortal.Render(0); - Skydome.Render(Threads.MainThread(), WorldToClip); - MainPortal.RenderTranslucent(0); + + PolyPortalViewpoint mainViewpoint; + mainViewpoint.WorldToView = WorldToView; + mainViewpoint.WorldToClip = WorldToClip; + mainViewpoint.StencilValue = GetNextStencilValue(); + mainViewpoint.PortalPlane = PolyClipPlane(0.0f, 0.0f, 0.0f, 1.0f); + Scene.Render(&mainViewpoint); + Skydome.Render(Threads.MainThread(), WorldToView, WorldToClip); + Scene.RenderTranslucent(&mainViewpoint); PlayerSprites.Render(Threads.MainThread()); Viewpoint.camera->renderflags = savedflags; @@ -159,9 +176,11 @@ void PolyRenderer::RenderRemainingPlayerSprites() void PolyRenderer::ClearBuffers() { Threads.Clear(); - PolyStencilBuffer::Instance()->Clear(RenderTarget->GetWidth(), RenderTarget->GetHeight(), 0); - PolyZBuffer::Instance()->Resize(RenderTarget->GetPitch(), RenderTarget->GetHeight()); + PolyTriangleDrawer::ClearBuffers(RenderTarget); NextStencilValue = 0; + Threads.MainThread()->SectorPortals.clear(); + Threads.MainThread()->LinePortals.clear(); + Threads.MainThread()->TranslucentObjects.clear(); } void PolyRenderer::SetSceneViewport() @@ -177,11 +196,11 @@ void PolyRenderer::SetSceneViewport() height = (screenblocks*SCREENHEIGHT / 10) & ~7; int bottom = SCREENHEIGHT - (height + viewwindowy - ((height - viewheight) / 2)); - PolyTriangleDrawer::set_viewport(viewwindowx, SCREENHEIGHT - bottom - height, viewwidth, height, RenderTarget); + PolyTriangleDrawer::SetViewport(Threads.MainThread()->DrawQueue, viewwindowx, SCREENHEIGHT - bottom - height, viewwidth, height, RenderTarget, false); } else // Rendering to camera texture { - PolyTriangleDrawer::set_viewport(0, 0, RenderTarget->GetWidth(), RenderTarget->GetHeight(), RenderTarget); + PolyTriangleDrawer::SetViewport(Threads.MainThread()->DrawQueue, 0, 0, RenderTarget->GetWidth(), RenderTarget->GetHeight(), RenderTarget, false); } } @@ -195,7 +214,6 @@ void PolyRenderer::SetupPerspectiveMatrix() bDidSetup = true; } - // Code provided courtesy of Graf Zahl. Now we just have to plug it into the viewmatrix code... // We have to scale the pitch to account for the pixel stretching, because the playsim doesn't know about this and treats it as 1:1. double radPitch = Viewpoint.Angles.Pitch.Normalized180().Radians(); double angx = cos(radPitch); @@ -209,12 +227,24 @@ void PolyRenderer::SetupPerspectiveMatrix() float fovy = (float)(2 * DAngle::ToDegrees(atan(tan(Viewpoint.FieldOfView.Radians() / 2) / fovratio)).Degrees); WorldToView = - TriMatrix::rotate((float)Viewpoint.Angles.Roll.Radians(), 0.0f, 0.0f, 1.0f) * - TriMatrix::rotate(adjustedPitch, 1.0f, 0.0f, 0.0f) * - TriMatrix::rotate(adjustedViewAngle, 0.0f, -1.0f, 0.0f) * - TriMatrix::scale(1.0f, level.info->pixelstretch, 1.0f) * - TriMatrix::swapYZ() * - TriMatrix::translate((float)-Viewpoint.Pos.X, (float)-Viewpoint.Pos.Y, (float)-Viewpoint.Pos.Z); + Mat4f::Rotate((float)Viewpoint.Angles.Roll.Radians(), 0.0f, 0.0f, 1.0f) * + Mat4f::Rotate(adjustedPitch, 1.0f, 0.0f, 0.0f) * + Mat4f::Rotate(adjustedViewAngle, 0.0f, -1.0f, 0.0f) * + Mat4f::Scale(1.0f, level.info->pixelstretch, 1.0f) * + Mat4f::SwapYZ() * + Mat4f::Translate((float)-Viewpoint.Pos.X, (float)-Viewpoint.Pos.Y, (float)-Viewpoint.Pos.Z); - WorldToClip = TriMatrix::perspective(fovy, ratio, 5.0f, 65535.0f) * WorldToView; + WorldToClip = Mat4f::Perspective(fovy, ratio, 5.0f, 65535.0f, Handedness::Right, ClipZRange::NegativePositiveW) * WorldToView; +} + +cycle_t PolyCullCycles, PolyOpaqueCycles, PolyMaskedCycles, PolyDrawerWaitCycles; +int PolyTotalBatches, PolyTotalTriangles, PolyTotalDrawCalls; + +ADD_STAT(polyfps) +{ + FString out; + out.Format("frame=%04.1f ms cull=%04.1f ms opaque=%04.1f ms masked=%04.1f ms drawers=%04.1f ms", + FrameCycles.TimeMS(), PolyCullCycles.TimeMS(), PolyOpaqueCycles.TimeMS(), PolyMaskedCycles.TimeMS(), PolyDrawerWaitCycles.TimeMS()); + out.AppendFormat("\nbatches drawn: %d triangles drawn: %d drawcalls: %d", PolyTotalBatches, PolyTotalTriangles, PolyTotalDrawCalls); + return out; } diff --git a/src/polyrenderer/poly_renderer.h b/src/polyrenderer/poly_renderer.h index 2ef60a0ea..19ee8bd6f 100644 --- a/src/polyrenderer/poly_renderer.h +++ b/src/polyrenderer/poly_renderer.h @@ -34,12 +34,16 @@ #include "scene/poly_light.h" #include "swrenderer/r_memory.h" #include "poly_renderthread.h" +#include "stats.h" class AActor; class DCanvas; class DrawerCommandQueue; typedef std::shared_ptr DrawerCommandQueuePtr; +extern cycle_t PolyCullCycles, PolyOpaqueCycles, PolyMaskedCycles, PolyDrawerWaitCycles; +extern int PolyTotalBatches, PolyTotalTriangles, PolyTotalDrawCalls; + class PolyRenderer { public: @@ -60,9 +64,10 @@ public: FViewWindow Viewwindow; FRenderViewpoint Viewpoint; PolyLightVisibility Light; + RenderPolyScene Scene; - TriMatrix WorldToView; - TriMatrix WorldToClip; + Mat4f WorldToView; + Mat4f WorldToClip; private: void RenderActorView(AActor *actor, bool dontmaplines); @@ -70,7 +75,6 @@ private: void SetSceneViewport(); void SetupPerspectiveMatrix(); - RenderPolyScene MainPortal; PolySkyDome Skydome; RenderPolyPlayerSprites PlayerSprites; uint32_t NextStencilValue = 0; diff --git a/src/polyrenderer/poly_renderthread.h b/src/polyrenderer/poly_renderthread.h index afed28b19..92269aff8 100644 --- a/src/polyrenderer/poly_renderthread.h +++ b/src/polyrenderer/poly_renderthread.h @@ -29,6 +29,9 @@ class DrawerCommandQueue; typedef std::shared_ptr DrawerCommandQueuePtr; class RenderMemory; +class PolyTranslucentObject; +class PolyDrawSectorPortal; +class PolyDrawLinePortal; class PolyRenderThread { @@ -46,6 +49,10 @@ public: std::unique_ptr FrameMemory; DrawerCommandQueuePtr DrawQueue; + std::vector TranslucentObjects; + std::vector> SectorPortals; + std::vector> LinePortals; + // Make sure texture can accessed safely void PrepareTexture(FTexture *texture, FRenderStyle style); @@ -72,6 +79,8 @@ public: PolyRenderThread *MainThread() { return Threads.front().get(); } int NumThreads() const { return (int)Threads.size(); } + std::vector> Threads; + private: void RenderThreadSlice(PolyRenderThread *thread); @@ -80,7 +89,6 @@ private: std::function WorkerCallback; - std::vector> Threads; std::mutex start_mutex; std::condition_variable start_condition; bool shutdown_flag = false; diff --git a/src/polyrenderer/scene/poly_decal.cpp b/src/polyrenderer/scene/poly_decal.cpp index c15814460..9c3afd67c 100644 --- a/src/polyrenderer/scene/poly_decal.cpp +++ b/src/polyrenderer/scene/poly_decal.cpp @@ -32,7 +32,7 @@ #include "a_sharedglobal.h" #include "swrenderer/scene/r_scene.h" -void RenderPolyDecal::RenderWallDecals(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, const seg_t *line, uint32_t stencilValue) +void RenderPolyDecal::RenderWallDecals(PolyRenderThread *thread, const PolyClipPlane &clipPlane, const seg_t *line, uint32_t stencilValue) { if (line->linedef == nullptr && line->sidedef == nullptr) return; @@ -40,11 +40,11 @@ void RenderPolyDecal::RenderWallDecals(PolyRenderThread *thread, const TriMatrix for (DBaseDecal *decal = line->sidedef->AttachedDecals; decal != nullptr; decal = decal->WallNext) { RenderPolyDecal render; - render.Render(thread, worldToClip, clipPlane, decal, line, stencilValue); + render.Render(thread, clipPlane, decal, line, stencilValue); } } -void RenderPolyDecal::Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, DBaseDecal *decal, const seg_t *line, uint32_t stencilValue) +void RenderPolyDecal::Render(PolyRenderThread *thread, const PolyClipPlane &clipPlane, DBaseDecal *decal, const seg_t *line, uint32_t stencilValue) { if (decal->RenderFlags & RF_INVISIBLE || !viewactive || !decal->PicNum.isValid()) return; @@ -186,15 +186,12 @@ void RenderPolyDecal::Render(PolyRenderThread *thread, const TriMatrix &worldToC args.SetLight(GetColorTable(front->Colormap), lightlevel, PolyRenderer::Instance()->Light.WallGlobVis(foggy), fullbrightSprite); args.SetColor(0xff000000 | decal->AlphaColor, decal->AlphaColor >> 24); args.SetStyle(decal->RenderStyle, decal->Alpha, decal->AlphaColor, decal->Translation, tex, false); - args.SetTransform(&worldToClip); - args.SetFaceCullCCW(true); args.SetStencilTestValue(stencilValue); - args.SetWriteStencil(true, stencilValue); args.SetClipPlane(0, clipPlane); args.SetDepthTest(true); args.SetWriteStencil(false); args.SetWriteDepth(false); - args.DrawArray(thread, vertices, 4, PolyDrawMode::TriangleFan); + args.DrawArray(thread->DrawQueue, vertices, 4, PolyDrawMode::TriangleFan); } void RenderPolyDecal::GetDecalSectors(DBaseDecal *decal, const seg_t *line, sector_t **front, sector_t **back) diff --git a/src/polyrenderer/scene/poly_decal.h b/src/polyrenderer/scene/poly_decal.h index 0317e14a9..17207b569 100644 --- a/src/polyrenderer/scene/poly_decal.h +++ b/src/polyrenderer/scene/poly_decal.h @@ -27,10 +27,10 @@ class RenderPolyDecal { public: - static void RenderWallDecals(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, const seg_t *line, uint32_t stencilValue); + static void RenderWallDecals(PolyRenderThread *thread, const PolyClipPlane &clipPlane, const seg_t *line, uint32_t stencilValue); private: - void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, DBaseDecal *decal, const seg_t *line, uint32_t stencilValue); + void Render(PolyRenderThread *thread, const PolyClipPlane &clipPlane, DBaseDecal *decal, const seg_t *line, uint32_t stencilValue); void GetDecalSectors(DBaseDecal *decal, const seg_t *line, sector_t **front, sector_t **back); double GetDecalZ(DBaseDecal *decal, const seg_t *line, sector_t *front, sector_t *back); diff --git a/src/polyrenderer/scene/poly_model.cpp b/src/polyrenderer/scene/poly_model.cpp index b2ce178cc..d147f1f65 100644 --- a/src/polyrenderer/scene/poly_model.cpp +++ b/src/polyrenderer/scene/poly_model.cpp @@ -36,13 +36,13 @@ void gl_FlushModels(); bool polymodelsInUse; -void PolyRenderModel(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, uint32_t stencilValue, float x, float y, float z, FSpriteModelFrame *smf, AActor *actor) +void PolyRenderModel(PolyRenderThread *thread, const Mat4f &worldToClip, const PolyClipPlane &clipPlane, uint32_t stencilValue, float x, float y, float z, FSpriteModelFrame *smf, AActor *actor) { PolyModelRenderer renderer(thread, worldToClip, clipPlane, stencilValue); renderer.RenderModel(x, y, z, smf, actor); } -void PolyRenderHUDModel(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, uint32_t stencilValue, DPSprite *psp, float ofsx, float ofsy) +void PolyRenderHUDModel(PolyRenderThread *thread, const Mat4f &worldToClip, const PolyClipPlane &clipPlane, uint32_t stencilValue, DPSprite *psp, float ofsx, float ofsy) { PolyModelRenderer renderer(thread, worldToClip, clipPlane, stencilValue); renderer.RenderHUDModel(psp, ofsx, ofsy); @@ -50,7 +50,7 @@ void PolyRenderHUDModel(PolyRenderThread *thread, const TriMatrix &worldToClip, ///////////////////////////////////////////////////////////////////////////// -PolyModelRenderer::PolyModelRenderer(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, uint32_t stencilValue) : Thread(thread), WorldToClip(worldToClip), ClipPlane(clipPlane), StencilValue(stencilValue) +PolyModelRenderer::PolyModelRenderer(PolyRenderThread *thread, const Mat4f &worldToClip, const PolyClipPlane &clipPlane, uint32_t stencilValue) : Thread(thread), WorldToClip(worldToClip), ClipPlane(clipPlane), StencilValue(stencilValue) { if (!polymodelsInUse) { @@ -62,7 +62,8 @@ PolyModelRenderer::PolyModelRenderer(PolyRenderThread *thread, const TriMatrix & void PolyModelRenderer::BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix) { ModelActor = actor; - const_cast(objectToWorldMatrix).copy(ObjectToWorld.matrix); + const_cast(objectToWorldMatrix).copy(ObjectToWorld.Matrix); + SetTransform(); } void PolyModelRenderer::EndDrawModel(AActor *actor, FSpriteModelFrame *smf) @@ -85,14 +86,14 @@ void PolyModelRenderer::ResetVertexBuffer() VSMatrix PolyModelRenderer::GetViewToWorldMatrix() { - TriMatrix swapYZ = TriMatrix::null(); - swapYZ.matrix[0 + 0 * 4] = 1.0f; - swapYZ.matrix[1 + 2 * 4] = 1.0f; - swapYZ.matrix[2 + 1 * 4] = 1.0f; - swapYZ.matrix[3 + 3 * 4] = 1.0f; + Mat4f swapYZ = Mat4f::Null(); + swapYZ.Matrix[0 + 0 * 4] = 1.0f; + swapYZ.Matrix[1 + 2 * 4] = 1.0f; + swapYZ.Matrix[2 + 1 * 4] = 1.0f; + swapYZ.Matrix[3 + 3 * 4] = 1.0f; VSMatrix worldToView; - worldToView.loadMatrix((PolyRenderer::Instance()->WorldToView * swapYZ).matrix); + worldToView.loadMatrix((PolyRenderer::Instance()->WorldToView * swapYZ).Matrix); VSMatrix objectToWorld; worldToView.inverseMatrix(objectToWorld); @@ -102,7 +103,8 @@ VSMatrix PolyModelRenderer::GetViewToWorldMatrix() void PolyModelRenderer::BeginDrawHUDModel(AActor *actor, const VSMatrix &objectToWorldMatrix) { ModelActor = actor; - const_cast(objectToWorldMatrix).copy(ObjectToWorld.matrix); + const_cast(objectToWorldMatrix).copy(ObjectToWorld.Matrix); + SetTransform(); } void PolyModelRenderer::EndDrawHUDModel(AActor *actor) @@ -120,6 +122,17 @@ void PolyModelRenderer::SetMaterial(FTexture *skin, bool clampNoFilter, int tran SkinTexture = skin; } +void PolyModelRenderer::SetTransform() +{ + Mat4f swapYZ = Mat4f::Null(); + swapYZ.Matrix[0 + 0 * 4] = 1.0f; + swapYZ.Matrix[1 + 2 * 4] = 1.0f; + swapYZ.Matrix[2 + 1 * 4] = 1.0f; + swapYZ.Matrix[3 + 3 * 4] = 1.0f; + + PolyTriangleDrawer::SetTransform(Thread->DrawQueue, Thread->FrameMemory->NewObject(WorldToClip * swapYZ * ObjectToWorld)); +} + void PolyModelRenderer::DrawArrays(int start, int count) { const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; @@ -131,19 +144,8 @@ void PolyModelRenderer::DrawArrays(int start, int count) bool fullbrightSprite = ((ModelActor->renderflags & RF_FULLBRIGHT) || (ModelActor->flags5 & MF5_BRIGHT)); int lightlevel = fullbrightSprite ? 255 : ModelActor->Sector->lightlevel + actualextralight; - TriMatrix swapYZ = TriMatrix::null(); - swapYZ.matrix[0 + 0 * 4] = 1.0f; - swapYZ.matrix[1 + 2 * 4] = 1.0f; - swapYZ.matrix[2 + 1 * 4] = 1.0f; - swapYZ.matrix[3 + 3 * 4] = 1.0f; - - TriMatrix *transform = Thread->FrameMemory->NewObject(); - *transform = WorldToClip * swapYZ * ObjectToWorld; - PolyDrawArgs args; args.SetLight(GetColorTable(sector->Colormap, sector->SpecialColors[sector_t::sprites], true), lightlevel, PolyRenderer::Instance()->Light.SpriteGlobVis(foggy), fullbrightSprite); - args.SetTransform(transform); - args.SetFaceCullCCW(true); args.SetStencilTestValue(StencilValue); args.SetClipPlane(0, PolyClipPlane()); args.SetStyle(TriBlendMode::TextureOpaque); @@ -151,7 +153,7 @@ void PolyModelRenderer::DrawArrays(int start, int count) args.SetDepthTest(true); args.SetWriteDepth(true); args.SetWriteStencil(false); - args.DrawArray(Thread, VertexBuffer + start, count); + args.DrawArray(Thread->DrawQueue, VertexBuffer + start, count); } void PolyModelRenderer::DrawElements(int numIndices, size_t offset) @@ -165,19 +167,8 @@ void PolyModelRenderer::DrawElements(int numIndices, size_t offset) bool fullbrightSprite = ((ModelActor->renderflags & RF_FULLBRIGHT) || (ModelActor->flags5 & MF5_BRIGHT)); int lightlevel = fullbrightSprite ? 255 : ModelActor->Sector->lightlevel + actualextralight; - TriMatrix swapYZ = TriMatrix::null(); - swapYZ.matrix[0 + 0 * 4] = 1.0f; - swapYZ.matrix[1 + 2 * 4] = 1.0f; - swapYZ.matrix[2 + 1 * 4] = 1.0f; - swapYZ.matrix[3 + 3 * 4] = 1.0f; - - TriMatrix *transform = Thread->FrameMemory->NewObject(); - *transform = WorldToClip * swapYZ * ObjectToWorld; - PolyDrawArgs args; args.SetLight(GetColorTable(sector->Colormap, sector->SpecialColors[sector_t::sprites], true), lightlevel, PolyRenderer::Instance()->Light.SpriteGlobVis(foggy), fullbrightSprite); - args.SetTransform(transform); - args.SetFaceCullCCW(true); args.SetStencilTestValue(StencilValue); args.SetClipPlane(0, PolyClipPlane()); args.SetStyle(TriBlendMode::TextureOpaque); @@ -185,12 +176,12 @@ void PolyModelRenderer::DrawElements(int numIndices, size_t offset) args.SetDepthTest(true); args.SetWriteDepth(true); args.SetWriteStencil(false); - args.DrawElements(Thread, VertexBuffer, IndexBuffer + offset / sizeof(unsigned int), numIndices); + args.DrawElements(Thread->DrawQueue, VertexBuffer, IndexBuffer + offset / sizeof(unsigned int), numIndices); } double PolyModelRenderer::GetTimeFloat() { - return (float)I_msTime() * (float)TICRATE / 1000.0f; + return (double)I_msTime() * (double)TICRATE / 1000.; } ///////////////////////////////////////////////////////////////////////////// @@ -227,7 +218,7 @@ void PolyModelVertexBuffer::SetupFrame(FModelRenderer *renderer, unsigned int fr { PolyModelRenderer *polyrenderer = (PolyModelRenderer *)renderer; - if (true)//if (frame1 == frame2 || size == 0 || polyrenderer->InterpolationFactor == 0.f) + if (frame1 == frame2 || size == 0 || polyrenderer->InterpolationFactor == 0.f) { TriVertex *vertices = polyrenderer->Thread->FrameMemory->AllocMemory(size); @@ -252,11 +243,12 @@ void PolyModelVertexBuffer::SetupFrame(FModelRenderer *renderer, unsigned int fr 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 * (1.0f - frac) + mVertexBuffer[frame2 + i].x * frac; - vertices[i].y = mVertexBuffer[frame1 + i].y * (1.0f - frac) + mVertexBuffer[frame2 + i].y * frac; - vertices[i].z = mVertexBuffer[frame1 + i].z * (1.0f - frac) + mVertexBuffer[frame2 + i].z * frac; + 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; diff --git a/src/polyrenderer/scene/poly_model.h b/src/polyrenderer/scene/poly_model.h index a064459e9..6ce9665fb 100644 --- a/src/polyrenderer/scene/poly_model.h +++ b/src/polyrenderer/scene/poly_model.h @@ -26,13 +26,13 @@ #include "r_data/matrix.h" #include "r_data/models/models.h" -void PolyRenderModel(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, uint32_t stencilValue, float x, float y, float z, FSpriteModelFrame *smf, AActor *actor); -void PolyRenderHUDModel(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, uint32_t stencilValue, DPSprite *psp, float ofsx, float ofsy); +void PolyRenderModel(PolyRenderThread *thread, const Mat4f &worldToClip, const PolyClipPlane &clipPlane, uint32_t stencilValue, float x, float y, float z, FSpriteModelFrame *smf, AActor *actor); +void PolyRenderHUDModel(PolyRenderThread *thread, const Mat4f &worldToClip, const PolyClipPlane &clipPlane, uint32_t stencilValue, DPSprite *psp, float ofsx, float ofsy); class PolyModelRenderer : public FModelRenderer { public: - PolyModelRenderer(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, uint32_t stencilValue); + PolyModelRenderer(PolyRenderThread *thread, const Mat4f &worldToClip, const PolyClipPlane &clipPlane, uint32_t stencilValue); void BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix) override; void EndDrawModel(AActor *actor, FSpriteModelFrame *smf) override; @@ -48,13 +48,15 @@ public: void DrawElements(int numIndices, size_t offset) override; double GetTimeFloat() override; + void SetTransform(); + PolyRenderThread *Thread = nullptr; - const TriMatrix &WorldToClip; + const Mat4f &WorldToClip; const PolyClipPlane &ClipPlane; uint32_t StencilValue = 0; AActor *ModelActor = nullptr; - TriMatrix ObjectToWorld; + Mat4f ObjectToWorld; FTexture *SkinTexture = nullptr; unsigned int *IndexBuffer = nullptr; TriVertex *VertexBuffer = nullptr; diff --git a/src/polyrenderer/scene/poly_particle.cpp b/src/polyrenderer/scene/poly_particle.cpp index 942ef1346..0e62a2008 100644 --- a/src/polyrenderer/scene/poly_particle.cpp +++ b/src/polyrenderer/scene/poly_particle.cpp @@ -32,7 +32,7 @@ EXTERN_CVAR(Int, gl_particles_style) -void RenderPolyParticle::Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, particle_t *particle, subsector_t *sub, uint32_t stencilValue) +void RenderPolyParticle::Render(PolyRenderThread *thread, const PolyClipPlane &clipPlane, particle_t *particle, subsector_t *sub, uint32_t stencilValue) { double timefrac = r_viewpoint.TicFrac; if (paused || bglobal.freeze || (level.flags2 & LEVEL2_FROZEN)) @@ -82,14 +82,12 @@ void RenderPolyParticle::Render(PolyRenderThread *thread, const TriMatrix &world args.SetDepthTest(true); args.SetColor(particle->color | 0xff000000, particle->color >> 24); args.SetStyle(TriBlendMode::Shaded, particle->alpha, 1.0 - particle->alpha); - args.SetTransform(&worldToClip); - args.SetFaceCullCCW(true); args.SetStencilTestValue(stencilValue); args.SetWriteStencil(false); args.SetWriteDepth(false); args.SetClipPlane(0, clipPlane); args.SetTexture(GetParticleTexture(), ParticleTextureSize, ParticleTextureSize); - args.DrawArray(thread, vertices, 4, PolyDrawMode::TriangleFan); + args.DrawArray(thread->DrawQueue, vertices, 4, PolyDrawMode::TriangleFan); } uint8_t *RenderPolyParticle::GetParticleTexture() diff --git a/src/polyrenderer/scene/poly_particle.h b/src/polyrenderer/scene/poly_particle.h index 3847b0fef..de0171b11 100644 --- a/src/polyrenderer/scene/poly_particle.h +++ b/src/polyrenderer/scene/poly_particle.h @@ -28,7 +28,7 @@ class RenderPolyParticle { public: - void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, particle_t *particle, subsector_t *sub, uint32_t stencilValue); + void Render(PolyRenderThread *thread, const PolyClipPlane &clipPlane, particle_t *particle, subsector_t *sub, uint32_t stencilValue); private: static uint8_t *GetParticleTexture(); @@ -45,10 +45,10 @@ class PolyTranslucentParticle : public PolyTranslucentObject public: PolyTranslucentParticle(particle_t *particle, subsector_t *sub, uint32_t subsectorDepth, uint32_t stencilValue) : PolyTranslucentObject(subsectorDepth, 0.0), particle(particle), sub(sub), StencilValue(stencilValue) { } - void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &portalPlane) override + void Render(PolyRenderThread *thread, const PolyClipPlane &portalPlane) override { RenderPolyParticle spr; - spr.Render(thread, worldToClip, portalPlane, particle, sub, StencilValue + 1); + spr.Render(thread, portalPlane, particle, sub, StencilValue + 1); } particle_t *particle = nullptr; diff --git a/src/polyrenderer/scene/poly_plane.cpp b/src/polyrenderer/scene/poly_plane.cpp index e2cbf1ccd..b5594cf32 100644 --- a/src/polyrenderer/scene/poly_plane.cpp +++ b/src/polyrenderer/scene/poly_plane.cpp @@ -36,30 +36,30 @@ EXTERN_CVAR(Int, r_3dfloors) -void RenderPolyPlane::RenderPlanes(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, double skyCeilingHeight, double skyFloorHeight, std::vector> §orPortals) +void RenderPolyPlane::RenderPlanes(PolyRenderThread *thread, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, double skyCeilingHeight, double skyFloorHeight, std::vector> §orPortals) { if (fakeflat.FrontSector->CenterFloor() == fakeflat.FrontSector->CenterCeiling()) return; RenderPolyPlane plane; - plane.Render(thread, worldToClip, clipPlane, fakeflat, stencilValue, true, skyCeilingHeight, sectorPortals); - plane.Render(thread, worldToClip, clipPlane, fakeflat, stencilValue, false, skyFloorHeight, sectorPortals); + plane.Render(thread, clipPlane, fakeflat, stencilValue, true, skyCeilingHeight, sectorPortals); + plane.Render(thread, clipPlane, fakeflat, stencilValue, false, skyFloorHeight, sectorPortals); } -void RenderPolyPlane::Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight, std::vector> §orPortals) +void RenderPolyPlane::Render(PolyRenderThread *thread, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight, std::vector> §orPortals) { FSectorPortal *portal = fakeflat.FrontSector->ValidatePortal(ceiling ? sector_t::ceiling : sector_t::floor); if (!portal || (portal->mFlags & PORTSF_INSKYBOX) == PORTSF_INSKYBOX) // Do not recurse into portals we already recursed into { - RenderNormal(thread, worldToClip, clipPlane, fakeflat, stencilValue, ceiling, skyHeight); + RenderNormal(thread, clipPlane, fakeflat, stencilValue, ceiling, skyHeight); } else { - RenderPortal(thread, worldToClip, clipPlane, fakeflat, stencilValue, ceiling, skyHeight, portal, sectorPortals); + RenderPortal(thread, clipPlane, fakeflat, stencilValue, ceiling, skyHeight, portal, sectorPortals); } } -void RenderPolyPlane::RenderNormal(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight) +void RenderPolyPlane::RenderNormal(PolyRenderThread *thread, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight) { const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; @@ -76,35 +76,30 @@ void RenderPolyPlane::RenderNormal(PolyRenderThread *thread, const TriMatrix &wo PolyDrawArgs args; SetLightLevel(thread, args, fakeflat, ceiling); SetDynLights(thread, args, fakeflat.Subsector, ceiling); - args.SetTransform(&worldToClip); - args.SetFaceCullCCW(true); args.SetStencilTestValue(stencilValue); args.SetWriteStencil(true, stencilValue + 1); args.SetClipPlane(0, clipPlane); args.SetTexture(tex, DefaultRenderStyle()); args.SetStyle(TriBlendMode::TextureOpaque); - args.DrawArray(thread, vertices, fakeflat.Subsector->numlines, PolyDrawMode::TriangleFan); + args.DrawArray(thread->DrawQueue, vertices, fakeflat.Subsector->numlines, PolyDrawMode::TriangleFan); } else { TriVertex *vertices = CreateSkyPlaneVertices(thread, fakeflat.Subsector, skyHeight); PolyDrawArgs args; - args.SetTransform(&worldToClip); - args.SetFaceCullCCW(true); args.SetStencilTestValue(stencilValue); - args.SetWriteStencil(true, stencilValue + 1); args.SetClipPlane(0, clipPlane); args.SetWriteStencil(true, 255); args.SetWriteColor(false); args.SetWriteDepth(false); - args.DrawArray(thread, vertices, fakeflat.Subsector->numlines, PolyDrawMode::TriangleFan); + args.DrawArray(thread->DrawQueue, vertices, fakeflat.Subsector->numlines, PolyDrawMode::TriangleFan); RenderSkyWalls(thread, args, fakeflat.Subsector, nullptr, ceiling, skyHeight); } } -void RenderPolyPlane::RenderPortal(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight, FSectorPortal *portal, std::vector> §orPortals) +void RenderPolyPlane::RenderPortal(PolyRenderThread *thread, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight, FSectorPortal *portal, std::vector> §orPortals) { const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; @@ -160,19 +155,16 @@ void RenderPolyPlane::RenderPortal(PolyRenderThread *thread, const TriMatrix &wo TriVertex *vertices = CreateSkyPlaneVertices(thread, fakeflat.Subsector, skyHeight); PolyDrawArgs args; - args.SetTransform(&worldToClip); - args.SetFaceCullCCW(true); args.SetStencilTestValue(stencilValue); - args.SetWriteStencil(true, stencilValue + 1); args.SetClipPlane(0, clipPlane); args.SetWriteStencil(true, polyportal->StencilValue); args.SetWriteColor(false); args.SetWriteDepth(false); - args.DrawArray(thread, vertices, fakeflat.Subsector->numlines, PolyDrawMode::TriangleFan); + args.DrawArray(thread->DrawQueue, vertices, fakeflat.Subsector->numlines, PolyDrawMode::TriangleFan); RenderSkyWalls(thread, args, fakeflat.Subsector, polyportal, ceiling, skyHeight); - polyportal->Shape.push_back({ vertices, (int)fakeflat.Subsector->numlines, true }); + polyportal->Shape.push_back({ vertices, (int)fakeflat.Subsector->numlines }); } void RenderPolyPlane::RenderSkyWalls(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub, PolyDrawSectorPortal *polyportal, bool ceiling, double skyHeight) @@ -246,11 +238,11 @@ void RenderPolyPlane::RenderSkyWalls(PolyRenderThread *thread, PolyDrawArgs &arg wallvert[3] = GetSkyVertex(line->v1, skyHeight); } - args.DrawArray(thread, wallvert, 4, PolyDrawMode::TriangleFan); + args.DrawArray(thread->DrawQueue, wallvert, 4, PolyDrawMode::TriangleFan); if (polyportal) { - polyportal->Shape.push_back({ wallvert, 4, args.FaceCullCCW() }); + polyportal->Shape.push_back({ wallvert, 4 }); } } } @@ -421,7 +413,7 @@ PolyPlaneUVTransform::PolyPlaneUVTransform(const FTransform &transform, FTexture ///////////////////////////////////////////////////////////////////////////// -void Render3DFloorPlane::RenderPlanes(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, uint32_t subsectorDepth, std::vector &translucentObjects) +void Render3DFloorPlane::RenderPlanes(PolyRenderThread *thread, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, uint32_t subsectorDepth, std::vector &translucentObjects) { if (!r_3dfloors || sub->sector->CenterFloor() == sub->sector->CenterCeiling()) return; @@ -465,7 +457,7 @@ void Render3DFloorPlane::RenderPlanes(PolyRenderThread *thread, const TriMatrix } if (!plane.Masked) - plane.Render(thread, worldToClip, clipPlane); + plane.Render(thread, clipPlane); else translucentObjects.push_back(thread->FrameMemory->NewObject(plane, subsectorDepth)); } @@ -505,14 +497,14 @@ void Render3DFloorPlane::RenderPlanes(PolyRenderThread *thread, const TriMatrix } if (!plane.Masked) - plane.Render(thread, worldToClip, clipPlane); + plane.Render(thread, clipPlane); else translucentObjects.push_back(thread->FrameMemory->NewObject(plane, subsectorDepth)); } } } -void Render3DFloorPlane::Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane) +void Render3DFloorPlane::Render(PolyRenderThread *thread, const PolyClipPlane &clipPlane) { FTextureID picnum = ceiling ? *fakeFloor->bottom.texture : *fakeFloor->top.texture; FTexture *tex = TexMan(picnum); @@ -555,7 +547,6 @@ void Render3DFloorPlane::Render(PolyRenderThread *thread, const TriMatrix &world PolyDrawArgs args; args.SetLight(GetColorTable(sub->sector->Colormap), lightlevel, PolyRenderer::Instance()->Light.WallGlobVis(foggy), false); - args.SetTransform(&worldToClip); if (!Masked) { args.SetStyle(TriBlendMode::TextureOpaque); @@ -567,12 +558,10 @@ void Render3DFloorPlane::Render(PolyRenderThread *thread, const TriMatrix &world args.SetStyle(TriBlendMode::TextureAdd, srcalpha, destalpha); args.SetDepthTest(true); args.SetWriteDepth(true); - args.SetWriteStencil(false); } - args.SetFaceCullCCW(true); args.SetStencilTestValue(stencilValue); args.SetWriteStencil(true, stencilValue + 1); args.SetTexture(tex, DefaultRenderStyle()); args.SetClipPlane(0, clipPlane); - args.DrawArray(thread, vertices, sub->numlines, PolyDrawMode::TriangleFan); + args.DrawArray(thread->DrawQueue, vertices, sub->numlines, PolyDrawMode::TriangleFan); } diff --git a/src/polyrenderer/scene/poly_plane.h b/src/polyrenderer/scene/poly_plane.h index c4af370c7..9895f5b2f 100644 --- a/src/polyrenderer/scene/poly_plane.h +++ b/src/polyrenderer/scene/poly_plane.h @@ -57,13 +57,13 @@ private: class RenderPolyPlane { public: - static void RenderPlanes(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, double skyCeilingHeight, double skyFloorHeight, std::vector> §orPortals); + static void RenderPlanes(PolyRenderThread *thread, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, double skyCeilingHeight, double skyFloorHeight, std::vector> §orPortals); private: - void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight, std::vector> §orPortals); + void Render(PolyRenderThread *thread, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight, std::vector> §orPortals); - void RenderPortal(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight, FSectorPortal *portal, std::vector> §orPortals); - void RenderNormal(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight); + void RenderPortal(PolyRenderThread *thread, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight, FSectorPortal *portal, std::vector> §orPortals); + void RenderNormal(PolyRenderThread *thread, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight); void RenderSkyWalls(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub, PolyDrawSectorPortal *polyportal, bool ceiling, double skyHeight); @@ -79,9 +79,9 @@ private: class Render3DFloorPlane { public: - static void RenderPlanes(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, uint32_t subsectorDepth, std::vector &translucentObjects); + static void RenderPlanes(PolyRenderThread *thread, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, uint32_t subsectorDepth, std::vector &translucentObjects); - void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane); + void Render(PolyRenderThread *thread, const PolyClipPlane &clipPlane); subsector_t *sub = nullptr; uint32_t stencilValue = 0; @@ -97,9 +97,9 @@ class PolyTranslucent3DFloorPlane : public PolyTranslucentObject public: PolyTranslucent3DFloorPlane(Render3DFloorPlane plane, uint32_t subsectorDepth) : PolyTranslucentObject(subsectorDepth, 1e7), plane(plane) { } - void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &portalPlane) override + void Render(PolyRenderThread *thread, const PolyClipPlane &portalPlane) override { - plane.Render(thread, worldToClip, portalPlane); + plane.Render(thread, portalPlane); } Render3DFloorPlane plane; diff --git a/src/polyrenderer/scene/poly_playersprite.cpp b/src/polyrenderer/scene/poly_playersprite.cpp index 5626e6f7b..d5064400d 100644 --- a/src/polyrenderer/scene/poly_playersprite.cpp +++ b/src/polyrenderer/scene/poly_playersprite.cpp @@ -43,8 +43,6 @@ void RenderPolyPlayerSprites::Render(PolyRenderThread *thread) // // We also can't move it because the model render code relies on it - //renderHUDModel = gl_IsHUDModelForPlayerAvailable(players[consoleplayer].camera->player); - const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; int i; @@ -62,6 +60,8 @@ void RenderPolyPlayerSprites::Render(PolyRenderThread *thread) (r_deathcamera && viewpoint.camera->health <= 0)) return; + renderHUDModel = gl_IsHUDModelForPlayerAvailable(players[consoleplayer].camera->player); + PolyTransferHeights fakeflat(viewpoint.camera->subsector); FDynamicColormap *basecolormap; diff --git a/src/polyrenderer/scene/poly_portal.cpp b/src/polyrenderer/scene/poly_portal.cpp index cbf4ccc9c..caf1f8145 100644 --- a/src/polyrenderer/scene/poly_portal.cpp +++ b/src/polyrenderer/scene/poly_portal.cpp @@ -30,6 +30,7 @@ #include "poly_portal.h" #include "polyrenderer/poly_renderer.h" #include "polyrenderer/scene/poly_light.h" +#include "polyrenderer/scene/poly_scene.h" ///////////////////////////////////////////////////////////////////////////// @@ -58,31 +59,35 @@ void PolyDrawSectorPortal::Render(int portalDepth) float ratio = viewwindow.WidescreenRatio; float fovratio = (viewwindow.WidescreenRatio >= 1.3f) ? 1.333333f : ratio; float fovy = (float)(2 * DAngle::ToDegrees(atan(tan(viewpoint.FieldOfView.Radians() / 2) / fovratio)).Degrees); - TriMatrix worldToView = - TriMatrix::rotate((float)viewpoint.Angles.Roll.Radians(), 0.0f, 0.0f, 1.0f) * - TriMatrix::rotate(adjustedPitch, 1.0f, 0.0f, 0.0f) * - TriMatrix::rotate(adjustedViewAngle, 0.0f, -1.0f, 0.0f) * - TriMatrix::scale(1.0f, level.info->pixelstretch, 1.0f) * - TriMatrix::swapYZ() * - TriMatrix::translate((float)-viewpoint.Pos.X, (float)-viewpoint.Pos.Y, (float)-viewpoint.Pos.Z); - TriMatrix worldToClip = TriMatrix::perspective(fovy, ratio, 5.0f, 65535.0f) * worldToView; + Mat4f worldToView = + Mat4f::Rotate((float)viewpoint.Angles.Roll.Radians(), 0.0f, 0.0f, 1.0f) * + Mat4f::Rotate(adjustedPitch, 1.0f, 0.0f, 0.0f) * + Mat4f::Rotate(adjustedViewAngle, 0.0f, -1.0f, 0.0f) * + Mat4f::Scale(1.0f, level.info->pixelstretch, 1.0f) * + Mat4f::SwapYZ() * + Mat4f::Translate((float)-viewpoint.Pos.X, (float)-viewpoint.Pos.Y, (float)-viewpoint.Pos.Z); + Mat4f worldToClip = Mat4f::Perspective(fovy, ratio, 5.0f, 65535.0f, Handedness::Right, ClipZRange::NegativePositiveW) * worldToView; - PolyClipPlane portalPlane(0.0f, 0.0f, 0.0f, 1.0f); - RenderPortal.SetViewpoint(worldToClip, portalPlane, StencilValue); - //RenderPortal.SetPortalSegments(Segments); - RenderPortal.Render(portalDepth); + PortalViewpoint = PolyPortalViewpoint(); + PortalViewpoint.WorldToView = worldToView; + PortalViewpoint.WorldToClip = worldToClip; + PortalViewpoint.StencilValue = StencilValue; + PortalViewpoint.PortalPlane = PolyClipPlane(0.0f, 0.0f, 0.0f, 1.0f); + PortalViewpoint.PortalDepth = portalDepth; + + PolyRenderer::Instance()->Scene.Render(&PortalViewpoint); RestoreGlobals(); } -void PolyDrawSectorPortal::RenderTranslucent(int portalDepth) +void PolyDrawSectorPortal::RenderTranslucent() { if (Portal->mType == PORTS_HORIZON || Portal->mType == PORTS_PLANE) return; SaveGlobals(); - RenderPortal.RenderTranslucent(portalDepth); + PolyRenderer::Instance()->Scene.RenderTranslucent(&PortalViewpoint); RestoreGlobals(); } @@ -169,16 +174,16 @@ void PolyDrawLinePortal::Render(int portalDepth) float ratio = viewwindow.WidescreenRatio; float fovratio = (viewwindow.WidescreenRatio >= 1.3f) ? 1.333333f : ratio; float fovy = (float)(2 * DAngle::ToDegrees(atan(tan(viewpoint.FieldOfView.Radians() / 2) / fovratio)).Degrees); - TriMatrix worldToView = - TriMatrix::rotate((float)viewpoint.Angles.Roll.Radians(), 0.0f, 0.0f, 1.0f) * - TriMatrix::rotate(adjustedPitch, 1.0f, 0.0f, 0.0f) * - TriMatrix::rotate(adjustedViewAngle, 0.0f, -1.0f, 0.0f) * - TriMatrix::scale(1.0f, level.info->pixelstretch, 1.0f) * - TriMatrix::swapYZ() * - TriMatrix::translate((float)-viewpoint.Pos.X, (float)-viewpoint.Pos.Y, (float)-viewpoint.Pos.Z); + Mat4f worldToView = + Mat4f::Rotate((float)viewpoint.Angles.Roll.Radians(), 0.0f, 0.0f, 1.0f) * + Mat4f::Rotate(adjustedPitch, 1.0f, 0.0f, 0.0f) * + Mat4f::Rotate(adjustedViewAngle, 0.0f, -1.0f, 0.0f) * + Mat4f::Scale(1.0f, level.info->pixelstretch, 1.0f) * + Mat4f::SwapYZ() * + Mat4f::Translate((float)-viewpoint.Pos.X, (float)-viewpoint.Pos.Y, (float)-viewpoint.Pos.Z); if (Mirror) - worldToView = TriMatrix::scale(-1.0f, 1.0f, 1.0f) * worldToView; - TriMatrix worldToClip = TriMatrix::perspective(fovy, ratio, 5.0f, 65535.0f) * worldToView; + worldToView = Mat4f::Scale(-1.0f, 1.0f, 1.0f) * worldToView; + Mat4f worldToClip = Mat4f::Perspective(fovy, ratio, 5.0f, 65535.0f, Handedness::Right, ClipZRange::NegativePositiveW) * worldToView; // Find portal destination line and make sure it faces the right way line_t *clipLine = Portal ? Portal->mDestination : Mirror; @@ -202,18 +207,23 @@ void PolyDrawLinePortal::Render(int portalDepth) Segments.clear(); Segments.push_back({ angle1, angle2 });*/ - RenderPortal.LastPortalLine = clipLine; - RenderPortal.SetViewpoint(worldToClip, portalPlane, StencilValue); - //RenderPortal.SetPortalSegments(Segments); - RenderPortal.Render(portalDepth); + PortalViewpoint = PolyPortalViewpoint(); + PortalViewpoint.WorldToView = worldToView; + PortalViewpoint.WorldToClip = worldToClip; + PortalViewpoint.StencilValue = StencilValue; + PortalViewpoint.PortalPlane = portalPlane; + PortalViewpoint.PortalDepth = portalDepth; + PortalViewpoint.LastPortalLine = clipLine; + + PolyRenderer::Instance()->Scene.Render(&PortalViewpoint); RestoreGlobals(); } -void PolyDrawLinePortal::RenderTranslucent(int portalDepth) +void PolyDrawLinePortal::RenderTranslucent() { SaveGlobals(); - RenderPortal.RenderTranslucent(portalDepth); + PolyRenderer::Instance()->Scene.RenderTranslucent(&PortalViewpoint); RestoreGlobals(); } @@ -304,7 +314,7 @@ void PolyDrawLinePortal::SaveGlobals() R_SetViewAngle(viewpoint, viewwindow); if (Mirror) - PolyTriangleDrawer::toggle_mirror(); + PolyTriangleDrawer::ToggleMirror(PolyRenderer::Instance()->Threads.MainThread()->DrawQueue); } void PolyDrawLinePortal::RestoreGlobals() @@ -328,5 +338,5 @@ void PolyDrawLinePortal::RestoreGlobals() R_SetViewAngle(viewpoint, viewwindow); if (Mirror) - PolyTriangleDrawer::toggle_mirror(); + PolyTriangleDrawer::ToggleMirror(PolyRenderer::Instance()->Threads.MainThread()->DrawQueue); } diff --git a/src/polyrenderer/scene/poly_portal.h b/src/polyrenderer/scene/poly_portal.h index a91c80d4e..6c58128e7 100644 --- a/src/polyrenderer/scene/poly_portal.h +++ b/src/polyrenderer/scene/poly_portal.h @@ -26,10 +26,9 @@ struct PolyPortalVertexRange { - PolyPortalVertexRange(const TriVertex *vertices, int count, bool ccw) : Vertices(vertices), Count(count), Ccw(ccw) { } + PolyPortalVertexRange(const TriVertex *vertices, int count) : Vertices(vertices), Count(count) { } const TriVertex *Vertices; int Count; - bool Ccw; }; class PolyPortalSegment @@ -45,7 +44,7 @@ public: PolyDrawSectorPortal(FSectorPortal *portal, bool ceiling); void Render(int portalDepth); - void RenderTranslucent(int portalDepth); + void RenderTranslucent(); FSectorPortal *Portal = nullptr; uint32_t StencilValue = 0; @@ -57,7 +56,7 @@ private: void RestoreGlobals(); bool Ceiling; - RenderPolyScene RenderPortal; + PolyPortalViewpoint PortalViewpoint; int savedextralight; DVector3 savedpos; @@ -74,7 +73,7 @@ public: PolyDrawLinePortal(line_t *mirror); void Render(int portalDepth); - void RenderTranslucent(int portalDepth); + void RenderTranslucent(); FLinePortal *Portal = nullptr; line_t *Mirror = nullptr; @@ -86,7 +85,7 @@ private: void SaveGlobals(); void RestoreGlobals(); - RenderPolyScene RenderPortal; + PolyPortalViewpoint PortalViewpoint; int savedextralight; DVector3 savedpos; diff --git a/src/polyrenderer/scene/poly_scene.cpp b/src/polyrenderer/scene/poly_scene.cpp index 42f6e815b..378264ef7 100644 --- a/src/polyrenderer/scene/poly_scene.cpp +++ b/src/polyrenderer/scene/poly_scene.cpp @@ -47,22 +47,45 @@ RenderPolyScene::~RenderPolyScene() { } -void RenderPolyScene::SetViewpoint(const TriMatrix &worldToClip, const PolyClipPlane &portalPlane, uint32_t stencilValue) +void RenderPolyScene::Render(PolyPortalViewpoint *viewpoint) { - WorldToClip = worldToClip; - StencilValue = stencilValue; - PortalPlane = portalPlane; -} + CurrentViewpoint = viewpoint; -void RenderPolyScene::Render(int portalDepth) -{ PolyRenderThread *thread = PolyRenderer::Instance()->Threads.MainThread(); - SectorPortals.clear(); - LinePortals.clear(); - Cull.CullScene(PortalPlane); + CurrentViewpoint->ObjectsStart = thread->TranslucentObjects.size(); + CurrentViewpoint->SectorPortalsStart = thread->SectorPortals.size(); + CurrentViewpoint->LinePortalsStart = thread->LinePortals.size(); + + PolyCullCycles.Clock(); + Cull.CullScene(CurrentViewpoint->PortalPlane); + PolyCullCycles.Unclock(); + RenderSectors(); - RenderPortals(portalDepth); + + PolyMaskedCycles.Clock(); + const auto &rviewpoint = PolyRenderer::Instance()->Viewpoint; + for (uint32_t sectorIndex : Cull.SeenSectors) + { + sector_t *sector = &level.sectors[sectorIndex]; + for (AActor *thing = sector->thinglist; thing != nullptr; thing = thing->snext) + { + DVector2 left, right; + if (!RenderPolySprite::GetLine(thing, left, right)) + continue; + double distanceSquared = (thing->Pos() - rviewpoint.Pos).LengthSquared(); + AddSprite(thread, thing, distanceSquared, left, right); + } + } + PolyMaskedCycles.Unclock(); + + CurrentViewpoint->ObjectsEnd = thread->TranslucentObjects.size(); + CurrentViewpoint->SectorPortalsEnd = thread->SectorPortals.size(); + CurrentViewpoint->LinePortalsEnd = thread->LinePortals.size(); + + RenderPortals(); + + CurrentViewpoint = nullptr; } void RenderPolyScene::RenderSectors() @@ -72,11 +95,18 @@ void RenderPolyScene::RenderSectors() int totalcount = (int)Cull.PvsSubsectors.size(); uint32_t *subsectors = Cull.PvsSubsectors.data(); - TranslucentObjects.resize(PolyRenderer::Instance()->Threads.NumThreads()); + PolyOpaqueCycles.Clock(); PolyRenderer::Instance()->Threads.RenderThreadSlices(totalcount, [&](PolyRenderThread *thread) { - TranslucentObjects[thread->ThreadIndex].clear(); + PolyTriangleDrawer::SetTransform(thread->DrawQueue, thread->FrameMemory->NewObject(CurrentViewpoint->WorldToClip)); + + if (thread != mainthread) + { + thread->TranslucentObjects.clear(); + thread->SectorPortals.clear(); + thread->LinePortals.clear(); + } int start = thread->Start; int end = thread->End; @@ -86,9 +116,11 @@ void RenderPolyScene::RenderSectors() } }, [&](PolyRenderThread *thread) { - const auto &objects = TranslucentObjects[thread->ThreadIndex]; - TranslucentObjects[0].insert(TranslucentObjects[0].end(), objects.begin(), objects.end()); + const auto &objects = thread->TranslucentObjects; + mainthread->TranslucentObjects.insert(mainthread->TranslucentObjects.end(), objects.begin(), objects.end()); }); + + PolyOpaqueCycles.Unclock(); } void RenderPolyScene::RenderSubsector(PolyRenderThread *thread, subsector_t *sub, uint32_t subsectorDepth) @@ -121,15 +153,15 @@ void RenderPolyScene::RenderSubsector(PolyRenderThread *thread, subsector_t *sub RenderPolyNode(thread, &sub->BSP->Nodes.Last(), subsectorDepth, frontsector); } - Render3DFloorPlane::RenderPlanes(thread, WorldToClip, PortalPlane, sub, StencilValue, subsectorDepth, TranslucentObjects[thread->ThreadIndex]); - RenderPolyPlane::RenderPlanes(thread, WorldToClip, PortalPlane, sub, StencilValue, Cull.MaxCeilingHeight, Cull.MinFloorHeight, SectorPortals); + Render3DFloorPlane::RenderPlanes(thread, CurrentViewpoint->PortalPlane, sub, CurrentViewpoint->StencilValue, subsectorDepth, thread->TranslucentObjects); + RenderPolyPlane::RenderPlanes(thread, CurrentViewpoint->PortalPlane, sub, CurrentViewpoint->StencilValue, Cull.MaxCeilingHeight, Cull.MinFloorHeight, thread->SectorPortals); } else { PolyTransferHeights fakeflat(sub); - Render3DFloorPlane::RenderPlanes(thread, WorldToClip, PortalPlane, sub, StencilValue, subsectorDepth, TranslucentObjects[thread->ThreadIndex]); - RenderPolyPlane::RenderPlanes(thread, WorldToClip, PortalPlane, fakeflat, StencilValue, Cull.MaxCeilingHeight, Cull.MinFloorHeight, SectorPortals); + Render3DFloorPlane::RenderPlanes(thread, CurrentViewpoint->PortalPlane, sub, CurrentViewpoint->StencilValue, subsectorDepth, thread->TranslucentObjects); + RenderPolyPlane::RenderPlanes(thread, CurrentViewpoint->PortalPlane, fakeflat, CurrentViewpoint->StencilValue, Cull.MaxCeilingHeight, Cull.MinFloorHeight, thread->SectorPortals); for (uint32_t i = 0; i < sub->numlines; i++) { @@ -147,7 +179,7 @@ void RenderPolyScene::RenderSubsector(PolyRenderThread *thread, subsector_t *sub for (int i = ParticlesInSubsec[subsectorIndex]; i != NO_PARTICLE; i = Particles[i].snext) { particle_t *particle = Particles + i; - TranslucentObjects[thread->ThreadIndex].push_back(thread->FrameMemory->NewObject(particle, sub, subsectorDepth, StencilValue)); + thread->TranslucentObjects.push_back(thread->FrameMemory->NewObject(particle, sub, subsectorDepth, CurrentViewpoint->StencilValue)); } } } @@ -200,7 +232,7 @@ void RenderPolyScene::RenderPolySubsector(PolyRenderThread *thread, subsector_t sub->flags |= SSECF_DRAWN; } - RenderPolyWall::RenderLine(thread, WorldToClip, PortalPlane, line, frontsector, subsectorDepth, StencilValue, TranslucentObjects[thread->ThreadIndex], LinePortals, LastPortalLine); + RenderPolyWall::RenderLine(thread, CurrentViewpoint->PortalPlane, line, frontsector, subsectorDepth, CurrentViewpoint->StencilValue, thread->TranslucentObjects, thread->LinePortals, CurrentViewpoint->LastPortalLine); } } } @@ -210,21 +242,21 @@ int RenderPolyScene::PointOnSide(const DVector2 &pos, const node_t *node) return DMulScale32(FLOAT2FIXED(pos.Y) - node->y, node->dx, node->x - FLOAT2FIXED(pos.X), node->dy) > 0; } -void RenderPolyScene::RenderSprite(PolyRenderThread *thread, AActor *thing, double sortDistance, const DVector2 &left, const DVector2 &right) +void RenderPolyScene::AddSprite(PolyRenderThread *thread, AActor *thing, double sortDistance, const DVector2 &left, const DVector2 &right) { if (level.nodes.Size() == 0) { subsector_t *sub = &level.subsectors[0]; if (Cull.SubsectorDepths[sub->Index()] != 0xffffffff) - TranslucentObjects[thread->ThreadIndex].push_back(thread->FrameMemory->NewObject(thing, sub, Cull.SubsectorDepths[sub->Index()], sortDistance, 0.0f, 1.0f, StencilValue)); + thread->TranslucentObjects.push_back(thread->FrameMemory->NewObject(thing, sub, Cull.SubsectorDepths[sub->Index()], sortDistance, 0.0f, 1.0f, CurrentViewpoint->StencilValue)); } else { - RenderSprite(thread, thing, sortDistance, left, right, 0.0, 1.0, level.HeadNode()); + AddSprite(thread, thing, sortDistance, left, right, 0.0, 1.0, level.HeadNode()); } } -void RenderPolyScene::RenderSprite(PolyRenderThread *thread, AActor *thing, double sortDistance, DVector2 left, DVector2 right, double t1, double t2, void *node) +void RenderPolyScene::AddSprite(PolyRenderThread *thread, AActor *thing, double sortDistance, DVector2 left, DVector2 right, double t1, double t2, void *node) { while (!((size_t)node & 1)) // Keep going until found a subsector { @@ -246,7 +278,7 @@ void RenderPolyScene::RenderSprite(PolyRenderThread *thread, AActor *thing, doub DVector2 mid = left * (1.0 - t) + right * t; double tmid = t1 * (1.0 - t) + t2 * t; - RenderSprite(thread, thing, sortDistance, mid, right, tmid, t2, bsp->children[sideRight]); + AddSprite(thread, thing, sortDistance, mid, right, tmid, t2, bsp->children[sideRight]); right = mid; t2 = tmid; } @@ -256,7 +288,7 @@ void RenderPolyScene::RenderSprite(PolyRenderThread *thread, AActor *thing, doub subsector_t *sub = (subsector_t *)((uint8_t *)node - 1); if (Cull.SubsectorDepths[sub->Index()] != 0xffffffff) - TranslucentObjects[thread->ThreadIndex].push_back(thread->FrameMemory->NewObject(thing, sub, Cull.SubsectorDepths[sub->Index()], sortDistance, (float)t1, (float)t2, StencilValue)); + thread->TranslucentObjects.push_back(thread->FrameMemory->NewObject(thing, sub, Cull.SubsectorDepths[sub->Index()], sortDistance, (float)t1, (float)t2, CurrentViewpoint->StencilValue)); } void RenderPolyScene::RenderLine(PolyRenderThread *thread, subsector_t *sub, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth) @@ -274,127 +306,129 @@ void RenderPolyScene::RenderLine(PolyRenderThread *thread, subsector_t *sub, seg for (unsigned int i = 0; i < line->backsector->e->XFloor.ffloors.Size(); i++) { F3DFloor *fakeFloor = line->backsector->e->XFloor.ffloors[i]; - RenderPolyWall::Render3DFloorLine(thread, WorldToClip, PortalPlane, line, frontsector, subsectorDepth, StencilValue, fakeFloor, TranslucentObjects[thread->ThreadIndex]); + RenderPolyWall::Render3DFloorLine(thread, CurrentViewpoint->PortalPlane, line, frontsector, subsectorDepth, CurrentViewpoint->StencilValue, fakeFloor, thread->TranslucentObjects); } } // Render wall, and update culling info if its an occlusion blocker - RenderPolyWall::RenderLine(thread, WorldToClip, PortalPlane, line, frontsector, subsectorDepth, StencilValue, TranslucentObjects[thread->ThreadIndex], LinePortals, LastPortalLine); + RenderPolyWall::RenderLine(thread, CurrentViewpoint->PortalPlane, line, frontsector, subsectorDepth, CurrentViewpoint->StencilValue, thread->TranslucentObjects, thread->LinePortals, CurrentViewpoint->LastPortalLine); } -void RenderPolyScene::RenderPortals(int portalDepth) +void RenderPolyScene::RenderPortals() { PolyRenderThread *thread = PolyRenderer::Instance()->Threads.MainThread(); bool foggy = false; - if (portalDepth < r_portal_recursions) + if (CurrentViewpoint->PortalDepth < r_portal_recursions) { - for (auto &portal : SectorPortals) - portal->Render(portalDepth + 1); + for (auto &portal : thread->SectorPortals) + portal->Render(CurrentViewpoint->PortalDepth + 1); - for (auto &portal : LinePortals) - portal->Render(portalDepth + 1); + for (auto &portal : thread->LinePortals) + portal->Render(CurrentViewpoint->PortalDepth + 1); } else // Fill with black { PolyDrawArgs args; - args.SetTransform(&WorldToClip); args.SetLight(&NormalLight, 255, PolyRenderer::Instance()->Light.WallGlobVis(foggy), true); args.SetColor(0, 0); - args.SetClipPlane(0, PortalPlane); + args.SetClipPlane(0, CurrentViewpoint->PortalPlane); args.SetStyle(TriBlendMode::FillOpaque); - for (auto &portal : SectorPortals) + for (auto &portal : thread->SectorPortals) { args.SetStencilTestValue(portal->StencilValue); args.SetWriteStencil(true, portal->StencilValue + 1); for (const auto &verts : portal->Shape) { - args.SetFaceCullCCW(verts.Ccw); - args.DrawArray(thread, verts.Vertices, verts.Count, PolyDrawMode::TriangleFan); + args.DrawArray(thread->DrawQueue, verts.Vertices, verts.Count, PolyDrawMode::TriangleFan); } } - for (auto &portal : LinePortals) + for (auto &portal : thread->LinePortals) { args.SetStencilTestValue(portal->StencilValue); args.SetWriteStencil(true, portal->StencilValue + 1); for (const auto &verts : portal->Shape) { - args.SetFaceCullCCW(verts.Ccw); - args.DrawArray(thread, verts.Vertices, verts.Count, PolyDrawMode::TriangleFan); + args.DrawArray(thread->DrawQueue, verts.Vertices, verts.Count, PolyDrawMode::TriangleFan); } } } } -void RenderPolyScene::RenderTranslucent(int portalDepth) +void RenderPolyScene::RenderTranslucent(PolyPortalViewpoint *viewpoint) { + CurrentViewpoint = viewpoint; + PolyRenderThread *thread = PolyRenderer::Instance()->Threads.MainThread(); - if (portalDepth < r_portal_recursions) + PolyTriangleDrawer::SetTransform(thread->DrawQueue, thread->FrameMemory->NewObject(CurrentViewpoint->WorldToClip)); + + if (CurrentViewpoint->PortalDepth < r_portal_recursions) { - for (auto it = SectorPortals.rbegin(); it != SectorPortals.rend(); ++it) + for (auto it = thread->SectorPortals.rbegin(); it != thread->SectorPortals.rend(); ++it) { auto &portal = *it; - portal->RenderTranslucent(portalDepth + 1); + portal->RenderTranslucent(); PolyDrawArgs args; - args.SetTransform(&WorldToClip); args.SetStencilTestValue(portal->StencilValue + 1); - args.SetWriteStencil(true, StencilValue + 1); - args.SetClipPlane(0, PortalPlane); + args.SetWriteStencil(true, CurrentViewpoint->StencilValue + 1); + args.SetClipPlane(0, CurrentViewpoint->PortalPlane); for (const auto &verts : portal->Shape) { - args.SetFaceCullCCW(verts.Ccw); args.SetWriteColor(false); - args.DrawArray(thread, verts.Vertices, verts.Count, PolyDrawMode::TriangleFan); + args.DrawArray(thread->DrawQueue, verts.Vertices, verts.Count, PolyDrawMode::TriangleFan); } } - for (auto it = LinePortals.rbegin(); it != LinePortals.rend(); ++it) + for (auto it = thread->LinePortals.rbegin(); it != thread->LinePortals.rend(); ++it) { auto &portal = *it; - portal->RenderTranslucent(portalDepth + 1); + portal->RenderTranslucent(); PolyDrawArgs args; - args.SetTransform(&WorldToClip); args.SetStencilTestValue(portal->StencilValue + 1); - args.SetWriteStencil(true, StencilValue + 1); - args.SetClipPlane(0, PortalPlane); + args.SetWriteStencil(true, CurrentViewpoint->StencilValue + 1); + args.SetClipPlane(0, CurrentViewpoint->PortalPlane); for (const auto &verts : portal->Shape) { - args.SetFaceCullCCW(verts.Ccw); args.SetWriteColor(false); - args.DrawArray(thread, verts.Vertices, verts.Count, PolyDrawMode::TriangleFan); + args.DrawArray(thread->DrawQueue, verts.Vertices, verts.Count, PolyDrawMode::TriangleFan); } } } - const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; - for (uint32_t sectorIndex : Cull.SeenSectors) + PolyMaskedCycles.Clock(); + + // Draw all translucent objects back to front + if (CurrentViewpoint->ObjectsEnd > CurrentViewpoint->ObjectsStart) { - sector_t *sector = &level.sectors[sectorIndex]; - for (AActor *thing = sector->thinglist; thing != nullptr; thing = thing->snext) + std::stable_sort( + thread->TranslucentObjects.begin() + CurrentViewpoint->ObjectsStart, + thread->TranslucentObjects.begin() + CurrentViewpoint->ObjectsEnd, + [](auto a, auto b) { return *a < *b; }); + + size_t i = CurrentViewpoint->ObjectsEnd - 1; + size_t start = CurrentViewpoint->ObjectsStart; + auto objects = thread->TranslucentObjects.data(); + while (true) { - DVector2 left, right; - if (!RenderPolySprite::GetLine(thing, left, right)) - continue; - double distanceSquared = (thing->Pos() - viewpoint.Pos).LengthSquared(); - RenderSprite(thread, thing, distanceSquared, left, right); + PolyTranslucentObject *obj = objects[i]; + obj->Render(thread, CurrentViewpoint->PortalPlane); + obj->~PolyTranslucentObject(); + if (i == start) + break; + i--; } } - std::stable_sort(TranslucentObjects[0].begin(), TranslucentObjects[0].end(), [](auto a, auto b) { return *a < *b; }); + thread->TranslucentObjects.clear(); - for (auto it = TranslucentObjects[0].rbegin(); it != TranslucentObjects[0].rend(); ++it) - { - PolyTranslucentObject *obj = *it; - obj->Render(thread, WorldToClip, PortalPlane); - obj->~PolyTranslucentObject(); - } + PolyMaskedCycles.Unclock(); - TranslucentObjects[0].clear(); + CurrentViewpoint = nullptr; } ///////////////////////////////////////////////////////////////////////////// diff --git a/src/polyrenderer/scene/poly_scene.h b/src/polyrenderer/scene/poly_scene.h index db9394eb6..3d1178f60 100644 --- a/src/polyrenderer/scene/poly_scene.h +++ b/src/polyrenderer/scene/poly_scene.h @@ -29,6 +29,7 @@ #include "doomdata.h" #include "r_utility.h" #include "polyrenderer/drawers/poly_triangle.h" +#include "polyrenderer/math/gpu_types.h" #include "poly_playersprite.h" #include "poly_cull.h" @@ -38,7 +39,7 @@ public: PolyTranslucentObject(uint32_t subsectorDepth = 0, double distanceSquared = 0.0) : subsectorDepth(subsectorDepth), DistanceSquared(distanceSquared) { } virtual ~PolyTranslucentObject() { } - virtual void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &portalPlane) = 0; + virtual void Render(PolyRenderThread *thread, const PolyClipPlane &portalPlane) = 0; bool operator<(const PolyTranslucentObject &other) const { @@ -53,41 +54,52 @@ class PolyDrawSectorPortal; class PolyDrawLinePortal; class PolyPortalSegment; +class PolyPortalViewpoint +{ +public: + Mat4f WorldToView; + Mat4f WorldToClip; + PolyClipPlane PortalPlane; + uint32_t StencilValue = 0; + int PortalDepth = 0; + + line_t *LastPortalLine = nullptr; + + size_t ObjectsStart = 0; + size_t ObjectsEnd = 0; + size_t SectorPortalsStart = 0; + size_t SectorPortalsEnd = 0; + size_t LinePortalsStart = 0; + size_t LinePortalsEnd = 0; +}; + // Renders everything from a specific viewpoint class RenderPolyScene { public: RenderPolyScene(); ~RenderPolyScene(); - void SetViewpoint(const TriMatrix &worldToClip, const PolyClipPlane &portalPlane, uint32_t stencilValue); - void Render(int portalDepth); - void RenderTranslucent(int portalDepth); + + void Render(PolyPortalViewpoint *viewpoint); + void RenderTranslucent(PolyPortalViewpoint *viewpoint); static const uint32_t SkySubsectorDepth = 0x7fffffff; - line_t *LastPortalLine = nullptr; + PolyPortalViewpoint *CurrentViewpoint = nullptr; private: - void RenderPortals(int portalDepth); + void RenderPortals(); void RenderSectors(); void RenderSubsector(PolyRenderThread *thread, subsector_t *sub, uint32_t subsectorDepth); void RenderLine(PolyRenderThread *thread, subsector_t *sub, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth); - void RenderSprite(PolyRenderThread *thread, AActor *thing, double sortDistance, const DVector2 &left, const DVector2 &right); - void RenderSprite(PolyRenderThread *thread, AActor *thing, double sortDistance, DVector2 left, DVector2 right, double t1, double t2, void *node); + void AddSprite(PolyRenderThread *thread, AActor *thing, double sortDistance, const DVector2 &left, const DVector2 &right); + void AddSprite(PolyRenderThread *thread, AActor *thing, double sortDistance, DVector2 left, DVector2 right, double t1, double t2, void *node); void RenderPolySubsector(PolyRenderThread *thread, subsector_t *sub, uint32_t subsectorDepth, sector_t *frontsector); void RenderPolyNode(PolyRenderThread *thread, void *node, uint32_t subsectorDepth, sector_t *frontsector); static int PointOnSide(const DVector2 &pos, const node_t *node); - TriMatrix WorldToClip; - PolyClipPlane PortalPlane; - uint32_t StencilValue = 0; PolyCull Cull; - bool PortalSegmentsAdded = false; - - std::vector> TranslucentObjects; - std::vector> SectorPortals; - std::vector> LinePortals; }; enum class PolyWaterFakeSide diff --git a/src/polyrenderer/scene/poly_sky.cpp b/src/polyrenderer/scene/poly_sky.cpp index 3306d4c8a..59539e19f 100644 --- a/src/polyrenderer/scene/poly_sky.cpp +++ b/src/polyrenderer/scene/poly_sky.cpp @@ -35,12 +35,12 @@ PolySkyDome::PolySkyDome() CreateDome(); } -void PolySkyDome::Render(PolyRenderThread *thread, const TriMatrix &worldToClip) +void PolySkyDome::Render(PolyRenderThread *thread, const Mat4f &worldToView, const Mat4f &worldToClip) { #ifdef USE_GL_DOME_MATH - TriMatrix modelMatrix = GLSkyMath(); + Mat4f modelMatrix = GLSkyMath(); #else - TriMatrix modelMatrix = TriMatrix::identity(); + Mat4f modelMatrix = Mat4f::Identity(); PolySkySetup frameSetup; frameSetup.Update(); @@ -76,14 +76,14 @@ void PolySkyDome::Render(PolyRenderThread *thread, const TriMatrix &worldToClip) #endif const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; - TriMatrix objectToWorld = TriMatrix::translate((float)viewpoint.Pos.X, (float)viewpoint.Pos.Y, (float)viewpoint.Pos.Z) * modelMatrix; - objectToClip = worldToClip * objectToWorld; + Mat4f objectToWorld = Mat4f::Translate((float)viewpoint.Pos.X, (float)viewpoint.Pos.Y, (float)viewpoint.Pos.Z) * modelMatrix; int rc = mRows + 1; + PolyTriangleDrawer::SetTransform(thread->DrawQueue, thread->FrameMemory->NewObject(worldToClip * objectToWorld)); + PolyDrawArgs args; args.SetLight(&NormalLight, 255, PolyRenderer::Instance()->Light.WallGlobVis(false), true); - args.SetTransform(&objectToClip); args.SetStencilTestValue(255); args.SetWriteStencil(true, 1); args.SetClipPlane(0, PolyClipPlane(0.0f, 0.0f, 0.0f, 1.0f)); @@ -107,10 +107,9 @@ void PolySkyDome::Render(PolyRenderThread *thread, const TriMatrix &worldToClip) void PolySkyDome::RenderRow(PolyRenderThread *thread, PolyDrawArgs &args, int row, uint32_t capcolor, uint8_t capcolorindex) { - args.SetFaceCullCCW(false); args.SetColor(capcolor, capcolorindex); args.SetStyle(TriBlendMode::Skycap); - args.DrawArray(thread, &mVertices[mPrimStart[row]], mPrimStart[row + 1] - mPrimStart[row], PolyDrawMode::TriangleStrip); + args.DrawArray(thread->DrawQueue, &mVertices[mPrimStart[row]], mPrimStart[row + 1] - mPrimStart[row], PolyDrawMode::TriangleStrip); } void PolySkyDome::RenderCapColorRow(PolyRenderThread *thread, PolyDrawArgs &args, FTexture *skytex, int row, bool bottomCap) @@ -118,10 +117,9 @@ void PolySkyDome::RenderCapColorRow(PolyRenderThread *thread, PolyDrawArgs &args uint32_t solid = skytex->GetSkyCapColor(bottomCap); uint8_t palsolid = RGB32k.RGB[(RPART(solid) >> 3)][(GPART(solid) >> 3)][(BPART(solid) >> 3)]; - args.SetFaceCullCCW(bottomCap); args.SetColor(solid, palsolid); args.SetStyle(TriBlendMode::FillOpaque); - args.DrawArray(thread, &mVertices[mPrimStart[row]], mPrimStart[row + 1] - mPrimStart[row], PolyDrawMode::TriangleFan); + args.DrawArray(thread->DrawQueue, &mVertices[mPrimStart[row]], mPrimStart[row + 1] - mPrimStart[row], PolyDrawMode::TriangleFan); } void PolySkyDome::CreateDome() @@ -141,7 +139,7 @@ void PolySkyDome::CreateSkyHemisphere(bool zflip) for (c = 0; c < mColumns; c++) { - SkyVertex(1, c, zflip); + SkyVertex(1, zflip ? c : (mColumns - 1 - c), zflip); } // The total number of triangles per hemisphere can be calculated @@ -151,8 +149,8 @@ void PolySkyDome::CreateSkyHemisphere(bool zflip) mPrimStart.Push(mVertices.Size()); for (c = 0; c <= mColumns; c++) { - SkyVertex(r + zflip, c, zflip); SkyVertex(r + 1 - zflip, c, zflip); + SkyVertex(r + zflip, c, zflip); } } } @@ -204,7 +202,7 @@ void PolySkyDome::SkyVertex(int r, int c, bool zflip) mInitialUV.Push({ vert.u, vert.v }); } -TriMatrix PolySkyDome::GLSkyMath() +Mat4f PolySkyDome::GLSkyMath() { PolySkySetup frameSetup; frameSetup.Update(); @@ -222,43 +220,43 @@ TriMatrix PolySkyDome::GLSkyMath() // 57 world units roughly represent one sky texel for the glTranslate call. const float skyoffsetfactor = 57; - TriMatrix modelMatrix = TriMatrix::identity(); + Mat4f modelMatrix = Mat4f::Identity(); if (tex) { texw = tex->GetWidth(); texh = tex->GetHeight(); - modelMatrix = TriMatrix::rotate(-180.0f + x_offset, 0.f, 0.f, 1.f); + modelMatrix = Mat4f::Rotate(-180.0f + x_offset, 0.f, 0.f, 1.f); float xscale = texw < 1024.f ? floor(1024.f / float(texw)) : 1.f; float yscale = 1.f; if (texh <= 128 && (level.flags & LEVEL_FORCETILEDSKY)) { - modelMatrix = modelMatrix * TriMatrix::translate(0.f, 0.f, (-40 + tex->SkyOffset + skyoffset)*skyoffsetfactor); - modelMatrix = modelMatrix * TriMatrix::scale(1.f, 1.f, 1.2f * 1.17f); + modelMatrix = modelMatrix * Mat4f::Translate(0.f, 0.f, (-40 + tex->SkyOffset + skyoffset)*skyoffsetfactor); + modelMatrix = modelMatrix * Mat4f::Scale(1.f, 1.f, 1.2f * 1.17f); yscale = 240.f / texh; } else if (texh < 128) { // smaller sky textures must be tiled. We restrict it to 128 sky pixels, though - modelMatrix = modelMatrix * TriMatrix::translate(0.f, 0.f, -1250.f); - modelMatrix = modelMatrix * TriMatrix::scale(1.f, 1.f, 128 / 230.f); + modelMatrix = modelMatrix * Mat4f::Translate(0.f, 0.f, -1250.f); + modelMatrix = modelMatrix * Mat4f::Scale(1.f, 1.f, 128 / 230.f); yscale = (float)(128 / texh); // intentionally left as integer. } else if (texh < 200) { - modelMatrix = modelMatrix * TriMatrix::translate(0.f, 0.f, -1250.f); - modelMatrix = modelMatrix * TriMatrix::scale(1.f, 1.f, texh / 230.f); + modelMatrix = modelMatrix * Mat4f::Translate(0.f, 0.f, -1250.f); + modelMatrix = modelMatrix * Mat4f::Scale(1.f, 1.f, texh / 230.f); } else if (texh <= 240) { - modelMatrix = modelMatrix * TriMatrix::translate(0.f, 0.f, (200 - texh + tex->SkyOffset + skyoffset)*skyoffsetfactor); - modelMatrix = modelMatrix * TriMatrix::scale(1.f, 1.f, 1.f + ((texh - 200.f) / 200.f) * 1.17f); + modelMatrix = modelMatrix * Mat4f::Translate(0.f, 0.f, (200 - texh + tex->SkyOffset + skyoffset)*skyoffsetfactor); + modelMatrix = modelMatrix * Mat4f::Scale(1.f, 1.f, 1.f + ((texh - 200.f) / 200.f) * 1.17f); } else { - modelMatrix = modelMatrix * TriMatrix::translate(0.f, 0.f, (-40 + tex->SkyOffset + skyoffset)*skyoffsetfactor); - modelMatrix = modelMatrix * TriMatrix::scale(1.f, 1.f, 1.2f * 1.17f); + modelMatrix = modelMatrix * Mat4f::Translate(0.f, 0.f, (-40 + tex->SkyOffset + skyoffset)*skyoffsetfactor); + modelMatrix = modelMatrix * Mat4f::Scale(1.f, 1.f, 1.2f * 1.17f); yscale = 240.f / texh; } diff --git a/src/polyrenderer/scene/poly_sky.h b/src/polyrenderer/scene/poly_sky.h index 5fcde6cba..6c70edbb0 100644 --- a/src/polyrenderer/scene/poly_sky.h +++ b/src/polyrenderer/scene/poly_sky.h @@ -46,14 +46,13 @@ class PolySkyDome { public: PolySkyDome(); - void Render(PolyRenderThread *thread, const TriMatrix &worldToClip); + void Render(PolyRenderThread *thread, const Mat4f &worldToView, const Mat4f &worldToClip); private: TArray mInitialUV; TArray mVertices; TArray mPrimStart; int mRows, mColumns; - TriMatrix objectToClip; void SkyVertex(int r, int c, bool yflip); void CreateSkyHemisphere(bool zflip); @@ -63,7 +62,7 @@ private: TriVertex SetVertexXYZ(float xx, float yy, float zz, float uu = 0, float vv = 0); - TriMatrix GLSkyMath(); + Mat4f GLSkyMath(); PolySkySetup mCurrentSetup; }; diff --git a/src/polyrenderer/scene/poly_sprite.cpp b/src/polyrenderer/scene/poly_sprite.cpp index 1db0fc951..d3310e614 100644 --- a/src/polyrenderer/scene/poly_sprite.cpp +++ b/src/polyrenderer/scene/poly_sprite.cpp @@ -72,18 +72,18 @@ bool RenderPolySprite::GetLine(AActor *thing, DVector2 &left, DVector2 &right) return true; } -void RenderPolySprite::Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, AActor *thing, subsector_t *sub, uint32_t stencilValue, float t1, float t2) +void RenderPolySprite::Render(PolyRenderThread *thread, const PolyClipPlane &clipPlane, AActor *thing, subsector_t *sub, uint32_t stencilValue, float t1, float t2) { - /*int spritenum = thing->sprite; + int spritenum = thing->sprite; bool isPicnumOverride = thing->picnum.isValid(); FSpriteModelFrame *modelframe = isPicnumOverride ? nullptr : gl_FindModelFrame(thing->GetClass(), spritenum, thing->frame, !!(thing->flags & MF_DROPPED)); if (modelframe) { const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; DVector3 pos = thing->InterpolatedPosition(viewpoint.TicFrac); - PolyRenderModel(thread, worldToClip, clipPlane, stencilValue, (float)pos.X, (float)pos.Y, (float)pos.Z, modelframe, thing); + PolyRenderModel(thread, PolyRenderer::Instance()->WorldToClip, clipPlane, stencilValue, (float)pos.X, (float)pos.Y, (float)pos.Z, modelframe, thing); return; - }*/ + } DVector2 line[2]; if (!GetLine(thing, line[0], line[1])) @@ -157,10 +157,7 @@ void RenderPolySprite::Render(PolyRenderThread *thread, const TriMatrix &worldTo PolyDrawArgs args; SetDynlight(thing, args); args.SetLight(GetColorTable(sub->sector->Colormap, sub->sector->SpecialColors[sector_t::sprites], true), lightlevel, PolyRenderer::Instance()->Light.SpriteGlobVis(foggy), fullbrightSprite); - args.SetTransform(&worldToClip); - args.SetFaceCullCCW(true); args.SetStencilTestValue(stencilValue); - args.SetWriteStencil(true, stencilValue); args.SetClipPlane(0, clipPlane); if ((thing->renderflags & RF_ZDOOMTRANS) && r_UseVanillaTransparency) args.SetStyle(LegacyRenderStyles[STYLE_Normal], 1.0f, thing->fillcolor, thing->Translation, tex, fullbrightSprite); @@ -169,7 +166,7 @@ void RenderPolySprite::Render(PolyRenderThread *thread, const TriMatrix &worldTo args.SetDepthTest(true); args.SetWriteDepth(false); args.SetWriteStencil(false); - args.DrawArray(thread, vertices, 4, PolyDrawMode::TriangleFan); + args.DrawArray(thread->DrawQueue, vertices, 4, PolyDrawMode::TriangleFan); } double RenderPolySprite::GetSpriteFloorZ(AActor *thing, const DVector2 &thingpos) diff --git a/src/polyrenderer/scene/poly_sprite.h b/src/polyrenderer/scene/poly_sprite.h index 84c4905dc..ba4738c73 100644 --- a/src/polyrenderer/scene/poly_sprite.h +++ b/src/polyrenderer/scene/poly_sprite.h @@ -27,7 +27,7 @@ class RenderPolySprite { public: - void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, AActor *thing, subsector_t *sub, uint32_t stencilValue, float t1, float t2); + void Render(PolyRenderThread *thread, const PolyClipPlane &clipPlane, AActor *thing, subsector_t *sub, uint32_t stencilValue, float t1, float t2); static bool GetLine(AActor *thing, DVector2 &left, DVector2 &right); static bool IsThingCulled(AActor *thing); @@ -45,17 +45,17 @@ class PolyTranslucentThing : public PolyTranslucentObject public: PolyTranslucentThing(AActor *thing, subsector_t *sub, uint32_t subsectorDepth, double dist, float t1, float t2, uint32_t stencilValue) : PolyTranslucentObject(subsectorDepth, dist), thing(thing), sub(sub), SpriteLeft(t1), SpriteRight(t2), StencilValue(stencilValue) { } - void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &portalPlane) override + void Render(PolyRenderThread *thread, const PolyClipPlane &portalPlane) override { if ((thing->renderflags & RF_SPRITETYPEMASK) == RF_WALLSPRITE) { RenderPolyWallSprite wallspr; - wallspr.Render(thread, worldToClip, portalPlane, thing, sub, StencilValue + 1); + wallspr.Render(thread, portalPlane, thing, sub, StencilValue + 1); } else { RenderPolySprite spr; - spr.Render(thread, worldToClip, portalPlane, thing, sub, StencilValue + 1, SpriteLeft, SpriteRight); + spr.Render(thread, portalPlane, thing, sub, StencilValue + 1, SpriteLeft, SpriteRight); } } diff --git a/src/polyrenderer/scene/poly_wall.cpp b/src/polyrenderer/scene/poly_wall.cpp index 545eb9232..136007702 100644 --- a/src/polyrenderer/scene/poly_wall.cpp +++ b/src/polyrenderer/scene/poly_wall.cpp @@ -40,7 +40,7 @@ EXTERN_CVAR(Bool, r_drawmirrors) EXTERN_CVAR(Bool, r_fogboundary) -bool RenderPolyWall::RenderLine(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, std::vector &translucentWallsOutput, std::vector> &linePortals, line_t *lastPortalLine) +bool RenderPolyWall::RenderLine(PolyRenderThread *thread, const PolyClipPlane &clipPlane, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, std::vector &translucentWallsOutput, std::vector> &linePortals, line_t *lastPortalLine) { double frontceilz1 = frontsector->ceilingplane.ZatPoint(line->v1); double frontfloorz1 = frontsector->floorplane.ZatPoint(line->v1); @@ -108,7 +108,7 @@ bool RenderPolyWall::RenderLine(PolyRenderThread *thread, const TriMatrix &world wall.Wallpart = side_t::mid; wall.Texture = GetTexture(wall.Line, wall.Side, side_t::mid); wall.Polyportal = polyportal; - wall.Render(thread, worldToClip, clipPlane); + wall.Render(thread, clipPlane); return true; } } @@ -145,7 +145,7 @@ bool RenderPolyWall::RenderLine(PolyRenderThread *thread, const TriMatrix &world wall.BottomTexZ = MIN(MIN(backceilz1, frontceilz1), MIN(backceilz2, frontceilz2)); wall.Wallpart = side_t::top; wall.Texture = GetTexture(wall.Line, wall.Side, side_t::top); - wall.Render(thread, worldToClip, clipPlane); + wall.Render(thread, clipPlane); } if ((bottomfloorz1 < bottomceilz1 || bottomfloorz2 < bottomceilz2) && line->sidedef && !bothSkyFloor) @@ -157,7 +157,7 @@ bool RenderPolyWall::RenderLine(PolyRenderThread *thread, const TriMatrix &world wall.UnpeggedCeil2 = topceilz2; wall.Wallpart = side_t::bottom; wall.Texture = GetTexture(wall.Line, wall.Side, side_t::bottom); - wall.Render(thread, worldToClip, clipPlane); + wall.Render(thread, clipPlane); } if (line->sidedef) @@ -179,7 +179,7 @@ bool RenderPolyWall::RenderLine(PolyRenderThread *thread, const TriMatrix &world if (polyportal) { wall.Polyportal = polyportal; - wall.Render(thread, worldToClip, clipPlane); + wall.Render(thread, clipPlane); } } } @@ -193,7 +193,7 @@ bool RenderPolyWall::IsFogBoundary(sector_t *front, sector_t *back) (front->GetTexture(sector_t::ceiling) != skyflatnum || back->GetTexture(sector_t::ceiling) != skyflatnum); } -void RenderPolyWall::Render3DFloorLine(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, F3DFloor *fakeFloor, std::vector &translucentWallsOutput) +void RenderPolyWall::Render3DFloorLine(PolyRenderThread *thread, const PolyClipPlane &clipPlane, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, F3DFloor *fakeFloor, std::vector &translucentWallsOutput) { if (!(fakeFloor->flags & FF_EXISTS)) return; if (!(fakeFloor->flags & FF_RENDERPLANES)) return; @@ -243,7 +243,7 @@ void RenderPolyWall::Render3DFloorLine(PolyRenderThread *thread, const TriMatrix wall.Texture = GetTexture(wall.Line, wall.Side, side_t::mid); if (!wall.Masked) - wall.Render(thread, worldToClip, clipPlane); + wall.Render(thread, clipPlane); else translucentWallsOutput.push_back(thread->FrameMemory->NewObject(wall)); } @@ -258,7 +258,7 @@ void RenderPolyWall::SetCoords(const DVector2 &v1, const DVector2 &v2, double ce this->floor2 = floor2; } -void RenderPolyWall::Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane) +void RenderPolyWall::Render(PolyRenderThread *thread, const PolyClipPlane &clipPlane) { bool foggy = false; if (!Texture && !Polyportal && !FogBoundary) @@ -322,10 +322,7 @@ void RenderPolyWall::Render(PolyRenderThread *thread, const TriMatrix &worldToCl PolyDrawArgs args; args.SetLight(Colormap, GetLightLevel(), PolyRenderer::Instance()->Light.WallGlobVis(foggy), false); - args.SetTransform(&worldToClip); - args.SetFaceCullCCW(true); args.SetStencilTestValue(StencilValue); - args.SetWriteStencil(true, StencilValue + 1); if (Texture && !Polyportal) args.SetTexture(Texture, DefaultRenderStyle()); args.SetClipPlane(0, clipPlane); @@ -339,7 +336,7 @@ void RenderPolyWall::Render(PolyRenderThread *thread, const TriMatrix &worldToCl args.SetDepthTest(true); args.SetWriteDepth(true); args.SetWriteStencil(false); - args.DrawArray(thread, vertices, 4, PolyDrawMode::TriangleFan); + args.DrawArray(thread->DrawQueue, vertices, 4, PolyDrawMode::TriangleFan); if (!Texture) return; } @@ -349,11 +346,12 @@ void RenderPolyWall::Render(PolyRenderThread *thread, const TriMatrix &worldToCl args.SetWriteStencil(true, Polyportal->StencilValue); args.SetWriteColor(false); args.SetWriteDepth(false); - args.DrawArray(thread, vertices, 4, PolyDrawMode::TriangleFan); - Polyportal->Shape.push_back({ vertices, 4, true }); + args.DrawArray(thread->DrawQueue, vertices, 4, PolyDrawMode::TriangleFan); + Polyportal->Shape.push_back({ vertices, 4 }); } else if (!Masked) { + args.SetWriteStencil(true, StencilValue + 1); args.SetStyle(TriBlendMode::TextureOpaque); DrawStripes(thread, args, vertices); } @@ -368,7 +366,7 @@ void RenderPolyWall::Render(PolyRenderThread *thread, const TriMatrix &worldToCl DrawStripes(thread, args, vertices); } - RenderPolyDecal::RenderWallDecals(thread, worldToClip, clipPlane, LineSeg, StencilValue); + RenderPolyDecal::RenderWallDecals(thread, clipPlane, LineSeg, StencilValue); } void RenderPolyWall::SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args) @@ -465,7 +463,7 @@ void RenderPolyWall::DrawStripes(PolyRenderThread *thread, PolyDrawArgs &args, T args.SetClipPlane(1, topPlane); args.SetClipPlane(2, bottomPlane); - args.DrawArray(thread, vertices, 4, PolyDrawMode::TriangleFan); + args.DrawArray(thread->DrawQueue, vertices, 4, PolyDrawMode::TriangleFan); FDynamicColormap *basecolormap = GetColorTable(lit->extra_colormap, Line->frontsector->SpecialColors[sector_t::walltop]); @@ -488,11 +486,11 @@ void RenderPolyWall::DrawStripes(PolyRenderThread *thread, PolyDrawArgs &args, T args.SetClipPlane(1, topPlane); args.SetClipPlane(2, PolyClipPlane()); - args.DrawArray(thread, vertices, 4, PolyDrawMode::TriangleFan); + args.DrawArray(thread->DrawQueue, vertices, 4, PolyDrawMode::TriangleFan); } else { - args.DrawArray(thread, vertices, 4, PolyDrawMode::TriangleFan); + args.DrawArray(thread->DrawQueue, vertices, 4, PolyDrawMode::TriangleFan); } } diff --git a/src/polyrenderer/scene/poly_wall.h b/src/polyrenderer/scene/poly_wall.h index 5b2385db6..f4e0d11f0 100644 --- a/src/polyrenderer/scene/poly_wall.h +++ b/src/polyrenderer/scene/poly_wall.h @@ -31,11 +31,11 @@ class PolyCull; class RenderPolyWall { public: - static bool RenderLine(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, std::vector &translucentWallsOutput, std::vector> &linePortals, line_t *lastPortalLine); - static void Render3DFloorLine(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, F3DFloor *fakeFloor, std::vector &translucentWallsOutput); + static bool RenderLine(PolyRenderThread *thread, const PolyClipPlane &clipPlane, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, std::vector &translucentWallsOutput, std::vector> &linePortals, line_t *lastPortalLine); + static void Render3DFloorLine(PolyRenderThread *thread, const PolyClipPlane &clipPlane, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, F3DFloor *fakeFloor, std::vector &translucentWallsOutput); void SetCoords(const DVector2 &v1, const DVector2 &v2, double ceil1, double floor1, double ceil2, double floor2); - void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane); + void Render(PolyRenderThread *thread, const PolyClipPlane &clipPlane); DVector2 v1; DVector2 v2; @@ -101,9 +101,9 @@ class PolyTranslucentWall : public PolyTranslucentObject public: PolyTranslucentWall(RenderPolyWall wall) : PolyTranslucentObject(wall.SubsectorDepth, 1e6), wall(wall) { } - void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &portalPlane) override + void Render(PolyRenderThread *thread, const PolyClipPlane &portalPlane) override { - wall.Render(thread, worldToClip, portalPlane); + wall.Render(thread, portalPlane); } RenderPolyWall wall; diff --git a/src/polyrenderer/scene/poly_wallsprite.cpp b/src/polyrenderer/scene/poly_wallsprite.cpp index 4f0e2ba52..6c793313e 100644 --- a/src/polyrenderer/scene/poly_wallsprite.cpp +++ b/src/polyrenderer/scene/poly_wallsprite.cpp @@ -30,7 +30,7 @@ #include "polyrenderer/scene/poly_light.h" #include "polyrenderer/poly_renderthread.h" -void RenderPolyWallSprite::Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, AActor *thing, subsector_t *sub, uint32_t stencilValue) +void RenderPolyWallSprite::Render(PolyRenderThread *thread, const PolyClipPlane &clipPlane, AActor *thing, subsector_t *sub, uint32_t stencilValue) { if (RenderPolySprite::IsThingCulled(thing)) return; @@ -102,8 +102,6 @@ void RenderPolyWallSprite::Render(PolyRenderThread *thread, const TriMatrix &wor PolyDrawArgs args; args.SetLight(GetColorTable(sub->sector->Colormap, sub->sector->SpecialColors[sector_t::sprites], true), lightlevel, PolyRenderer::Instance()->Light.WallGlobVis(foggy), fullbrightSprite); - args.SetTransform(&worldToClip); - args.SetFaceCullCCW(true); args.SetStencilTestValue(stencilValue); args.SetTexture(tex, thing->RenderStyle); args.SetClipPlane(0, clipPlane); @@ -111,5 +109,5 @@ void RenderPolyWallSprite::Render(PolyRenderThread *thread, const TriMatrix &wor args.SetWriteDepth(false); args.SetWriteStencil(false); args.SetStyle(TriBlendMode::TextureMasked); - args.DrawArray(thread, vertices, 4, PolyDrawMode::TriangleFan); + args.DrawArray(thread->DrawQueue, vertices, 4, PolyDrawMode::TriangleFan); } diff --git a/src/polyrenderer/scene/poly_wallsprite.h b/src/polyrenderer/scene/poly_wallsprite.h index 2ee8c3ba5..aa3461ccd 100644 --- a/src/polyrenderer/scene/poly_wallsprite.h +++ b/src/polyrenderer/scene/poly_wallsprite.h @@ -27,5 +27,5 @@ class RenderPolyWallSprite { public: - void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, AActor *thing, subsector_t *sub, uint32_t stencilValue); + void Render(PolyRenderThread *thread, const PolyClipPlane &clipPlane, AActor *thing, subsector_t *sub, uint32_t stencilValue); }; diff --git a/src/swrenderer/drawers/r_draw.cpp b/src/swrenderer/drawers/r_draw.cpp index 3250c1186..048d0807a 100644 --- a/src/swrenderer/drawers/r_draw.cpp +++ b/src/swrenderer/drawers/r_draw.cpp @@ -292,7 +292,7 @@ namespace swrenderer class DepthSpanCommand : public DrawerCommand { public: - DepthSpanCommand(const SpanDrawerArgs &args, float idepth) : idepth(idepth) + DepthSpanCommand(const SpanDrawerArgs &args, float idepth1, float idepth2) : idepth1(idepth1), idepth2(idepth2) { y = args.DestY(); x1 = args.DestX1(); @@ -310,16 +310,30 @@ namespace swrenderer int pitch = PolyStencilBuffer::Instance()->BlockWidth() * 8; float *values = zbuffer->Values() + y * pitch; int end = x2; - float depth = idepth; - for (int x = x1; x <= end; x++) + + if (idepth1 == idepth2) { - values[x] = depth; + float depth = idepth1; + for (int x = x1; x <= end; x++) + { + values[x] = depth; + } + } + else + { + float depth = idepth1; + float step = (idepth2 - idepth1) / (x2 - x1 + 1); + for (int x = x1; x <= end; x++) + { + values[x] = depth; + depth += step; + } } } private: int y, x1, x2; - float idepth; + float idepth1, idepth2; }; void SWPixelFormatDrawers::DrawDepthSkyColumn(const SkyDrawerArgs &args, float idepth) @@ -332,8 +346,8 @@ namespace swrenderer Queue->Push(args, idepth); } - void SWPixelFormatDrawers::DrawDepthSpan(const SpanDrawerArgs &args, float idepth) + void SWPixelFormatDrawers::DrawDepthSpan(const SpanDrawerArgs &args, float idepth1, float idepth2) { - Queue->Push(args, idepth); + Queue->Push(args, idepth1, idepth2); } } diff --git a/src/swrenderer/drawers/r_draw.h b/src/swrenderer/drawers/r_draw.h index fa83ca6f6..5d699791b 100644 --- a/src/swrenderer/drawers/r_draw.h +++ b/src/swrenderer/drawers/r_draw.h @@ -97,7 +97,7 @@ namespace swrenderer void DrawDepthSkyColumn(const SkyDrawerArgs &args, float idepth); void DrawDepthWallColumn(const WallDrawerArgs &args, float idepth); - void DrawDepthSpan(const SpanDrawerArgs &args, float idepth); + void DrawDepthSpan(const SpanDrawerArgs &args, float idepth1, float idepth2); DrawerCommandQueuePtr Queue; }; diff --git a/src/swrenderer/drawers/r_thread.h b/src/swrenderer/drawers/r_thread.h index 6927d14c7..53c9bea44 100644 --- a/src/swrenderer/drawers/r_thread.h +++ b/src/swrenderer/drawers/r_thread.h @@ -32,6 +32,8 @@ // Use multiple threads when drawing EXTERN_CVAR(Bool, r_multithreaded) +class PolyTriangleThreadData; + // Worker data for each thread executing drawer commands class DrawerThread { @@ -48,6 +50,8 @@ public: // Working buffer used by the tilted (sloped) span drawer const uint8_t *tiltlighting[MAXWIDTH]; + std::shared_ptr poly; + // Checks if a line is rendered by this thread bool line_skipped_by_thread(int line) { diff --git a/src/swrenderer/plane/r_flatplane.cpp b/src/swrenderer/plane/r_flatplane.cpp index 82e27f89f..d582aaf48 100644 --- a/src/swrenderer/plane/r_flatplane.cpp +++ b/src/swrenderer/plane/r_flatplane.cpp @@ -276,7 +276,7 @@ namespace swrenderer drawerargs.DrawSpan(Thread); if (r_models) - drawerargs.DrawDepthSpan(Thread, zbufferdepth); + drawerargs.DrawDepthSpan(Thread, zbufferdepth, zbufferdepth); } ///////////////////////////////////////////////////////////////////////// diff --git a/src/swrenderer/plane/r_slopeplane.cpp b/src/swrenderer/plane/r_slopeplane.cpp index bf9c84666..6c2a5175b 100644 --- a/src/swrenderer/plane/r_slopeplane.cpp +++ b/src/swrenderer/plane/r_slopeplane.cpp @@ -88,6 +88,14 @@ namespace swrenderer auto viewport = Thread->Viewport.get(); + DVector3 worldNormal = pl->height.Normal(); + double worldD = pl->height.fD(); + planeNormal.X = worldNormal.X * viewport->viewpoint.Sin - worldNormal.Y * viewport->viewpoint.Cos; + planeNormal.Y = worldNormal.X * viewport->viewpoint.Cos + worldNormal.Y * viewport->viewpoint.Sin; + planeNormal.Z = worldNormal.Z; + planeD = worldD + planeNormal.Z * viewport->viewpoint.Pos.Z; + + drawerargs.SetSolidColor(3); drawerargs.SetTexture(Thread, texture); @@ -205,14 +213,23 @@ namespace swrenderer void RenderSlopePlane::RenderLine(int y, int x1, int x2) { - /* To do: project (x1,y) and (x2,y) on the plane to calculate the depth - double distance = Thread->Viewport->PlaneDepth(y, planeheight); - float zbufferdepth = 1.0f / (distance * Thread->Viewport->viewwindow.FocalTangent); - drawerargs.SetDestX1(x1); - drawerargs.SetDestX2(x2); - drawerargs.SetDestY(Thread->Viewport.get(), y); - drawerargs.DrawDepthSpan(Thread, zbufferdepth); - */ + if (r_models) + { + // Calculate normalized device coordinates for the span + // 1.5 is not a typo. The range is [x1,x2] + double devY = -(y + 0.5 - Thread->Viewport->CenterY) / Thread->Viewport->InvZtoScale / Thread->Viewport->viewwindow.FocalTangent; + double devX1 = (x1 + 0.5 - Thread->Viewport->CenterX) / Thread->Viewport->CenterX; + double devX2 = (x2 + 1.5 - Thread->Viewport->CenterX) / Thread->Viewport->CenterX; + + // Find depth values for the span + float zbufferdepth1 = (float)-planeD / (planeNormal | DVector3(devX1, 1.0, devY)); + float zbufferdepth2 = (float)-planeD / (planeNormal | DVector3(devX2, 1.0, devY)); + + drawerargs.SetDestX1(x1); + drawerargs.SetDestX2(x2); + drawerargs.SetDestY(Thread->Viewport.get(), y); + drawerargs.DrawDepthSpan(Thread, 1.0f / zbufferdepth1, 1.0f / zbufferdepth2); + } drawerargs.DrawTiltedSpan(Thread, y, x1, x2, plane_sz, plane_su, plane_sv, plane_shade, planeshade, planelightfloat, pviewx, pviewy, basecolormap); } diff --git a/src/swrenderer/plane/r_slopeplane.h b/src/swrenderer/plane/r_slopeplane.h index ae4610254..c59fa3f58 100644 --- a/src/swrenderer/plane/r_slopeplane.h +++ b/src/swrenderer/plane/r_slopeplane.h @@ -48,5 +48,8 @@ namespace swrenderer fixed_t xscale, yscale; FDynamicColormap *basecolormap; SpanDrawerArgs drawerargs; + + DVector3 planeNormal; + double planeD; }; } diff --git a/src/swrenderer/r_swcanvas.cpp b/src/swrenderer/r_swcanvas.cpp index 5522d89dc..564fa8ca5 100644 --- a/src/swrenderer/r_swcanvas.cpp +++ b/src/swrenderer/r_swcanvas.cpp @@ -401,7 +401,7 @@ void SWCanvas::DrawLine(DCanvas *canvas, int x0, int y0, int x1, int y1, int pal palColor = PalFromRGB(realcolor); } - canvas->Lock(); + canvas->Lock(true); int deltaX, deltaY, xDir; if (y0 > y1) diff --git a/src/swrenderer/r_swrenderer.cpp b/src/swrenderer/r_swrenderer.cpp index c31908a17..25b3539d1 100644 --- a/src/swrenderer/r_swrenderer.cpp +++ b/src/swrenderer/r_swrenderer.cpp @@ -203,16 +203,15 @@ void FSoftwareRenderer::RemapVoxels() void FSoftwareRenderer::WriteSavePic (player_t *player, FileWriter *file, int width, int height) { - DCanvas *pic = new DSimpleCanvas (width, height, false); + DSimpleCanvas pic(width, height, false); PalEntry palette[256]; // Take a snapshot of the player's view - pic->Lock (); if (r_polyrenderer) { PolyRenderer::Instance()->Viewpoint = r_viewpoint; PolyRenderer::Instance()->Viewwindow = r_viewwindow; - PolyRenderer::Instance()->RenderViewToCanvas(player->mo, pic, 0, 0, width, height, true); + PolyRenderer::Instance()->RenderViewToCanvas(player->mo, &pic, 0, 0, width, height, true); r_viewpoint = PolyRenderer::Instance()->Viewpoint; r_viewwindow = PolyRenderer::Instance()->Viewwindow; } @@ -220,14 +219,12 @@ void FSoftwareRenderer::WriteSavePic (player_t *player, FileWriter *file, int wi { mScene.MainThread()->Viewport->viewpoint = r_viewpoint; mScene.MainThread()->Viewport->viewwindow = r_viewwindow; - mScene.RenderViewToCanvas(player->mo, pic, 0, 0, width, height); + mScene.RenderViewToCanvas(player->mo, &pic, 0, 0, width, height); r_viewpoint = mScene.MainThread()->Viewport->viewpoint; r_viewwindow = mScene.MainThread()->Viewport->viewwindow; } screen->GetFlashedPalette (palette); - M_CreatePNG (file, pic->GetBuffer(), palette, SS_PAL, width, height, pic->GetPitch(), Gamma); - pic->Unlock (); - delete pic; + M_CreatePNG (file, pic.GetBuffer(), palette, SS_PAL, width, height, pic.GetPitch(), Gamma); } void FSoftwareRenderer::DrawRemainingPlayerSprites() diff --git a/src/swrenderer/scene/r_scene.cpp b/src/swrenderer/scene/r_scene.cpp index 8c0b81cef..d18d0200a 100644 --- a/src/swrenderer/scene/r_scene.cpp +++ b/src/swrenderer/scene/r_scene.cpp @@ -67,7 +67,7 @@ EXTERN_CVAR(Bool, r_shadercolormaps) EXTERN_CVAR(Int, r_clearbuffer) CVAR(Bool, r_scene_multithreaded, false, 0); -CVAR(Bool, r_models, false, 0); +CVAR(Bool, r_models, true, 0); namespace swrenderer { @@ -98,6 +98,8 @@ namespace swrenderer float trueratio; ActiveRatio(width, height, &trueratio); viewport->SetViewport(MainThread(), width, height, trueratio); + if (r_models) + PolyTriangleDrawer::ClearBuffers(viewport->RenderTarget); if (r_clearbuffer != 0) { @@ -158,7 +160,7 @@ namespace swrenderer R_UpdateFuzzPosFrameStart(); if (r_models) - MainThread()->Viewport->SetupPolyViewport(); + MainThread()->Viewport->SetupPolyViewport(MainThread()); ActorRenderFlags savedflags = MainThread()->Viewport->viewpoint.camera->renderflags; // Never draw the player unless in chasecam mode @@ -267,6 +269,8 @@ namespace swrenderer thread->OpaquePass->ResetFakingUnderwater(); // [RH] Hack to make windows into underwater areas possible thread->Portal->SetMainPortal(); + PolyTriangleDrawer::SetViewport(thread->DrawQueue, viewwindowx, viewwindowy, viewwidth, viewheight, thread->Viewport->RenderTarget, true); + // Cull things outside the range seen by this thread VisibleSegmentRenderer visitor; if (thread->X1 > 0) @@ -361,6 +365,8 @@ namespace swrenderer viewwindowy = y; viewactive = true; viewport->SetViewport(MainThread(), width, height, MainThread()->Viewport->viewwindow.WidescreenRatio); + if (r_models) + PolyTriangleDrawer::ClearBuffers(viewport->RenderTarget); RenderActorView(actor, dontmaplines); DrawerWaitCycles.Clock(); @@ -372,9 +378,7 @@ namespace swrenderer R_ExecuteSetViewSize(MainThread()->Viewport->viewpoint, MainThread()->Viewport->viewwindow); float trueratio; ActiveRatio(width, height, &trueratio); - screen->Lock(true); viewport->SetViewport(MainThread(), width, height, trueratio); - screen->Unlock(); viewactive = savedviewactive; } @@ -387,9 +391,7 @@ namespace swrenderer int height = SCREENHEIGHT; float trueratio; ActiveRatio(width, height, &trueratio); - screen->Lock(true); viewport->SetViewport(MainThread(), SCREENWIDTH, SCREENHEIGHT, trueratio); - screen->Unlock(); } void RenderScene::Init() diff --git a/src/swrenderer/things/r_model.cpp b/src/swrenderer/things/r_model.cpp index b6f5fe0c7..e6db29716 100644 --- a/src/swrenderer/things/r_model.cpp +++ b/src/swrenderer/things/r_model.cpp @@ -92,7 +92,8 @@ namespace swrenderer void SWModelRenderer::BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix) { ModelActor = actor; - const_cast(objectToWorldMatrix).copy(ObjectToWorld.matrix); + const_cast(objectToWorldMatrix).copy(ObjectToWorld.Matrix); + SetTransform(); } void SWModelRenderer::EndDrawModel(AActor *actor, FSpriteModelFrame *smf) @@ -127,21 +128,21 @@ namespace swrenderer float ratio = Viewwindow.WidescreenRatio; float fovratio = (Viewwindow.WidescreenRatio >= 1.3f) ? 1.333333f : ratio; float fovy = (float)(2 * DAngle::ToDegrees(atan(tan(Viewpoint.FieldOfView.Radians() / 2) / fovratio)).Degrees); - TriMatrix altWorldToView = - TriMatrix::rotate(adjustedPitch, 1.0f, 0.0f, 0.0f) * - TriMatrix::rotate(adjustedViewAngle, 0.0f, -1.0f, 0.0f) * - TriMatrix::scale(1.0f, level.info->pixelstretch, 1.0f) * - TriMatrix::swapYZ() * - TriMatrix::translate((float)-Viewpoint.Pos.X, (float)-Viewpoint.Pos.Y, (float)-Viewpoint.Pos.Z); + Mat4f altWorldToView = + Mat4f::Rotate(adjustedPitch, 1.0f, 0.0f, 0.0f) * + Mat4f::Rotate(adjustedViewAngle, 0.0f, -1.0f, 0.0f) * + Mat4f::Scale(1.0f, level.info->pixelstretch, 1.0f) * + Mat4f::SwapYZ() * + Mat4f::Translate((float)-Viewpoint.Pos.X, (float)-Viewpoint.Pos.Y, (float)-Viewpoint.Pos.Z); - TriMatrix swapYZ = TriMatrix::null(); - swapYZ.matrix[0 + 0 * 4] = 1.0f; - swapYZ.matrix[1 + 2 * 4] = 1.0f; - swapYZ.matrix[2 + 1 * 4] = 1.0f; - swapYZ.matrix[3 + 3 * 4] = 1.0f; + Mat4f swapYZ = Mat4f::Null(); + swapYZ.Matrix[0 + 0 * 4] = 1.0f; + swapYZ.Matrix[1 + 2 * 4] = 1.0f; + swapYZ.Matrix[2 + 1 * 4] = 1.0f; + swapYZ.Matrix[3 + 3 * 4] = 1.0f; VSMatrix worldToView; - worldToView.loadMatrix((altWorldToView * swapYZ).matrix); + worldToView.loadMatrix((altWorldToView * swapYZ).Matrix); VSMatrix objectToWorld; worldToView.inverseMatrix(objectToWorld); @@ -151,7 +152,8 @@ namespace swrenderer void SWModelRenderer::BeginDrawHUDModel(AActor *actor, const VSMatrix &objectToWorldMatrix) { ModelActor = actor; - const_cast(objectToWorldMatrix).copy(ObjectToWorld.matrix); + const_cast(objectToWorldMatrix).copy(ObjectToWorld.Matrix); + SetTransform(); } void SWModelRenderer::EndDrawHUDModel(AActor *actor) @@ -169,6 +171,17 @@ namespace swrenderer SkinTexture = skin; } + void SWModelRenderer::SetTransform() + { + Mat4f swapYZ = Mat4f::Null(); + swapYZ.Matrix[0 + 0 * 4] = 1.0f; + swapYZ.Matrix[1 + 2 * 4] = 1.0f; + swapYZ.Matrix[2 + 1 * 4] = 1.0f; + swapYZ.Matrix[3 + 3 * 4] = 1.0f; + + PolyTriangleDrawer::SetTransform(Thread->DrawQueue, Thread->FrameMemory->NewObject(Thread->Viewport->WorldToClip * swapYZ * ObjectToWorld)); + } + void SWModelRenderer::DrawArrays(int start, int count) { const auto &viewpoint = Thread->Viewport->viewpoint; @@ -180,19 +193,8 @@ namespace swrenderer bool fullbrightSprite = ((ModelActor->renderflags & RF_FULLBRIGHT) || (ModelActor->flags5 & MF5_BRIGHT)); int lightlevel = fullbrightSprite ? 255 : ModelActor->Sector->lightlevel + actualextralight; - TriMatrix swapYZ = TriMatrix::null(); - swapYZ.matrix[0 + 0 * 4] = 1.0f; - swapYZ.matrix[1 + 2 * 4] = 1.0f; - swapYZ.matrix[2 + 1 * 4] = 1.0f; - swapYZ.matrix[3 + 3 * 4] = 1.0f; - - TriMatrix *transform = Thread->FrameMemory->NewObject(); - *transform = Thread->Viewport->WorldToClip * swapYZ * ObjectToWorld; - PolyDrawArgs args; args.SetLight(GetColorTable(sector->Colormap, sector->SpecialColors[sector_t::sprites], true), lightlevel, Thread->Light->SpriteGlobVis(foggy), fullbrightSprite); - args.SetTransform(transform); - args.SetFaceCullCCW(true); args.SetClipPlane(0, PolyClipPlane()); args.SetStyle(TriBlendMode::TextureOpaque); @@ -218,19 +220,8 @@ namespace swrenderer bool fullbrightSprite = ((ModelActor->renderflags & RF_FULLBRIGHT) || (ModelActor->flags5 & MF5_BRIGHT)); int lightlevel = fullbrightSprite ? 255 : ModelActor->Sector->lightlevel + actualextralight; - TriMatrix swapYZ = TriMatrix::null(); - swapYZ.matrix[0 + 0 * 4] = 1.0f; - swapYZ.matrix[1 + 2 * 4] = 1.0f; - swapYZ.matrix[2 + 1 * 4] = 1.0f; - swapYZ.matrix[3 + 3 * 4] = 1.0f; - - TriMatrix *transform = Thread->FrameMemory->NewObject(); - *transform = Thread->Viewport->WorldToClip * swapYZ * ObjectToWorld; - PolyDrawArgs args; args.SetLight(GetColorTable(sector->Colormap, sector->SpecialColors[sector_t::sprites], true), lightlevel, Thread->Light->SpriteGlobVis(foggy), fullbrightSprite); - args.SetTransform(transform); - args.SetFaceCullCCW(true); args.SetClipPlane(0, PolyClipPlane()); args.SetStyle(TriBlendMode::TextureOpaque); @@ -247,7 +238,7 @@ namespace swrenderer double SWModelRenderer::GetTimeFloat() { - return (double)screen->FrameTime * (double)TICRATE / 1000.0; + return (double)I_msTime() * (double)TICRATE / 1000.; } ///////////////////////////////////////////////////////////////////////////// @@ -282,11 +273,11 @@ namespace swrenderer void SWModelVertexBuffer::SetupFrame(FModelRenderer *renderer, unsigned int frame1, unsigned int frame2, unsigned int size) { - SWModelRenderer *polyrenderer = (SWModelRenderer *)renderer; + SWModelRenderer *swrenderer = (SWModelRenderer *)renderer; - if (true)//if (frame1 == frame2 || size == 0 || polyrenderer->InterpolationFactor == 0.f) + if (frame1 == frame2 || size == 0 || swrenderer->InterpolationFactor == 0.f) { - TriVertex *vertices = polyrenderer->Thread->FrameMemory->AllocMemory(size); + TriVertex *vertices = swrenderer->Thread->FrameMemory->AllocMemory(size); for (unsigned int i = 0; i < size; i++) { @@ -301,26 +292,27 @@ namespace swrenderer }; } - polyrenderer->VertexBuffer = vertices; - polyrenderer->IndexBuffer = &mIndexBuffer[0]; + swrenderer->VertexBuffer = vertices; + swrenderer->IndexBuffer = &mIndexBuffer[0]; } else { - TriVertex *vertices = polyrenderer->Thread->FrameMemory->AllocMemory(size); + TriVertex *vertices = swrenderer->Thread->FrameMemory->AllocMemory(size); - float frac = polyrenderer->InterpolationFactor; + 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 * (1.0f - frac) + mVertexBuffer[frame2 + i].x * frac; - vertices[i].y = mVertexBuffer[frame1 + i].y * (1.0f - frac) + mVertexBuffer[frame2 + i].y * frac; - vertices[i].z = mVertexBuffer[frame1 + i].z * (1.0f - frac) + mVertexBuffer[frame2 + i].z * frac; + 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]; + swrenderer->VertexBuffer = vertices; + swrenderer->IndexBuffer = &mIndexBuffer[0]; } } } diff --git a/src/swrenderer/things/r_model.h b/src/swrenderer/things/r_model.h index 3f6fd0e90..7006ca8dd 100644 --- a/src/swrenderer/things/r_model.h +++ b/src/swrenderer/things/r_model.h @@ -68,10 +68,12 @@ namespace swrenderer void DrawElements(int numIndices, size_t offset) override; double GetTimeFloat() override; + void SetTransform(); + RenderThread *Thread = nullptr; AActor *ModelActor = nullptr; - TriMatrix ObjectToWorld; + Mat4f ObjectToWorld; FTexture *SkinTexture = nullptr; unsigned int *IndexBuffer = nullptr; TriVertex *VertexBuffer = nullptr; diff --git a/src/swrenderer/viewport/r_spandrawer.cpp b/src/swrenderer/viewport/r_spandrawer.cpp index e5adf5409..0c1689f14 100644 --- a/src/swrenderer/viewport/r_spandrawer.cpp +++ b/src/swrenderer/viewport/r_spandrawer.cpp @@ -107,9 +107,9 @@ namespace swrenderer } } - void SpanDrawerArgs::DrawDepthSpan(RenderThread *thread, float idepth) + void SpanDrawerArgs::DrawDepthSpan(RenderThread *thread, float idepth1, float idepth2) { - thread->Drawers(ds_viewport)->DrawDepthSpan(*this, idepth); + thread->Drawers(ds_viewport)->DrawDepthSpan(*this, idepth1, idepth2); } void SpanDrawerArgs::DrawSpan(RenderThread *thread) diff --git a/src/swrenderer/viewport/r_spandrawer.h b/src/swrenderer/viewport/r_spandrawer.h index fe3363c98..3dc7c6191 100644 --- a/src/swrenderer/viewport/r_spandrawer.h +++ b/src/swrenderer/viewport/r_spandrawer.h @@ -27,7 +27,7 @@ namespace swrenderer void SetTextureVStep(double vstep) { ds_ystep = (uint32_t)(int64_t)(vstep * 4294967296.0); } void SetSolidColor(int colorIndex) { ds_color = colorIndex; } - void DrawDepthSpan(RenderThread *thread, float idepth); + void DrawDepthSpan(RenderThread *thread, float idepth1, float idepth2); void DrawSpan(RenderThread *thread); void DrawTiltedSpan(RenderThread *thread, int y, int x1, int x2, const FVector3 &plane_sz, const FVector3 &plane_su, const FVector3 &plane_sv, bool plane_shade, int planeshade, float planelightfloat, fixed_t pviewx, fixed_t pviewy, FDynamicColormap *basecolormap); void DrawColoredSpan(RenderThread *thread, int y, int x1, int x2); diff --git a/src/swrenderer/viewport/r_viewport.cpp b/src/swrenderer/viewport/r_viewport.cpp index a0535e434..73fb7fe48 100644 --- a/src/swrenderer/viewport/r_viewport.cpp +++ b/src/swrenderer/viewport/r_viewport.cpp @@ -59,17 +59,35 @@ namespace swrenderer { } - void RenderViewport::SetupPolyViewport() + void RenderViewport::SetupPolyViewport(RenderThread *thread) { - PolyStencilBuffer::Instance()->Clear(RenderTarget->GetWidth(), RenderTarget->GetHeight(), 0); - PolyZBuffer::Instance()->Resize(RenderTarget->GetPitch(), RenderTarget->GetHeight()); - - PolyTriangleDrawer::set_viewport(viewwindowx, viewwindowy, viewwidth, viewheight, RenderTarget); - WorldToView = TriMatrix::worldToView(viewpoint); - ViewToClip = TriMatrix::viewToClip(viewwindow.FocalTangent, CenterY, YaspectMul); + WorldToView = SoftwareWorldToView(viewpoint); + ViewToClip = SoftwareViewToClip(viewwindow.FocalTangent, CenterY, YaspectMul); WorldToClip = ViewToClip * WorldToView; } + Mat4f RenderViewport::SoftwareWorldToView(const FRenderViewpoint &viewpoint) + { + Mat4f m = Mat4f::Null(); + m.Matrix[0 + 0 * 4] = (float)viewpoint.Sin; + m.Matrix[0 + 1 * 4] = (float)-viewpoint.Cos; + m.Matrix[1 + 2 * 4] = 1.0f; + m.Matrix[2 + 0 * 4] = (float)-viewpoint.Cos; + m.Matrix[2 + 1 * 4] = (float)-viewpoint.Sin; + m.Matrix[3 + 3 * 4] = 1.0f; + return m * Mat4f::Translate((float)-viewpoint.Pos.X, (float)-viewpoint.Pos.Y, (float)-viewpoint.Pos.Z); + } + + Mat4f RenderViewport::SoftwareViewToClip(double focalTangent, double centerY, double YaspectMul) + { + float near = 5.0f; + float far = 65536.0f; + float width = (float)(focalTangent * near); + float top = (float)(centerY / viewheight * YaspectMul * near); + float bottom = (float)(top - YaspectMul * near); + return Mat4f::Frustum(-width, width, bottom, top, near, far, Handedness::Right, ClipZRange::NegativePositiveW); + } + void RenderViewport::SetViewport(RenderThread *thread, int fullWidth, int fullHeight, float trueratio) { int virtheight, virtwidth, virtwidth2, virtheight2; diff --git a/src/swrenderer/viewport/r_viewport.h b/src/swrenderer/viewport/r_viewport.h index b8ce166a7..0eee6fa1c 100644 --- a/src/swrenderer/viewport/r_viewport.h +++ b/src/swrenderer/viewport/r_viewport.h @@ -5,7 +5,7 @@ #include #include "v_video.h" #include "r_defs.h" -#include "polyrenderer/math/tri_matrix.h" +#include "polyrenderer/math/gpu_types.h" namespace swrenderer { @@ -20,11 +20,11 @@ namespace swrenderer void SetViewport(RenderThread *thread, int width, int height, float trueratio); void SetupFreelook(); - void SetupPolyViewport(); + void SetupPolyViewport(RenderThread *thread); - TriMatrix WorldToView; - TriMatrix ViewToClip; - TriMatrix WorldToClip; + Mat4f WorldToView; + Mat4f ViewToClip; + Mat4f WorldToClip; DCanvas *RenderTarget = nullptr; @@ -72,5 +72,8 @@ namespace swrenderer private: void InitTextureMapping(); void SetupBuffer(); + + static Mat4f SoftwareWorldToView(const FRenderViewpoint &viewpoint); + static Mat4f SoftwareViewToClip(double focalTangent, double centerY, double YaspectMul); }; }