flat shading

This commit is contained in:
jb 2025-07-14 18:24:46 -07:00
parent 28c30a7fcf
commit 5b72bd3337
5 changed files with 69 additions and 29 deletions

View File

@ -10,6 +10,7 @@ add_executable(${PROJECT_NAME} scripts/main.c
scripts/matrix.c scripts/matrix.c
scripts/mesh.c scripts/mesh.c
scripts/triangle.c scripts/triangle.c
scripts/light.c
scripts/display.c) scripts/display.c)
# --- SDL2 SETUP --- # --- SDL2 SETUP ---

View File

@ -29,6 +29,8 @@ enum cull_methods {
CULL_BACKFACE, CULL_BACKFACE,
}; };
typedef uint32_t color_t;
bool initialize_window(void); bool initialize_window(void);
void draw_grid(void); void draw_grid(void);
void draw_pixel(int x, int y, uint32_t color); void draw_pixel(int x, int y, uint32_t color);

13
scripts/light.c Normal file
View File

@ -0,0 +1,13 @@
#include <stdint.h>
uint32_t light_apply_intensity(uint32_t original_color, float p) {
if (p < 0) p = 0;
if (p > 1) p = 1;
uint32_t a = (original_color & 0xFF000000);
uint32_t r = (original_color & 0x00FF0000) * p;
uint32_t g = (original_color & 0x0000FF00) * p;
uint32_t b = (original_color & 0x000000FF) * p;
return (a | (r & 0x00FF0000) | (g & 0x0000FF00) | (b & 0x000000FF));
}

14
scripts/light.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef LIGHT_H
#define LIGHT_H
#include <stdint.h>
#include "vector.h"
typedef struct {
vec3_t direction;
} light_t;
uint32_t light_apply_intensity(uint32_t original_color, float p);
#endif

View File

@ -8,6 +8,7 @@
#include "vector.h" #include "vector.h"
#include "array.h" #include "array.h"
#include "matrix.h" #include "matrix.h"
#include "light.h"
#define STEP 0.075 #define STEP 0.075
@ -31,10 +32,12 @@ triangle_t* triangles_to_render = NULL; //[N_MESH_FACES];
vec3_t camera_position = { 0, 0, 0 }; vec3_t camera_position = { 0, 0, 0 };
mat4_t proj_matrix; mat4_t proj_matrix;
light_t light = { .direction = { .x = 0, .y = 0, .z = 1 }};
bool is_running = false; bool is_running = false;
int cull_method = CULL_BACKFACE; int cull_method = CULL_BACKFACE;
int render_method = RENDER_WIRE_VERTEX; int render_method = RENDER_FILL_TRIANGLE;
bool sort_faces = true; bool sort_faces = true;
uint32_t previous_frame_time = 0; uint32_t previous_frame_time = 0;
@ -56,11 +59,12 @@ void setup(void) {
float aspect = (float)window_height / (float)window_width; float aspect = (float)window_height / (float)window_width;
float znear = 0.0f; float znear = 0.0f;
float zfar = 100.0f; float zfar = 100.0f;
proj_matrix = mat4_make_perspective(fov, aspect, znear, zfar); proj_matrix = mat4_make_perspective(fov, aspect, znear, zfar);
// load cube mesh data // load cube mesh data
//load_file("..\\assets\\tank.obj"); load_file("..\\assets\\f22.obj");
load_cube_mesh_data(); //load_cube_mesh_data();
} }
@ -137,14 +141,14 @@ void update(void) {
previous_frame_time = SDL_GetTicks(); previous_frame_time = SDL_GetTicks();
mesh.rotation.y += 0.01f; //mesh.rotation.y += 0.01f;
mesh.rotation.x -= 0.01f; mesh.rotation.x -= 0.01f;
mesh.rotation.z += 0.01f; //mesh.rotation.z += 0.01f;
mesh.translation.x += 0.004f; //mesh.translation.x += 0.004f;
mesh.translation.z = 5.0f; mesh.translation.z = 5.0f;
mesh.scale.x += 0.002f; //mesh.scale.x += 0.002f;
//mesh.scale.y += 0.002f; //mesh.scale.y += 0.002f;
// create scale matrix that will be used // create scale matrix that will be used
@ -190,21 +194,22 @@ void update(void) {
transformed_vertices[j] = transformed_vertex; transformed_vertices[j] = transformed_vertex;
} }
vec3_t vector_a = vec3_from_vec4(transformed_vertices[0]); /* A */
vec3_t vector_b = vec3_from_vec4(transformed_vertices[1]); /* / \ */
vec3_t vector_c = vec3_from_vec4(transformed_vertices[2]); /* C---B */
// get the vector subtraction of B-A and C-A
vec3_t vector_ab = vec3_subtract(vector_b, vector_a);
vec3_t vector_ac = vec3_subtract(vector_c, vector_a);
vec3_normalize(&vector_ab);
vec3_normalize(&vector_ac);
// compute the face normal using the cross product to find perpindicular
vec3_t normal = vec3_cross(vector_ab, vector_ac);
vec3_normalize(&normal);
if (cull_method == CULL_BACKFACE) { if (cull_method == CULL_BACKFACE) {
// check backface culling // check backface culling
vec3_t vector_a = vec3_from_vec4(transformed_vertices[0]); /* A */
vec3_t vector_b = vec3_from_vec4(transformed_vertices[1]); /* / \ */
vec3_t vector_c = vec3_from_vec4(transformed_vertices[2]); /* C---B */
// get the vector subtraction of B-A and C-A
vec3_t vector_ab = vec3_subtract(vector_b, vector_a);
vec3_t vector_ac = vec3_subtract(vector_c, vector_a);
vec3_normalize(&vector_ab);
vec3_normalize(&vector_ac);
// compute the face normal using the cross product to find perpindicular
vec3_t normal = vec3_cross(vector_ab, vector_ac);
vec3_normalize(&normal);
// find the vector between a point in the triangle and the camera origin // find the vector between a point in the triangle and the camera origin
vec3_t camera_ray = vec3_subtract(camera_position, vector_a); vec3_t camera_ray = vec3_subtract(camera_position, vector_a);
@ -224,26 +229,31 @@ void update(void) {
projected_points[j] = mat4_mul_vec4_project(proj_matrix, transformed_vertices[j]); projected_points[j] = mat4_mul_vec4_project(proj_matrix, transformed_vertices[j]);
// Scale into the view // Scale into the view
projected_points[j].x *= roundf(window_width / 2.0); projected_points[j].x *= (window_width / 2.0);
projected_points[j].y *= roundf(window_height / 2.0); projected_points[j].y *= (window_height / 2.0);
// Translate the projected points to the middle of the screen // Translate the projected points to the middle of the screen
projected_points[j].x += roundf(window_width / 2.0); projected_points[j].x += (window_width / 2.0);
projected_points[j].y += roundf(window_height / 2.0); projected_points[j].y += (window_height / 2.0);
//projected_triangle.points[j] = projected_point; //projected_triangle.points[j] = projected_point;
} }
// calculate color using normal and light direction, then invert
float dot_color_p = -vec3_dot(normal, light.direction);
color_t flat_shaded_color = light_apply_intensity(0xFFFFFFFF, dot_color_p);
// calculate the average depth of the triangle // calculate the average depth of the triangle
float avg_depth = (transformed_vertices[0].z + transformed_vertices[1].z + transformed_vertices[2].z) / 3.0f; float avg_depth = (transformed_vertices[0].z + transformed_vertices[1].z + transformed_vertices[2].z) / 3.0f;
#define FUNC3 roundf
triangle_t projected_triangle = { triangle_t projected_triangle = {
.points = { .points = {
{ projected_points[0].x, projected_points[0].y }, { FUNC3(projected_points[0].x), FUNC3(projected_points[0].y) },
{ projected_points[1].x, projected_points[1].y }, { FUNC3(projected_points[1].x), FUNC3(projected_points[1].y) },
{ projected_points[2].x, projected_points[2].y }, { FUNC3(projected_points[2].x), FUNC3(projected_points[2].y) },
}, },
.color = mesh_face.color, .color = flat_shaded_color,
.average_depth = avg_depth, .average_depth = avg_depth,
}; };