~zjm/Moon3D

5c5fd6f65109d6206b2f23da367bc49f32e96941 — Zack Michener a month ago e433867 master
add unoptimized depth buffering
3 files changed, 41 insertions(+), 30 deletions(-)

M src/viewport.c
M src/viewport.h
M test/performance.test.c
M src/viewport.c => src/viewport.c +33 -27
@@ 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);
}

M src/viewport.h => src/viewport.h +2 -0
@@ 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);

M test/performance.test.c => test/performance.test.c +6 -3
@@ 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);