textures rendering, but not quite working

This commit is contained in:
jb 2025-07-20 07:20:11 -07:00
parent 7a91b72708
commit 6991731160
6 changed files with 148 additions and 42 deletions

View File

@ -71,17 +71,7 @@ void draw_rect(int x, int y, int width, int height, uint32_t color) {
}
}
void draw_triangle_old(int x0, int y0, int x1, int y1, int x2, int y2, uint32_t color) {
draw_line(x0, y0, x1, y1, color);
draw_line(x1, y1, x2, y2, color);
draw_line(x2, y2, x0, y0, color);
}
void draw_triangle(triangle_t triangle, uint32_t color) {
draw_line(triangle.points[0].x, triangle.points[0].y, triangle.points[1].x, triangle.points[1].y, color);
draw_line(triangle.points[1].x, triangle.points[1].y, triangle.points[2].x, triangle.points[2].y, color);
draw_line(triangle.points[2].x, triangle.points[2].y, triangle.points[0].x, triangle.points[0].y, color);
}
void draw_line(int x0, int y0, int x1, int y1, uint32_t color) {
int delta_x = (x1 - x0);

View File

@ -38,8 +38,6 @@ void draw_grid(void);
void draw_pixel(int x, int y, uint32_t color);
void draw_line(int x0, int y0, int x1, int y1, uint32_t color);
void draw_rect(int x, int y, int width, int height, uint32_t color);
void draw_triangle(triangle_t triangle, uint32_t color);
void draw_triangle_old(int x0, int y0, int x1, int y1, int x2, int y2, uint32_t color);
void render_color_buffer(void);
void clear_color_buffer(uint32_t color);
void destroy_window(void);

View File

@ -38,7 +38,7 @@ light_t light = { .direction = { .x = 0, .y = 0, .z = 1 }};
bool is_running = false;
int cull_method = CULL_BACKFACE;
int render_method = RENDER_FILL_TRIANGLE;
int render_method = RENDER_TEXTURED;
bool sort_faces = true;
uint32_t previous_frame_time = 0;
@ -68,8 +68,8 @@ void setup(void) {
texture_width = 64;
// load cube mesh data
load_file("..\\assets\\f22.obj");
//load_cube_mesh_data();
//load_file("..\\assets\\f22.obj");
load_cube_mesh_data();
}
@ -152,9 +152,9 @@ void update(void) {
previous_frame_time = SDL_GetTicks();
mesh.rotation.y += 0.01f;
//mesh.rotation.y += 0.01f;
mesh.rotation.x -= 0.01f;
mesh.rotation.z += 0.01f;
//mesh.rotation.z += 0.01f;
//mesh.translation.x += 0.004f;
mesh.translation.z = 5.0f;
@ -334,10 +334,20 @@ void render(void) {
draw_triangle(triangle, 0xff0000ff);
break;
case RENDER_TEXTURED:
//draw_textured_triangle(triangle, mesh_texture);
draw_textured_triangle(
triangle.points[0].x, triangle.points[0].y, triangle.texcoords[0].u, triangle.texcoords[0].v, // vertex A
triangle.points[1].x, triangle.points[1].y, triangle.texcoords[1].u, triangle.texcoords[1].v, // vertex B
triangle.points[2].x, triangle.points[2].y, triangle.texcoords[2].u, triangle.texcoords[2].v, // vertex C
mesh_texture
);
break;
case RENDER_TEXTURED_LINE:
//draw_textured_triangle(triangle, mesh_texture);
draw_textured_triangle(
triangle.points[0].x, triangle.points[0].y, triangle.texcoords[0].u, triangle.texcoords[0].v, // vertex A
triangle.points[1].x, triangle.points[1].y, triangle.texcoords[1].u, triangle.texcoords[1].v, // vertex B
triangle.points[2].x, triangle.points[2].y, triangle.texcoords[2].u, triangle.texcoords[2].v, // vertex C
mesh_texture
);
draw_triangle(triangle, 0xff0000ff);
default:
break;

View File

@ -29,23 +29,23 @@ vec3_t cube_vertices[N_CUBE_VERTICES] = {
face_t cube_faces[N_CUBE_FACES] = {
// front
{ .a = 1, .b = 2, .c = 3, .a_uv = { 0, 0 }, .b_uv = { 0, 1 }, .c_uv = { 1, 1 }, .color = COLOR_ORANGE},
{ .a = 1, .b = 3, .c = 4, .a_uv = { 0, 0 }, .b_uv = { 1, 1 }, .c_uv = { 1, 0 }, .color = COLOR_ORANGE},
{ .a = 1, .b = 2, .c = 3, .a_uv = { 0, 0 }, .b_uv = { 0, 1 }, .c_uv = { 1, 1 }, .color = 0xFFFFFFFF },
{ .a = 1, .b = 3, .c = 4, .a_uv = { 0, 0 }, .b_uv = { 1, 1 }, .c_uv = { 1, 0 }, .color = 0xFFFFFFFF },
// right
{ .a = 4, .b = 3, .c = 5, .a_uv = { 0, 0 }, .b_uv = { 0, 1 }, .c_uv = { 1, 1 }, .color = COLOR_TEAL_GREEN },
{ .a = 4, .b = 5, .c = 6, .a_uv = { 0, 0 }, .b_uv = { 1, 1 }, .c_uv = { 1, 0 }, .color = COLOR_TEAL_GREEN},
{ .a = 4, .b = 3, .c = 5, .a_uv = { 0, 0 }, .b_uv = { 0, 1 }, .c_uv = { 1, 1 }, .color = 0xFFFFFFFF },
{ .a = 4, .b = 5, .c = 6, .a_uv = { 0, 0 }, .b_uv = { 1, 1 }, .c_uv = { 1, 0 }, .color = 0xFFFFFFFF },
// back
{ .a = 6, .b = 5, .c = 7, .a_uv = { 0, 0 }, .b_uv = { 0, 1 }, .c_uv = { 1, 1 }, .color = COLOR_RED },
{ .a = 6, .b = 7, .c = 8, .a_uv = { 0, 0 }, .b_uv = { 1, 1 }, .c_uv = { 1, 0 }, .color = COLOR_RED },
{ .a = 6, .b = 5, .c = 7, .a_uv = { 0, 0 }, .b_uv = { 0, 1 }, .c_uv = { 1, 1 }, .color = 0xFFFFFFFF },
{ .a = 6, .b = 7, .c = 8, .a_uv = { 0, 0 }, .b_uv = { 1, 1 }, .c_uv = { 1, 0 }, .color = 0xFFFFFFFF },
// left
{ .a = 8, .b = 7, .c = 2, .a_uv = { 0, 0 }, .b_uv = { 0, 1 }, .c_uv = { 1, 1 }, .color = COLOR_PURPLE },
{ .a = 8, .b = 2, .c = 1, .a_uv = { 0, 0 }, .b_uv = { 1, 1 }, .c_uv = { 1, 0 }, .color = COLOR_PURPLE },
{ .a = 8, .b = 7, .c = 2, .a_uv = { 0, 0 }, .b_uv = { 0, 1 }, .c_uv = { 1, 1 }, .color = 0xFFFFFFFF },
{ .a = 8, .b = 2, .c = 1, .a_uv = { 0, 0 }, .b_uv = { 1, 1 }, .c_uv = { 1, 0 }, .color = 0xFFFFFFFF },
// top
{ .a = 2, .b = 7, .c = 5, .a_uv = { 0, 0 }, .b_uv = { 0, 1 }, .c_uv = { 1, 1 }, .color = COLOR_GREY },
{ .a = 2, .b = 5, .c = 3, .a_uv = { 0, 0 }, .b_uv = { 1, 1 }, .c_uv = { 1, 0 }, .color = COLOR_GREY },
{ .a = 2, .b = 7, .c = 5, .a_uv = { 0, 0 }, .b_uv = { 0, 1 }, .c_uv = { 1, 1 }, .color = 0xFFFFFFFF },
{ .a = 2, .b = 5, .c = 3, .a_uv = { 0, 0 }, .b_uv = { 1, 1 }, .c_uv = { 1, 0 }, .color = 0xFFFFFFFF },
// bottom
{ .a = 6, .b = 8, .c = 1, .a_uv = { 0, 0 }, .b_uv = { 0, 1 }, .c_uv = { 1, 1 }, .color = COLOR_LIGHT_GREEN_BLUE },
{ .a = 6, .b = 1, .c = 4, .a_uv = { 0, 0 }, .b_uv = { 1, 1 }, .c_uv = { 1, 0 }, .color = COLOR_LIGHT_GREEN_BLUE }
{ .a = 6, .b = 8, .c = 1, .a_uv = { 0, 0 }, .b_uv = { 0, 1 }, .c_uv = { 1, 1 }, .color = 0xFFFFFFFF },
{ .a = 6, .b = 1, .c = 4, .a_uv = { 0, 0 }, .b_uv = { 1, 1 }, .c_uv = { 1, 0 }, .color = 0xFFFFFFFF }
};
void load_cube_mesh_data(void) {

View File

@ -24,6 +24,12 @@ uint32_t invert_rgb(uint32_t color) {
return a | rgb;
}
void draw_triangle(triangle_t triangle, uint32_t color) {
draw_line(triangle.points[0].x, triangle.points[0].y, triangle.points[1].x, triangle.points[1].y, color);
draw_line(triangle.points[1].x, triangle.points[1].y, triangle.points[2].x, triangle.points[2].y, color);
draw_line(triangle.points[2].x, triangle.points[2].y, triangle.points[0].x, triangle.points[0].y, color);
}
///////////////////////////////////////////////////////////////////////////////
// Draw a filled a triangle with a flat bottom
///////////////////////////////////////////////////////////////////////////////
@ -141,7 +147,60 @@ void draw_filled_triangle(int x0, int y0, int x1, int y1, int x2, int y2, uint32
}
}
void draw_textured_triangle(int x0, int y0, int x1, int y1, int x2, int y2, uint32_t* texture) {
vec3_t barycentric_weights(vec2_t a, vec2_t b, vec2_t c, vec2_t p) {
// Find the vectors between the vertices ABC and point p
vec2_t ac = vec2_subtract(c, a);
vec2_t ab = vec2_subtract(b, a);
vec2_t ap = vec2_subtract(p, a);
vec2_t pc = vec2_subtract(c, p);
vec2_t pb = vec2_subtract(b, p);
// Compute the area of the full parallegram/triangle ABC using 2D cross product
float area_parallelogram_abc = (ac.x * ab.y - ac.y * ab.x); // || AC x AB ||
// Alpha is the area of the small parallelogram/triangle PBC divided by the area of the full parallelogram/triangle ABC
float alpha = (pc.x * pb.y - pc.y * pb.x) / area_parallelogram_abc;
// Beta is the area of the small parallelogram/triangle APC divided by the area of the full parallelogram/triangle ABC
float beta = (ac.x * ap.y - ac.y * ap.x) / area_parallelogram_abc;
// Weight gamma is easily found since barycentric coordinates always add up to 1.0
float gamma = 1 - alpha - beta;
vec3_t weights = { alpha, beta, gamma };
return weights;
}
////////////////////////////
// Function to draw textue at x/y using interpolation
void draw_texel(
int x, int y, uint32_t* texture,
vec2_t point_a, vec2_t point_b, vec2_t point_c,
float u0, float v0, float u1, float v1, float u2, float v2) {
vec2_t point_p = { x, y };
vec3_t weights = barycentric_weights(point_a, point_b, point_c, point_p);
float alpha = weights.x;
float beta = weights.y;
float gamma = weights.z;
// Perform the interpolation of all U and V values using barycentric weights
float interpolated_u = (u0) * alpha + (u1) * beta + (u2) * gamma;
float interpolated_v = (v0) * alpha + (v1) * beta + (v2) * gamma;
// Map the UV coordinate to the full texture width and height
int tex_x = abs((int)(interpolated_u * texture_width));
int tex_y = abs((int)(interpolated_v * texture_height));
draw_pixel(x, y, texture[(texture_width * tex_y) + tex_x]);
}
void draw_textured_triangle(
int x0, int y0, float u0, float v0,
int x1, int y1, float u1, float v1,
int x2, int y2, float u2, float v2,
uint32_t* texture) {
// sort by y
int temp = 0, min_idx = 0, mid_idx = 1, max_idx = 2;
@ -159,21 +218,62 @@ void draw_textured_triangle(int x0, int y0, int x1, int y1, int x2, int y2, uint
int_swap(&x0, &x1);
}
// create vector points after sorting vertices
vec2_t point_a = { x0, y0 };
vec2_t point_b = { x1, y1 };
vec2_t point_c = { x2, y2 };
// FLAT BOTTOM
float inv_slope_1 = 0;
float inv_slope_2 = 0;
/*if (triangle.points[mid_idx].y - triangle.points[min_idx].y != 0) {
inv_slope_1 = (float)(triangle.points[mid_idx].x - triangle.points[min_idx].x) / fabsf(triangle.points[mid_idx].y - triangle.points[min_idx].y);
if (y1 - y0 != 0) inv_slope_1 = (float)(x1 - x0) / abs(y1 - y0);
if (y2 - y0 != 0) inv_slope_2 = (float)(x2 - x0) / abs(y2 - y0);
if (y1 - y0 != 0) {
for (int y = y0; y <= y1; y++) {
int x_start = x1 + (y - y1) * inv_slope_1;
int x_end = x0 + (y - y0) * inv_slope_2;
if (x_end < x_start) {
int_swap(&x_start, &x_end);
}
for (int x = x_start; x < x_end; x++) {
// draw pixel with color from texture
//draw_pixel(x, y, (x % 2 == 0 && y % 2 == 0) ? 0xFF00FF00 : 0xFF000000);
draw_texel(x, y, texture, point_a, point_b, point_c, u0, v0, u1, v1, u2, v2);
}
}
}
if (triangle.points[max_idx].y - triangle.points[min_idx].y != 0) {
inv_slope_2 = (float)(triangle.points[max_idx].x - triangle.points[min_idx].x) / fabsf(triangle.points[max_idx].y - triangle.points[min_idx].y);
// FLAT TOP
inv_slope_1 = 0;
inv_slope_2 = 0;
if (y2 - y1 != 0) inv_slope_1 = (float)(x2 - x1) / abs(y2 - y1);
if (y2 - y0 != 0) inv_slope_2 = (float)(x2 - x0) / abs(y2 - y0);
if (y2 - y1 != 0) {
for (int y = y1; y <= y2; y++) {
int x_start = x1 + (y - y1) * inv_slope_1;
int x_end = x0 + (y - y0) * inv_slope_2;
if (x_end < x_start) {
int_swap(&x_start, &x_end);
}
for (int x = x_start; x < x_end; x++) {
// draw pixel with color from texture
//draw_pixel(x, y, (x % 2 == 0 && y % 2 == 0) ? 0xFF00FF00 : 0xFF000000);
draw_texel(x, y, texture, point_a, point_b, point_c, u0, v0, u1, v1, u2, v2);
}
}
}
for (int y = triangle.points[min_idx].y; y <= triangle.points[mid_idx].y; y++) {
//float x_start = triangle
}
*/
}

View File

@ -32,8 +32,16 @@ typedef struct {
float average_depth;
} triangle_t;
void draw_triangle(triangle_t triangle, uint32_t color);
void draw_filled_triangle(int x0, int y0, int x1, int y1, int x2, int y2, color_t color);
void draw_textured_triangle(int x0, int y0, int x1, int y1, int x2, int y2, uint32_t* texture);
void draw_textured_triangle(
int x0, int y0, float u0, float v0,
int x1, int y1, float u1, float v1,
int x2, int y2, float u2, float v2,
uint32_t* texture);
void draw_texel(
int x, int y, uint32_t* texture,
vec2_t point_a, vec2_t point_b, vec2_t point_c,
float u0, float v0, float u1, float v1, float u2, float v2);
#endif