From 2bea7218db67c0158b1c54a671d49c74efd11c3e Mon Sep 17 00:00:00 2001 From: Abdelrahman Date: Mon, 19 Aug 2024 00:05:59 +0100 Subject: [PATCH] Test implementation of phong shader --- src/main.c | 4 +-- src/model/obj.h | 7 +++++ src/shader/shaders.c | 62 +++++++++++++++++++++++++++++++++++++------- src/vec/vec.h | 25 +++++++++++++++++- 4 files changed, 85 insertions(+), 13 deletions(-) diff --git a/src/main.c b/src/main.c index 49df6c9..f39a2c1 100644 --- a/src/main.c +++ b/src/main.c @@ -41,9 +41,9 @@ int main(void) { PhongMaterial material = { .ambient = 0.1f, - .diffuse = 0.8f, + .diffuse = 1.2f, .specular = 0.1f, - .shininess = 0.5f, + .shininess = 0.8f, }; obj.material = material; diff --git a/src/model/obj.h b/src/model/obj.h index 186b003..4bda0d7 100644 --- a/src/model/obj.h +++ b/src/model/obj.h @@ -33,6 +33,13 @@ struct phong_material { f32 shininess; }; +typedef struct directional_light DirectionalLight; +struct directional_light { + V3f diffuse_intensity; + V3f specular_intensity; + V3f direction; +}; + typedef struct model Model; struct model { LIST_TYPE(V3f) * vertices; diff --git a/src/shader/shaders.c b/src/shader/shaders.c index 84ee0ea..6100892 100644 --- a/src/shader/shaders.c +++ b/src/shader/shaders.c @@ -1,8 +1,11 @@ +#include "aliases.h" #include "img.h" +#include "obj.h" #include "render.h" #include "shader.h" #include "utils.h" #include "vec.h" +#include typedef struct shader Shader; struct shader { @@ -18,7 +21,12 @@ ShaderID orthographic_albedo = {0}; internal Shader perspective = {0}; internal Shader orthographic = {0}; -internal V3f g_directional_light = {0.0f, 0.0f, 1.0f}; +internal V3f g_ambient_light = {0.3f, 0.75f, 0.15f}; +internal DirectionalLight g_directional_light = { + .diffuse_intensity = {0.9f, 0.8f, 0.6f}, + .specular_intensity = {0.5f, 0.8f, 2.0f}, + .direction = {0.0f, 0.0f, 1.0f}, +}; internal V3f g_eye = {0.2f, 0.1f, 0.75f}; internal V3f g_target = {0}; internal V3f g_up = {0.0f, 1.0f, 0.0f}; @@ -80,18 +88,16 @@ internal FragmentResult phong_shader_fragment(void *shader, const FragmentData *data, const Colour *colour, const Model *model) { - f32 intensity; + V3f norm; if (model->normal) { u64 nm_x = data->tex_coords.u * model->normal->width; u64 nm_y = (1.0f - data->tex_coords.v) * model->normal->height; Colour pixel = get_pixel(Colour, model->normal, nm_x, nm_y); - V3f norm = {.x = pixel.r, .y = pixel.g, .z = pixel.b}; + norm = (V3f){.x = pixel.r, .y = pixel.g, .z = pixel.b}; normalise_v3(norm); - - intensity = get_intensity(&norm); } else { - intensity = get_intensity(&data->normal); + norm = data->normal; } Colour output; @@ -103,9 +109,45 @@ internal FragmentResult phong_shader_fragment(void *shader, output = *colour; } - output.r = clamp(intensity * output.r, 0.0f, 255.0f); - output.g = clamp(intensity * output.g, 0.0f, 255.0f); - output.b = clamp(intensity * output.b, 0.0f, 255.0f); + V3f local_colour = {.r = output.r, .g = output.g, .b = output.b}; + local_colour = num_div_v3(local_colour, 255.0f); + + // Ambient term + V3f intensity = num_mul_v3(g_ambient_light, model->material.ambient); + + // Diffuse term + f32 l_dot_n = dot_v3(norm, g_directional_light.direction); + if (l_dot_n <= 0.0f) { + goto RETURN_OUTPUT_COLOUR; + } + + V3f diffuse = num_mul_v3(g_directional_light.diffuse_intensity, + model->material.diffuse * l_dot_n); + intensity = add_v3(intensity, diffuse); + + // Specular term + V3f _2_l_dot_n_norm = num_mul_v3(norm, 2.0f * l_dot_n); + V3f reflected = sub_v3(_2_l_dot_n_norm, g_directional_light.direction); + f32 r_dot_v = dot_v3(reflected, data->position); + if (r_dot_v <= 0.0f) { + goto RETURN_OUTPUT_COLOUR; + } + + V3f specular = num_mul_v3( + g_directional_light.specular_intensity, + powf(model->material.specular * r_dot_v, model->material.shininess)); + intensity = add_v3(intensity, specular); + +RETURN_OUTPUT_COLOUR: + intensity.r = clamp(intensity.r, 0.0f, 1.0f); + intensity.g = clamp(intensity.g, 0.0f, 1.0f); + intensity.b = clamp(intensity.b, 0.0f, 1.0f); + + local_colour = mul_v3(local_colour, intensity); + + output.r = 255.0f * local_colour.r; + output.g = 255.0f * local_colour.g; + output.b = 255.0f * local_colour.b; return (FragmentResult){.colour = output}; } @@ -131,7 +173,7 @@ internal M4x4f get_projection_matrix(ProjectionType projection_type) { } internal f32 get_intensity(const V3f *normal) { - V3f light = g_directional_light; + V3f light = g_directional_light.direction; normalise_v3(light); f32 intensity = dot_v3((*normal), light); diff --git a/src/vec/vec.h b/src/vec/vec.h index 86ca1b4..f19b146 100644 --- a/src/vec/vec.h +++ b/src/vec/vec.h @@ -90,7 +90,30 @@ MAKE_LIST_TYPE(V2f); #define dot_v3(V1, V2) \ ((f32)V1.x * (f32)V2.x + (f32)V1.y * (f32)V2.y + (f32)V1.z * (f32)V2.z) -#define num_mul_v3(N, V) ((V3f){.x = N * V.x, .y = N * V.y, .z = N * V.z}) +#define add_v3(V1, V2) \ + ((V3f){ \ + .x = V1.x + V2.x, \ + .y = V1.y + V2.y, \ + .z = V1.z + V2.z, \ + }) + +#define sub_v3(V1, V2) \ + ((V3f){ \ + .x = V1.x - V2.x, \ + .y = V1.y - V2.y, \ + .z = V1.z - V2.z, \ + }) + +#define mul_v3(V1, V2) \ + ((V3f){ \ + .x = V1.x * V2.x, \ + .y = V1.y * V2.y, \ + .z = V1.z * V2.z, \ + }) + +#define num_mul_v3(V, N) ((V3f){.x = (N) * V.x, .y = (N) * V.y, .z = (N) * V.z}) + +#define num_div_v3(V, N) ((V3f){.x = V.x / (N), .y = V.y / (N), .z = V.z / (N)}) #define magnitude_v3(V) (sqrtf(dot_v3(V, V)))