增加扫描线光栅算法
This commit is contained in:
@@ -415,6 +415,7 @@ struct iFloat2
|
|||||||
iFloat2() : x(0), y(0) {}
|
iFloat2() : x(0), y(0) {}
|
||||||
iFloat2(const iFloat2& other) : x(other.x), y(other.y) {}
|
iFloat2(const iFloat2& other) : x(other.x), y(other.y) {}
|
||||||
iFloat2(float32_t _x, float32_t _y) : x(_x), y(_y) {}
|
iFloat2(float32_t _x, float32_t _y) : x(_x), y(_y) {}
|
||||||
|
iFloat2(iFloat _x, iFloat _y) : x(_x), y(_y) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct iFloat3
|
struct iFloat3
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ public:
|
|||||||
|
|
||||||
//Scaleline algorithm
|
//Scaleline algorithm
|
||||||
static void drawTriangleScanline(int32_t canvasWidth, int32_t canvasHeight,
|
static void drawTriangleScanline(int32_t canvasWidth, int32_t canvasHeight,
|
||||||
const fVector3& v0, const fVector3& v1, const fVector3& v2,
|
const fVector2& v0, const fVector2& v1, const fVector2& v2,
|
||||||
DrawTriangleCallback callback);
|
DrawTriangleCallback callback, bool ccw = true);
|
||||||
};
|
};
|
||||||
|
|
||||||
DV_CORE_END_NAMESPACE
|
DV_CORE_END_NAMESPACE
|
||||||
|
|||||||
@@ -544,58 +544,80 @@ void Rasterizer::drawTriangleLarrabee(int32_t canvasWidth, int32_t canvasHeight,
|
|||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
void Rasterizer::drawTriangleScanline(int32_t canvasWidth, int32_t canvasHeight, const fVector3& v0, const fVector3& v1, const fVector3& v2, DrawTriangleCallback callback)
|
void Rasterizer::drawTriangleScanline(int32_t canvasWidth, int32_t canvasHeight,
|
||||||
|
const fVector2& _v0, const fVector2& _v1, const fVector2& _v2,
|
||||||
|
DrawTriangleCallback callback, bool ccw)
|
||||||
{
|
{
|
||||||
#if 0
|
//Whether the three input vertices are in the agreed clockwise order or not,
|
||||||
//back cull
|
// it indicates that the triangle is invisible
|
||||||
fVector3 edge0 = v2 - v1;
|
bool isCCW = (_v1 - _v0).crossProduct(_v2 - _v1) > 0;
|
||||||
fVector3 edge1 = v0 - v2;
|
if (isCCW != ccw) return;
|
||||||
fVector3 vnormal = edge0.crossProduct(edge1);
|
|
||||||
if (vnormal.z > 0) return;
|
|
||||||
|
|
||||||
fVector3 edge2 = v1 - v0;
|
fVector2 v[3];
|
||||||
|
v[0] = _v0;
|
||||||
|
v[1] = ccw ? _v1 : _v2;
|
||||||
|
v[2] = ccw ? _v2 : _v1;
|
||||||
|
|
||||||
float xmin = MathUtil::min3(v0.x, v1.x, v2.x);
|
float32_t xmin = MathUtil::min3(v[0].x, v[1].x, v[2].x);
|
||||||
float ymin = MathUtil::min3(v0.y, v1.y, v2.y);
|
float32_t ymin = MathUtil::min3(v[0].y, v[1].y, v[2].y);
|
||||||
float xmax = MathUtil::max3(v0.x, v1.x, v2.x);
|
float32_t xmax = MathUtil::max3(v[0].x, v[1].x, v[2].x);
|
||||||
float ymax = MathUtil::max3(v0.y, v1.y, v2.y);
|
float32_t ymax = MathUtil::max3(v[0].y, v[1].y, v[2].y);
|
||||||
|
|
||||||
float area = _edge(v0, v1, v2);
|
|
||||||
|
|
||||||
int32_t x0 = MathUtil::max2(0, (int32_t)std::floor(xmin));
|
int32_t x0 = MathUtil::max2(0, (int32_t)std::floor(xmin));
|
||||||
int32_t x1 = MathUtil::min2(canvasWidth - 1, (int32_t)std::floor(xmax));
|
int32_t x1 = MathUtil::min2(canvasWidth - 1, (int32_t)std::floor(xmax));
|
||||||
int32_t y0 = MathUtil::max2(0, (int32_t)std::floor(ymin));
|
int32_t y0 = MathUtil::max2(0, (int32_t)std::floor(ymin));
|
||||||
int32_t y1 = MathUtil::min2(canvasHeight - 1, (int32_t)std::floor(ymax));
|
int32_t y1 = MathUtil::min2(canvasHeight - 1, (int32_t)std::floor(ymax));
|
||||||
|
|
||||||
|
float32_t area = (v[1] - v[0]).crossProduct(v[2] - v[1]);
|
||||||
|
|
||||||
|
//edge function
|
||||||
|
// e(x,y)=(x1-x0)(y-y0)-(y1-y0))(x-x0)=ax+by+c
|
||||||
|
// a=y0-y1, b=x1-x0, c=(y1-y0)x0-(x1-x0)y0
|
||||||
|
|
||||||
|
iFloat edge_a[3], edge_b[3], edge_c[3];
|
||||||
|
bool edge_tl[3]; //is top-left edge?
|
||||||
|
|
||||||
|
for (int32_t i = 0; i < 3; i++) {
|
||||||
|
int32_t next = (i + 1) % 3;
|
||||||
|
iFloat2 v0 = iFloat2(v[i].x, v[i].y);
|
||||||
|
iFloat2 v1 = iFloat2(v[next].x, v[next].y);
|
||||||
|
|
||||||
|
edge_a[i] = v0.y - v1.y;
|
||||||
|
edge_b[i] = v1.x - v0.x;
|
||||||
|
edge_c[i] = (v1.y - v0.y) * v0.x - (v1.x - v0.x) * v0.y;
|
||||||
|
edge_tl[i] = (edge_a[i] != 0) ? (edge_a[i] > 0) : (edge_b[i] < 0);
|
||||||
|
}
|
||||||
|
|
||||||
for (int32_t y = y0; y <= y1; y++) {
|
for (int32_t y = y0; y <= y1; y++) {
|
||||||
for (int32_t x = x0; x <= x1; x++) {
|
for (int32_t x = x0; x <= x1; x++) {
|
||||||
|
|
||||||
fVector3 pixel(x + 0.5f, y + 0.5f, 0.f);
|
iFloat2 iPixel(iFloat(x) + iFloat::kHalf, iFloat(y) + iFloat::kHalf);
|
||||||
|
|
||||||
bool overlaps = true;
|
bool outsideTriangle = false;
|
||||||
|
for (int32_t i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
iFloat edge = edge_a[i] * iPixel.x + edge_b[i] * iPixel.y + edge_c[i];
|
||||||
|
bool insideEdge = edge.s3132 > 0 || (edge.s3132 == 0 && edge_tl[i]);
|
||||||
|
|
||||||
float w0 = _edge(v1, v2, pixel);
|
if (!insideEdge) {
|
||||||
overlaps &= (w0 == 0 ? ((edge0.y == 0 && edge0.x > 0) || edge0.y > 0) : (w0 > 0));
|
outsideTriangle = true;
|
||||||
if (!overlaps) continue;
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (outsideTriangle) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
float w1 = _edge(v2, v0, pixel);
|
fVector2 pixel(x + 0.5f, y + 0.5f);
|
||||||
overlaps &= (w1 == 0 ? ((edge1.y == 0 && edge1.x > 0) || edge1.y > 0) : (w1 > 0));
|
float32_t w0 = (v[2] - v[1]).crossProduct(pixel - v[2]);
|
||||||
if (!overlaps) continue;
|
float32_t w1 = (v[0] - v[2]).crossProduct(pixel - v[0]);
|
||||||
|
float32_t w2 = (v[1] - v[0]).crossProduct(pixel - v[1]);
|
||||||
|
|
||||||
float w2 = _edge(v0, v1, pixel);
|
fVector3 t = fVector3(w0 / area, (ccw ? w1 : w2) / area, (ccw ? w2 : w1) / area);
|
||||||
overlaps &= (w2 == 0 ? ((edge2.y == 0 && edge2.x > 0) || edge2.y > 0) : (w2 > 0));
|
|
||||||
if (!overlaps) continue;
|
|
||||||
|
|
||||||
|
|
||||||
fVector3 t = fVector3(w0 / area, w1 / area, w2 / area);
|
|
||||||
|
|
||||||
float invZ = MathUtil::lerp3(v0.z, v1.z, v2.z, t);
|
|
||||||
t *= fVector3(v0.z / invZ, v1.z / invZ, v2.z / invZ);
|
|
||||||
|
|
||||||
callback(std::make_pair(x, y), t);
|
callback(std::make_pair(x, y), t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DV_CORE_END_NAMESPACE
|
DV_CORE_END_NAMESPACE
|
||||||
|
|||||||
Reference in New Issue
Block a user