diff --git a/assets/krita/plaster_texture_1k.png b/assets/krita/plaster_texture_1k.png new file mode 100644 index 0000000..345e4e3 Binary files /dev/null and b/assets/krita/plaster_texture_1k.png differ diff --git a/shaders/shader.frag b/shaders/shader.frag index c79f91f..6b54218 100644 --- a/shaders/shader.frag +++ b/shaders/shader.frag @@ -1,4 +1,4 @@ -#version 330 +#version 460 core in vec4 vertex_color; in vec2 texture_coord; @@ -9,6 +9,7 @@ out vec4 color; // Must match the same as in math.h const int MAX_POINT_LIGHTS = 3; +const int MAX_SPOT_LIGHTS = 3; struct Light { vec3 color; @@ -17,18 +18,25 @@ struct Light { }; struct Directional_Light { - Light base; + Light light; vec3 direction; }; struct Point_Light { - Light base; + Light light; vec3 position; float constant; float linear; float exponent; }; +struct Spot_Light { + Point_Light point_light; + + vec3 direction; + float edge; +}; + struct Material { float shininess; float specular_intensity; @@ -37,8 +45,10 @@ struct Material { uniform Directional_Light sun; uniform Point_Light point_lights[MAX_POINT_LIGHTS]; +uniform Spot_Light spot_lights[MAX_SPOT_LIGHTS]; uniform int point_light_count; +uniform int spot_light_count; uniform sampler2D tex; uniform Material material; uniform vec3 eye_position; @@ -65,27 +75,55 @@ vec4 calculate_light_by_direction(Light light, vec3 direction) { return ambient_color + diffuse_color + specular_color; } +vec4 calculate_point_light(Point_Light point_light) { + vec3 direction = frag_pos - point_light.position; + float distance = length(direction); + direction = normalize(direction); + + vec4 light_color = calculate_light_by_direction(point_light.light, direction); + float attentuation = point_light.exponent * distance * distance + point_light.linear * distance + point_light.constant; + + return (light_color / attentuation); +} + vec4 calculate_point_lights() { vec4 final_color = vec4(0, 0, 0, 0); for (int i=0; i spot_light.edge) { + vec4 light_color = calculate_point_light(spot_light.point_light); + + return light_color * (1.0f - (1.0f - spot_light_factor)*(1.0f/(1.0f - spot_light.edge))); + } + + return vec4(0, 0, 0, 0); +} + +vec4 calculate_spot_lights() { + vec4 final_color = vec4(0, 0, 0, 0); + + for (int i=0; iview = glGetUniformLocation(shader->id, "view"); shader->eye_position = glGetUniformLocation(shader->id, "eye_position"); - shader->directional_light.color = glGetUniformLocation(shader->id, "sun.base.color"); - shader->directional_light.ambient_intensity = glGetUniformLocation(shader->id, "sun.base.ambient_intensity"); - shader->directional_light.diffuse_intensity = glGetUniformLocation(shader->id, "sun.base.diffuse_intensity"); + shader->directional_light.color = glGetUniformLocation(shader->id, "sun.light.color"); + shader->directional_light.ambient_intensity = glGetUniformLocation(shader->id, "sun.light.ambient_intensity"); + shader->directional_light.diffuse_intensity = glGetUniformLocation(shader->id, "sun.light.diffuse_intensity"); shader->directional_light.direction = glGetUniformLocation(shader->id, "sun.direction"); shader->shininess = glGetUniformLocation(shader->id, "material.shininess"); shader->specular_intensity = glGetUniformLocation(shader->id, "material.specular_intensity"); shader->point_light_count = glGetUniformLocation(shader->id, "point_light_count"); + shader->spot_light_count = glGetUniformLocation(shader->id, "spot_light_count"); + // Point lights for (size_t i=0; ipoint_lights[i].color = glGetUniformLocation(shader->id, location_buffer); - snprintf(location_buffer, sizeof(location_buffer), "point_lights[%zu].base.ambient_intensity", i); + snprintf(location_buffer, sizeof(location_buffer), "point_lights[%zu].light.ambient_intensity", i); shader->point_lights[i].ambient_intensity = glGetUniformLocation(shader->id, location_buffer); - snprintf(location_buffer, sizeof(location_buffer), "point_lights[%zu].base.diffuse_intensity", i); + snprintf(location_buffer, sizeof(location_buffer), "point_lights[%zu].light.diffuse_intensity", i); shader->point_lights[i].diffuse_intensity = glGetUniformLocation(shader->id, location_buffer); snprintf(location_buffer, sizeof(location_buffer), "point_lights[%zu].position", i); @@ -91,6 +93,31 @@ bool create_shader(Shader *shader, const char *vertex_shader_path, const char *f shader->point_lights[i].constant = glGetUniformLocation(shader->id, location_buffer); } + // Spot lights + for (size_t i=0; ispot_lights[i].color = glGetUniformLocation(shader->id, location_buffer); + snprintf(location_buffer, sizeof(location_buffer), "spot_lights[%zu].point_light.light.ambient_intensity", i); + shader->spot_lights[i].ambient_intensity = glGetUniformLocation(shader->id, location_buffer); + snprintf(location_buffer, sizeof(location_buffer), "spot_lights[%zu].point_light.light.diffuse_intensity", i); + shader->spot_lights[i].diffuse_intensity = glGetUniformLocation(shader->id, location_buffer); + + snprintf(location_buffer, sizeof(location_buffer), "spot_lights[%zu].point_light.position", i); + shader->spot_lights[i].position = glGetUniformLocation(shader->id, location_buffer); + snprintf(location_buffer, sizeof(location_buffer), "spot_lights[%zu].point_light.constant", i); + shader->spot_lights[i].constant = glGetUniformLocation(shader->id, location_buffer); + snprintf(location_buffer, sizeof(location_buffer), "spot_lights[%zu].point_light.constant", i); + shader->spot_lights[i].constant = glGetUniformLocation(shader->id, location_buffer); + + snprintf(location_buffer, sizeof(location_buffer), "spot_lights[%zu].direction", i); + shader->spot_lights[i].direction = glGetUniformLocation(shader->id, location_buffer); + snprintf(location_buffer, sizeof(location_buffer), "spot_lights[%zu].edge", i); + shader->spot_lights[i].edge = glGetUniformLocation(shader->id, location_buffer); + } + return true; } @@ -156,3 +183,23 @@ void use_light(Shader *shader, Point_Light *point_lights, u32 point_light_count) } } +void use_light(Shader *shader, Spot_Light *spot_lights, u32 spot_light_count) { + if (spot_light_count > MAX_SPOT_LIGHTS) spot_light_count = MAX_SPOT_LIGHTS; + + glUniform1i(shader->spot_light_count, spot_light_count); + + for (size_t i = 0; i < spot_light_count; i++) { + glUniform3f(shader->spot_lights[i].color, spot_lights[i].color.x, spot_lights[i].color.y, spot_lights[i].color.z); + glUniform1f(shader->spot_lights[i].ambient_intensity, spot_lights[i].ambient_intensity); + glUniform1f(shader->spot_lights[i].diffuse_intensity, spot_lights[i].diffuse_intensity); + + glUniform3f(shader->spot_lights[i].position, spot_lights[i].position.x, spot_lights[i].position.y, spot_lights[i].position.z); + glUniform1f(shader->spot_lights[i].constant, spot_lights[i].constant); + glUniform1f(shader->spot_lights[i].linear, spot_lights[i].linear); + glUniform1f(shader->spot_lights[i].exponent, spot_lights[i].exponent); + + glUniform3f(shader->spot_lights[i].direction, spot_lights[i].direction.x, spot_lights[i].direction.y, spot_lights[i].direction.z); + glUniform1f(shader->spot_lights[i].edge, spot_lights[i].processed_edge); + } +} + diff --git a/src/shader.h b/src/shader.h index f61def4..bb3344a 100644 --- a/src/shader.h +++ b/src/shader.h @@ -45,6 +45,22 @@ struct Shader { u32 exponent; } point_lights[MAX_POINT_LIGHTS]; + u32 spot_light_count = 0; + + struct { + u32 color; + u32 ambient_intensity; + u32 diffuse_intensity; + + u32 position; + u32 constant; + u32 linear; + u32 exponent; + + u32 direction; + u32 edge; + } spot_lights[MAX_SPOT_LIGHTS]; + ~Shader(); }; @@ -52,6 +68,6 @@ bool create_shader(Shader *shader, const char *vertex_shader_path, const char *f bool add_shader(Shader *shader, const char *shader_code, Shader_Type type); void clear_shader(Shader *shader); -// Some of these should be u32 void use_light(Shader *shader, Directional_Light *light); void use_light(Shader *shader, Point_Light *light, u32 point_light_count); +void use_light(Shader *shader, Spot_Light *light, u32 point_light_count);