From 936e326229d7c4450c68fd811b0d899412ce4b76 Mon Sep 17 00:00:00 2001 From: thejinchao Date: Tue, 29 Jul 2025 22:22:40 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=85=89=E6=A0=85=E5=8C=96?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=EF=BC=8C=E4=BD=BF=E7=94=A8=E5=90=8C=E4=B8=80?= =?UTF-8?q?=E5=A5=97tile=E7=BB=98=E5=88=B6=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rasterizer/dvc_rasterizer_triangle.h | 16 +- .../rasterizer/dvc_rasterizer_triangle.cpp | 464 +++++++----------- 2 files changed, 181 insertions(+), 299 deletions(-) diff --git a/source/core/include/rasterizer/dvc_rasterizer_triangle.h b/source/core/include/rasterizer/dvc_rasterizer_triangle.h index 208810e..f988cf2 100644 --- a/source/core/include/rasterizer/dvc_rasterizer_triangle.h +++ b/source/core/include/rasterizer/dvc_rasterizer_triangle.h @@ -8,16 +8,7 @@ DV_CORE_BEGIN_NAMESPACE class DV_CORE_API Rasterizer { - //Draw Line -public: - typedef std::function&, float)> DrawLineCallback; - - //Bresenham's line algorithm - static void drawLine(int32_t canvasWidth, int32_t canvasHeight, - const fVector2& start, const fVector2& end, - DrawLineCallback callback); - - //Draw Triangle + //Draw Triangle with Larrabee public: typedef std::function& pos, const fVector3& percent)> DrawTriangleCallback; @@ -40,8 +31,9 @@ public: const fVector2& v0, const fVector2& v1, const fVector2& v2, DrawTriangleCallback callback, bool ccw=true, const DebugParam* debugParam=nullptr); - //Scaleline algorithm - static void drawTriangleScanline(int32_t canvasWidth, int32_t canvasHeight, +public: + //BoundingBox algorithm + static void drawTriangleBoundingBox(int32_t canvasWidth, int32_t canvasHeight, const fVector2& v0, const fVector2& v1, const fVector2& v2, DrawTriangleCallback callback, bool ccw = true); }; diff --git a/source/core/source/rasterizer/dvc_rasterizer_triangle.cpp b/source/core/source/rasterizer/dvc_rasterizer_triangle.cpp index d96f3ed..b5ad10f 100644 --- a/source/core/source/rasterizer/dvc_rasterizer_triangle.cpp +++ b/source/core/source/rasterizer/dvc_rasterizer_triangle.cpp @@ -2,6 +2,8 @@ #include "math/dvc_fix_point.h" #include "math/dvc_math_util.h" +#include + /* https://github.com/nlguillemot/vigilant-system https://wiki.joak.org/public:cs:rasterization_on_larrabee @@ -9,337 +11,221 @@ https://wiki.joak.org/public:cs:rasterization_on_larrabee DV_CORE_BEGIN_NAMESPACE -//------------------------------------------------------------------------------------- +using bool3_t = std::array; + +inline bool operator==(const bool3_t& arr, bool value) +{ + return arr[0] == value && arr[1] == value && arr[2] == value; +} + struct DrawTriangleParam { - int32_t widthInTiles; bool ccw; fVector2 verts[3]; float32_t bbox_min_x; float32_t bbox_max_x; float32_t bbox_min_y; float32_t bbox_max_y; - bool tlBorder[3]; + bool3_t tlBorder; float32_t area; iFloat3 edgesDX, edgesDY; + iFloat3 halfEdge; Rasterizer::DebugParam debugParam; }; -//------------------------------------------------------------------------------------- -enum { TILE_WIDTH_IN_PIXELS = 64, COARSE_BLOCK_WIDTH_IN_PIXELS = 16, FINE_BLOCK_WIDTH_IN_PIXELS = 4 }; +enum { MIN_TILE_WIDTH_IN_PIXELS = 64 }; -//------------------------------------------------------------------------------------- -void _drawTriangle_Fine(int32_t tile_id, int32_t coarse_id, int32_t fine_id, - const DrawTriangleParam& param, const iFloat3& edges0, uint32_t testEdgeMask, - Rasterizer::DrawTriangleCallback callback) +void _fillPixel(const DrawTriangleParam& param, int32_t xLB, int32_t yLB, Rasterizer::DrawTriangleCallback callback) { - iFloat3 kHalfDX = param.edgesDX; kHalfDX.mul(iFloat::kHalf); - iFloat3 kHalfDY = param.edgesDY; kHalfDY.mul(iFloat::kHalf); - - iFloat3 pixelEdges(edges0); - pixelEdges.sub(kHalfDY); - pixelEdges.add(kHalfDX); - + fVector2 pixel(xLB + 0.5f, yLB + 0.5f); const fVector2 v0(param.verts[0]), v1(param.verts[1]), v2(param.verts[2]); - const bool edgeMask[3] = { (testEdgeMask & 1) != 0 , (testEdgeMask & 2) != 0 , (testEdgeMask & 4) != 0 }; - int32_t fine_start_x = (tile_id % param.widthInTiles) * TILE_WIDTH_IN_PIXELS - + (coarse_id % 4) * COARSE_BLOCK_WIDTH_IN_PIXELS + (fine_id % 4) * FINE_BLOCK_WIDTH_IN_PIXELS; + float32_t w0 = (v2 - v1).crossProduct(pixel - v2); + float32_t w1 = (v0 - v2).crossProduct(pixel - v0); + float32_t w2 = (v1 - v0).crossProduct(pixel - v1); - int32_t fine_start_y = (tile_id / param.widthInTiles) * TILE_WIDTH_IN_PIXELS - + (coarse_id / 4) * COARSE_BLOCK_WIDTH_IN_PIXELS + (fine_id / 4)*FINE_BLOCK_WIDTH_IN_PIXELS; + fVector3 t = fVector3(w0 / param.area, (param.ccw ? w1 : w2) / param.area, (param.ccw ? w2 : w1) / param.area); - for (int32_t y_index=0, y= fine_start_y; y_index < 4; y_index++, y++) - { - iFloat3 edgesRow(pixelEdges); - - for (int32_t x_index = 0, x=fine_start_x; x_index < 4; x_index++, x++) - { - if (param.debugParam.debug) - { - if (x == param.debugParam.x && y == param.debugParam.y) - { - iFloat3 LBEdges(edges0); - LBEdges.sub(kHalfDY); - LBEdges.add(kHalfDX); - - fprintf(param.debugParam.fpOutput, "======= Fine =======\n"); - fprintf(param.debugParam.fpOutput, "LeftBottom=[%d,%d](%f,%f)\n", fine_start_x, fine_start_y, fine_start_x+0.5f, fine_start_y+0.5f); - fprintf(param.debugParam.fpOutput, "Edge0=(%f,%f,%f)[%lld,%lld,%lld]\n", - edges0.x.to_float(), edges0.y.to_float(), edges0.z.to_float(), - edges0.x.s3132, edges0.y.s3132, edges0.z.s3132 - ); - fprintf(param.debugParam.fpOutput, "Edge0+0.5=(%f,%f,%f)[%lld,%lld,%lld]\n", - LBEdges.x.to_float(), LBEdges.y.to_float(), LBEdges.z.to_float(), - LBEdges.x.s3132, LBEdges.y.s3132, LBEdges.z.s3132 - ); - - fprintf(param.debugParam.fpOutput, "======= Pixel =======\n"); - fprintf(param.debugParam.fpOutput, "Position=[%d,%d](%f,%f)\n", x, y, x+0.5f, y+0.5f); - fprintf(param.debugParam.fpOutput, "IndexInFind=[%d,%d]\n", x_index, y_index); - fprintf(param.debugParam.fpOutput, "Edge=(%f,%f,%f)[%lld,%lld,%lld]\n", - edgesRow.x.to_float(), edgesRow.y.to_float(), edgesRow.z.to_float(), - edgesRow.x.s3132, edgesRow.y.s3132, edgesRow.z.s3132 - ); - } - } - - bool rejected = - (edgeMask[0] && (edgesRow.x < 0 || (!param.tlBorder[0] && edgesRow.x == 0))) || - (edgeMask[1] && (edgesRow.y < 0 || (!param.tlBorder[1] && edgesRow.y == 0))) || - (edgeMask[2] && (edgesRow.z < 0 || (!param.tlBorder[2] && edgesRow.z == 0))); - - if (!rejected) - { - fVector2 pixel(x + 0.5f, y + 0.5f); - - float32_t w0 = (v2 - v1).crossProduct(pixel - v2); - float32_t w1 = (v0 - v2).crossProduct(pixel - v0); - float32_t w2 = (v1 - v0).crossProduct(pixel - v1); - - fVector3 t = fVector3(w0 / param.area, (param.ccw ? w1 : w2) / param.area, (param.ccw ? w2 : w1) / param.area); - - callback(std::make_pair(x, y), t); - } - edgesRow.sub(param.edgesDY); - } - pixelEdges.add(param.edgesDX); - } + callback(std::make_pair(xLB, yLB), t); } -//------------------------------------------------------------------------------------- -void _drawTriangle_Coarse(int32_t tile_id, int32_t coarse_id, - DrawTriangleParam& param, const iFloat3& edges0, uint32_t testEdgeMask, - Rasterizer::DrawTriangleCallback callback) +void _fillTile(const DrawTriangleParam& param, int32_t currentTileSize, + int32_t xLB, int32_t yLB, Rasterizer::DrawTriangleCallback callback) { - const iFloat3 blockEdgesDX( - param.edgesDX.x * FINE_BLOCK_WIDTH_IN_PIXELS, - param.edgesDX.y * FINE_BLOCK_WIDTH_IN_PIXELS, - param.edgesDX.z * FINE_BLOCK_WIDTH_IN_PIXELS - ); - const iFloat3 blockEdgesDY( - param.edgesDY.x * FINE_BLOCK_WIDTH_IN_PIXELS, - param.edgesDY.y * FINE_BLOCK_WIDTH_IN_PIXELS, - param.edgesDY.z * FINE_BLOCK_WIDTH_IN_PIXELS - ); - const bool edgeMask[3] = { (testEdgeMask & 1) != 0 , (testEdgeMask & 2) != 0 , (testEdgeMask & 4) != 0 }; - - iFloat3 blockReject(edges0); - iFloat3 blockAccept(edges0); - iFloat3 blockEdges(edges0); - - for (size_t v = 0; v < 3; v++) + if (currentTileSize == 1) { - if (edgeMask[v]) - { - if (blockEdgesDX[v] > 0) blockReject[v] += blockEdgesDX[v]; - else if (blockEdgesDX[v] < 0) blockAccept[v] += blockEdgesDX[v]; - - if (blockEdgesDY[v] > 0) blockAccept[v] -= blockEdgesDY[v]; - else if (blockEdgesDY[v] < 0) blockReject[v] -= blockEdgesDY[v]; - } + _fillPixel(param, xLB, yLB, callback); + return; } - int32_t block_start_x = (tile_id % param.widthInTiles) * TILE_WIDTH_IN_PIXELS + (coarse_id % 4) * COARSE_BLOCK_WIDTH_IN_PIXELS; - int32_t block_start_y = (tile_id / param.widthInTiles) * TILE_WIDTH_IN_PIXELS + (coarse_id / 4) * COARSE_BLOCK_WIDTH_IN_PIXELS; - - for (int32_t y_index = 0; y_index < 4; y_index++) + for (int32_t yIndex = yLB; yIndex < yLB + currentTileSize; yIndex++) { - if (block_start_y + y_index * FINE_BLOCK_WIDTH_IN_PIXELS > param.bbox_max_y) + for (int32_t xIndex = xLB; xIndex < xLB + currentTileSize; xIndex++) { - break; - } - - if (block_start_y + (y_index + 1)*FINE_BLOCK_WIDTH_IN_PIXELS >= param.bbox_min_y) - { - iFloat3 edgesRow(blockEdges); - iFloat3 edgesRowReject, edgesRowAccept; - - for (size_t v = 0; v < 3; v++) - { - if (edgeMask[v]) - { - edgesRowReject[v] = blockReject[v]; - edgesRowAccept[v] = blockAccept[v]; - } - } - for (int32_t x_index = 0; x_index < 4; x_index++) - { - if (block_start_x + x_index * FINE_BLOCK_WIDTH_IN_PIXELS > param.bbox_max_x) break; - if (block_start_x + (x_index + 1)*FINE_BLOCK_WIDTH_IN_PIXELS >= param.bbox_min_x) - { - bool rejected = - (edgeMask[0] && (edgesRowReject[0] < 0 || (!param.tlBorder[0] && edgesRowReject[0] == 0))) || - (edgeMask[1] && (edgesRowReject[1] < 0 || (!param.tlBorder[1] && edgesRowReject[1] == 0))) || - (edgeMask[2] && (edgesRowReject[2] < 0 || (!param.tlBorder[2] && edgesRowReject[2] == 0))); - - if (!rejected) - { - uint32_t newTestEdgeMask = testEdgeMask; - for (size_t v = 0; v < 3; v++) - { - if (edgeMask[v]) - { - if (edgesRowAccept[v] > 0 || (edgesRowAccept[v] == 0 && param.tlBorder[v])) - { - newTestEdgeMask &= ~(1 << v); - } - } - } - - _drawTriangle_Fine(tile_id, coarse_id, y_index * 4 + x_index, param, edgesRow, newTestEdgeMask, callback); - } - } - - edgesRow.sub(blockEdgesDY); - for (size_t v = 0; v < 3; v++) - { - if (edgeMask[v]) - { - edgesRowReject[v] -= blockEdgesDY[v]; - edgesRowAccept[v] -= blockEdgesDY[v]; - } - } - } - } - - blockEdges.add(blockEdgesDX); - for (size_t v = 0; v < 3; v++) - { - if (edgeMask[v]) - { - blockReject[v] += blockEdgesDX[v]; - blockAccept[v] += blockEdgesDX[v]; - } + _fillPixel(param, xIndex, yIndex, callback); } } } -//------------------------------------------------------------------------------------- -void _drawTriangle_Title(int32_t tile_id, - DrawTriangleParam& param, const iFloat3& edges0, uint32_t testEdgeMask, +void _drawPixel(DrawTriangleParam& param, + int32_t xLB, int32_t yLB, const iFloat3& edgesLB, const bool3_t& intersectant, Rasterizer::DrawTriangleCallback callback) { - const iFloat3 blockEdgesDX( - param.edgesDX[0] * COARSE_BLOCK_WIDTH_IN_PIXELS, - param.edgesDX[1] * COARSE_BLOCK_WIDTH_IN_PIXELS, - param.edgesDX[2] * COARSE_BLOCK_WIDTH_IN_PIXELS - ); + iFloat3 centerEdges(edgesLB); + centerEdges.add(param.halfEdge); - const iFloat3 blockEdgesDY( - param.edgesDY[0] * COARSE_BLOCK_WIDTH_IN_PIXELS, - param.edgesDY[1] * COARSE_BLOCK_WIDTH_IN_PIXELS, - param.edgesDY[2] * COARSE_BLOCK_WIDTH_IN_PIXELS - ); - const bool edgeMask[3] = { (testEdgeMask & 1) != 0 , (testEdgeMask & 2) != 0 , (testEdgeMask & 4) != 0 }; + bool insideTriangle = + (centerEdges.x > 0 || (param.tlBorder[0] && centerEdges.x == 0)) && + (centerEdges.y > 0 || (param.tlBorder[1] && centerEdges.y == 0)) && + (centerEdges.z > 0 || (param.tlBorder[2] && centerEdges.z == 0)); - iFloat3 blockReject(edges0); - iFloat3 blockAccept(edges0); - iFloat3 blockEdges(edges0); - - for (size_t v = 0; v < 3; v++) + if (insideTriangle) { - if (edgeMask[v]) - { - if (blockEdgesDX[v] > 0) blockReject[v] += blockEdgesDX[v]; - else if (blockEdgesDX[v] < 0) blockAccept[v] += blockEdgesDX[v]; + _fillPixel(param, xLB, yLB, callback); + } +} - if (blockEdgesDY[v] > 0) blockAccept[v] -= blockEdgesDY[v]; - else if (blockEdgesDY[v] < 0) blockReject[v] -= blockEdgesDY[v]; +void _drawTriangle_Tile(DrawTriangleParam& param, int32_t currentTileSize, + int32_t xLB, int32_t yLB, const iFloat3& edgesLB, const bool3_t& intersectant, + Rasterizer::DrawTriangleCallback callback) +{ + if (intersectant==false) + { + _fillTile(param, currentTileSize, xLB, yLB, callback); + return; + } + + if (currentTileSize == 1) + { + _drawPixel(param, xLB, yLB, edgesLB, intersectant, callback); + return; + } + + int32_t subTileSize = currentTileSize / 4; + + iFloat3 subTileEdgesDX(param.edgesDX); + subTileEdgesDX.mul(subTileSize); + + iFloat3 subTileEdgesDY(param.edgesDY); + subTileEdgesDY.mul(subTileSize); + + iFloat3 rowRejectEdges(edgesLB); + iFloat3 rowAcceptEdges(edgesLB); + iFloat3 rowLBEdges(edgesLB); + + for (size_t v = 0; v < 3; v++) + { + if (intersectant[v]) + { + if (subTileEdgesDX[v] > 0) rowRejectEdges[v] += subTileEdgesDX[v]; + else if (subTileEdgesDX[v] < 0) rowAcceptEdges[v] += subTileEdgesDX[v]; + + if (subTileEdgesDY[v] > 0) rowAcceptEdges[v] -= subTileEdgesDY[v]; + else if (subTileEdgesDY[v] < 0) rowRejectEdges[v] -= subTileEdgesDY[v]; } } - int32_t block_start_x = (tile_id % param.widthInTiles) * TILE_WIDTH_IN_PIXELS; - int32_t block_start_y = (tile_id / param.widthInTiles) * TILE_WIDTH_IN_PIXELS; - - for (int32_t y_index = 0; y_index < 4; y_index++) + int32_t yPos = yLB; + for (int32_t yIndex = 0; yIndex < 4; yIndex++) { - if (block_start_y + y_index * COARSE_BLOCK_WIDTH_IN_PIXELS > param.bbox_max_y) + if (yPos > param.bbox_max_y) { break; } - if (block_start_y + (y_index + 1)*COARSE_BLOCK_WIDTH_IN_PIXELS >= param.bbox_min_y) + if (yPos + subTileSize >= param.bbox_min_y) { - iFloat3 edges(blockEdges); - iFloat3 edgesRowReject, edgesRowAccept; + iFloat3 subTileLBEdges(rowLBEdges); + iFloat3 subTileRjectEdges(rowRejectEdges); + iFloat3 subTileAcceptEdges(rowAcceptEdges); - for (size_t v = 0; v < 3; v++) + int32_t xPos = xLB; + for (int32_t xIndex = 0; xIndex < 4; xIndex++) { - if (edgeMask[v]) - { - edgesRowReject[v] = blockReject[v]; - edgesRowAccept[v] = blockAccept[v]; - } - } - - for (int32_t x_index = 0; x_index < 4; x_index++) - { - if (block_start_x + x_index * COARSE_BLOCK_WIDTH_IN_PIXELS > param.bbox_max_x) + if (xPos > param.bbox_max_x) { break; } - if (block_start_x + (x_index + 1)*COARSE_BLOCK_WIDTH_IN_PIXELS >= param.bbox_min_x) + if (xPos + subTileSize >= param.bbox_min_x) { - bool rejected = - (edgeMask[0] && (edgesRowReject[0] < 0 || (!param.tlBorder[0] && edgesRowReject[0] == 0))) || - (edgeMask[1] && (edgesRowReject[1] < 0 || (!param.tlBorder[1] && edgesRowReject[1] == 0))) || - (edgeMask[2] && (edgesRowReject[2] < 0 || (!param.tlBorder[2] && edgesRowReject[2] == 0))); + bool rejected = + (intersectant[0] && (subTileRjectEdges[0] < 0 || (!param.tlBorder[0] && subTileRjectEdges[0] == 0))) || + (intersectant[1] && (subTileRjectEdges[1] < 0 || (!param.tlBorder[1] && subTileRjectEdges[1] == 0))) || + (intersectant[2] && (subTileRjectEdges[2] < 0 || (!param.tlBorder[2] && subTileRjectEdges[2] == 0))); - if (!rejected) + if (!rejected) { - uint32_t newTestEdgeMask = testEdgeMask; - for (size_t v = 0; v < 3; v++) + bool3_t newIntersectant = intersectant; + for (size_t v = 0; v < 3; v++) { - if (edgeMask[v]) + if (intersectant[v]) { - if (edgesRowAccept[v] > 0 || (edgesRowAccept[v] == 0 && param.tlBorder[v])) + if (subTileAcceptEdges[v] > 0 || (subTileAcceptEdges[v] == 0 && param.tlBorder[v])) { - newTestEdgeMask &= ~(1 << v); + newIntersectant[v] = false; } } } - - _drawTriangle_Coarse(tile_id, y_index * 4 + x_index, param, edges, newTestEdgeMask, callback); + _drawTriangle_Tile(param, subTileSize, xPos, yPos, subTileLBEdges, newIntersectant, callback); } } - edges.sub(blockEdgesDY); + xPos += subTileSize; + subTileLBEdges.sub(subTileEdgesDY); - for (size_t v = 0; v < 3; v++) + for (size_t v = 0; v < 3; v++) { - if (edgeMask[v]) + if (intersectant[v]) { - edgesRowReject[v] -= blockEdgesDY[v]; - edgesRowAccept[v] -= blockEdgesDY[v]; + subTileRjectEdges[v] -= subTileEdgesDY[v]; + subTileAcceptEdges[v] -= subTileEdgesDY[v]; } } } } - - blockEdges.add(blockEdgesDX); - for (size_t v = 0; v < 3; v++) + + yPos += subTileSize; + rowLBEdges.add(subTileEdgesDX); + for (size_t v = 0; v < 3; v++) { - if (edgeMask[v]) + if (intersectant[v]) { - blockReject[v] += blockEdgesDX[v]; - blockAccept[v] += blockEdgesDX[v]; + rowRejectEdges[v] += subTileEdgesDX[v]; + rowAcceptEdges[v] += subTileEdgesDX[v]; } } } } -//------------------------------------------------------------------------------------- void Rasterizer::drawTriangleLarrabee(int32_t canvasWidth, int32_t canvasHeight, const fVector2& v0, const fVector2& v1, const fVector2& v2, DrawTriangleCallback callback, bool ccw, const DebugParam* debugParam) { - assert(canvasWidth >= TILE_WIDTH_IN_PIXELS && canvasHeight >= TILE_WIDTH_IN_PIXELS); - assert(canvasWidth%TILE_WIDTH_IN_PIXELS == 0 && canvasHeight%TILE_WIDTH_IN_PIXELS == 0); + assert(canvasWidth >= MIN_TILE_WIDTH_IN_PIXELS && canvasHeight >= MIN_TILE_WIDTH_IN_PIXELS); + assert(canvasWidth% MIN_TILE_WIDTH_IN_PIXELS == 0 && canvasHeight% MIN_TILE_WIDTH_IN_PIXELS == 0); + + if (canvasWidth < MIN_TILE_WIDTH_IN_PIXELS || canvasHeight < MIN_TILE_WIDTH_IN_PIXELS) + { + return; //canvas too small + } + + if (canvasWidth % MIN_TILE_WIDTH_IN_PIXELS != 0 && canvasHeight % MIN_TILE_WIDTH_IN_PIXELS != 0) + { + return; + } + + //The minimum size of the tile is 64 pixels, + int32_t tileSize = MIN_TILE_WIDTH_IN_PIXELS; + while(canvasWidth >= tileSize && canvasHeight >= tileSize && + canvasWidth% tileSize ==0 && canvasHeight% tileSize ==0) + { + tileSize *= 4; + } + tileSize /= 4; DrawTriangleParam param; - param.widthInTiles = canvasWidth / TILE_WIDTH_IN_PIXELS; + int32_t widthInTiles = canvasWidth / tileSize; //Whether the three input vertices are in the agreed clockwise order or not, // it indicates that the triangle is invisible @@ -354,12 +240,6 @@ void Rasterizer::drawTriangleLarrabee(int32_t canvasWidth, int32_t canvasHeight, param.verts[2] = ccw ? v2 : v1; param.area = (param.verts[1] - param.verts[0]).crossProduct(param.verts[2] - param.verts[1]); - iFloat2 vertices[3]; - for (size_t i = 0; i < 3; i++) - { - vertices[i] = iFloat2(param.verts[i].x, param.verts[i].y); - } - //get window coordinates bounding box param.bbox_min_x = MathUtil::min3(v0.x, v1.x, v2.x); param.bbox_max_x = MathUtil::max3(v0.x, v1.x, v2.x); @@ -381,30 +261,37 @@ void Rasterizer::drawTriangleLarrabee(int32_t canvasWidth, int32_t canvasHeight, if (param.bbox_max_y > canvasHeight - 1.f) param.bbox_max_y = canvasHeight - 1.f; // tile range - int32_t first_tile_x = (int32_t)(param.bbox_min_x / TILE_WIDTH_IN_PIXELS); - int32_t first_tile_y = (int32_t)(param.bbox_min_y / TILE_WIDTH_IN_PIXELS); - int32_t last_tile_x = (int32_t)(param.bbox_max_x / TILE_WIDTH_IN_PIXELS); - int32_t last_tile_y = (int32_t)(param.bbox_max_y / TILE_WIDTH_IN_PIXELS); + int32_t first_tile_x = (int32_t)(param.bbox_min_x / tileSize); + int32_t first_tile_y = (int32_t)(param.bbox_min_y / tileSize); + int32_t last_tile_x = (int32_t)(param.bbox_max_x / tileSize); + int32_t last_tile_y = (int32_t)(param.bbox_max_y / tileSize); - //The first Title is the Title at the lower left corner within the bounding box range covered by the triangle - iFloat firstTileX = iFloat(first_tile_x * TILE_WIDTH_IN_PIXELS); - iFloat firstTileY = iFloat(first_tile_y * TILE_WIDTH_IN_PIXELS); + //The first tile is the tile at the lower left corner within the bounding box range covered by the triangle + iFloat firstTileX = iFloat(first_tile_x * tileSize); + iFloat firstTileY = iFloat(first_tile_y * tileSize); - iFloat3 edgesLB; //The edge value at the lower left corner of the first title + iFloat3 edgesFirstLB; //The edge value at the lower left corner of the first tile iFloat3 tileEdgesDX, tileEdgesDY; iFloat3 edgesReject, edgesAccept; + iFloat2 vertices[3]; + for (size_t i = 0; i < 3; i++) + { + vertices[i] = iFloat2(param.verts[i].x, param.verts[i].y); + } + for (size_t v = 0; v < 3; v++) { size_t v_end = (v + 1) % 3; param.edgesDX[v] = vertices[v_end].x - vertices[v].x; param.edgesDY[v] = vertices[v_end].y - vertices[v].y; + param.halfEdge[v] = (param.edgesDX[v]- param.edgesDY[v]) * iFloat::kHalf; - tileEdgesDX[v] = param.edgesDX[v] * TILE_WIDTH_IN_PIXELS; - tileEdgesDY[v] = param.edgesDY[v] * TILE_WIDTH_IN_PIXELS; + tileEdgesDX[v] = param.edgesDX[v] * tileSize; + tileEdgesDY[v] = param.edgesDY[v] * tileSize; //(V0,V1) X (V0, P) = (x1-x0)(py-y0)-(y1-y0)(px-x0) - edgesLB[v] = param.edgesDX[v] * (firstTileY - vertices[v].y) + edgesFirstLB[v] = param.edgesDX[v] * (firstTileY - vertices[v].y) - param.edgesDY[v] * (firstTileX - vertices[v].x); // Top-left rule: @@ -420,7 +307,7 @@ void Rasterizer::drawTriangleLarrabee(int32_t canvasWidth, int32_t canvasHeight, param.tlBorder[v] = false; } - edgesReject[v] = edgesAccept[v] = edgesLB[v]; + edgesReject[v] = edgesAccept[v] = edgesFirstLB[v]; if (tileEdgesDX[v] > 0) edgesReject[v] += tileEdgesDX[v]; else if (tileEdgesDX[v] < 0) edgesAccept[v] += tileEdgesDX[v]; @@ -444,12 +331,12 @@ void Rasterizer::drawTriangleLarrabee(int32_t canvasWidth, int32_t canvasHeight, fprintf(param.debugParam.fpOutput, "v%d=(%f,%f)[%lld,%lld]\n", i, param.verts[i].x, param.verts[i].y, vertices[i].x.s3132, vertices[i].y.s3132); } - fprintf(param.debugParam.fpOutput, "===== TitleRange ====\n"); + fprintf(param.debugParam.fpOutput, "===== TileRange ====\n"); fprintf(param.debugParam.fpOutput, "tile_x={%d, %d}\ntile_y={%d, %d}\n", first_tile_x, last_tile_x, first_tile_y, last_tile_y); fprintf(param.debugParam.fpOutput, - "FirstTitle=(%f,%f)[%lld,%lld]\n", firstTileX.to_float(), firstTileY.to_float(), + "FirstTile=(%f,%f)[%lld,%lld]\n", firstTileX.to_float(), firstTileY.to_float(), firstTileX.s3132, firstTileY.s3132 ); @@ -468,9 +355,9 @@ void Rasterizer::drawTriangleLarrabee(int32_t canvasWidth, int32_t canvasHeight, param.edgesDX[i].to_float(), vertices[i].y.to_float(), param.edgesDY[i].to_float(), vertices[i].x.to_float() ); } - fprintf(param.debugParam.fpOutput, "EdgeLB=(%f,%f,%f)[%lld,%lld,%lld]\n", - edgesLB.x.to_float(), edgesLB.y.to_float(), edgesLB.z.to_float(), - edgesLB.x.s3132, edgesLB.y.s3132, edgesLB.z.s3132 + fprintf(param.debugParam.fpOutput, "EdgeFirstLB=(%f,%f,%f)[%lld,%lld,%lld]\n", + edgesFirstLB.x.to_float(), edgesFirstLB.y.to_float(), edgesFirstLB.z.to_float(), + edgesFirstLB.x.s3132, edgesFirstLB.y.s3132, edgesFirstLB.z.s3132 ); for (int32_t i = 0; i < 3; i++) { @@ -486,20 +373,24 @@ void Rasterizer::drawTriangleLarrabee(int32_t canvasWidth, int32_t canvasHeight, } } - iFloat3 rowEdges(edgesLB); + iFloat3 rowEdges(edgesFirstLB); + + int32_t tile_row_start = first_tile_y * tileSize + first_tile_x; + int32_t yLB = first_tile_y * tileSize; - int32_t tile_row_start = first_tile_y * param.widthInTiles + first_tile_x; for (int32_t tile_y = first_tile_y; tile_y <= last_tile_y; tile_y++) { - iFloat3 edges(rowEdges); + iFloat3 edgesTileLB(rowEdges); iFloat3 tileEdgesReject(edgesReject); iFloat3 tileEdgesAccept(edgesAccept); int32_t tile_i = tile_row_start; + int32_t xLB = first_tile_x * tileSize; + for (int32_t tile_x = first_tile_x; tile_x <= last_tile_x; tile_x++) { - //If the title is excluded by any edge, - // it indicates that the title is completely outside the triangle and does not require rendering + //If the tile is excluded by any edge, + // it indicates that the tile is completely outside the triangle and does not require rendering bool rejected = ((tileEdgesReject[0] < 0 || (!param.tlBorder[0] && tileEdgesReject[0] == 0))) || ((tileEdgesReject[1] < 0 || (!param.tlBorder[1] && tileEdgesReject[1] == 0))) || @@ -507,33 +398,32 @@ void Rasterizer::drawTriangleLarrabee(int32_t canvasWidth, int32_t canvasHeight, if (!rejected) { - //draw title - uint32_t testEdgeMask = 0; + //draw tile + bool3_t intersectant; for (size_t v = 0; v < 3; v++) { - if (tileEdgesAccept[v] < 0 || (tileEdgesAccept[v] == 0 && !param.tlBorder[v])) - { - //whether the accepting vertex of this title is on the "outside" of the three edges, - // that is, it may intersect or be completely outside - testEdgeMask += (1 << v); - } + //whether the accepting vertex of this tile is on the "outside" of the three edges, + // that is, it may intersect or be completely outside + intersectant[v] = (tileEdgesAccept[v] < 0 || (tileEdgesAccept[v] == 0 && !param.tlBorder[v])); } - _drawTriangle_Title(tile_i, param, edges, testEdgeMask, callback); + _drawTriangle_Tile(param, tileSize, xLB, yLB, edgesTileLB, intersectant, callback); } //x setp - edges.sub(tileEdgesDY); + edgesTileLB.sub(tileEdgesDY); tileEdgesReject.sub(tileEdgesDY); tileEdgesAccept.sub(tileEdgesDY); tile_i++; + xLB += tileSize; } //y step rowEdges.add(tileEdgesDX); edgesReject.add(tileEdgesDX); edgesAccept.add(tileEdgesDX); - tile_row_start += param.widthInTiles; + tile_row_start += widthInTiles; + yLB += tileSize; } if (debugParam != nullptr && debugParam->debug) @@ -544,7 +434,7 @@ void Rasterizer::drawTriangleLarrabee(int32_t canvasWidth, int32_t canvasHeight, } //------------------------------------------------------------------------------------- -void Rasterizer::drawTriangleScanline(int32_t canvasWidth, int32_t canvasHeight, +void Rasterizer::drawTriangleBoundingBox(int32_t canvasWidth, int32_t canvasHeight, const fVector2& _v0, const fVector2& _v1, const fVector2& _v2, DrawTriangleCallback callback, bool ccw) {