Test implementation of phong shader

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

View File

@@ -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 <math.h>
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);