Implement diffuse lighting
This commit is contained in:
parent
f34e234609
commit
8b9ac28402
@ -15,9 +15,28 @@ typedef struct {
|
|||||||
colour_t colour;
|
colour_t colour;
|
||||||
} sphere_t;
|
} sphere_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
LIGHT_TYPE_POINT,
|
||||||
|
LIGHT_TYPE_DIRECTIONAL,
|
||||||
|
LIGHT_TYPE_AMBIENT,
|
||||||
|
|
||||||
|
COUNT_LIGHT_TYPE,
|
||||||
|
} light_type_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
light_type_t type;
|
||||||
|
f32 intensity;
|
||||||
|
union {
|
||||||
|
vec3f_t position;
|
||||||
|
vec3f_t direction;
|
||||||
|
};
|
||||||
|
} light_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
sphere_t *spheres;
|
sphere_t *spheres;
|
||||||
u32 count;
|
light_t *lights;
|
||||||
|
u32 spheres_count;
|
||||||
|
u32 lights_count;
|
||||||
} scene_t;
|
} scene_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -29,6 +48,9 @@ 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 light_diffuse(f32 light_intensity, vec3f_t light_direction,
|
||||||
|
vec3f_t surface_normal);
|
||||||
|
|
||||||
i32 main(i32 argc, char *argv[]) {
|
i32 main(i32 argc, char *argv[]) {
|
||||||
colour_t bg =
|
colour_t bg =
|
||||||
@ -67,11 +89,37 @@ i32 main(i32 argc, char *argv[]) {
|
|||||||
(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},
|
||||||
},
|
},
|
||||||
|
(sphere_t){
|
||||||
|
.radius = 5000.0f,
|
||||||
|
.centre = (vec3f_t){.x = 0.0f, .y = -5001.0f, .z = 0.0f},
|
||||||
|
.colour =
|
||||||
|
(colour_t){
|
||||||
|
.rgba.r = 255, .rgba.g = 255, .rgba.b = 0, .rgba.a = 255},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
light_t lights[] = {
|
||||||
|
(light_t){
|
||||||
|
.type = LIGHT_TYPE_AMBIENT,
|
||||||
|
.intensity = 0.2f,
|
||||||
|
},
|
||||||
|
(light_t){
|
||||||
|
.type = LIGHT_TYPE_POINT,
|
||||||
|
.intensity = 0.6f,
|
||||||
|
.position = (vec3f_t){.x = 2.0f, .y = 1.0f, .z = 0.0f},
|
||||||
|
},
|
||||||
|
(light_t){
|
||||||
|
.type = LIGHT_TYPE_DIRECTIONAL,
|
||||||
|
.intensity = 0.2f,
|
||||||
|
.direction = (vec3f_t){.x = 1.0f, .y = 4.0f, .z = 4.0f},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
scene_t scene = {
|
scene_t scene = {
|
||||||
.spheres = spheres,
|
.spheres = spheres,
|
||||||
.count = ARR_LEN(spheres),
|
.lights = lights,
|
||||||
|
.spheres_count = ARR_LEN(spheres),
|
||||||
|
.lights_count = ARR_LEN(lights),
|
||||||
};
|
};
|
||||||
|
|
||||||
i32 w_min = ((i32)window.half_width) * -1;
|
i32 w_min = ((i32)window.half_width) * -1;
|
||||||
@ -131,7 +179,7 @@ colour_t trace_ray(vec3f_t origin, vec3f_t direction, f32 t_min, f32 t_max,
|
|||||||
f32 closest_t = INFINITY;
|
f32 closest_t = INFINITY;
|
||||||
sphere_t *closest_sphere = NULL;
|
sphere_t *closest_sphere = NULL;
|
||||||
|
|
||||||
for (u32 i = 0; i < scene->count; ++i) {
|
for (u32 i = 0; i < scene->spheres_count; ++i) {
|
||||||
solutions_t solutions =
|
solutions_t solutions =
|
||||||
ray_intersects_sphere(origin, direction, scene->spheres[i]);
|
ray_intersects_sphere(origin, direction, scene->spheres[i]);
|
||||||
|
|
||||||
@ -152,5 +200,63 @@ colour_t trace_ray(vec3f_t origin, vec3f_t direction, f32 t_min, f32 t_max,
|
|||||||
return default_colour;
|
return default_colour;
|
||||||
}
|
}
|
||||||
|
|
||||||
return closest_sphere->colour;
|
vec3f_t P =
|
||||||
|
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);
|
||||||
|
|
||||||
|
return (colour_t){.rgba.r = closest_sphere->colour.rgba.r * light,
|
||||||
|
.rgba.g = closest_sphere->colour.rgba.g * light,
|
||||||
|
.rgba.b = closest_sphere->colour.rgba.b * light,
|
||||||
|
.rgba.a = closest_sphere->colour.rgba.a};
|
||||||
|
}
|
||||||
|
|
||||||
|
f32 compute_lighting(vec3f_t P, vec3f_t N, const scene_t *scene) {
|
||||||
|
f32 I = 0.0f;
|
||||||
|
light_t light = {0};
|
||||||
|
|
||||||
|
for (u32 i = 0; i < scene->lights_count; ++i) {
|
||||||
|
light = scene->lights[i];
|
||||||
|
|
||||||
|
if (light.type == LIGHT_TYPE_AMBIENT) {
|
||||||
|
I += light.intensity;
|
||||||
|
} else {
|
||||||
|
vec3f_t L = {0};
|
||||||
|
|
||||||
|
switch (light.type) {
|
||||||
|
case LIGHT_TYPE_POINT:
|
||||||
|
L = vec_sub(vec3f_t, light.position, P);
|
||||||
|
break;
|
||||||
|
case LIGHT_TYPE_DIRECTIONAL:
|
||||||
|
L = light.direction;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
I += light_diffuse(light.intensity, L, N);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return I;
|
||||||
|
}
|
||||||
|
|
||||||
|
f32 light_diffuse(f32 light_intensity, vec3f_t light_direction,
|
||||||
|
vec3f_t surface_normal) {
|
||||||
|
f32 dot_product = vec_dot(vec3f_t, light_direction, surface_normal);
|
||||||
|
|
||||||
|
if (dot_product < 0.0f) {
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
f32 divisor = vec_magnitude(vec3f_t, light_direction) *
|
||||||
|
vec_magnitude(vec3f_t, surface_normal);
|
||||||
|
|
||||||
|
if (divisor == 0.0f) {
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
return light_intensity * dot_product / divisor;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user