From 91ec1463b87a26f3f0394743b1dd9d199cb7c51e Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Fri, 31 May 2019 08:49:08 +0200 Subject: [PATCH] - add line drawer --- .../polyrenderer/backend/poly_renderstate.cpp | 10 +- .../polyrenderer/drawers/poly_draw_args.h | 2 + .../polyrenderer/drawers/poly_triangle.cpp | 144 +++++++++++++++++- .../polyrenderer/drawers/poly_triangle.h | 2 + 4 files changed, 151 insertions(+), 7 deletions(-) diff --git a/src/rendering/polyrenderer/backend/poly_renderstate.cpp b/src/rendering/polyrenderer/backend/poly_renderstate.cpp index 25690564e..4adf4a59b 100644 --- a/src/rendering/polyrenderer/backend/poly_renderstate.cpp +++ b/src/rendering/polyrenderer/backend/poly_renderstate.cpp @@ -17,11 +17,11 @@ static PolyDrawMode dtToDrawMode[] = { - PolyDrawMode::Triangles, // DT_Points - PolyDrawMode::Triangles, // DT_Lines - PolyDrawMode::Triangles, // DT_Triangles - PolyDrawMode::TriangleFan, // DT_TriangleFan - PolyDrawMode::TriangleStrip, // DT_TriangleStrip + PolyDrawMode::Points, + PolyDrawMode::Lines, + PolyDrawMode::Triangles, + PolyDrawMode::TriangleFan, + PolyDrawMode::TriangleStrip, }; PolyRenderState::PolyRenderState() diff --git a/src/rendering/polyrenderer/drawers/poly_draw_args.h b/src/rendering/polyrenderer/drawers/poly_draw_args.h index 83df64421..3a15c3a31 100644 --- a/src/rendering/polyrenderer/drawers/poly_draw_args.h +++ b/src/rendering/polyrenderer/drawers/poly_draw_args.h @@ -32,6 +32,8 @@ class Mat4f; enum class PolyDrawMode { + Points, + Lines, Triangles, TriangleFan, TriangleStrip diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/rendering/polyrenderer/drawers/poly_triangle.cpp index 022ca963f..c9584b187 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/poly_triangle.cpp @@ -520,7 +520,7 @@ void PolyTriangleThreadData::DrawIndexed(int index, int vcount, PolyDrawMode dra std::swap(vert[1], vert[2]); } } - else // TriangleDrawMode::TriangleStrip + else if (drawmode == PolyDrawMode::TriangleStrip) { bool toggleccw = ccw; *vert[0] = ShadeVertex(*(elements++)); @@ -536,6 +536,23 @@ void PolyTriangleThreadData::DrawIndexed(int index, int vcount, PolyDrawMode dra toggleccw = !toggleccw; } } + else if (drawmode == PolyDrawMode::Lines) + { + for (int i = 0; i < vcount / 2; i++) + { + *vert[0] = ShadeVertex(*(elements++)); + *vert[1] = ShadeVertex(*(elements++)); + DrawShadedLine(vert); + } + } + else if (drawmode == PolyDrawMode::Points) + { + for (int i = 0; i < vcount; i++) + { + *vert[0] = ShadeVertex(*(elements++)); + DrawShadedPoint(vert); + } + } } void PolyTriangleThreadData::Draw(int index, int vcount, PolyDrawMode drawmode) @@ -570,7 +587,7 @@ void PolyTriangleThreadData::Draw(int index, int vcount, PolyDrawMode drawmode) std::swap(vert[1], vert[2]); } } - else // TriangleDrawMode::TriangleStrip + else if (drawmode == PolyDrawMode::TriangleStrip) { bool toggleccw = ccw; *vert[0] = ShadeVertex(vinput++); @@ -586,6 +603,23 @@ void PolyTriangleThreadData::Draw(int index, int vcount, PolyDrawMode drawmode) toggleccw = !toggleccw; } } + else if (drawmode == PolyDrawMode::Lines) + { + for (int i = 0; i < vcount / 2; i++) + { + *vert[0] = ShadeVertex(vinput++); + *vert[1] = ShadeVertex(vinput++); + DrawShadedLine(vert); + } + } + else if (drawmode == PolyDrawMode::Points) + { + for (int i = 0; i < vcount; i++) + { + *vert[0] = ShadeVertex(vinput++); + DrawShadedPoint(vert); + } + } } ShadedTriVertex PolyTriangleThreadData::ShadeVertex(int index) @@ -647,6 +681,112 @@ bool PolyTriangleThreadData::IsFrontfacing(TriDrawTriangleArgs *args) return a <= 0.0f; } +void PolyTriangleThreadData::DrawShadedPoint(const ShadedTriVertex *const* vertex) +{ +} + +void PolyTriangleThreadData::DrawShadedLine(const ShadedTriVertex *const* vert) +{ + static const int numclipdistances = 9; + float clipdistance[numclipdistances * 2]; + float *clipd = clipdistance; + for (int i = 0; i < 2; i++) + { + const auto &v = *vert[i]; + clipd[0] = v.gl_Position.X + v.gl_Position.W; + clipd[1] = v.gl_Position.W - v.gl_Position.X; + clipd[2] = v.gl_Position.Y + v.gl_Position.W; + clipd[3] = v.gl_Position.W - v.gl_Position.Y; + clipd[4] = v.gl_Position.Z + v.gl_Position.W; + clipd[5] = v.gl_Position.W - v.gl_Position.Z; + clipd[6] = v.gl_ClipDistance[0]; + clipd[7] = v.gl_ClipDistance[1]; + clipd[8] = v.gl_ClipDistance[2]; + clipd += numclipdistances; + } + + float t1 = 0.0f; + float t2 = 1.0f; + for (int p = 0; p < numclipdistances; p++) + { + float clipdistance1 = clipdistance[0 * numclipdistances + p]; + float clipdistance2 = clipdistance[1 * numclipdistances + p]; + if (clipdistance1 < 0.0f) t1 = MAX(-clipdistance1 / (clipdistance2 - clipdistance1), t1); + if (clipdistance2 < 0.0f) t2 = MIN(1.0f + clipdistance2 / (clipdistance1 - clipdistance2), t2); + if (t1 >= t2) + return; + } + + float weights[] = { 1.0f - t1, t1, 1.0f - t2, t2 }; + + ScreenTriVertex clippedvert[2]; + for (int i = 0; i < 2; i++) + { + auto &v = clippedvert[i]; + memset(&v, 0, sizeof(ScreenTriVertex)); + for (int w = 0; w < 2; w++) + { + float weight = weights[i * 2 + w]; + v.x += vert[w]->gl_Position.X * weight; + v.y += vert[w]->gl_Position.Y * weight; + v.z += vert[w]->gl_Position.Z * weight; + v.w += vert[w]->gl_Position.W * weight; + v.u += vert[w]->vTexCoord.X * weight; + v.v += vert[w]->vTexCoord.Y * weight; + v.worldX += vert[w]->pixelpos.X * weight; + v.worldY += vert[w]->pixelpos.Y * weight; + v.worldZ += vert[w]->pixelpos.Z * weight; + } + + // Calculate normalized device coordinates: + v.w = 1.0f / v.w; + v.x *= v.w; + v.y *= v.w; + v.z *= v.w; + + // Apply viewport scale to get screen coordinates: + v.x = viewport_x + viewport_width * (1.0f + v.x) * 0.5f; + v.y = viewport_y + viewport_height * (1.0f - v.y) * 0.5f; + } + + uint32_t color = vert[0]->vColor; + + // Slow and naive implementation. Hopefully fast enough.. + + float x1 = clippedvert[0].x; + float y1 = clippedvert[0].y; + float x2 = clippedvert[1].x; + float y2 = clippedvert[1].y; + float dx = x2 - x1; + float dy = y2 - y1; + float step = (abs(dx) >= abs(dy)) ? abs(dx) : abs(dy); + dx /= step; + dy /= step; + float x = x1; + float y = y1; + int istep = (int)step; + int pixelsize = dest_bgra ? 4 : 1; + for (int i = 0; i <= istep; i++) + { + int scrx = (int)x; + int scry = (int)y; + if (scrx >= clip.left && scrx < clip.right && scry >= clip.top && scry < clip.bottom && !line_skipped_by_thread(scry)) + { + uint8_t *destpixel = dest + (scrx + scry * dest_width) * pixelsize; + if (pixelsize == 4) + { + *reinterpret_cast(destpixel) = color; + } + else + { + *destpixel = color; + } + } + x += dx; + y += dy; + } +} + void PolyTriangleThreadData::DrawShadedTriangle(const ShadedTriVertex *const* vert, bool ccw, TriDrawTriangleArgs *args) { // Reject triangle if degenerate diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.h b/src/rendering/polyrenderer/drawers/poly_triangle.h index f3ffaee7c..683ebbd40 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.h +++ b/src/rendering/polyrenderer/drawers/poly_triangle.h @@ -246,6 +246,8 @@ public: private: ShadedTriVertex ShadeVertex(int index); + void DrawShadedPoint(const ShadedTriVertex *const* vertex); + void DrawShadedLine(const ShadedTriVertex *const* vertices); void DrawShadedTriangle(const ShadedTriVertex *const* vertices, bool ccw, TriDrawTriangleArgs *args); static bool IsDegenerate(const ShadedTriVertex *const* vertices); static bool IsFrontfacing(TriDrawTriangleArgs *args);