Software Rendering Utilities (Lines & Polygons)

A small, self‑contained C99 library that provides a framebuffer abstraction and basic software rendering primitives

c (c99) 2025-12-27 AI Generated c99 software-rendering lines polygons graphics

Code

RAW
#include <stdint.h>#include <stdlib.h>#include <string.h>#include <stdbool.h>/* ------------------------------------------------------------ * Basic Types * ------------------------------------------------------------ */typedef struct {    uint8_t r, g, b, a;   /* 0‑255 per channel */} Color;typedef struct {    uint32_t width;    uint32_t height;    Color *pixels;        /* Row‑major order: pixels[y * width + x] */} Framebuffer;typedef struct {    int x;    int y;} Point;/* ------------------------------------------------------------ * Framebuffer Management * ------------------------------------------------------------ */static inline Framebuffer *fb_create(uint32_t width, uint32_t height, Color clear_color){    Framebuffer *fb = (Framebuffer *)malloc(sizeof(Framebuffer));    if (!fb) return NULL;    fb->width  = width;    fb->height = height;    fb->pixels = (Color *)malloc(width * height * sizeof(Color));    if (!fb->pixels) {        free(fb);        return NULL;    }    /* Initialise with clear colour */    for (uint32_t i = 0; i < width * height; ++i) {        fb->pixels[i] = clear_color;    }    return fb;}static inline void fb_destroy(Framebuffer *fb){    if (fb) {        free(fb->pixels);        free(fb);    }}static inline void fb_clear(Framebuffer *fb, Color color){    if (!fb) return;    for (uint32_t i = 0; i < fb->width * fb->height; ++i) {        fb->pixels[i] = color;    }}/* ------------------------------------------------------------ * Pixel Operations * ------------------------------------------------------------ */static inline bool fb_set_pixel(Framebuffer *fb, int x, int y, Color color){    if (!fb) return false;    if (x < 0 || y < 0 || (uint32_t)x >= fb->width || (uint32_t)y >= fb->height)        return false;               /* Out of bounds – silently ignore */    fb->pixels[y * fb->width + x] = color;    return true;}/* ------------------------------------------------------------ * Line Drawing – Bresenham (integer only, no anti‑aliasing) * ------------------------------------------------------------ */static void draw_line(Framebuffer *fb, Point p0, Point p1, Color color){    int x0 = p0.x, y0 = p0.y;    int x1 = p1.x, y1 = p1.y;    int dx = abs(x1 - x0);    int dy = -abs(y1 - y0);    int sx = (x0 < x1) ? 1 : -1;    int sy = (y0 < y1) ? 1 : -1;    int err = dx + dy;   /* error value e_xy */    while (true) {        fb_set_pixel(fb, x0, y0, color);        if (x0 == x1 && y0 == y1) break;        int e2 = 2 * err;        if (e2 >= dy) { err += dy; x0 += sx; }        if (e2 <= dx) { err += dx; y0 += sy; }    }}/* ------------------------------------------------------------ * Polygon Stroking – draws edges using draw_line * ------------------------------------------------------------ */static void draw_polygon(Framebuffer *fb, const Point *pts, size_t count, Color color){    if (count < 2) return;    for (size_t i = 0; i < count; ++i) {        Point a = pts[i];        Point b = pts[(i + 1) % count];        draw_line(fb, a, b, color);    }}/* ------------------------------------------------------------ * Polygon Fill – simple even‑odd scan‑line algorithm * ------------------------------------------------------------ */static void fill_polygon(Framebuffer *fb, const Point *pts, size_t count, Color color){    if (count < 3) return;   /* Not a polygon */    /* Find vertical bounds */    int min_y = pts[0].y, max_y = pts[0].y;    for (size_t i = 1; i < count; ++i) {        if (pts[i].y < min_y) min_y = pts[i].y;        if (pts[i].y > max_y) max_y = pts[i].y;    }    /* Clamp to framebuffer */    if (min_y < 0) min_y = 0;    if ((uint32_t)max_y >= fb->height) max_y = fb->height - 1;    /* For each scan line, compute intersections with polygon edges */    for (int y = min_y; y <= max_y; ++y) {        /* Collect x intersections */        int intersections[64];   /* Reasonable static limit; can be expanded */        size_t n = 0;        for (size_t i = 0; i < count; ++i) {            Point v1 = pts[i];            Point v2 = pts[(i + 1) % count];            if (v1.y == v2.y) continue;               /* Horizontal edge – ignore */            if ((y < v1.y && y < v2.y) || (y > v1.y && y > v2.y))                continue;                             /* Edge not crossing scan line */            /* Compute intersection X coordinate */            double x = v1.x + (double)(y - v1.y) * (v2.x - v1.x) / (v2.y - v1.y);            if (n < sizeof(intersections)/sizeof(intersections[0]))                intersections[n++] = (int) (x + 0.5); /* Round to nearest pixel */        }        if (n < 2) continue;   /* No spans on this line */        /* Sort intersections (simple insertion sort – n is tiny) */        for (size_t i = 1; i < n; ++i) {            int key = intersections[i];            size_t j = i;            while (j > 0 && intersections[j-1] > key) {                intersections[j] = intersections[j-1];                --j;            }            intersections[j] = key;        }        /* Fill between pairs */        for (size_t i = 0; i + 1 < n; i += 2) {            int x_start = intersections[i];            int x_end   = intersections[i+1];            if (x_start > x_end) continue;            if (x_start < 0) x_start = 0;            if ((uint32_t)x_end >= fb->width) x_end = fb->width - 1;            for (int x = x_start; x <= x_end; ++x) {                fb_set_pixel(fb, x, y, color);            }        }    }}/* ------------------------------------------------------------ * Example usage (commented out – keep library header‑only) * ------------------------------------------------------------ *//*int main(void){    Color black = {0,0,0,255};    Color red   = {255,0,0,255};    Framebuffer *fb = fb_create(640, 480, black);    if (!fb) return 1;    Point poly[] = {{100,100},{200,80},{250,200},{150,250}};    draw_polygon(fb, poly, 4, red);    fill_polygon(fb, poly, 4, red);    /* At this point you could write fb->pixels to a BMP/PNG file or       blit it to a window using your platform‑specific code. */    fb_destroy(fb);    return 0;}*/

Comments

No comments yet. Be the first to comment!