From the 3D rasterizer code that I will give you, I want you to rewrite the outputting pipeline to user the linux framebuffer .
```c
/* 
   Simple 3D Rasterizer in Pure C with Lighting System
   - Renders triangles in the terminal using ASCII characters.
   - Supports perspective projection with a field of view (FOV) of 90 degrees.
   - Allows global and local transformations (translation, rotation, scaling) for triangles.
   - Includes camera transformations (translation and rotation).
   - Continuously rotates the first triangle around its Z-axis in a loop.
   - Implements a basic lighting system based on distance from a light source.

   Compile with:
       gcc -o rasterizer rasterizer.c -lm
*/

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <unistd.h>   // For usleep()


/* Screen dimensions */
#define WIDTH 60
#define HEIGHT 40

/* Depth range */
#define ZNEAR 0.1f     // Near clipping plane
#define ZFAR 1000.0f   // Far clipping plane


/* Field of view in degrees */
#define FOV 90.0f

/* Aspect ratio correction (characters are taller than they are wide) */
#define ASPECT_RATIO_CORRECTION 1.2f

/* Precompute FOV scaling factor */
#define FOV_RAD (FOV * (M_PI / 180.0f))
#define F_SCALE (1.0f / tanf(FOV_RAD / 2.0f))

/* Type Definitions */
typedef unsigned char u8_t;
typedef float f32_t;
typedef int i32_t;
typedef unsigned int u32_t;

#define MATH_INFINITY ((u32_t) -1)

typedef struct { u8_t r, g, b; } col_t;
typedef struct { f32_t x, y, z; } vec3_t;
typedef struct { f32_t x, y, z, w; } vec4_t;
typedef struct { f32_t m[4][4]; } mat4x4_t;

typedef struct { vec3_t p; col_t c; } vert_t;
typedef struct { vert_t a, b, c; } tri_t;
typedef struct { i32_t x, y; f32_t z; } screen_vert_t;
typedef struct { screen_vert_t a, b, c; } screen_tri_t;

/* Camera Structure */
typedef struct {
    vec3_t position;
    f32_t pitch; // Rotation around X-axis (in radians)
    f32_t yaw;   // Rotation around Y-axis (in radians)
    f32_t roll;  // Rotation around Z-axis (in radians)
} camera_t;

/* Light Structure */
/* === Added Light Structure === */
typedef struct {
    vec3_t position;    // Position of the light in world space
    col_t color;        // Color of the light
    f32_t intensity;    // Intensity of the light
    f32_t range;        // Range of the light
} light_t;

/* Function Prototypes */

/* Matrix Operations */
void mat4x4_identity(mat4x4_t *mat);
void mat4x4_multiply(mat4x4_t *result, const mat4x4_t *a, const mat4x4_t *b);
void mat4x4_translate(mat4x4_t *mat, const vec3_t *t);
void mat4x4_rotate_x(mat4x4_t *mat, f32_t angle);
void mat4x4_rotate_y(mat4x4_t *mat, f32_t angle);
void mat4x4_rotate_z(mat4x4_t *mat, f32_t angle);
void mat4x4_scale(mat4x4_t *mat, const vec3_t *s);
vec3_t mat4x4_multiply_vec3(const mat4x4_t *mat, const vec3_t *v);

/* Transformation Functions for Triangles */
void translate_triangle(tri_t *tri, vec3_t t);
void translate_triangle_local_along_normal(tri_t *tri, float distance);
void rotate_triangle(tri_t *tri, f32_t angle_x, f32_t angle_y, f32_t angle_z);
void rotate_triangle_deg(tri_t *tri, f32_t angle_x_deg, f32_t angle_y_deg, f32_t angle_z_deg);
void scale_triangle(tri_t *tri, const vec3_t s);
void scale_triangle_local(tri_t *tri, const vec3_t s);
void scale_triangle_local_uniform(tri_t *tri, f32_t scale_factor);
void rotate_triangle_local(tri_t *tri, f32_t angle_x, f32_t angle_y, f32_t angle_z);
void rotate_triangle_local_deg(tri_t *tri, f32_t angle_x_deg, f32_t angle_y_deg, f32_t angle_z_deg);
vec3_t compute_centroid(const tri_t *tri);

/* Camera Transformation Functions */
void translate_camera(camera_t *cam, const vec3_t *t);
void rotate_camera(camera_t *cam, f32_t angle_x, f32_t angle_y, f32_t angle_z);
void rotate_camera_deg(camera_t *cam, f32_t angle_x_deg, f32_t angle_y_deg, f32_t angle_z_deg);

/* Rendering Functions */
void set_color(col_t c);
void next_line();
void clear_screen();
void clear_fb(col_t fb[HEIGHT][WIDTH], f32_t zb_buffer[HEIGHT][WIDTH], f32_t distance_buffer[HEIGHT][WIDTH]);
void render_fb_distance(const col_t fb[HEIGHT][WIDTH], const f32_t distance_buffer[HEIGHT][WIDTH], const light_t *light);

/* Projection and Rasterization */
vec3_t apply_camera_transform(const camera_t *cam, const vec3_t *p);
screen_vert_t project_vertex(const camera_t *cam, const vec3_t *p_world);
void compute_barycentric(int px, int py, screen_tri_t tri, f32_t *u, f32_t *v, f32_t *w);
/* === Updated Rasterize Function to Accept Light Position === */
void rasterize_triangle(const tri_t *tri, const camera_t *cam, const vec3_t *light_cam_space_pos, col_t fb[HEIGHT][WIDTH], f32_t zb_buffer[HEIGHT][WIDTH], f32_t distance_buffer[HEIGHT][WIDTH]);

/* Helper Functions */
f32_t deg_to_rad(f32_t degrees);

/* Function Implementations */

/* Helper function to convert degrees to radians */
f32_t deg_to_rad(f32_t degrees) {
    return degrees * (M_PI / 180.0f);
}

/* Matrix Operations Implementations */

void mat4x4_identity(mat4x4_t *mat) {
    memset(mat, 0, sizeof(mat4x4_t));
    for(int i = 0; i < 4; i++) {
        mat->m[i][i] = 1.0f;
    }
}

void mat4x4_multiply(mat4x4_t *result, const mat4x4_t *a, const mat4x4_t *b) {
    mat4x4_t temp;
    for(int i = 0; i < 4; i++) {
        for(int j = 0; j < 4; j++) {
            temp.m[i][j] = 0.0f;
            for(int k = 0; k < 4; k++) {
                temp.m[i][j] += a->m[i][k] * b->m[k][j];
            }
        }
    }
    *result = temp;
}

void mat4x4_translate(mat4x4_t *mat, const vec3_t *t) {
    mat4x4_identity(mat);
    mat->m[0][3] = t->x;
    mat->m[1][3] = t->y;
    mat->m[2][3] = t->z;
}

void mat4x4_rotate_x(mat4x4_t *mat, f32_t angle) {
    mat4x4_identity(mat);
    f32_t c = cosf(angle);
    f32_t s = sinf(angle);
    mat->m[1][1] = c;
    mat->m[1][2] = -s;
    mat->m[2][1] = s;
    mat->m[2][2] = c;
}

void mat4x4_rotate_y(mat4x4_t *mat, f32_t angle) {
    mat4x4_identity(mat);
    f32_t c = cosf(angle);
    f32_t s = sinf(angle);
    mat->m[0][0] = c;
    mat->m[0][2] = s;
    mat->m[2][0] = -s;
    mat->m[2][2] = c;
}

void mat4x4_rotate_z(mat4x4_t *mat, f32_t angle) {
    mat4x4_identity(mat);
    f32_t c = cosf(angle);
    f32_t s = sinf(angle);
    mat->m[0][0] = c;
    mat->m[0][1] = -s;
    mat->m[1][0] = s;
    mat->m[1][1] = c;
}

void mat4x4_scale(mat4x4_t *mat, const vec3_t *s) {
    mat4x4_identity(mat);
    mat->m[0][0] = s->x;
    mat->m[1][1] = s->y;
    mat->m[2][2] = s->z;
}

vec3_t mat4x4_multiply_vec3(const mat4x4_t *mat, const vec3_t *v) {
    vec4_t result;
    result.x = mat->m[0][0]*v->x + mat->m[0][1]*v->y + mat->m[0][2]*v->z + mat->m[0][3]*1.0f;
    result.y = mat->m[1][0]*v->x + mat->m[1][1]*v->y + mat->m[1][2]*v->z + mat->m[1][3]*1.0f;
    result.z = mat->m[2][0]*v->x + mat->m[2][1]*v->y + mat->m[2][2]*v->z + mat->m[2][3]*1.0f;
    result.w = mat->m[3][0]*v->x + mat->m[3][1]*v->y + mat->m[3][2]*v->z + mat->m[3][3]*1.0f;
    
    // Perform perspective divide if w is not 1
    if(result.w != 0.0f && result.w != 1.0f) {
        result.x /= result.w;
        result.y /= result.w;
        result.z /= result.w;
    }
    
    vec3_t final = { result.x, result.y, result.z };
    return final;
}

/* Transformation Functions for Triangles */

/* Function to translate a triangle globally */
void translate_triangle(tri_t *tri, vec3_t t) {
    tri->a.p.x += t.x;
    tri->a.p.y += t.y;
    tri->a.p.z += t.z;

    tri->b.p.x += t.x;
    tri->b.p.y += t.y;
    tri->b.p.z += t.z;

    tri->c.p.x += t.x;
    tri->c.p.y += t.y;
    tri->c.p.z += t.z;
}

/* Function to compute the normal vector of a triangle */
vec3_t compute_normal(const tri_t *tri) {
    // Calculate vectors AB and AC
    vec3_t ab = { tri->b.p.x - tri->a.p.x, tri->b.p.y - tri->a.p.y, tri->b.p.z - tri->a.p.z };
    vec3_t ac = { tri->c.p.x - tri->a.p.x, tri->c.p.y - tri->a.p.y, tri->c.p.z - tri->a.p.z };

    // Cross product AB x AC
    vec3_t cross = {
        ab.y * ac.z - ab.z * ac.y,
        ab.z * ac.x - ab.x * ac.z,
        ab.x * ac.y - ab.y * ac.x
    };

    // Normalize the vector
    f32_t length = sqrtf(cross.x * cross.x + cross.y * cross.y + cross.z * cross.z);
    if(length == 0.0f) return (vec3_t){0.0f, 0.0f, 0.0f};
    cross.x /= length;
    cross.y /= length;
    cross.z /= length;

    return cross;
}

/* Function to translate a triangle locally along its normal vector */
void translate_triangle_local_along_normal(tri_t *tri, float distance) {
    // Step 1: Compute the centroid
    vec3_t centroid = compute_centroid(tri);
    
    // Step 2: Compute the normal vector
    vec3_t normal = compute_normal(tri);
    
    // Step 3: Create translation vector along the normal
    vec3_t translation = { normal.x * distance, normal.y * distance, normal.z * distance };
    
    // Step 4: Translate the triangle by the translation vector
    translate_triangle(tri, translation);
}

/* Function to rotate a triangle globally using radians */
void rotate_triangle(tri_t *tri, f32_t angle_x, f32_t angle_y, f32_t angle_z) {
    mat4x4_t rot_x, rot_y, rot_z, temp, rot_total;

    /* Rotate around X-axis */
    mat4x4_rotate_x(&rot_x, angle_x);
    
    /* Rotate around Y-axis */
    mat4x4_rotate_y(&rot_y, angle_y);
    
    /* Rotate around Z-axis */
    mat4x4_rotate_z(&rot_z, angle_z);
    
    /* Combine rotations: Rz * Ry * Rx */
    mat4x4_multiply(&temp, &rot_y, &rot_x);
    mat4x4_multiply(&rot_total, &rot_z, &temp);
    
    /* Apply rotation to each vertex */
    tri->a.p = mat4x4_multiply_vec3(&rot_total, &tri->a.p);
    tri->b.p = mat4x4_multiply_vec3(&rot_total, &tri->b.p);
    tri->c.p = mat4x4_multiply_vec3(&rot_total, &tri->c.p);
}

/* Function to rotate a triangle globally using degrees */
void rotate_triangle_deg(tri_t *tri, f32_t angle_x_deg, f32_t angle_y_deg, f32_t angle_z_deg) {
    f32_t angle_x_rad = deg_to_rad(angle_x_deg);
    f32_t angle_y_rad = deg_to_rad(angle_y_deg);
    f32_t angle_z_rad = deg_to_rad(angle_z_deg);
    rotate_triangle(tri, angle_x_rad, angle_y_rad, angle_z_rad);
}

/* Function to scale a triangle globally */
void scale_triangle(tri_t *tri, const vec3_t s) {
    tri->a.p.x *= s.x;
    tri->a.p.y *= s.y;
    tri->a.p.z *= s.z;

    tri->b.p.x *= s.x;
    tri->b.p.y *= s.y;
    tri->b.p.z *= s.z;

    tri->c.p.x *= s.x;
    tri->c.p.y *= s.y;
    tri->c.p.z *= s.z;
}

/* Function to compute the centroid of a triangle */
vec3_t compute_centroid(const tri_t *tri) {
    vec3_t centroid;
    centroid.x = (tri->a.p.x + tri->b.p.x + tri->c.p.x) / 3.0f;
    centroid.y = (tri->a.p.y + tri->b.p.y + tri->c.p.y) / 3.0f;
    centroid.z = (tri->a.p.z + tri->b.p.z + tri->c.p.z) / 3.0f;
    return centroid;
}

/* Function to rotate a triangle around its centroid using radians */
void rotate_triangle_local(tri_t *tri, f32_t angle_x, f32_t angle_y, f32_t angle_z) {
    // Step 1: Compute the centroid
    vec3_t centroid = compute_centroid(tri);
    
    // Step 2: Translate the triangle so that the centroid is at the origin
    translate_triangle(tri, (vec3_t){ -centroid.x, -centroid.y, -centroid.z });
    
    // Step 3: Apply rotation
    rotate_triangle(tri, angle_x, angle_y, angle_z);
    
    // Step 4: Translate the triangle back to its original position
    translate_triangle(tri, centroid);
}

/* Function to rotate a triangle around its centroid using degrees */
void rotate_triangle_local_deg(tri_t *tri, f32_t angle_x_deg, f32_t angle_y_deg, f32_t angle_z_deg) {
    f32_t angle_x_rad = deg_to_rad(angle_x_deg);
    f32_t angle_y_rad = deg_to_rad(angle_y_deg);
    f32_t angle_z_rad = deg_to_rad(angle_z_deg);
    rotate_triangle_local(tri, angle_x_rad, angle_y_rad, angle_z_rad);
}

/* Function to scale a triangle relative to its centroid using scaling factors */
void scale_triangle_local(tri_t *tri, const vec3_t s) {
    // Step 1: Compute the centroid
    vec3_t centroid = compute_centroid(tri);
    
    // Step 2: Translate the triangle so that the centroid is at the origin
    translate_triangle(tri, (vec3_t){ -centroid.x, -centroid.y, -centroid.z });
    
    // Step 3: Apply scaling
    scale_triangle(tri, s);
    
    // Step 4: Translate the triangle back to its original position
    translate_triangle(tri, centroid);
}

/* Function to scale a triangle uniformly relative to its centroid */
void scale_triangle_local_uniform(tri_t *tri, f32_t scale_factor) {
    vec3_t scale = { scale_factor, scale_factor, scale_factor };
    scale_triangle_local(tri, scale);
}

/* Camera Transformation Functions */

/* Function to translate the camera */
void translate_camera(camera_t *cam, const vec3_t *t) {
    cam->position.x += t->x;
    cam->position.y += t->y;
    cam->position.z += t->z;
}

/* Function to rotate the camera using radians */
void rotate_camera(camera_t *cam, f32_t angle_x, f32_t angle_y, f32_t angle_z) {
    cam->pitch += angle_x;
    cam->yaw   += angle_y;
    cam->roll  += angle_z;
}

/* Function to rotate the camera using degrees */
void rotate_camera_deg(camera_t *cam, f32_t angle_x_deg, f32_t angle_y_deg, f32_t angle_z_deg) {
    f32_t angle_x_rad = deg_to_rad(angle_x_deg);
    f32_t angle_y_rad = deg_to_rad(angle_y_deg);
    f32_t angle_z_rad = deg_to_rad(angle_z_deg);
    rotate_camera(cam, angle_x_rad, angle_y_rad, angle_z_rad);
}

/* Function to apply camera transformation to a point (world space to camera space) */
vec3_t apply_camera_transform(const camera_t *cam, const vec3_t *p) {
    // Translate
    vec3_t translated = {
        p->x - cam->position.x,
        p->y - cam->position.y,
        p->z - cam->position.z
    };

    // Apply inverse rotations (pitch, yaw, roll)
    // Rotation order: Roll -> Pitch -> Yaw
    // Inverse rotations: Negate the angles

    // Rotate around Z-axis (Roll)
    f32_t cos_z = cosf(-cam->roll);
    f32_t sin_z = sinf(-cam->roll);
    f32_t x1 = translated.x * cos_z - translated.y * sin_z;
    f32_t y1 = translated.x * sin_z + translated.y * cos_z;
    f32_t z1 = translated.z;

    // Rotate around X-axis (Pitch)
    f32_t cos_x = cosf(-cam->pitch);
    f32_t sin_x = sinf(-cam->pitch);
    f32_t x2 = x1;
    f32_t y2 = y1 * cos_x - z1 * sin_x;
    f32_t z2 = y1 * sin_x + z1 * cos_x;

    // Rotate around Y-axis (Yaw)
    f32_t cos_y = cosf(-cam->yaw);
    f32_t sin_y = sinf(-cam->yaw);
    f32_t x3 = x2 * cos_y + z2 * sin_y;
    f32_t y3 = y2;
    f32_t z3 = -x2 * sin_y + z2 * cos_y;

    vec3_t final = { x3, y3, z3 };
    return final;
}

/* Projection Function: Project a 3D point to 2D screen space using perspective projection and camera transform */
screen_vert_t project_vertex(const camera_t *cam, const vec3_t *p_world) {
    screen_vert_t sv;
    
    // Transform the point to camera space
    vec3_t p_cam = apply_camera_transform(cam, p_world);
    
    // Prevent division by zero and handle points behind the camera
    if (p_cam.z <= ZNEAR) {
        p_cam.z = ZNEAR;
    }

    // Apply perspective projection
    f32_t x_proj = (p_cam.x * F_SCALE) / p_cam.z;
    f32_t y_proj = (p_cam.y * F_SCALE) / p_cam.z;

    // Adjust for aspect ratio correction
    y_proj /= ASPECT_RATIO_CORRECTION;

    // Map normalized device coordinates [-1, 1] to screen coordinates [0, WIDTH] and [0, HEIGHT]
    sv.x = (int)((x_proj + 1.0f) * 0.5f * WIDTH);
    sv.y = (int)((1.0f - (y_proj + 1.0f) * 0.5f) * HEIGHT);
    sv.z = p_cam.z;

    return sv;
}

/* Function to compute barycentric coordinates */
void compute_barycentric(int px, int py, screen_tri_t tri, f32_t *u, f32_t *v, f32_t *w) {
    f32_t denom = (f32_t)((tri.b.y - tri.c.y)*(tri.a.x - tri.c.x) + (tri.c.x - tri.b.x)*(tri.a.y - tri.c.y));
    if (fabsf(denom) < 1e-6f) { // Degenerate triangle
        *u = *v = *w = -1.0f;
        return;
    }
    *u = ((tri.b.y - tri.c.y)*(px - tri.c.x) + (tri.c.x - tri.b.x)*(py - tri.c.y)) / denom;
    *v = ((tri.c.y - tri.a.y)*(px - tri.c.x) + (tri.a.x - tri.c.x)*(py - tri.c.y)) / denom;
    *w = 1.0f - (*u) - (*v);
}

/* Rasterization Function: Rasterize a single triangle with lighting based on light distance */
/* === Updated Rasterize Function to Compute Distance from Light === */
void rasterize_triangle(const tri_t *tri, const camera_t *cam, const vec3_t *light_cam_space_pos, col_t fb[HEIGHT][WIDTH], f32_t zb_buffer[HEIGHT][WIDTH], f32_t distance_buffer[HEIGHT][WIDTH]) {
    // Project vertices to screen space
    screen_tri_t st = {
        .a = project_vertex(cam, &tri->a.p),
        .b = project_vertex(cam, &tri->b.p),
        .c = project_vertex(cam, &tri->c.p)
    };

    // Compute bounding box
    i32_t minX = st.a.x < st.b.x ? (st.a.x < st.c.x ? st.a.x : st.c.x) : (st.b.x < st.c.x ? st.b.x : st.c.x);
    i32_t maxX = st.a.x > st.b.x ? (st.a.x > st.c.x ? st.a.x : st.c.x) : (st.b.x > st.c.x ? st.b.x : st.c.x);
    i32_t minY = st.a.y < st.b.y ? (st.a.y < st.c.y ? st.a.y : st.c.y) : (st.b.y < st.c.y ? st.b.y : st.c.y);
    i32_t maxY = st.a.y > st.b.y ? (st.a.y > st.c.y ? st.a.y : st.c.y) : (st.b.y > st.c.y ? st.b.y : st.c.y);

    // Clamp to screen dimensions
    if(minX < 0) minX = 0;
    if(maxX >= WIDTH) maxX = WIDTH -1;
    if(minY < 0) minY = 0;
    if(maxY >= HEIGHT) maxY = HEIGHT -1;

    // Iterate over the bounding box
    for(int y = minY; y <= maxY; y++) {
        for(int x = minX; x <= maxX; x++) {
            f32_t u, v, w;
            compute_barycentric(x + 0.5f, y + 0.5f, st, &u, &v, &w);

            // Check if inside the triangle
            if(u >= 0.0f && v >= 0.0f && w >= 0.0f) {
                // Interpolate depth (z)
                f32_t depth = u * st.a.z + v * st.b.z + w * st.c.z;

                // Z-buffer test
                if(depth < zb_buffer[y][x]) {
                    zb_buffer[y][x] = depth;

                    // Interpolate 3D position in camera space
                    vec3_t pos_a = apply_camera_transform(cam, &tri->a.p);
                    vec3_t pos_b = apply_camera_transform(cam, &tri->b.p);
                    vec3_t pos_c = apply_camera_transform(cam, &tri->c.p);

                    vec3_t pos = {
                        u * pos_a.x + v * pos_b.x + w * pos_c.x,
                        u * pos_a.y + v * pos_b.y + w * pos_c.y,
                        u * pos_a.z + v * pos_b.z + w * pos_c.z
                    };

                    // === Compute distance from light instead of camera ===
                    f32_t dx = pos.x - light_cam_space_pos->x;
                    f32_t dy = pos.y - light_cam_space_pos->y;
                    f32_t dz = pos.z - light_cam_space_pos->z;
                    f32_t distance = sqrtf(dx * dx + dy * dy + dz * dz);
                    distance_buffer[y][x] = distance;

                    // Interpolate color
                    col_t color = {
                        .r = (u * tri->a.c.r) + (v * tri->b.c.r) + (w * tri->c.c.r),
                        .g = (u * tri->a.c.g) + (v * tri->b.c.g) + (w * tri->c.c.g),
                        .b = (u * tri->a.c.b) + (v * tri->b.c.b) + (w * tri->c.c.b),
                    };
                    fb[y][x] = color;
                }
            }
        }
    }
}

/* Rendering Functions */
/* Set the terminal color using ANSI escape codes */
void set_color(col_t c) {
    printf("\x1b[38;2;%d;%d;%dm", c.r, c.g, c.b);
}

/* Move to the next line and reset color */
void next_line() {
    printf("\x1b[0m\n");
}

/* Clear the terminal screen and move the cursor to home position */
void clear_screen(){
    printf("\x1b[2J"); // Clear screen
    printf("\x1b[H");  // Move cursor to home position
}

/* Clear the frame buffer, Z-buffer, and Distance buffer */
void clear_fb(col_t fb[HEIGHT][WIDTH], f32_t zb_buffer[HEIGHT][WIDTH], f32_t distance_buffer[HEIGHT][WIDTH]) {
    for(u32_t i = 0; i < HEIGHT * WIDTH; i++) {
        ((col_t*)fb)[i] = (col_t){0, 0, 0}; // Black background
        ((f32_t*)zb_buffer)[i] = ZFAR;    // Initialize Z-buffer to farthest depth
        ((f32_t*)distance_buffer)[i] = MATH_INFINITY;   // Initialize Distance buffer to farthest distance for lighting
    }
}

/* Render the frame buffer with distance-based shading from the light source */
/* === Updated Render Function to Use Light Properties === */
void render_fb_distance(const col_t fb[HEIGHT][WIDTH], const f32_t distance_buffer[HEIGHT][WIDTH], const light_t *light) {
    for(int y = 0; y < HEIGHT; y++) {
        for(int x = 0; x < WIDTH; x++) {
            f32_t brightness = 1.0f;
            col_t color = fb[y][x];

            if (light) { // Ignore light processing if no light (flat shading)

                f32_t distance = distance_buffer[y][x];

                // Normalize distance between 0 and the range of the light
                f32_t normalized = distance / light->range;

                // Clamp the normalized value between 0 and 1
                if(normalized < 0.0f) normalized = 0.0f;
                if(normalized > 1.0f) normalized = 1.0f;

                // Invert the normalized distance for brightness (closer objects are brighter)
                brightness = 1.0f - normalized;

                // Apply light intensity
                brightness *= light->intensity;

                // Modulate the object's color with the light's color and brightness
                color.r = (u8_t)(color.r * brightness * (light->color.r / 255.0f));
                color.g = (u8_t)(color.g * brightness * (light->color.g / 255.0f));
                color.b = (u8_t)(color.b * brightness * (light->color.b / 255.0f));
            }
            

            // Set the color and print the character
            set_color(color);
            printf("%s", color.r == 0.0f && color.g == 0.0f && color.b == 0.0f ? " " : "@");
        }
        next_line();
    }

    // Reset terminal color at the end
    printf("\x1b[0m");
}

/* Main Function */
int main() {
    /* Initialize frame buffer, Z-buffer, and Distance buffer */
    col_t fb[HEIGHT][WIDTH];              // Frame buffer
    f32_t zb_buffer[HEIGHT][WIDTH];       // Z-buffer
    f32_t distance_buffer[HEIGHT][WIDTH]; // Distance buffer

    /* Example Triangles */
    tri_t t1 = {
        .a = { .p = { -5.0f, -5.0f, 8.0f }, .c = { 255, 0, 0 } },   // Red
        .b = { .p = {  5.0f, -5.0f, 8.0f }, .c = { 0, 255, 0 } },   // Green
        .c = { .p = {  0.0f,  5.0f, 8.0f }, .c = { 0, 0, 255 } }    // Blue
    };


    /* Initialize Camera */
    camera_t camera = {
        .position = {0.0f, 0.0f, -1.0f},
        .pitch = 0.0f,
        .yaw = 0.0f,
        .roll = 0.0f
    };

    /* Initialize Light */
    /* === Added Light Initialization === */
    light_t light = {
        .position = {0.0f, 0.0f, 3.0f},  // Position of the light in world space
        .color = {255, 255, 255},       // White light
        .intensity = 1.0f,                // Full intensity
        .range = 3.0f
    };

    /* Apply Initial Transformations (Optional) */
    // You can apply initial transformations here if desired

    f32_t counter = 0;

    /* Main Rendering Loop */
    while(1) {
        /* Clear the screen and buffers */
        clear_screen();
        clear_fb(fb, zb_buffer, distance_buffer);

        /* Apply Local Transformation: Rotate Triangle t1 around its centroid by 2 degrees on all axes */
        rotate_triangle_local_deg(&t1, 2.0f, 2.0f, 2.0f); // Rotate 2 degrees around X, Y, and Z axes

        /* === Compute Light Position in Camera Space === */
        vec3_t light_cam_space = apply_camera_transform(&camera, &light.position);
        light.position.y = 3 * cos(counter);
        counter += 0.01f;


        /* Rasterize the triangles with lighting */
        rasterize_triangle(&t1, &camera, &light_cam_space, fb, zb_buffer, distance_buffer);
        
        /* Render the frame buffer to the terminal with lighting */
        render_fb_distance(fb, distance_buffer, 0);

        printf("light position: (%.2f, %.2f, %.2f)\n", light.position.x, light.position.y, light.position.z);
        printf("camera position: (%.2f, %.2f, %.2f)\n", camera.position.x, camera.position.y, camera.position.z);

        /* Control Frame Rate: Sleep for 50,000 microseconds (50 ms) */
        usleep(200000); // Adjust as needed for smoother/faster animation
    }

    return 0;
}
```