Add shading

This commit is contained in:
Abdelrahman Said 2024-07-31 23:05:39 +01:00
parent 9f9cc2308d
commit c3c0dd732e
3 changed files with 48 additions and 6 deletions

View File

@ -37,8 +37,9 @@ int main(void) {
}
clear_image(&img, bg);
render_model(&model, &img, teal, RENDER_TYPE_FILLED, COLOUR_TYPE_RANDOM);
render_model(&model, &img, orange, RENDER_TYPE_WIREFRAME, COLOUR_TYPE_FIXED);
render_model(&model, &img, teal, RENDER_TYPE_SHADED, COLOUR_TYPE_FIXED);
// render_model(&model, &img, orange, RENDER_TYPE_WIREFRAME,
// COLOUR_TYPE_FIXED);
save_image(&img, "result.pam");
wapp_mem_arena_destroy(&arena);

View File

@ -5,15 +5,33 @@
#include "typed_list.h"
#include "utils.h"
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#define TRIANGLE_VERTICES 3
#define V2(T, ELEM_T, X0, Y0, X1, Y1) \
((T){(ELEM_T)X1 - (ELEM_T)X0, (ELEM_T)Y1 - (ELEM_T)Y0})
#define V3(T, ELEM_T, X0, Y0, Z0, X1, Y1, Z1) \
((T){(ELEM_T)X1 - (ELEM_T)X0, (ELEM_T)Y1 - (ELEM_T)Y0, \
(ELEM_T)Z1 - (ELEM_T)Z0})
#define dot_v2(V1, V2) ((f32)V1.x * (f32)V2.x + (f32)V1.y * (f32)V2.y)
#define dot_v3(V1, V2) \
((f32)V1.x * (f32)V2.x + (f32)V1.y * (f32)V2.y + (f32)V1.z * (f32)V2.z)
#define V2(T, ELEM_T, X0, Y0, X1, Y1) \
((T){(ELEM_T)X1 - (ELEM_T)X0, (ELEM_T)Y1 - (ELEM_T)Y0})
#define normalise_v3(V) \
do { \
f32 magnitude = sqrtf(dot_v3(V, V)); \
V.x /= magnitude; \
V.y /= magnitude; \
V.z /= magnitude; \
} while (0);
#define cross_product(V1, V2) \
((V3f){ \
.x = V1.y * V2.z - V1.z * V2.y, \
.y = V1.z * V2.x - V1.x * V2.z, \
.z = V1.x * V2.y - V1.y * V2.x, \
})
typedef struct triangle_bbox TriangleBBox;
struct triangle_bbox {
@ -63,6 +81,8 @@ internal void get_image_coordinates(const Vertex *vertex, const Image *img,
u64 *x, u64 *y);
internal u64 ndc_to_image_coordinate(f32 value, u64 max);
V3f g_light_dir = {0.0f, 0.0f, -1.0f};
Model load_obj_file(Arena *arena, const char *filename) {
if (!arena) {
return NULL_MODEL;
@ -148,9 +168,29 @@ internal void render_triangle(const Triangle *triangle, const Model *model,
draw_line(img, x0, y0, x1, y1, colour);
}
} else if (type == RENDER_TYPE_FILLED) {
} else if (type == RENDER_TYPE_FILLED || type == RENDER_TYPE_SHADED) {
f32 intensity = 1.0f;
if (type == RENDER_TYPE_SHADED) {
V3f ab = V3(V3f, f32, vertices[0].x, vertices[0].y, vertices[0].z,
vertices[1].x, vertices[1].y, vertices[1].z);
V3f ac = V3(V3f, f32, vertices[0].x, vertices[0].y, vertices[0].z,
vertices[2].x, vertices[2].y, vertices[2].z);
V3f normal = cross_product(ac, ab);
normalise_v3(normal);
intensity = dot_v3(normal, g_light_dir);
colour.r *= intensity;
colour.g *= intensity;
colour.b *= intensity;
}
if (intensity > 0.0f) {
fill_triangle(img, vertices, colour);
}
}
}
internal void fill_triangle(Image *img, Vertex vertices[TRIANGLE_VERTICES],

View File

@ -26,6 +26,7 @@ struct triangle {
typedef enum {
RENDER_TYPE_WIREFRAME,
RENDER_TYPE_FILLED,
RENDER_TYPE_SHADED,
COUNT_RENDER_TYPES,
} RenderType;