In the code provided, update the set_color function, making it cleaner. It should also manage odd aspect ratio correction values, as currently, giving it an odd aspect ratio would make the number of pixels per line un-even. Overall, rewrite the whole code for this function:
code:
```c
/* Implementation of a simple rasterized 3D renderer in pure C without external dependencies.
   This application is single-threaded and draws only triangles to the terminal.
   Shades are determined by brightness related to a light source and drawn as ASCII characters.
   Colors are fully supported through the extended palette of the terminal.
   This program only uses standard ISO C99 code. */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

#define WIDTH 80
#define HEIGHT 40

#define ZNEAR 0.1f
#define ZFAR 100.0f

#define FOV 90.0f

/* Aspect ratio correction is needed, as we display on a 80x40 terminal, with characters being taller than they are wide */
#define ASPECT_RATIO_CORRECTION 4

/* Types and basic structures */
typedef unsigned char u8_t;
typedef float f32_t;
typedef int i32_t;
typedef unsigned int u32_t;

typedef struct { u8_t r, g, b, a; } col_t;
typedef struct { f32_t x, y, z; } vec3_t;
typedef struct { f32_t m[3][3]; } mat3_t;
typedef struct { vec3_t p; col_t c; } vert_t;
typedef struct { vert_t a, b, c; } tri_t;
typedef struct { vec3_t p; u8_t a; } light_t;
typedef struct { i32_t x, y; f32_t z; } screen_vert_t;
typedef struct { screen_vert_t a, b, c; } screen_tri_t;

/* Shades are determined by brightness related to a light source. By default, the camera emits a light of intensity 1.0, for simplicity */
const u8_t *shades[] = { " ", ".", ":", "-", "+", "=", "*", "#", "%", "@", "█" };
#define NSHADES (sizeof(shades) / sizeof(shades[0]))

/* Canvas to draw on screen */
col_t fb[HEIGHT][WIDTH]; // Frame buffer
f32_t zb[HEIGHT][WIDTH]; // Z-buffer

/* Utility functions */
const u8_t *get_shade(f32_t a) {
    if (a < 0.0f) a = 0.0f;
    if (a > 1.0f) a = 1.0f;
    u8_t shade = (u8_t)(a * (NSHADES - 1));
    return shades[shade];
}

void set_color(col_t c, const u8_t *shade) {
    static i32_t counter;
    printf("\x1b[38;2;%d;%d;%dm%s", c.r, c.g, c.b, shade);
    if (counter % ASPECT_RATIO_CORRECTION == 0) {
        printf("\x1b[38;2;%d;%d;%dm%s", c.r, c.g, c.b, shade);
    }
    ++counter;
}

void next_line() {
    printf("\x1b[0m\n");
}

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

void clear_fb() {
    for(u32_t i = 0; i < HEIGHT * WIDTH; i++) {
        ((col_t*)fb)[i] = (col_t){0, 0, 0, 255}; // Black background with full alpha
        ((f32_t*)zb)[i] = ZFAR;
    }
}

/* Function to project 3D point to 2D screen space */
screen_vert_t project_vertex(vec3_t p) {
    screen_vert_t sv;
    sv.x = (int)((p.x + 1.0f) * 0.5f * WIDTH);
    sv.y = (int)((1.0f - (p.y + 1.0f) * 0.5f) * HEIGHT); // Invert Y for screen space
    sv.z = p.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 (fabs(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);
}

/* Function to rasterize a single triangle using screen_tri_t */
void rasterize_triangle(tri_t tri) {
    // Project vertices to screen space
    screen_tri_t st = {
        .a = project_vertex(tri.a.p),
        .b = project_vertex(tri.b.p),
        .c = project_vertex(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),
          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),
          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),
          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
                f32_t depth = u * st.a.z + v * st.b.z + w * st.c.z;

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

                    // 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),
                        .a = 255 // Full alpha
                    };

                    // Assign to frame buffer
                    fb[y][x] = color;
                }
            }
        }
    }
}


/* Alternative render function using fixed character */
void render_fb_fixed_char() {
    const u8_t *fixed_shade = "█"; // Using the darkest shade for fixed character
    for(int y = 0; y < HEIGHT; y++) {
        for(int x = 0; x < WIDTH; x++) {
            col_t color = fb[y][x];
            set_color(color, fixed_shade);
        }
        next_line();
    }
    // Reset color at the end
    printf("\x1b[0m");
}

int main() {
    /* Example triangle */
    tri_t triangle = {
        .a = { .p = { -1.0f, -1.0f, 1.0f }, .c = { 255, 0, 0, 255 } }, // Red
        .b = { .p = {  1.0f, -1.0f, 1.0f }, .c = { 0, 255, 0, 255 } }, // Green
        .c = { .p = {  0.0f,  1.0f, 1.0f }, .c = { 0, 0, 255, 255 } }  // Blue
    };

    // Clear the screen
    clear_screen();

    // Clear frame buffer and Z-buffer
    clear_fb();

    // Rasterize the triangle
    rasterize_triangle(triangle);

    // Render the frame buffer to terminal
    // Choose one of the rendering methods:
    render_fb_fixed_char(); // Use this for fixed character rendering
    // render_fb(); // Use this for brightness-based shading, TODO: Implement

    return 0;
}
```