Implement specularity
This commit is contained in:
parent
8b9ac28402
commit
451aa48b3a
@ -4,6 +4,7 @@
|
|||||||
#include "window/window.h"
|
#include "window/window.h"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
@ -13,6 +14,7 @@ typedef struct {
|
|||||||
f32 radius;
|
f32 radius;
|
||||||
vec3f_t centre;
|
vec3f_t centre;
|
||||||
colour_t colour;
|
colour_t colour;
|
||||||
|
f32 specular;
|
||||||
} sphere_t;
|
} sphere_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -48,9 +50,16 @@ solutions_t ray_intersects_sphere(vec3f_t origin, vec3f_t direction,
|
|||||||
sphere_t sphere);
|
sphere_t sphere);
|
||||||
colour_t trace_ray(vec3f_t origin, vec3f_t direction, f32 t_min, f32 t_max,
|
colour_t trace_ray(vec3f_t origin, vec3f_t direction, f32 t_min, f32 t_max,
|
||||||
const scene_t *scene, colour_t default_colour);
|
const scene_t *scene, colour_t default_colour);
|
||||||
f32 compute_lighting(vec3f_t P, vec3f_t N, const scene_t *scene);
|
f32 compute_lighting(vec3f_t position, vec3f_t surface_normal,
|
||||||
|
vec3f_t view_vector, f32 specular_exponent,
|
||||||
|
const scene_t *scene);
|
||||||
f32 light_diffuse(f32 light_intensity, vec3f_t light_direction,
|
f32 light_diffuse(f32 light_intensity, vec3f_t light_direction,
|
||||||
vec3f_t surface_normal);
|
vec3f_t surface_normal);
|
||||||
|
f32 light_specular(f32 light_intensity, vec3f_t light_direction,
|
||||||
|
vec3f_t surface_normal, vec3f_t view_vector,
|
||||||
|
f32 specular_exponent);
|
||||||
|
f32 cos_angle_between_vectors(vec3f_t v1, vec3f_t v2);
|
||||||
|
f32 clamp(f32 value, f32 min, f32 max);
|
||||||
|
|
||||||
i32 main(i32 argc, char *argv[]) {
|
i32 main(i32 argc, char *argv[]) {
|
||||||
colour_t bg =
|
colour_t bg =
|
||||||
@ -74,6 +83,7 @@ i32 main(i32 argc, char *argv[]) {
|
|||||||
.colour =
|
.colour =
|
||||||
(colour_t){
|
(colour_t){
|
||||||
.rgba.r = 245, .rgba.g = 238, .rgba.b = 158, .rgba.a = 255},
|
.rgba.r = 245, .rgba.g = 238, .rgba.b = 158, .rgba.a = 255},
|
||||||
|
.specular = 500.0f,
|
||||||
},
|
},
|
||||||
(sphere_t){
|
(sphere_t){
|
||||||
.radius = 1.0f,
|
.radius = 1.0f,
|
||||||
@ -81,6 +91,7 @@ i32 main(i32 argc, char *argv[]) {
|
|||||||
.colour =
|
.colour =
|
||||||
(colour_t){
|
(colour_t){
|
||||||
.rgba.r = 59, .rgba.g = 142, .rgba.b = 165, .rgba.a = 255},
|
.rgba.r = 59, .rgba.g = 142, .rgba.b = 165, .rgba.a = 255},
|
||||||
|
.specular = 10.0f,
|
||||||
},
|
},
|
||||||
(sphere_t){
|
(sphere_t){
|
||||||
.radius = 1.0f,
|
.radius = 1.0f,
|
||||||
@ -88,6 +99,7 @@ i32 main(i32 argc, char *argv[]) {
|
|||||||
.colour =
|
.colour =
|
||||||
(colour_t){
|
(colour_t){
|
||||||
.rgba.r = 171, .rgba.g = 52, .rgba.b = 40, .rgba.a = 255},
|
.rgba.r = 171, .rgba.g = 52, .rgba.b = 40, .rgba.a = 255},
|
||||||
|
.specular = 500.0f,
|
||||||
},
|
},
|
||||||
(sphere_t){
|
(sphere_t){
|
||||||
.radius = 5000.0f,
|
.radius = 5000.0f,
|
||||||
@ -95,6 +107,7 @@ i32 main(i32 argc, char *argv[]) {
|
|||||||
.colour =
|
.colour =
|
||||||
(colour_t){
|
(colour_t){
|
||||||
.rgba.r = 255, .rgba.g = 255, .rgba.b = 0, .rgba.a = 255},
|
.rgba.r = 255, .rgba.g = 255, .rgba.b = 0, .rgba.a = 255},
|
||||||
|
.specular = 1000.0f,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -200,20 +213,34 @@ colour_t trace_ray(vec3f_t origin, vec3f_t direction, f32 t_min, f32 t_max,
|
|||||||
return default_colour;
|
return default_colour;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3f_t P =
|
vec3f_t position =
|
||||||
vec_add(vec3f_t, origin, vec_mul_num(vec3f_t, direction, closest_t));
|
vec_add(vec3f_t, origin, vec_mul_num(vec3f_t, direction, closest_t));
|
||||||
vec3f_t N = vec_sub(vec3f_t, P, closest_sphere->centre);
|
|
||||||
N = vec_div_num(vec3f_t, N, vec_magnitude(vec3f_t, N));
|
|
||||||
|
|
||||||
f32 light = compute_lighting(P, N, scene);
|
vec3f_t surface_normal = vec_sub(vec3f_t, position, closest_sphere->centre);
|
||||||
|
surface_normal = vec_div_num(vec3f_t, surface_normal,
|
||||||
|
vec_magnitude(vec3f_t, surface_normal));
|
||||||
|
|
||||||
return (colour_t){.rgba.r = closest_sphere->colour.rgba.r * light,
|
vec3f_t view_vector = vec_mul_num(vec3f_t, direction, -1.0f);
|
||||||
.rgba.g = closest_sphere->colour.rgba.g * light,
|
|
||||||
.rgba.b = closest_sphere->colour.rgba.b * light,
|
f32 light = compute_lighting(position, surface_normal, view_vector,
|
||||||
|
closest_sphere->specular, scene);
|
||||||
|
|
||||||
|
f32 r = (f32)(closest_sphere->colour.rgba.r) * light;
|
||||||
|
r = clamp(r, 0.0f, (f32)UINT8_MAX);
|
||||||
|
f32 g = (f32)(closest_sphere->colour.rgba.g) * light;
|
||||||
|
g = clamp(g, 0.0f, (f32)UINT8_MAX);
|
||||||
|
f32 b = (f32)(closest_sphere->colour.rgba.b) * light;
|
||||||
|
b = clamp(b, 0.0f, (f32)UINT8_MAX);
|
||||||
|
|
||||||
|
return (colour_t){.rgba.r = (u8)r,
|
||||||
|
.rgba.g = (u8)g,
|
||||||
|
.rgba.b = (u8)b,
|
||||||
.rgba.a = closest_sphere->colour.rgba.a};
|
.rgba.a = closest_sphere->colour.rgba.a};
|
||||||
}
|
}
|
||||||
|
|
||||||
f32 compute_lighting(vec3f_t P, vec3f_t N, const scene_t *scene) {
|
f32 compute_lighting(vec3f_t position, vec3f_t surface_normal,
|
||||||
|
vec3f_t view_vector, f32 specular_exponent,
|
||||||
|
const scene_t *scene) {
|
||||||
f32 I = 0.0f;
|
f32 I = 0.0f;
|
||||||
light_t light = {0};
|
light_t light = {0};
|
||||||
|
|
||||||
@ -223,20 +250,25 @@ f32 compute_lighting(vec3f_t P, vec3f_t N, const scene_t *scene) {
|
|||||||
if (light.type == LIGHT_TYPE_AMBIENT) {
|
if (light.type == LIGHT_TYPE_AMBIENT) {
|
||||||
I += light.intensity;
|
I += light.intensity;
|
||||||
} else {
|
} else {
|
||||||
vec3f_t L = {0};
|
vec3f_t light_direction = {0};
|
||||||
|
|
||||||
switch (light.type) {
|
switch (light.type) {
|
||||||
case LIGHT_TYPE_POINT:
|
case LIGHT_TYPE_POINT:
|
||||||
L = vec_sub(vec3f_t, light.position, P);
|
light_direction = vec_sub(vec3f_t, light.position, position);
|
||||||
break;
|
break;
|
||||||
case LIGHT_TYPE_DIRECTIONAL:
|
case LIGHT_TYPE_DIRECTIONAL:
|
||||||
L = light.direction;
|
light_direction = light.direction;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
I += light_diffuse(light.intensity, L, N);
|
I += light_diffuse(light.intensity, light_direction, surface_normal);
|
||||||
|
|
||||||
|
if (specular_exponent != -1.0f) {
|
||||||
|
I += light_specular(light.intensity, light_direction, surface_normal,
|
||||||
|
view_vector, specular_exponent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -245,18 +277,48 @@ f32 compute_lighting(vec3f_t P, vec3f_t N, const scene_t *scene) {
|
|||||||
|
|
||||||
f32 light_diffuse(f32 light_intensity, vec3f_t light_direction,
|
f32 light_diffuse(f32 light_intensity, vec3f_t light_direction,
|
||||||
vec3f_t surface_normal) {
|
vec3f_t surface_normal) {
|
||||||
|
return light_intensity *
|
||||||
|
cos_angle_between_vectors(light_direction, surface_normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
f32 light_specular(f32 light_intensity, vec3f_t light_direction,
|
||||||
|
vec3f_t surface_normal, vec3f_t view_vector,
|
||||||
|
f32 specular_exponent) {
|
||||||
|
vec3f_t _2N = vec_mul_num(vec3f_t, surface_normal, 2.0f);
|
||||||
f32 dot_product = vec_dot(vec3f_t, light_direction, surface_normal);
|
f32 dot_product = vec_dot(vec3f_t, light_direction, surface_normal);
|
||||||
|
|
||||||
|
vec3f_t _2N_mul_dot = vec_mul_num(vec3f_t, _2N, dot_product);
|
||||||
|
|
||||||
|
vec3f_t R = vec_sub(vec3f_t, _2N_mul_dot, light_direction);
|
||||||
|
|
||||||
|
return light_intensity *
|
||||||
|
powf(cos_angle_between_vectors(R, view_vector), specular_exponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
f32 cos_angle_between_vectors(vec3f_t v1, vec3f_t v2) {
|
||||||
|
f32 dot_product = vec_dot(vec3f_t, v1, v2);
|
||||||
|
|
||||||
if (dot_product < 0.0f) {
|
if (dot_product < 0.0f) {
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
f32 divisor = vec_magnitude(vec3f_t, light_direction) *
|
f32 divisor = vec_magnitude(vec3f_t, v1) * vec_magnitude(vec3f_t, v2);
|
||||||
vec_magnitude(vec3f_t, surface_normal);
|
|
||||||
|
|
||||||
if (divisor == 0.0f) {
|
if (divisor == 0.0f) {
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
return light_intensity * dot_product / divisor;
|
return dot_product / divisor;
|
||||||
|
}
|
||||||
|
|
||||||
|
f32 clamp(f32 value, f32 min, f32 max) {
|
||||||
|
if (value < min) {
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value > max) {
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user