From 70784cdb24628e758df27cbe1965ff83102decb0 Mon Sep 17 00:00:00 2001 From: sanine-a Date: Wed, 3 Jun 2020 00:34:36 -0500 Subject: add multiple lights to shaders --- CMakeLists.txt | 2 +- cel.fs | 110 +++++++ demo.c | 122 ++++---- demo.vs | 14 +- include/common.h | 2 +- include/honey.h | 1 + include/light.h | 33 +++ include/shader.h | 21 ++ sphere-tex.png | Bin 0 -> 55783 bytes sphere-tex.xcf | Bin 0 -> 386241 bytes sphere.mtl | 13 + sphere.obj | 855 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ sphere.png | Bin 0 -> 82423 bytes src/light.c | 20 ++ src/shader.c | 57 ++++ 15 files changed, 1176 insertions(+), 74 deletions(-) create mode 100644 cel.fs create mode 100644 include/light.h create mode 100644 sphere-tex.png create mode 100644 sphere-tex.xcf create mode 100644 sphere.mtl create mode 100644 sphere.obj create mode 100644 sphere.png create mode 100644 src/light.c diff --git a/CMakeLists.txt b/CMakeLists.txt index b48428d..41cb559 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,7 @@ add_executable(honey_engine_demo demo.c) set(CMAKE_C_FLAGS "-g") -add_library(honey src/honey.c src/camera.c src/error.c src/input.c src/mesh.c src/model.c src/primitives.c src/shader.c src/texture.c) +add_library(honey src/honey.c src/camera.c src/error.c src/input.c src/light.c src/mesh.c src/model.c src/primitives.c src/shader.c src/texture.c) add_library(glad src/glad.c) add_library(stb_image src/stb_image.c) diff --git a/cel.fs b/cel.fs new file mode 100644 index 0000000..ef9cd6a --- /dev/null +++ b/cel.fs @@ -0,0 +1,110 @@ +#version 330 core + +/* input from the vector shader */ +in vec3 in_normal; +in vec2 in_texture_coordinate; +in vec3 in_fragment_position; + +/* light uniforms */ +uniform vec3 ambient_color; + +struct point_light { + vec3 position; /* view position */ + + float constant; + float linear; + float quadratic; + + vec3 color; +}; + +struct directional_light { + vec3 direction; + vec3 color; +}; + +#define MAX_POINT_LIGHTS 8 +#define MAX_DIRECTIONAL_LIGHTS 8 + +uniform point_light point_lights[MAX_POINT_LIGHTS]; +uniform int n_point_lights; + +uniform directional_light directional_lights[MAX_DIRECTIONAL_LIGHTS]; +uniform int n_directional_lights; + +/* texture uniforms */ +uniform sampler2D tex; + +/* view matrix */ +uniform mat4 view; + +out vec4 fragment_color; + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/* compute phong cel-shader intensity */ +float compute_light_intensity(vec3 normal, vec3 light_direction, vec3 view_direction) { + /* diffuse light */ + float diffuse_intensity = max(dot(normal, light_direction), 0); + diffuse_intensity = smoothstep(0, 0.01, diffuse_intensity); + + /* specular highlight */ + vec3 reflection_direction = reflect(-light_direction, normal); + float specular_intensity = pow(max(dot(view_direction, reflection_direction), 0), 256); + specular_intensity = smoothstep(0.005, 0.01, specular_intensity); + + return diffuse_intensity + specular_intensity; +} + +/* compute directional light contribution */ +vec3 compute_directional_light(directional_light light, vec3 normal, vec3 view_direction) { + vec3 light_direction = -vec3(view * vec4(light.direction.xyz, 0.0)); + return light.color * compute_light_intensity(normal, light_direction, view_direction); +} + +/* compute point light contribution */ +vec3 compute_point_light(point_light light, vec3 normal, vec3 fragment_position, vec3 view_direction) { + vec3 light_position = vec3(view * vec4(light.position.xyz, 1.0)); + vec3 light_direction = normalize(light_position - fragment_position); + + float light_intensity = compute_light_intensity(normal, light_direction, view_direction); + + /* attenuation */ + float distance = length(light_position - fragment_position); + float attenuation = 1.0 / (light.constant + + light.linear * distance + + light.quadratic * distance * distance); + + return attenuation * light.color * light_intensity; +} + +void main() +{ + vec3 normal = normalize(in_normal); + vec3 view_direction = normalize(-in_fragment_position); + + vec3 point_light_contrib = vec3(0, 0, 0); + for (int i=0; iposition[0] = x; + light->position[1] = y; + light->position[2] = z; + + light->color[0] = r; + light->color[1] = g; + light->color[2] = b; + + light->constant = constant; + light->linear = linear; + light->quadratic = quadratic; +} diff --git a/src/shader.c b/src/shader.c index d250629..d570f52 100644 --- a/src/shader.c +++ b/src/shader.c @@ -164,4 +164,61 @@ void honey_shader_set_mat4(honey_shader shader, } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void honey_shader_set_point_light(honey_shader shader, + int point_light_index, + honey_point_light light) { + char name[HONEY_MAX_LIGHT_NAME_LENGTH]; + + snprintf(name, + HONEY_MAX_LIGHT_NAME_LENGTH, + "point_lights[%d].position", + point_light_index); + honey_shader_set_vec3(shader, name, light.position); + + snprintf(name, + HONEY_MAX_LIGHT_NAME_LENGTH, + "point_lights[%d].color", + point_light_index); + honey_shader_set_vec3(shader, name, light.color); + + snprintf(name, + HONEY_MAX_LIGHT_NAME_LENGTH, + "point_lights[%d].constant", + point_light_index); + honey_shader_set_float(shader, name, light.constant); + + snprintf(name, + HONEY_MAX_LIGHT_NAME_LENGTH, + "point_lights[%d].linear", + point_light_index); + honey_shader_set_float(shader, name, light.linear); + + snprintf(name, + HONEY_MAX_LIGHT_NAME_LENGTH, + "point_lights[%d].quadratic", + point_light_index); + honey_shader_set_float(shader, name, light.quadratic); +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void honey_shader_set_directional_light(honey_shader shader, + int directional_light_index, + honey_directional_light light) { + char name[HONEY_MAX_LIGHT_NAME_LENGTH]; + + snprintf(name, + HONEY_MAX_LIGHT_NAME_LENGTH, + "directional_lights[%d].direction", + directional_light_index); + honey_shader_set_vec3(shader, name, light.direction); + + snprintf(name, + HONEY_MAX_LIGHT_NAME_LENGTH, + "directional_lights[%d].color", + directional_light_index); + honey_shader_set_vec3(shader, name, light.color); +} + -- cgit v1.2.1