diff options
-rw-r--r-- | res/shaders/colors.fs | 137 | ||||
-rw-r--r-- | src/cubes.odin | 7 | ||||
-rw-r--r-- | src/main.odin | 77 |
3 files changed, 173 insertions, 48 deletions
diff --git a/res/shaders/colors.fs b/res/shaders/colors.fs index 228f555..d10e45a 100644 --- a/res/shaders/colors.fs +++ b/res/shaders/colors.fs @@ -14,6 +14,7 @@ struct Light { vec3 direction; float cutOff; + float outerCutOff; vec3 ambient; vec3 diffuse; @@ -32,37 +33,127 @@ uniform vec3 view_position; uniform Material material; uniform Light light; -void main() { - vec3 light_dir = normalize(light.position - FragPos); - float theta = dot(light_dir, normalize(-light.direction)); +struct DirLight { + vec3 direction; - if (theta > light.cutOff) { - // ambient - vec3 ambient = light.ambient * texture(material.diffuse, TexCoords).rgb; + vec3 ambient; + vec3 diffuse; + vec3 specular; +}; +uniform DirLight dirLight; - // diffuse - vec3 norm = normalize(Normal); - float diff = max(dot(norm, light_dir), 0.0); - vec3 diffuse = light.diffuse * diff * texture(material.diffuse, TexCoords).rgb; +struct PointLight { + vec3 position; - // specular - vec3 view_dir = normalize(view_position - FragPos); - vec3 reflect_dir = reflect(-light_dir, norm); - float spec = pow(max(dot(view_dir, reflect_dir), 0.0), material.shininess); - vec3 specular = light.specular * spec * texture(material.specular, TexCoords).rgb; + float constant; + float linear; + float quadratic; - float distance = length(light.position - FragPos); - float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance)); + vec3 ambient; + vec3 diffuse; + vec3 specular; +}; +#define NR_POINT_LIGHTS 4 +uniform PointLight pointLights[NR_POINT_LIGHTS]; - diffuse *= attenuation; - specular *= attenuation; +struct SpotLight { + vec3 position; + vec3 direction; + + float cutOff; + float outerCutOff; + + float constant; + float linear; + float quadratic; + + vec3 ambient; + vec3 diffuse; + vec3 specular; +}; +uniform SpotLight spotLight; + +vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir); +vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir); +vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir); + +void main() +{ + vec3 norm = normalize(Normal); + vec3 viewDir = normalize(view_position - FragPos); + + vec3 result = CalcDirLight(dirLight, norm, viewDir); - vec3 result = ambient + diffuse + specular; - FragColor = vec4(result, 1.0); - } else { - FragColor = vec4(light.ambient * texture(material.diffuse, TexCoords).rgb, 1.0); + for (int i = 0; i < NR_POINT_LIGHTS; i++) { + result += CalcPointLight(pointLights[i], norm, FragPos, viewDir); } + result += CalcSpotLight(spotLight, norm, FragPos, viewDir); + FragColor = vec4(result, 1.0); +} + +// calculates the color when using a directional light. +vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir) +{ + vec3 lightDir = normalize(-light.direction); + // diffuse shading + float diff = max(dot(normal, lightDir), 0.0); + // specular shading + vec3 reflectDir = reflect(-lightDir, normal); + float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); + // combine results + vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords)); + vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords)); + vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords)); + return (ambient + diffuse + specular); +} + +// calculates the color when using a point light. +vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir) +{ + vec3 lightDir = normalize(light.position - fragPos); + // diffuse shading + float diff = max(dot(normal, lightDir), 0.0); + // specular shading + vec3 reflectDir = reflect(-lightDir, normal); + float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); + // attenuation + float distance = length(light.position - fragPos); + float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance)); + // combine results + vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords)); + vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords)); + vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords)); + ambient *= attenuation; + diffuse *= attenuation; + specular *= attenuation; + return (ambient + diffuse + specular); +} + +// calculates the color when using a spot light. +vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir) +{ + vec3 lightDir = normalize(light.position - fragPos); + // diffuse shading + float diff = max(dot(normal, lightDir), 0.0); + // specular shading + vec3 reflectDir = reflect(-lightDir, normal); + float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); + // attenuation + float distance = length(light.position - fragPos); + float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance)); + // spotlight intensity + float theta = dot(lightDir, normalize(-light.direction)); + float epsilon = light.cutOff - light.outerCutOff; + float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0); + // combine results + vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords)); + vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords)); + vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords)); + ambient *= attenuation * intensity; + diffuse *= attenuation * intensity; + specular *= attenuation * intensity; + return (ambient + diffuse + specular); } diff --git a/src/cubes.odin b/src/cubes.odin index b6bcd1c..d96bbc3 100644 --- a/src/cubes.odin +++ b/src/cubes.odin @@ -56,3 +56,10 @@ cube_positions : []Vec3 : { Vec3{ 1.5, 0.2, -1.5}, Vec3{-1.3, 1.0, -1.5} } + +point_light_positions : []Vec3 : { + Vec3{0.7, 0.2, 2.0}, + Vec3{2.3, -3.3, -4.0}, + Vec3{-4.0, 2.0, -12.0}, + Vec3{0.0, 0.0, -3.0} +} diff --git a/src/main.odin b/src/main.odin index 997aeb2..d518e93 100644 --- a/src/main.odin +++ b/src/main.odin @@ -187,28 +187,55 @@ main :: proc() { shader_use(lighting_shader) + shader_set_vec3(lighting_shader, cstring("view_position"), &camera.position) + shader_set_f32(lighting_shader, cstring("material.shininess"), 32.0) + + // directional light + shader_set_vec3(lighting_shader, "dirLight.direction", &Vec3{-0.2, -1.0, -0.3}) + shader_set_vec3(lighting_shader, "dirLight.ambient", &Vec3{0.05, 0.05, 0.05}) + shader_set_vec3(lighting_shader, "dirLight.diffuse", &Vec3{0.04, 0.04, 0.04}) + shader_set_vec3(lighting_shader, "dirLight.specular", &Vec3{0.5, 0.5, 0.5}) + + // point lights + for &pos, i in point_light_positions { + positon_key := fmt.caprintf("pointLights[%i].position", i) + ambient_key := fmt.caprintf("pointLights[%i].ambient", i) + diffuse_key := fmt.caprintf("pointLights[%i].diffuse", i) + specular_key := fmt.caprintf("pointLights[%i].specular", i) + constant_key := fmt.caprintf("pointLights[%i].constant", i) + linear_key := fmt.caprintf("pointLights[%i].linear", i) + quadratic_key := fmt.caprintf("pointLights[%i].quadratic", i) + + - light_ambient := Vec3{0.2, 0.2, 0.2} - light_diffuse := Vec3{0.5, 0.5, 0.05} - light_specular := Vec3{1.0, 1.0, 1.0} + shader_set_vec3(lighting_shader, positon_key, &pos) + shader_set_vec3(lighting_shader, ambient_key, &Vec3{0.05, 0.05, 0.05}) + shader_set_vec3(lighting_shader, diffuse_key, &Vec3{0.8, 0.8, 0.8}) + shader_set_vec3(lighting_shader, specular_key, &Vec3{1.0, 1.0, 1.0}) - shader_set_vec3(lighting_shader, cstring("light.ambient"), &light_ambient) - shader_set_vec3(lighting_shader, cstring("light.diffuse"), &light_diffuse) - shader_set_vec3(lighting_shader, cstring("light.specular"), &light_specular) + shader_set_f32(lighting_shader, constant_key, 1.0) + shader_set_f32(lighting_shader, linear_key, 0.09) + shader_set_f32(lighting_shader, quadratic_key, 0.032) + } - shader_set_vec3(lighting_shader, cstring("light.position"), &camera.position) - shader_set_vec3(lighting_shader, cstring("light.direction"), &camera.front) + // spot cutoff_angle : f32 = math.cos(linalg.to_radians(f32(12.5))) - shader_set_f32(lighting_shader, "light.cutOff", cutoff_angle) + outer_cutoff_angle : f32 = math.cos(linalg.to_radians(f32(15.0))) - shader_set_vec3(lighting_shader, cstring("view_position"), &camera.position) + shader_set_vec3(lighting_shader, "spotLight.position", &camera.position) + shader_set_vec3(lighting_shader, "spotLight.direction", &camera.front) + shader_set_vec3(lighting_shader, "spotLight.ambient", &Vec3{0.0, 0.0, 0.0}) + shader_set_vec3(lighting_shader, "spotLight.diffuse", &Vec3{1.0, 1.0, 1.0}) + shader_set_vec3(lighting_shader, "spotLight.specular", &Vec3{1.0, 1.0, 1.0}) - shader_set_f32(lighting_shader, "light.constant", 1.0) - shader_set_f32(lighting_shader, "light.linear", 0.09) - shader_set_f32(lighting_shader, "light.qudratic", 0.032) + shader_set_f32(lighting_shader, "spotLight.constant", 1.0) + shader_set_f32(lighting_shader, "spotLight.linear", 0.09) + shader_set_f32(lighting_shader, "spotLight.quadratic", 0.032) - shader_set_f32(lighting_shader, cstring("material.shininess"), 32.0) + + shader_set_f32(lighting_shader, "spotLight.cutOff", cutoff_angle) + shader_set_f32(lighting_shader, "spotLight.outerCutOff", outer_cutoff_angle) aspect: f32 = 800.0 / 600.0 projection := linalg.matrix4_perspective_f32( @@ -236,7 +263,6 @@ main :: proc() { gl.BindTexture(gl.TEXTURE_2D, specular_map) gl.BindVertexArray(cube_vao) - // gl.DrawArrays(gl.TRIANGLES, 0, 36) for position, i in cube_positions { model = linalg.MATRIX4F32_IDENTITY model *= linalg.matrix4_translate_f32(position) @@ -244,20 +270,21 @@ main :: proc() { model *= linalg.matrix4_rotate_f32(angle, Vec3{1.0, 0.3, 0.5}) shader_set_mat4(lighting_shader, "model", &model) - gl.DrawArrays(gl.TRIANGLES, 0, 36) + gl.DrawArrays(gl.TRIANGLES, 0, 36); } - // lamp cube object drawing - shader_use(light_cube_shader) - shader_set_mat4(light_cube_shader, cstring("projection"), &projection) - shader_set_mat4(light_cube_shader, cstring("view"), &view) - - model = linalg.matrix4_translate_f32(light_pos) - model *= linalg.matrix4_scale_f32(Vec3{0.2, 0.2, 0.2}) - shader_set_mat4(light_cube_shader, cstring("model"), &model) + shader_use(light_cube_shader) + shader_set_mat4(light_cube_shader, "projection", &projection) + shader_set_mat4(light_cube_shader, "view", &view) gl.BindVertexArray(light_cube_vao) - gl.DrawArrays(gl.TRIANGLES, 0, 36) + for pos, i in point_light_positions { + model = linalg.MATRIX4F32_IDENTITY + model *= linalg.matrix4_translate_f32(pos) + model *= linalg.matrix4_scale_f32(Vec3{0.2, 0.2, 0.2}) + shader_set_mat4(light_cube_shader, cstring("model"), &model) + gl.DrawArrays(gl.TRIANGLES, 0, 36) + } glfw.SwapBuffers(window) glfw.PollEvents() |