Test implementation of phong shader

This commit is contained in:
Abdelrahman Said 2024-08-19 00:05:59 +01:00
parent afc10fb79a
commit 2bea7218db
4 changed files with 85 additions and 13 deletions

View File

@ -41,9 +41,9 @@ int main(void) {
PhongMaterial material = { PhongMaterial material = {
.ambient = 0.1f, .ambient = 0.1f,
.diffuse = 0.8f, .diffuse = 1.2f,
.specular = 0.1f, .specular = 0.1f,
.shininess = 0.5f, .shininess = 0.8f,
}; };
obj.material = material; obj.material = material;

View File

@ -33,6 +33,13 @@ struct phong_material {
f32 shininess; f32 shininess;
}; };
typedef struct directional_light DirectionalLight;
struct directional_light {
V3f diffuse_intensity;
V3f specular_intensity;
V3f direction;
};
typedef struct model Model; typedef struct model Model;
struct model { struct model {
LIST_TYPE(V3f) * vertices; LIST_TYPE(V3f) * vertices;

View File

@ -1,8 +1,11 @@
#include "aliases.h"
#include "img.h" #include "img.h"
#include "obj.h"
#include "render.h" #include "render.h"
#include "shader.h" #include "shader.h"
#include "utils.h" #include "utils.h"
#include "vec.h" #include "vec.h"
#include <math.h>
typedef struct shader Shader; typedef struct shader Shader;
struct shader { struct shader {
@ -18,7 +21,12 @@ ShaderID orthographic_albedo = {0};
internal Shader perspective = {0}; internal Shader perspective = {0};
internal Shader orthographic = {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_eye = {0.2f, 0.1f, 0.75f};
internal V3f g_target = {0}; internal V3f g_target = {0};
internal V3f g_up = {0.0f, 1.0f, 0.0f}; 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 FragmentData *data,
const Colour *colour, const Colour *colour,
const Model *model) { const Model *model) {
f32 intensity; V3f norm;
if (model->normal) { if (model->normal) {
u64 nm_x = data->tex_coords.u * model->normal->width; u64 nm_x = data->tex_coords.u * model->normal->width;
u64 nm_y = (1.0f - data->tex_coords.v) * model->normal->height; u64 nm_y = (1.0f - data->tex_coords.v) * model->normal->height;
Colour pixel = get_pixel(Colour, model->normal, nm_x, nm_y); 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); normalise_v3(norm);
intensity = get_intensity(&norm);
} else { } else {
intensity = get_intensity(&data->normal); norm = data->normal;
} }
Colour output; Colour output;
@ -103,9 +109,45 @@ internal FragmentResult phong_shader_fragment(void *shader,
output = *colour; output = *colour;
} }
output.r = clamp(intensity * output.r, 0.0f, 255.0f); V3f local_colour = {.r = output.r, .g = output.g, .b = output.b};
output.g = clamp(intensity * output.g, 0.0f, 255.0f); local_colour = num_div_v3(local_colour, 255.0f);
output.b = clamp(intensity * output.b, 0.0f, 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}; return (FragmentResult){.colour = output};
} }
@ -131,7 +173,7 @@ internal M4x4f get_projection_matrix(ProjectionType projection_type) {
} }
internal f32 get_intensity(const V3f *normal) { internal f32 get_intensity(const V3f *normal) {
V3f light = g_directional_light; V3f light = g_directional_light.direction;
normalise_v3(light); normalise_v3(light);
f32 intensity = dot_v3((*normal), light); f32 intensity = dot_v3((*normal), light);

View File

@ -90,7 +90,30 @@ MAKE_LIST_TYPE(V2f);
#define dot_v3(V1, V2) \ #define dot_v3(V1, V2) \
((f32)V1.x * (f32)V2.x + (f32)V1.y * (f32)V2.y + (f32)V1.z * (f32)V2.z) ((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))) #define magnitude_v3(V) (sqrtf(dot_v3(V, V)))