diff options
-rw-r--r-- | source/main.cpp | 165 | ||||
-rw-r--r-- | source/shaders/light_subject.fs.glsl | 178 |
2 files changed, 265 insertions, 78 deletions
diff --git a/source/main.cpp b/source/main.cpp index 94974e5..1562ed1 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -780,40 +780,108 @@ int main(int argc, char* argv[]) int shine_factor_loc = glGetUniformLocation(shader_program, "material.shininess"); glUniform1f(shine_factor_loc, specular_shine_factor); - // light uniforms - Vec3 light_location = Vec3{ 0.0f, 0.0f, 3.0f }; - Vec3 light_direction = Vec3{ -0.0f, -0.0f, -0.3f }; - Vec3 light_ambient = Vec3{ 0.2f, 0.2f, 0.2f }; - Vec3 light_diffuse = Vec3{ 0.5f, 0.5f, 0.5f }; - Vec3 light_specular = Vec3{ 1.0f, 1.0f, 1.0f }; - - int light_ambient_loc = glGetUniformLocation(shader_program, "pointLight.ambient"); - glUniform3fv(light_ambient_loc, 1, light_ambient.data); - - int light_diffuse_loc = glGetUniformLocation(shader_program, "pointLight.diffuse"); - glUniform3fv(light_diffuse_loc, 1, light_diffuse.data); - - int light_specular_loc = glGetUniformLocation(shader_program, "pointLight.specular"); - glUniform3fv(light_specular_loc, 1, light_diffuse.data); - - int light_pos_loc = glGetUniformLocation(shader_program, "pointLight.position"); - glUniform3fv(light_pos_loc, 1, light_location.data); - + // directional light things + // - directional light params + Vec3 DL_direction = Vec3{ 0.0f, -1.0f, 0.0f }; + Vec3 DL_ambient = Vec3{ 0.2f, 0.2f, 0.2f }; + Vec3 DL_diffuse = Vec3{ 0.5f, 0.5f, 0.5f }; + Vec3 DL_specular = Vec3{ 1.0f, 1.0f, 1.0f }; + + int DL_ambient_loc = glGetUniformLocation(shader_program, "dirLight.ambient"); + int DL_diffuse_loc = glGetUniformLocation(shader_program, "dirLight.diffuse"); + int DL_specular_loc = glGetUniformLocation(shader_program, "dirLight.specular"); + int DL_dir_loc = glGetUniformLocation(shader_program, "dirLight.direction"); + + glUniform3fv(DL_dir_loc, 1, DL_direction.data); + glUniform3fv(DL_ambient_loc, 1, DL_ambient.data); + glUniform3fv(DL_diffuse_loc, 1, DL_diffuse.data); + glUniform3fv(DL_specular_loc, 1, DL_specular.data); + + // pointlight things + // - point light params + Vec3 MPL_position[4] = { + Vec3{ 0.0f, 0.0f, 5.0f }, + Vec3{ 0.0f, 0.0f, -8.0f }, + Vec3{ -5.0f, 0.0f, -5.0f }, + Vec3{ 5.0f, 0.0f, -5.0f }, + }; + Vec3 MPL_ambient[4] = { + Vec3{ 0.2f, 0.2f, 0.2f }, + Vec3{ 0.2f, 0.2f, 0.2f }, + Vec3{ 0.2f, 0.2f, 0.2f }, + Vec3{ 0.2f, 0.2f, 0.2f } + }; + Vec3 MPL_diffuse[4] = { + Vec3{ 0.5f, 0.5f, 0.5f }, + Vec3{ 0.5f, 0.5f, 0.5f }, + Vec3{ 0.5f, 0.5f, 0.5f }, + Vec3{ 0.5f, 0.5f, 0.5f } + }; + Vec3 MPL_specular[4] = { + Vec3{ 1.0f, 1.0f, 1.0f }, + Vec3{ 1.0f, 1.0f, 1.0f }, + Vec3{ 1.0f, 1.0f, 1.0f }, + Vec3{ 1.0f, 1.0f, 1.0f } + }; + + for (int i=0; i < 4; i++) + { + char buffer[64]; + sprintf(buffer, "multiPointLight[%i].ambient", i); + int MPL_ambient_loc = glGetUniformLocation(shader_program, buffer); + sprintf(buffer, "multiPointLight[%i].diffuse", i); + int MPL_diffuse_loc = glGetUniformLocation(shader_program, buffer); + sprintf(buffer, "multiPointLight[%i].specular", i); + int MPL_specular_loc = glGetUniformLocation(shader_program, buffer); + sprintf(buffer, "multiPointLight[%i].position", i); + int MPL_pos_loc = glGetUniformLocation(shader_program, buffer); + sprintf(buffer, "multiPointLight[%i].kC", i); + int MPL_kc_loc = glGetUniformLocation(shader_program, buffer); + sprintf(buffer, "multiPointLight[%i].kL", i); + int MPL_kl_loc = glGetUniformLocation(shader_program, buffer); + sprintf(buffer, "multiPointLight[%i].kQ", i); + int MPL_kq_loc = glGetUniformLocation(shader_program, buffer); + + glUniform3fv(MPL_pos_loc, 1, MPL_position[i].data); + glUniform3fv(MPL_ambient_loc, 1, MPL_ambient[i].data); + glUniform3fv(MPL_diffuse_loc, 1, MPL_diffuse[i].data); + glUniform3fv(MPL_specular_loc, 1, MPL_specular[i].data); + // attenuation factors + glUniform1f(MPL_kc_loc, 1.0f); + glUniform1f(MPL_kl_loc, 0.09f); + glUniform1f(MPL_kq_loc, 0.032f); + } + + + + // spotlight things + // - spot light params + Vec3 SL_ambient = Vec3{ 0.2f, 0.2f, 0.2f }; + Vec3 SL_diffuse = Vec3{ 0.5f, 0.5f, 0.5f }; + Vec3 SL_specular = Vec3{ 1.0f, 1.0f, 1.0f }; + + int SL_ambient_loc = glGetUniformLocation(shader_program, "spotLight.ambient"); + int SL_diffuse_loc = glGetUniformLocation(shader_program, "spotLight.diffuse"); + int SL_specular_loc = glGetUniformLocation(shader_program, "spotLight.specular"); + int SL_pos_loc = glGetUniformLocation(shader_program, "spotLight.position"); + int SL_kc_loc = glGetUniformLocation(shader_program, "spotLight.kC"); + int SL_kl_loc = glGetUniformLocation(shader_program, "spotLight.kL"); + int SL_kq_loc = glGetUniformLocation(shader_program, "spotLight.kQ"); + int SL_radius_inner = glGetUniformLocation(shader_program, "spotLight.radius_inner"); + int SL_radius_outer = glGetUniformLocation(shader_program, "spotLight.radius_outer"); + int SL_front_loc = glGetUniformLocation(shader_program, "spotLight.front"); + + glUniform3fv(SL_ambient_loc, 1, SL_ambient.data); + glUniform3fv(SL_diffuse_loc, 1, SL_diffuse.data); + glUniform3fv(SL_specular_loc, 1, SL_specular.data); // attenuation factors - int kc_loc = glGetUniformLocation(shader_program, "pointLight.kC"); - glUniform1f(kc_loc, 1.0f); - - int kl_loc = glGetUniformLocation(shader_program, "pointLight.kL"); - glUniform1f(kl_loc, 0.09f); - - int kq_loc = glGetUniformLocation(shader_program, "pointLight.kQ"); - glUniform1f(kq_loc, 0.032f); - // texture uniforms - //int smiling_loc = glGetUniformLocation(shader_program, "smilingTexture"); - //glUniform1i(smiling_loc, 0); - - //int container_loc = glGetUniformLocation(shader_program, "containerTexture"); - //glUniform1i(container_loc, 1); + glUniform1f(SL_kc_loc, 1.0f); + glUniform1f(SL_kl_loc, 0.09f); + glUniform1f(SL_kq_loc, 0.032f); + // radius + glUniform1f(SL_radius_inner, cosf(To_Radian(10.0f))); + glUniform1f(SL_radius_outer, cosf(To_Radian(15.00f))); + // end spotlight things int light_uniform_loc = glGetUniformLocation(shader_program, "lightColor"); glUniform3fv(light_uniform_loc, 1, light_color.data); @@ -824,7 +892,7 @@ int main(int argc, char* argv[]) // objects Vec3 model_translations[] = { Vec3{ 0.0, 0.0, 0.0}, - Vec3{ -1.0, -1.0, -2.0}, + Vec3{ -1.0, 0.0, -2.0}, Vec3{ 2.0, 0.0, -5.0}, Vec3{ -3.0, 5.0, -6.0}, Vec3{ 3.0, -7.0, -6.0}, @@ -859,14 +927,8 @@ int main(int argc, char* argv[]) glUniformMatrix4fv(proj_loc, 1, GL_TRUE, proj.buffer); glUseProgram(light_sp); - Mat4 light_model = translation_matrix4m(light_location.x, light_location.y, light_location.z); - - uint32_t light_model_loc = glGetUniformLocation(light_sp, "Model"); - glUniformMatrix4fv(light_model_loc, 1, GL_TRUE, light_model.buffer); - uint32_t light_view_loc = glGetUniformLocation(light_sp, "View"); glUniformMatrix4fv(light_view_loc, 1, GL_TRUE, view.buffer); - uint32_t light_proj_loc = glGetUniformLocation(light_sp, "Projection"); glUniformMatrix4fv(light_proj_loc, 1, GL_TRUE, proj.buffer); @@ -1004,22 +1066,27 @@ int main(int argc, char* argv[]) } // light_location.z = 10.00 * sinf(time_curr/10.0); view = camera_create4m(camera_pos, add3v(camera_pos, camera_look), preset_up_dir); + // object shader program stuff glUseProgram(shader_program); - //glUniform1f(shine_factor_loc, specular_shine_factor); + + // Update spot light params + glUniform3fv(SL_pos_loc, 1, camera_pos.data); + glUniform3fv(SL_front_loc, 1, camera_look.data); glUniformMatrix4fv(view_loc, 1, GL_TRUE, view.buffer); glUniform3fv(camera_pos_loc, 1, camera_pos.data); // light/lamp shader program stuff - glUseProgram(light_sp); - glUniformMatrix4fv(light_view_loc, 1, GL_TRUE, view.buffer); + //glUseProgram(light_sp); + //glUniformMatrix4fv(light_view_loc, 1, GL_TRUE, view.buffer); time_prev = time_curr; // OUTPUT - glClearColor(1.0f, 0.6f, .6f, 1.0f); + //glClearColor(1.0f, 0.6f, .6f, 1.0f); + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //glActiveTexture(GL_TEXTURE1); @@ -1027,7 +1094,15 @@ int main(int argc, char* argv[]) glUseProgram(light_sp); glBindVertexArray(light_VAO); - glDrawArrays(GL_TRIANGLES, 0, 36); + for (int i = 0; i < 4; i++) + { + Mat4 light_model = translation_matrix4m(MPL_position[i].x, MPL_position[i].y, MPL_position[i].z); + uint32_t light_model_loc = glGetUniformLocation(light_sp, "Model"); + glUniformMatrix4fv(light_model_loc, 1, GL_TRUE, light_model.buffer); + + glUniformMatrix4fv(light_view_loc, 1, GL_TRUE, view.buffer); + glDrawArrays(GL_TRIANGLES, 0, 36); + } glBindVertexArray(0); glUseProgram(0); diff --git a/source/shaders/light_subject.fs.glsl b/source/shaders/light_subject.fs.glsl index aa3cf36..f3e1d58 100644 --- a/source/shaders/light_subject.fs.glsl +++ b/source/shaders/light_subject.fs.glsl @@ -1,5 +1,21 @@ #version 330 core +/* +@note: an explanation of why the light direction vector is taken from fragment to the +light source. +Basic LA really, we need to calculate the angle between the direction of the 2 vectors: + a. The direction at which light incidents with the fragment + b. The normal vector +The reason the light direction is taken from the fragment to the light source, is precisely so we can calculate +the angle between the normal and the direction at which light would hit. This if taken as starting from the light +source would actually be incorrect, since we would be calculating the angle between the light source in the direction +of the fragment and the normal. Consider what happens when it is directly above. The angle becomes 180, not 0. This +is because the normal moves in the direction opposite to the lights direction if taken this way, which is not what +we expect or want. +Reversing this, allows us to consider the angle at the point in which light hits the fragment, and the normal vector +of the fragment. +*/ + struct Material { sampler2D diffuse; sampler2D specular; @@ -35,53 +51,149 @@ struct PointLight { float kQ; }; +struct SpotLight { + vec3 position; + + vec3 ambient; + vec3 diffuse; + vec3 specular; + + // attenuation factors + float kC; + float kL; + float kQ; + + // vector for the direction directly in front of the spotlight + vec3 front; + + // spot radius + float radius_inner; + float radius_outer; // to smooth out the light + +}; + +// this is the result of a light creation. This contains the multipliers for each kind of a light we want +// to have. +struct LightFactor { + vec3 ambient; + vec3 diffuse; + vec3 specular; +}; + in vec2 texCoords; in vec3 fragNormal; in vec3 worldPosition; uniform Material material; + uniform Light light; uniform DirectionalLight dirLight; uniform PointLight pointLight; +uniform PointLight multiPointLight[4]; +uniform SpotLight spotLight; + uniform vec3 cameraPosition; uniform vec3 lightColor; out vec4 FragColor; +LightFactor make_directional_light(DirectionalLight light, vec3 CONST_viewDir) { + LightFactor res; + + vec3 DL_lightDir = normalize(-light.direction); + res.ambient = light.ambient; + + float DL_diffuseStrength = max(dot(DL_lightDir, fragNormal), 0.0); + res.diffuse = light.diffuse * DL_diffuseStrength; + + vec3 DL_reflectDir = reflect(-DL_lightDir, fragNormal); + float DL_specularity = max(dot(CONST_viewDir, DL_reflectDir), 0.0); + float DL_shinePower = pow(DL_specularity, material.shininess); + res.specular = light.specular * DL_shinePower; + + return res; +}; + +LightFactor make_point_light(PointLight light, vec3 CONST_viewDir) { + LightFactor res; + + float PL_lightDistance = length(light.position - worldPosition); + float PL_attenuationFactor = 1.0 / + (light.kC + (light.kL * PL_lightDistance) + (light.kQ * PL_lightDistance * PL_lightDistance)); + res.ambient = PL_attenuationFactor * light.ambient; + + vec3 PL_lightDir = normalize(light.position - worldPosition); + float PL_diffuseStrength = max(dot(PL_lightDir, fragNormal), 0.0); + res.diffuse = PL_attenuationFactor * light.diffuse * PL_diffuseStrength; + + vec3 PL_reflectDir = reflect(-PL_lightDir, fragNormal); + float PL_specularity = max(dot(CONST_viewDir, PL_reflectDir), 0.0); + float PL_shinePower = pow(PL_specularity, material.shininess); + res.specular = PL_attenuationFactor * PL_shinePower * light.specular; + + return res; +} + +LightFactor make_spot_light(SpotLight light, vec3 CONST_viewDir) { + LightFactor res; + + float SL_lightDistance = length(light.position - worldPosition); + float SL_attenuationFactor = 1.0 / + (light.kC + (light.kL * SL_lightDistance) + (light.kQ * SL_lightDistance * SL_lightDistance)); + vec3 SL_lightDir = normalize(light.position - worldPosition); + + res.ambient = SL_attenuationFactor * light.ambient; + + float SL_diffAmount = dot(SL_lightDir, normalize(-light.front)); + float SL_spotLightFadeFactor = clamp((SL_diffAmount - light.radius_outer)/(light.radius_inner - light.radius_outer), 0.0f, 1.0f); + float SL_diffuseStrength = max(dot(SL_lightDir, fragNormal), 0.0); + res.diffuse = SL_spotLightFadeFactor * SL_attenuationFactor * light.diffuse * SL_diffuseStrength; + + vec3 SL_reflectDir = reflect(-SL_lightDir, fragNormal); + float SL_specularity = max(dot(CONST_viewDir, SL_reflectDir), 0.0); + float SL_shinePower = pow(SL_specularity, material.shininess); + res.specular = SL_spotLightFadeFactor * SL_attenuationFactor * SL_shinePower * light.specular; + + return res; +} + void main() { - float lightDistance = length(pointLight.position - worldPosition); - float attenuationFactor = 1.0 / - (pointLight.kC + (pointLight.kL * lightDistance) + (pointLight.kQ * lightDistance * lightDistance)); - - vec3 ambientLight = attenuationFactor * pointLight.ambient * vec3(texture(material.diffuse, texCoords)); - -// @note: Diffuse calculations - //vec3 lightDir = normalize(light.position - worldPosition); - /* - @note: an explanation of why the light direction vector is taken from fragment to the - light source. - Basic LA really, we need to calculate the angle between the direction of the 2 vectors: - a. The direction at which light incidents with the fragment - b. The normal vector - The reason the light direction is taken from the fragment to the light source, is precisely so we can calculate - the angle between the normal and the direction at which light would hit. This if taken as starting from the light - source would actually be incorrect, since we would be calculating the angle between the light source in the direction - of the fragment and the normal. Consider what happens when it is directly above. The angle becomes 180, not 0. This - is because the normal moves in the direction opposite to the lights direction if taken this way, which is not what - we expect or want. - Reversing this, allows us to consider the angle at the point in which light hits the fragment, and the normal vector - of the fragment. - */ - vec3 lightDir = normalize(pointLight.position - worldPosition); - float diffuseStrength = max(dot(lightDir, fragNormal), 0.0); - vec3 diffuseLight = attenuationFactor * pointLight.diffuse * diffuseStrength * vec3(texture(material.diffuse, texCoords)); - -// @note: Specular calculations - vec3 viewDir = normalize(cameraPosition - worldPosition); - vec3 reflectDir = reflect(-lightDir, fragNormal); - float specularity = max(dot(viewDir, reflectDir), 0.0); - float shinePower = pow(specularity, material.shininess); - vec3 specularLight = attenuationFactor * pointLight.specular * shinePower * vec3(texture(material.specular, texCoords)); + vec3 CONST_viewDir = normalize(cameraPosition - worldPosition); + vec3 combinedAmbience = vec3(0.0); + vec3 combinedDiffuse = vec3(0.0); + vec3 combinedSpecular = vec3(0.0); + + // directional light calculations and stuff + //LightFactor DL_factors = make_directional_light(dirLight, CONST_viewDir); + //combinedAmbience += DL_factors.ambient; + //combinedDiffuse += DL_factors.diffuse; + //combinedSpecular += DL_factors.specular; + + // pointlight calculations and stuff + //LightFactor PL_factors = make_point_light(pointLight, CONST_viewDir); + //combinedAmbience += PL_factors.ambient; + //combinedDiffuse += PL_factors.diffuse; + //combinedSpecular += PL_factors.specular; + + // multiple point lights + for (int i=0; i<4; i++) + { + PointLight pl = multiPointLight[i]; + LightFactor MPL_factors = make_point_light(pl, CONST_viewDir); + combinedAmbience += MPL_factors.ambient; + combinedDiffuse += MPL_factors.diffuse; + combinedSpecular += MPL_factors.specular; + } + + // spotlight calculations + LightFactor SL_factors = make_spot_light(spotLight, CONST_viewDir); + combinedAmbience += SL_factors.ambient; + combinedDiffuse += SL_factors.diffuse; + combinedSpecular += SL_factors.specular; + + vec3 ambientLight = combinedAmbience * vec3(texture(material.diffuse, texCoords)); + vec3 diffuseLight = combinedDiffuse * vec3(texture(material.diffuse, texCoords)); + vec3 specularLight = combinedSpecular * vec3(texture(material.specular, texCoords)); vec3 color = ambientLight + diffuseLight + specularLight; FragColor = vec4(color, 1.0); |