diff --git a/FinalProject/FinalProject.vcxproj b/FinalProject/FinalProject.vcxproj index 2722289..ede62bd 100644 --- a/FinalProject/FinalProject.vcxproj +++ b/FinalProject/FinalProject.vcxproj @@ -108,6 +108,7 @@ + diff --git a/FinalProject/FinalProject.vcxproj.filters b/FinalProject/FinalProject.vcxproj.filters index 8190b67..a4b9fad 100644 --- a/FinalProject/FinalProject.vcxproj.filters +++ b/FinalProject/FinalProject.vcxproj.filters @@ -168,6 +168,9 @@ Source Files\OpenGL Abstractions + + Source Files\OpenGL Abstractions + diff --git a/FinalProject/illuminer.cpp b/FinalProject/illuminer.cpp new file mode 100644 index 0000000..828c9f0 --- /dev/null +++ b/FinalProject/illuminer.cpp @@ -0,0 +1,136 @@ +#include "illuminer.h" +#include "logger.h" + +Illuminer::Illuminer(glm::vec3 color) : + _lightColor(color) +{} + +Illuminer::~Illuminer() {} + +DirLight::DirLight(glm::vec3 direction, glm::vec3 color) : + Illuminer(color), _direction(direction) +{} + +DirLight::~DirLight() {} + +void DirLight::updateShader(ShaderProgram shader) const { + // Recall DirLight structure in fragment shader + // ------------- + // struct DirLight { + // vec3 direction; + // vec3 ambient; + // vec3 diffuse; + // vec3 specular; + // }; + + shader.setUniform("DirLight.direction", -_direction); + shader.setUniform("DirLight.ambient", ambientLightColor()); + shader.setUniform("DirLight.diffuse", diffuseLightColor()); + shader.setUniform("DirLight.specular", specularLightColor()); +} + +ScopedLight::ScopedLight(glm::vec3 position, glm::vec3 direction, glm::vec3 color) : + Illuminer(color), _position(position), _direction(direction) +{ + updateLinear(); + updateQuadratic(); +} + +ScopedLight::ScopedLight(int distance, glm::vec3 position, glm::vec3 direction, glm::vec3 color) : + Illuminer(color), _position(position), _direction(direction), _idealDistance(distance) +{ + updateLinear(); + updateQuadratic(); +} + +ScopedLight::~ScopedLight() {} + +inline void ScopedLight::updateLinear() { + // Double is used here to prevent precision loss + double linear = -0.0001 + 4.7688 / (double)_idealDistance; + _attLinear = (float)linear; +} + +inline void ScopedLight::updateQuadratic() { + // Double is used here to prevent precision loss + double quadratic = 82.4448 * glm::pow((double)_idealDistance, -2.0192); + _attQuadratic = (float)quadratic; +} + +void ScopedLight::setIdealDistance(int distance) { + if (distance < 10) { + distance = 10; + } + if (distance > 3500) { + distance = 3500; + } + _idealDistance = distance; + updateLinear(); + updateQuadratic(); +} + +void ScopedLight::setCutOffAngle(float angle) { + if (angle < 0.0f) { + angle = 0.0f; + } + if (angle > 180.0f) { + angle = 180.0f; + } + _cutOffAngle = angle; +} + +inline float ScopedLight::innerCutOffAngle() const { + return 0.0011 * glm::pow(_cutOffAngle, 2) + 0.6440 * _cutOffAngle; +} + +void ScopedLight::updateShader(ShaderProgram shader) const { + // Recall PointLight and SpotLight structure in fragment shader + // ------------- + // struct PointLight { + // vec3 position; + // vec3 ambient; + // vec3 diffuse; + // vec3 specular; + // float constant; + // float linear; + // float quadratic; + // }; + // ------------ + // struct SpotLight { + // vec3 position; + // vec3 direction; + // vec3 ambient; + // vec3 diffuse; + // vec3 specular; + // float constant; + // float linear; + // float quadratic; + // float cutOff; + // float outerCutOff; + // }; + + // Check the cutoff angle to determine the type of light + if (abs(_cutOffAngle - 180.0f) < 1e-6) { + // Point light + shader.setUniform("PointLight.position", _position); + shader.setUniform("PointLight.ambient", ambientLightColor()); + shader.setUniform("PointLight.diffuse", diffuseLightColor()); + shader.setUniform("PointLight.specular", specularLightColor()); + shader.setUniform("PointLight.constant", _attConstant); + shader.setUniform("PointLight.linear", _attLinear); + shader.setUniform("PointLight.quadratic", _attQuadratic); + } + else { + // Spot light + shader.setUniform("SpotLight.position", _position); + shader.setUniform("SpotLight.direction", -_direction); + shader.setUniform("SpotLight.ambient", ambientLightColor()); + shader.setUniform("SpotLight.diffuse", diffuseLightColor()); + shader.setUniform("SpotLight.specular", specularLightColor()); + shader.setUniform("SpotLight.constant", _attConstant); + shader.setUniform("SpotLight.linear", _attLinear); + shader.setUniform("SpotLight.quadratic", _attQuadratic); + shader.setUniform("SpotLight.innercutoff", glm::cos(glm::radians(innerCutOffAngle()))); + shader.setUniform("SpotLight.outercutoff", glm::cos(glm::radians(_cutOffAngle))); + } +} \ No newline at end of file diff --git a/FinalProject/illuminer.h b/FinalProject/illuminer.h index 8fd1524..1d07fb5 100644 --- a/FinalProject/illuminer.h +++ b/FinalProject/illuminer.h @@ -5,7 +5,6 @@ #include #include "shader.h" -#include "logger.h" class Illuminer { protected: @@ -15,7 +14,7 @@ public: Illuminer(glm::vec3 color); ~Illuminer(); -public: +protected: virtual glm::vec3 ambientLightColor() const = 0; virtual glm::vec3 diffuseLightColor() const = 0; virtual glm::vec3 specularLightColor() const = 0; @@ -36,11 +35,13 @@ public: DirLight(glm::vec3 direction = glm::vec3(0.0f, -1.0f, 0.0f), glm::vec3 color = glm::vec3(1.0f)); ~DirLight(); +protected: + virtual glm::vec3 ambientLightColor() const override { return _lightColor * 0.2f; } + virtual glm::vec3 diffuseLightColor() const override { return _lightColor * 0.5f; } + virtual glm::vec3 specularLightColor() const override { return _lightColor * 0.9f; } + public: - // Getter APIs glm::vec3 lightDirection() const { return _direction; } // The same direction as the outgoing direction - - // Setter void setLightDirection(glm::vec3 direction) { _direction = direction; } // Render util function @@ -56,8 +57,7 @@ protected: // Light source status glm::vec3 _position; glm::vec3 _direction; - float _innerCutOffAngle = 162.5f; - float _outerCutOffAngle = 180.0f; + float _cutOffAngle = 180.0f; // Light property int _idealDistance = 32; // ideally calculated distance @@ -67,16 +67,27 @@ protected: public: ScopedLight(glm::vec3 position, glm::vec3 direction = glm::vec3(0.0f, -1.0f, 0.0f), glm::vec3 color = glm::vec3(1.0f)); - ScopedLight(glm::vec3 distance, glm::vec3 position, glm::vec3 direction = glm::vec3(0.0f, -1.0f, 0.0f), glm::vec3 color = glm::vec3(1.0f)); + ScopedLight(int distance, glm::vec3 position, glm::vec3 direction = glm::vec3(0.0f, -1.0f, 0.0f), glm::vec3 color = glm::vec3(1.0f)); ~ScopedLight(); +private: + // Util function + inline void updateLinear(); + inline void updateQuadratic(); + inline float innerCutOffAngle() const; + +protected: + virtual glm::vec3 ambientLightColor() const override { return _lightColor * 0.2f; } + virtual glm::vec3 diffuseLightColor() const override { return _lightColor * 0.5f; } + virtual glm::vec3 specularLightColor() const override { return _lightColor * 0.9f; } + public: // Property setters and getters int idealDistance() const { return _idealDistance; } void setIdealDistance(int distance); glm::vec3 lightDirection() const { return _direction; } void setLightDirection(glm::vec3 direction) { _direction = direction; } - float cutOffAngle() const { return _outerCutOffAngle; } + float cutOffAngle() const { return _cutOffAngle; } void setCutOffAngle(float angle); // Render util function