@@ 43,34 43,33 @@ void DrawTriangle(int *polygon, Vertex *vertices, Color color, Viewport *viewpor
{
assert(NumPolygonVertices(polygon) == 3);
Rect bounding_box = PolygonBounds(polygon, vertices);
- EdgeTracker a = TrackEdge(PolygonVertex(polygon, vertices, 0), PolygonVertex(polygon, vertices, 1), V(bounding_box.left, bounding_box.bottom, 0));
- EdgeTracker b = TrackEdge(PolygonVertex(polygon, vertices, 1), PolygonVertex(polygon, vertices, 2), V(bounding_box.left, bounding_box.bottom, 0));
- EdgeTracker c = TrackEdge(PolygonVertex(polygon, vertices, 2), PolygonVertex(polygon, vertices, 0), V(bounding_box.left, bounding_box.bottom, 0));
+ Vertex *a = PolygonVertex(polygon, vertices, 0);
+ Vertex *b = PolygonVertex(polygon, vertices, 1);
+ Vertex *c = PolygonVertex(polygon, vertices, 2);
- for (int y = bounding_box.bottom; y < bounding_box.top; y += 2) {
+ EdgeTracker ab = TrackEdge(a, b, V(bounding_box.left, bounding_box.bottom, 0));
+ EdgeTracker bc = TrackEdge(b, c, V(bounding_box.left, bounding_box.bottom, 0));
+ EdgeTracker ca = TrackEdge(c, a, V(bounding_box.left, bounding_box.bottom, 0));
+ float area = TriArea(a, b, c);
+
+ for (int y = bounding_box.bottom; y < bounding_box.top; y++) {
for (int x = bounding_box.left; x <= bounding_box.right; x++) {
- if (a.value < 0 && b.value < 0 && c.value < 0) {
- // TryWritePixel(x, y, z, color, viewport);
- WritePixel(x, y, color, viewport);
- }
- a.value += a.dy;
- b.value += b.dy;
- c.value += c.dy;
- }
- a.value -= a.dx;
- b.value -= b.dx;
- c.value -= c.dx;
- for (int x = bounding_box.right; x >= bounding_box.left; x--) {
- if (a.value < 0 && b.value < 0 && c.value < 0) {
- WritePixel(x, y + 1, color, viewport);
+ if (ab.value < 0 && bc.value < 0 && ca.value < 0) {
+ float z = bc.value/area*a->z + b->z*ca.value/area + c->z*ab.value/area;
+ if (UpdateDepthBuffer(x, y, -z, viewport)) {
+ WritePixel(x, y, color, viewport);
+ }
}
- a.value -= a.dy;
- b.value -= b.dy;
- c.value -= c.dy;
+ ab.value += ab.dy;
+ bc.value += bc.dy;
+ ca.value += ca.dy;
}
- a.value -= a.dx;
- b.value -= b.dx;
- c.value -= c.dx;
+ ab.row_value -= ab.dx;
+ ab.value = ab.row_value;
+ bc.row_value -= bc.dx;
+ bc.value = bc.row_value;
+ ca.row_value -= ca.dx;
+ ca.value = ca.row_value;
}
}
@@ 219,13 218,13 @@ void DrawPoint(Vertex p, Color color, Viewport *viewport)
Rect PolygonBounds(int *polygon, Vertex *vertices)
{
- Rect r = { floor(vertices[0].x), floor(vertices[0].y), floor(vertices[0].x), floor(vertices[0].y) };
+ Rect r = { floor(vertices[0].x), floor(vertices[0].y), ceil(vertices[0].x), ceil(vertices[0].y) };
for (int i = 0; i < *polygon; i++) {
Vertex v = vertices[polygon[i+1]];
if (v.x < r.left) r.left = floor(v.x);
- if (v.x > r.right) r.right = floor(v.x);
+ if (v.x > r.right) r.right = ceil(v.x);
if (v.y < r.bottom) r.bottom = floor(v.y);
- if (v.y > r.top) r.top = floor(v.y);
+ if (v.y > r.top) r.top = ceil(v.y);
}
return r;
}
@@ 244,5 243,12 @@ EdgeTracker TrackEdge(Vertex *a, Vertex *b, Vertex start)
et.dx = b->x - a->x;
et.dy = b->y - a->y;
et.value = (start.x - a->x)*et.dy - (start.y - a->y)*et.dx;
+ et.row_value = et.value;
return et;
}
+
+float TriArea(Vertex *a, Vertex *b, Vertex *c)
+/* Returns twice the signed area of the triangle */
+{
+ return (b->x - a->x)*(c->y - a->y) - (c->x - a->x)*(b->y - a->y);
+}
@@ 39,6 39,7 @@ typedef struct Rect {
typedef struct EdgeTracker {
float dx;
float dy;
+ float row_value;
float value;
} EdgeTracker;
@@ 60,3 61,4 @@ void DrawPoint(Vertex p, Color color, Viewport *viewport);
Rect PolygonBounds(int *polygon, Vertex *vertices);
void PrintRect(Rect r);
EdgeTracker TrackEdge(Vertex *a, Vertex *b, Vertex start);
+float TriArea(Vertex *a, Vertex *b, Vertex *c);
@@ 8,7 8,7 @@ void TestRandomTriangles(void)
{
Scene *scene = NewScene();
- for (int i = 0; i < 10000; ++i) {
+ for (int i = 0; i < 9999; ++i) {
Model *model = NewModel(scene->model_pool);
Renderable *r = NewRenderable(scene->renderable_pool, model, BLACK);
Vertex *a = NewVertex(r->mesh->vertices);
@@ 37,9 37,12 @@ void TestRandomTriangles(void)
float clocksPerMs = CLOCKS_PER_SEC/1000;
float startTime = (float)clock()/(clocksPerMs);
- RenderScene(scene, renderer);
+ int numRenders = 100;
+ for (int i = 0; i < numRenders; i++) {
+ RenderScene(scene, renderer);
+ }
float endTime = (float)clock()/(clocksPerMs);
- float renderTime = (endTime - startTime);
+ float renderTime = (endTime - startTime) / numRenders;
float targetTime = (1/30.f)*1000; // one frame, ~33 ms
printf("Render time: %.2fms (target max: %.2fms)\n", renderTime, targetTime);