diff --git a/CMakeLists.txt b/CMakeLists.txt index 3cb2c56..4f6626f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,7 @@ add_executable(${PROJECT_NAME} scripts/main.c scripts/matrix.c scripts/mesh.c scripts/triangle.c + scripts/light.c scripts/display.c) # --- SDL2 SETUP --- diff --git a/scripts/display.h b/scripts/display.h index 96bf99b..6fc47a3 100644 --- a/scripts/display.h +++ b/scripts/display.h @@ -29,6 +29,8 @@ enum cull_methods { CULL_BACKFACE, }; +typedef uint32_t color_t; + bool initialize_window(void); void draw_grid(void); void draw_pixel(int x, int y, uint32_t color); diff --git a/scripts/light.c b/scripts/light.c new file mode 100644 index 0000000..617a585 --- /dev/null +++ b/scripts/light.c @@ -0,0 +1,13 @@ +#include + +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)); +} \ No newline at end of file diff --git a/scripts/light.h b/scripts/light.h new file mode 100644 index 0000000..9e914ae --- /dev/null +++ b/scripts/light.h @@ -0,0 +1,14 @@ +#ifndef LIGHT_H +#define LIGHT_H + +#include +#include "vector.h" + +typedef struct { + vec3_t direction; +} light_t; + +uint32_t light_apply_intensity(uint32_t original_color, float p); + +#endif + diff --git a/scripts/main.c b/scripts/main.c index bbb473f..90b9607 100644 --- a/scripts/main.c +++ b/scripts/main.c @@ -8,6 +8,7 @@ #include "vector.h" #include "array.h" #include "matrix.h" +#include "light.h" #define STEP 0.075 @@ -31,10 +32,12 @@ triangle_t* triangles_to_render = NULL; //[N_MESH_FACES]; vec3_t camera_position = { 0, 0, 0 }; mat4_t proj_matrix; +light_t light = { .direction = { .x = 0, .y = 0, .z = 1 }}; + bool is_running = false; int cull_method = CULL_BACKFACE; -int render_method = RENDER_WIRE_VERTEX; +int render_method = RENDER_FILL_TRIANGLE; bool sort_faces = true; uint32_t previous_frame_time = 0; @@ -56,11 +59,12 @@ void setup(void) { float aspect = (float)window_height / (float)window_width; float znear = 0.0f; float zfar = 100.0f; + proj_matrix = mat4_make_perspective(fov, aspect, znear, zfar); // load cube mesh data - //load_file("..\\assets\\tank.obj"); - load_cube_mesh_data(); + load_file("..\\assets\\f22.obj"); + //load_cube_mesh_data(); } @@ -137,14 +141,14 @@ 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.x += 0.004f; mesh.translation.z = 5.0f; - mesh.scale.x += 0.002f; + //mesh.scale.x += 0.002f; //mesh.scale.y += 0.002f; // create scale matrix that will be used @@ -190,21 +194,22 @@ void update(void) { 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) { // 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 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]); // Scale into the view - projected_points[j].x *= roundf(window_width / 2.0); - projected_points[j].y *= roundf(window_height / 2.0); + projected_points[j].x *= (window_width / 2.0); + projected_points[j].y *= (window_height / 2.0); // Translate the projected points to the middle of the screen - projected_points[j].x += roundf(window_width / 2.0); - projected_points[j].y += roundf(window_height / 2.0); + projected_points[j].x += (window_width / 2.0); + projected_points[j].y += (window_height / 2.0); //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 float avg_depth = (transformed_vertices[0].z + transformed_vertices[1].z + transformed_vertices[2].z) / 3.0f; - +#define FUNC3 roundf triangle_t projected_triangle = { .points = { - { projected_points[0].x, projected_points[0].y }, - { projected_points[1].x, projected_points[1].y }, - { projected_points[2].x, projected_points[2].y }, + { FUNC3(projected_points[0].x), FUNC3(projected_points[0].y) }, + { FUNC3(projected_points[1].x), FUNC3(projected_points[1].y) }, + { FUNC3(projected_points[2].x), FUNC3(projected_points[2].y) }, }, - .color = mesh_face.color, + .color = flat_shaded_color, .average_depth = avg_depth, };