#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef struct {
float x, y; // Viewport coordinates
float u, v; // Texture coordinates
} Vertex;
typedef struct {
int width;
int height;
unsigned char *data; // Assume 3 bytes per pixel (RGB)
} Texture;
typedef struct {
int width;
int height;
unsigned char *data; // Assume 3 bytes per pixel (RGB)
} Framebuffer;
void rasterize_triangle(Vertex v0, Vertex v1, Vertex v2, Texture *texture, Framebuffer *framebuffer)
{
// Compute bounding box of the triangle
int minX = (int)floorf(fminf(fminf(v0.x, v1.x), v2.x));
int minY = (int)floorf(fminf(fminf(v0.y, v1.y), v2.y));
int maxX = (int)ceilf(fmaxf(fmaxf(v0.x, v1.x), v2.x));
int maxY = (int)ceilf(fmaxf(fmaxf(v0.y, v1.y), v2.y));
// Clamp bounding box to framebuffer dimensions
minX = fmaxf(minX, 0);
minY = fmaxf(minY, 0);
maxX = fminf(maxX, framebuffer->width - 1);
maxY = fminf(maxY, framebuffer->height - 1);
// Precompute reciprocal of denominator to avoid division in the loop
float denom = ((v1.y - v2.y)*(v0.x - v2.x) + (v2.x - v1.x)*(v0.y - v2.y));
if (denom == 0.0f)
return; // The triangle has zero area, nothing to draw
float invDenom = 1.0f / denom;
// For each pixel in the bounding box
for (int y = minY; y <= maxY; y++)
{
for (int x = minX; x <= maxX; x++)
{
// Compute barycentric coordinates
float w0 = ((v1.y - v2.y)*(x - v2.x) + (v2.x - v1.x)*(y - v2.y)) * invDenom;
float w1 = ((v2.y - v0.y)*(x - v2.x) + (v0.x - v2.x)*(y - v2.y)) * invDenom;
float w2 = 1.0f - w0 - w1;
// If point is inside the triangle (all weights >= 0)
if (w0 >= 0.0f && w1 >= 0.0f && w2 >= 0.0f)
{
// Interpolate texture coordinates
float u = w0 * v0.u + w1 * v1.u + w2 * v2.u;
float v = w0 * v0.v + w1 * v1.v + w2 * v2.v;
// Clamp texture coordinates
u = fminf(fmaxf(u, 0.0f), 1.0f);
v = fminf(fmaxf(v, 0.0f), 1.0f);
// Sample the texture
int texU = (int)(u * (texture->width - 1));
int texV = (int)(v * (texture->height - 1));
int texIndex = (texV * texture->width + texU) * 3;
unsigned char r = texture->data[texIndex];
unsigned char g = texture->data[texIndex + 1];
unsigned char b = texture->data[texIndex + 2];
// Write to framebuffer
int fbIndex = (y * framebuffer->width + x) * 3;
framebuffer->data[fbIndex] = r;
framebuffer->data[fbIndex + 1] = g;
framebuffer->data[fbIndex + 2] = b;
}
}
}
}