修改光栅化代码,使用同一套tile绘制机制
This commit is contained in:
@@ -8,16 +8,7 @@ DV_CORE_BEGIN_NAMESPACE
|
|||||||
|
|
||||||
class DV_CORE_API Rasterizer
|
class DV_CORE_API Rasterizer
|
||||||
{
|
{
|
||||||
//Draw Line
|
//Draw Triangle with Larrabee
|
||||||
public:
|
|
||||||
typedef std::function<void(const std::pair<int32_t, int32_t>&, 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
|
|
||||||
public:
|
public:
|
||||||
typedef std::function<void(const std::pair<int32_t, int32_t>& pos, const fVector3& percent)> DrawTriangleCallback;
|
typedef std::function<void(const std::pair<int32_t, int32_t>& pos, const fVector3& percent)> DrawTriangleCallback;
|
||||||
|
|
||||||
@@ -40,8 +31,9 @@ public:
|
|||||||
const fVector2& v0, const fVector2& v1, const fVector2& v2,
|
const fVector2& v0, const fVector2& v1, const fVector2& v2,
|
||||||
DrawTriangleCallback callback, bool ccw=true, const DebugParam* debugParam=nullptr);
|
DrawTriangleCallback callback, bool ccw=true, const DebugParam* debugParam=nullptr);
|
||||||
|
|
||||||
//Scaleline algorithm
|
public:
|
||||||
static void drawTriangleScanline(int32_t canvasWidth, int32_t canvasHeight,
|
//BoundingBox algorithm
|
||||||
|
static void drawTriangleBoundingBox(int32_t canvasWidth, int32_t canvasHeight,
|
||||||
const fVector2& v0, const fVector2& v1, const fVector2& v2,
|
const fVector2& v0, const fVector2& v1, const fVector2& v2,
|
||||||
DrawTriangleCallback callback, bool ccw = true);
|
DrawTriangleCallback callback, bool ccw = true);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
#include "math/dvc_fix_point.h"
|
#include "math/dvc_fix_point.h"
|
||||||
#include "math/dvc_math_util.h"
|
#include "math/dvc_math_util.h"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
https://github.com/nlguillemot/vigilant-system
|
https://github.com/nlguillemot/vigilant-system
|
||||||
https://wiki.joak.org/public:cs:rasterization_on_larrabee
|
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
|
DV_CORE_BEGIN_NAMESPACE
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
using bool3_t = std::array<bool, 3>;
|
||||||
|
|
||||||
|
inline bool operator==(const bool3_t& arr, bool value)
|
||||||
|
{
|
||||||
|
return arr[0] == value && arr[1] == value && arr[2] == value;
|
||||||
|
}
|
||||||
|
|
||||||
struct DrawTriangleParam
|
struct DrawTriangleParam
|
||||||
{
|
{
|
||||||
int32_t widthInTiles;
|
|
||||||
bool ccw;
|
bool ccw;
|
||||||
fVector2 verts[3];
|
fVector2 verts[3];
|
||||||
float32_t bbox_min_x;
|
float32_t bbox_min_x;
|
||||||
float32_t bbox_max_x;
|
float32_t bbox_max_x;
|
||||||
float32_t bbox_min_y;
|
float32_t bbox_min_y;
|
||||||
float32_t bbox_max_y;
|
float32_t bbox_max_y;
|
||||||
bool tlBorder[3];
|
bool3_t tlBorder;
|
||||||
float32_t area;
|
float32_t area;
|
||||||
iFloat3 edgesDX, edgesDY;
|
iFloat3 edgesDX, edgesDY;
|
||||||
|
iFloat3 halfEdge;
|
||||||
Rasterizer::DebugParam debugParam;
|
Rasterizer::DebugParam debugParam;
|
||||||
};
|
};
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
enum { MIN_TILE_WIDTH_IN_PIXELS = 64 };
|
||||||
enum { TILE_WIDTH_IN_PIXELS = 64, COARSE_BLOCK_WIDTH_IN_PIXELS = 16, FINE_BLOCK_WIDTH_IN_PIXELS = 4 };
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
void _fillPixel(const DrawTriangleParam& param, int32_t xLB, int32_t yLB, Rasterizer::DrawTriangleCallback callback)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
iFloat3 kHalfDX = param.edgesDX; kHalfDX.mul(iFloat::kHalf);
|
fVector2 pixel(xLB + 0.5f, yLB + 0.5f);
|
||||||
iFloat3 kHalfDY = param.edgesDY; kHalfDY.mul(iFloat::kHalf);
|
|
||||||
|
|
||||||
iFloat3 pixelEdges(edges0);
|
|
||||||
pixelEdges.sub(kHalfDY);
|
|
||||||
pixelEdges.add(kHalfDX);
|
|
||||||
|
|
||||||
const fVector2 v0(param.verts[0]), v1(param.verts[1]), v2(param.verts[2]);
|
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
|
float32_t w0 = (v2 - v1).crossProduct(pixel - v2);
|
||||||
+ (coarse_id % 4) * COARSE_BLOCK_WIDTH_IN_PIXELS + (fine_id % 4) * FINE_BLOCK_WIDTH_IN_PIXELS;
|
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
|
fVector3 t = fVector3(w0 / param.area, (param.ccw ? w1 : w2) / param.area, (param.ccw ? w2 : w1) / param.area);
|
||||||
+ (coarse_id / 4) * COARSE_BLOCK_WIDTH_IN_PIXELS + (fine_id / 4)*FINE_BLOCK_WIDTH_IN_PIXELS;
|
|
||||||
|
|
||||||
for (int32_t y_index=0, y= fine_start_y; y_index < 4; y_index++, y++)
|
callback(std::make_pair(xLB, yLB), t);
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
void _fillTile(const DrawTriangleParam& param, int32_t currentTileSize,
|
||||||
void _drawTriangle_Coarse(int32_t tile_id, int32_t coarse_id,
|
int32_t xLB, int32_t yLB, Rasterizer::DrawTriangleCallback callback)
|
||||||
DrawTriangleParam& param, const iFloat3& edges0, uint32_t testEdgeMask,
|
|
||||||
Rasterizer::DrawTriangleCallback callback)
|
|
||||||
{
|
{
|
||||||
const iFloat3 blockEdgesDX(
|
if (currentTileSize == 1)
|
||||||
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 (edgeMask[v])
|
_fillPixel(param, xLB, yLB, callback);
|
||||||
{
|
return;
|
||||||
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];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t block_start_x = (tile_id % param.widthInTiles) * TILE_WIDTH_IN_PIXELS + (coarse_id % 4) * COARSE_BLOCK_WIDTH_IN_PIXELS;
|
for (int32_t yIndex = yLB; yIndex < yLB + currentTileSize; yIndex++)
|
||||||
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++)
|
|
||||||
{
|
{
|
||||||
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;
|
_fillPixel(param, xIndex, yIndex, callback);
|
||||||
}
|
|
||||||
|
|
||||||
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];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
void _drawPixel(DrawTriangleParam& param,
|
||||||
void _drawTriangle_Title(int32_t tile_id,
|
int32_t xLB, int32_t yLB, const iFloat3& edgesLB, const bool3_t& intersectant,
|
||||||
DrawTriangleParam& param, const iFloat3& edges0, uint32_t testEdgeMask,
|
|
||||||
Rasterizer::DrawTriangleCallback callback)
|
Rasterizer::DrawTriangleCallback callback)
|
||||||
{
|
{
|
||||||
const iFloat3 blockEdgesDX(
|
iFloat3 centerEdges(edgesLB);
|
||||||
param.edgesDX[0] * COARSE_BLOCK_WIDTH_IN_PIXELS,
|
centerEdges.add(param.halfEdge);
|
||||||
param.edgesDX[1] * COARSE_BLOCK_WIDTH_IN_PIXELS,
|
|
||||||
param.edgesDX[2] * COARSE_BLOCK_WIDTH_IN_PIXELS
|
|
||||||
);
|
|
||||||
|
|
||||||
const iFloat3 blockEdgesDY(
|
bool insideTriangle =
|
||||||
param.edgesDY[0] * COARSE_BLOCK_WIDTH_IN_PIXELS,
|
(centerEdges.x > 0 || (param.tlBorder[0] && centerEdges.x == 0)) &&
|
||||||
param.edgesDY[1] * COARSE_BLOCK_WIDTH_IN_PIXELS,
|
(centerEdges.y > 0 || (param.tlBorder[1] && centerEdges.y == 0)) &&
|
||||||
param.edgesDY[2] * COARSE_BLOCK_WIDTH_IN_PIXELS
|
(centerEdges.z > 0 || (param.tlBorder[2] && centerEdges.z == 0));
|
||||||
);
|
|
||||||
const bool edgeMask[3] = { (testEdgeMask & 1) != 0 , (testEdgeMask & 2) != 0 , (testEdgeMask & 4) != 0 };
|
|
||||||
|
|
||||||
iFloat3 blockReject(edges0);
|
if (insideTriangle)
|
||||||
iFloat3 blockAccept(edges0);
|
|
||||||
iFloat3 blockEdges(edges0);
|
|
||||||
|
|
||||||
for (size_t v = 0; v < 3; v++)
|
|
||||||
{
|
{
|
||||||
if (edgeMask[v])
|
_fillPixel(param, xLB, yLB, callback);
|
||||||
{
|
}
|
||||||
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];
|
void _drawTriangle_Tile(DrawTriangleParam& param, int32_t currentTileSize,
|
||||||
else if (blockEdgesDY[v] < 0) blockReject[v] -= blockEdgesDY[v];
|
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 yPos = yLB;
|
||||||
int32_t block_start_y = (tile_id / param.widthInTiles) * TILE_WIDTH_IN_PIXELS;
|
for (int32_t yIndex = 0; yIndex < 4; yIndex++)
|
||||||
|
|
||||||
for (int32_t y_index = 0; y_index < 4; y_index++)
|
|
||||||
{
|
{
|
||||||
if (block_start_y + y_index * COARSE_BLOCK_WIDTH_IN_PIXELS > param.bbox_max_y)
|
if (yPos > param.bbox_max_y)
|
||||||
{
|
{
|
||||||
break;
|
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 subTileLBEdges(rowLBEdges);
|
||||||
iFloat3 edgesRowReject, edgesRowAccept;
|
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])
|
if (xPos > param.bbox_max_x)
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
break;
|
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 =
|
bool rejected =
|
||||||
(edgeMask[0] && (edgesRowReject[0] < 0 || (!param.tlBorder[0] && edgesRowReject[0] == 0))) ||
|
(intersectant[0] && (subTileRjectEdges[0] < 0 || (!param.tlBorder[0] && subTileRjectEdges[0] == 0))) ||
|
||||||
(edgeMask[1] && (edgesRowReject[1] < 0 || (!param.tlBorder[1] && edgesRowReject[1] == 0))) ||
|
(intersectant[1] && (subTileRjectEdges[1] < 0 || (!param.tlBorder[1] && subTileRjectEdges[1] == 0))) ||
|
||||||
(edgeMask[2] && (edgesRowReject[2] < 0 || (!param.tlBorder[2] && edgesRowReject[2] == 0)));
|
(intersectant[2] && (subTileRjectEdges[2] < 0 || (!param.tlBorder[2] && subTileRjectEdges[2] == 0)));
|
||||||
|
|
||||||
if (!rejected)
|
if (!rejected)
|
||||||
{
|
{
|
||||||
uint32_t newTestEdgeMask = testEdgeMask;
|
bool3_t newIntersectant = intersectant;
|
||||||
for (size_t v = 0; v < 3; v++)
|
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_Tile(param, subTileSize, xPos, yPos, subTileLBEdges, newIntersectant, callback);
|
||||||
_drawTriangle_Coarse(tile_id, y_index * 4 + x_index, param, edges, newTestEdgeMask, 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];
|
subTileRjectEdges[v] -= subTileEdgesDY[v];
|
||||||
edgesRowAccept[v] -= blockEdgesDY[v];
|
subTileAcceptEdges[v] -= subTileEdgesDY[v];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
blockEdges.add(blockEdgesDX);
|
yPos += subTileSize;
|
||||||
for (size_t v = 0; v < 3; v++)
|
rowLBEdges.add(subTileEdgesDX);
|
||||||
|
for (size_t v = 0; v < 3; v++)
|
||||||
{
|
{
|
||||||
if (edgeMask[v])
|
if (intersectant[v])
|
||||||
{
|
{
|
||||||
blockReject[v] += blockEdgesDX[v];
|
rowRejectEdges[v] += subTileEdgesDX[v];
|
||||||
blockAccept[v] += blockEdgesDX[v];
|
rowAcceptEdges[v] += subTileEdgesDX[v];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
|
||||||
void Rasterizer::drawTriangleLarrabee(int32_t canvasWidth, int32_t canvasHeight,
|
void Rasterizer::drawTriangleLarrabee(int32_t canvasWidth, int32_t canvasHeight,
|
||||||
const fVector2& v0, const fVector2& v1, const fVector2& v2,
|
const fVector2& v0, const fVector2& v1, const fVector2& v2,
|
||||||
DrawTriangleCallback callback, bool ccw, const DebugParam* debugParam)
|
DrawTriangleCallback callback, bool ccw, const DebugParam* debugParam)
|
||||||
{
|
{
|
||||||
assert(canvasWidth >= TILE_WIDTH_IN_PIXELS && canvasHeight >= TILE_WIDTH_IN_PIXELS);
|
assert(canvasWidth >= MIN_TILE_WIDTH_IN_PIXELS && canvasHeight >= MIN_TILE_WIDTH_IN_PIXELS);
|
||||||
assert(canvasWidth%TILE_WIDTH_IN_PIXELS == 0 && canvasHeight%TILE_WIDTH_IN_PIXELS == 0);
|
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;
|
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,
|
//Whether the three input vertices are in the agreed clockwise order or not,
|
||||||
// it indicates that the triangle is invisible
|
// 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.verts[2] = ccw ? v2 : v1;
|
||||||
param.area = (param.verts[1] - param.verts[0]).crossProduct(param.verts[2] - param.verts[1]);
|
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
|
//get window coordinates bounding box
|
||||||
param.bbox_min_x = MathUtil::min3(v0.x, v1.x, v2.x);
|
param.bbox_min_x = MathUtil::min3(v0.x, v1.x, v2.x);
|
||||||
param.bbox_max_x = MathUtil::max3(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;
|
if (param.bbox_max_y > canvasHeight - 1.f) param.bbox_max_y = canvasHeight - 1.f;
|
||||||
|
|
||||||
// tile range
|
// tile range
|
||||||
int32_t first_tile_x = (int32_t)(param.bbox_min_x / 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 / TILE_WIDTH_IN_PIXELS);
|
int32_t first_tile_y = (int32_t)(param.bbox_min_y / tileSize);
|
||||||
int32_t last_tile_x = (int32_t)(param.bbox_max_x / TILE_WIDTH_IN_PIXELS);
|
int32_t last_tile_x = (int32_t)(param.bbox_max_x / tileSize);
|
||||||
int32_t last_tile_y = (int32_t)(param.bbox_max_y / TILE_WIDTH_IN_PIXELS);
|
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
|
//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 * TILE_WIDTH_IN_PIXELS);
|
iFloat firstTileX = iFloat(first_tile_x * tileSize);
|
||||||
iFloat firstTileY = iFloat(first_tile_y * TILE_WIDTH_IN_PIXELS);
|
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 tileEdgesDX, tileEdgesDY;
|
||||||
iFloat3 edgesReject, edgesAccept;
|
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++)
|
for (size_t v = 0; v < 3; v++)
|
||||||
{
|
{
|
||||||
size_t v_end = (v + 1) % 3;
|
size_t v_end = (v + 1) % 3;
|
||||||
param.edgesDX[v] = vertices[v_end].x - vertices[v].x;
|
param.edgesDX[v] = vertices[v_end].x - vertices[v].x;
|
||||||
param.edgesDY[v] = vertices[v_end].y - vertices[v].y;
|
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;
|
tileEdgesDX[v] = param.edgesDX[v] * tileSize;
|
||||||
tileEdgesDY[v] = param.edgesDY[v] * TILE_WIDTH_IN_PIXELS;
|
tileEdgesDY[v] = param.edgesDY[v] * tileSize;
|
||||||
|
|
||||||
//(V0,V1) X (V0, P) = (x1-x0)(py-y0)-(y1-y0)(px-x0)
|
//(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);
|
- param.edgesDY[v] * (firstTileX - vertices[v].x);
|
||||||
|
|
||||||
// Top-left rule:
|
// Top-left rule:
|
||||||
@@ -420,7 +307,7 @@ void Rasterizer::drawTriangleLarrabee(int32_t canvasWidth, int32_t canvasHeight,
|
|||||||
param.tlBorder[v] = false;
|
param.tlBorder[v] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
edgesReject[v] = edgesAccept[v] = edgesLB[v];
|
edgesReject[v] = edgesAccept[v] = edgesFirstLB[v];
|
||||||
|
|
||||||
if (tileEdgesDX[v] > 0) edgesReject[v] += tileEdgesDX[v];
|
if (tileEdgesDX[v] > 0) edgesReject[v] += tileEdgesDX[v];
|
||||||
else if (tileEdgesDX[v] < 0) edgesAccept[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,
|
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);
|
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,
|
fprintf(param.debugParam.fpOutput,
|
||||||
"tile_x={%d, %d}\ntile_y={%d, %d}\n",
|
"tile_x={%d, %d}\ntile_y={%d, %d}\n",
|
||||||
first_tile_x, last_tile_x, first_tile_y, last_tile_y);
|
first_tile_x, last_tile_x, first_tile_y, last_tile_y);
|
||||||
fprintf(param.debugParam.fpOutput,
|
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
|
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()
|
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",
|
fprintf(param.debugParam.fpOutput, "EdgeFirstLB=(%f,%f,%f)[%lld,%lld,%lld]\n",
|
||||||
edgesLB.x.to_float(), edgesLB.y.to_float(), edgesLB.z.to_float(),
|
edgesFirstLB.x.to_float(), edgesFirstLB.y.to_float(), edgesFirstLB.z.to_float(),
|
||||||
edgesLB.x.s3132, edgesLB.y.s3132, edgesLB.z.s3132
|
edgesFirstLB.x.s3132, edgesFirstLB.y.s3132, edgesFirstLB.z.s3132
|
||||||
);
|
);
|
||||||
for (int32_t i = 0; i < 3; i++)
|
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++)
|
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 tileEdgesReject(edgesReject);
|
||||||
iFloat3 tileEdgesAccept(edgesAccept);
|
iFloat3 tileEdgesAccept(edgesAccept);
|
||||||
|
|
||||||
int32_t tile_i = tile_row_start;
|
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++)
|
for (int32_t tile_x = first_tile_x; tile_x <= last_tile_x; tile_x++)
|
||||||
{
|
{
|
||||||
//If the title is excluded by any edge,
|
//If the tile is excluded by any edge,
|
||||||
// it indicates that the title is completely outside the triangle and does not require rendering
|
// it indicates that the tile is completely outside the triangle and does not require rendering
|
||||||
bool rejected =
|
bool rejected =
|
||||||
((tileEdgesReject[0] < 0 || (!param.tlBorder[0] && tileEdgesReject[0] == 0))) ||
|
((tileEdgesReject[0] < 0 || (!param.tlBorder[0] && tileEdgesReject[0] == 0))) ||
|
||||||
((tileEdgesReject[1] < 0 || (!param.tlBorder[1] && tileEdgesReject[1] == 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)
|
if (!rejected)
|
||||||
{
|
{
|
||||||
//draw title
|
//draw tile
|
||||||
uint32_t testEdgeMask = 0;
|
bool3_t intersectant;
|
||||||
for (size_t v = 0; v < 3; v++)
|
for (size_t v = 0; v < 3; v++)
|
||||||
{
|
{
|
||||||
if (tileEdgesAccept[v] < 0 || (tileEdgesAccept[v] == 0 && !param.tlBorder[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
|
||||||
//whether the accepting vertex of this title is on the "outside" of the three edges,
|
intersectant[v] = (tileEdgesAccept[v] < 0 || (tileEdgesAccept[v] == 0 && !param.tlBorder[v]));
|
||||||
// that is, it may intersect or be completely outside
|
|
||||||
testEdgeMask += (1 << v);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_drawTriangle_Title(tile_i, param, edges, testEdgeMask, callback);
|
_drawTriangle_Tile(param, tileSize, xLB, yLB, edgesTileLB, intersectant, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
//x setp
|
//x setp
|
||||||
edges.sub(tileEdgesDY);
|
edgesTileLB.sub(tileEdgesDY);
|
||||||
tileEdgesReject.sub(tileEdgesDY);
|
tileEdgesReject.sub(tileEdgesDY);
|
||||||
tileEdgesAccept.sub(tileEdgesDY);
|
tileEdgesAccept.sub(tileEdgesDY);
|
||||||
tile_i++;
|
tile_i++;
|
||||||
|
xLB += tileSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
//y step
|
//y step
|
||||||
rowEdges.add(tileEdgesDX);
|
rowEdges.add(tileEdgesDX);
|
||||||
edgesReject.add(tileEdgesDX);
|
edgesReject.add(tileEdgesDX);
|
||||||
edgesAccept.add(tileEdgesDX);
|
edgesAccept.add(tileEdgesDX);
|
||||||
tile_row_start += param.widthInTiles;
|
tile_row_start += widthInTiles;
|
||||||
|
yLB += tileSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debugParam != nullptr && debugParam->debug)
|
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,
|
const fVector2& _v0, const fVector2& _v1, const fVector2& _v2,
|
||||||
DrawTriangleCallback callback, bool ccw)
|
DrawTriangleCallback callback, bool ccw)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user