diff --git a/assets/shaders/orange.fs b/assets/shaders/orange.fs deleted file mode 100644 index a9cb901..0000000 --- a/assets/shaders/orange.fs +++ /dev/null @@ -1,7 +0,0 @@ -#version 330 core - -out vec3 color; - -void main() { - color = vec3(0.2f, 0.2f, 0.8f); -} \ No newline at end of file diff --git a/assets/shaders/orange.vs b/assets/shaders/orange.vs deleted file mode 100644 index a44d266..0000000 --- a/assets/shaders/orange.vs +++ /dev/null @@ -1,7 +0,0 @@ -#version 330 core - -in vec3 pos; - -void main() { - gl_Position = vec4(pos, 1.0f); -} \ No newline at end of file diff --git a/assets/shaders/phong.fs b/assets/shaders/phong.fs new file mode 100644 index 0000000..d1debe6 --- /dev/null +++ b/assets/shaders/phong.fs @@ -0,0 +1,108 @@ +#version 330 core + +// Implements the Phong lighting model with respect to materials and lighting materials + +// Structs + +struct Material { + vec3 diffuse; + vec3 specular; + float shininess; +}; + +struct DirLight { + vec3 direction; + vec3 ambient; + vec3 diffuse; + vec3 specular; +}; + +struct PointLight { + vec3 position; + // vec3 direction; + vec3 ambient; + vec3 diffuse; + vec3 specular; + + float constant; + float linear; + float quadratic; +}; + +// I/O + +in vec3 vPos; +in vec3 vNormal; +in vec2 vTexCoords; + +out vec4 FragColor; + +#define NR_POINT_LIGHTS 4 + +uniform vec3 viewPos; +uniform PointLight pointLights[NR_POINT_LIGHTS]; +uniform int numPointLights; +uniform DirLight sunLight; +uniform Material material; + +// Functions + +vec3 calculateDirectionalLight(DirLight light); +vec3 calculatePointLight(PointLight light); + + +// Main + +void main() { + vec3 result = vec3(0.0); + + result += calculateDirectionalLight(sunLight); + + for (int i = 0; i < numPointLights; i++) { + result += calculatePointLight(pointLights[i]); + } + + FragColor = vec4(result, 1.0); +} + +vec3 calculateDirectionalLight(DirLight light) { + // Calculate diffuse + vec3 norm = normalize(vNormal); + vec3 lightDir = normalize(-light.direction); + float diff = max(dot(norm, lightDir), 0.0); + + // Calculate specular + vec3 viewDir = normalize(viewPos - vPos); + vec3 reflectDir = reflect(-lightDir, norm); + float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); + + vec3 ambient = light.ambient * material.diffuse; + vec3 diffuse = light.diffuse * diff * material.diffuse; + vec3 specular = light.specular * spec * material.specular; + + return (ambient + diffuse + specular); +} + +vec3 calculatePointLight(PointLight light) { + // Calculate ambient light + + // Calculate diffuse light + vec3 norm = normalize(vNormal); + vec3 lightDir = normalize(light.position - vPos); + float diff = max(dot(norm, lightDir), 0.0); + + // Calculate specular + vec3 viewDir = normalize(viewPos - vPos); + vec3 reflectDir = reflect(-lightDir, norm); + float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); + + // Calculate attenuation + float distance = length(light.position - vPos); + float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance)); + + vec3 ambient = light.ambient * material.diffuse; + vec3 diffuse = light.diffuse * diff * material.diffuse; + vec3 specular = light.specular * spec * material.specular; + + return (ambient + diffuse + specular) * attenuation; +} \ No newline at end of file diff --git a/assets/shaders/phong.vs b/assets/shaders/phong.vs new file mode 100644 index 0000000..075cf4d --- /dev/null +++ b/assets/shaders/phong.vs @@ -0,0 +1,20 @@ +#version 330 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 2) in vec2 aTexCoords; + +out vec3 vPos; +out vec3 vNormal; +out vec2 vTexCoords; + +uniform mat4 model; +uniform mat3 normalMatrix; +uniform mat4 view; +uniform mat4 projection; + +void main() +{ + gl_Position = projection * view * model * vec4(aPos, 1.0); + vPos = vec3(model * vec4(aPos, 1.0)); + vNormal = normalMatrix * aNormal; +} diff --git a/src/light.h b/src/light.h new file mode 100644 index 0000000..13c1104 --- /dev/null +++ b/src/light.h @@ -0,0 +1,20 @@ +#pragma once +#include + +struct DirLight { + glm::vec3 direction; + glm::vec3 ambient; + glm::vec3 diffuse; + glm::vec3 specular; +}; + +struct PointLight { + glm::vec3 position; + glm::vec3 ambient; + glm::vec3 diffuse; + glm::vec3 specular; + + float constant; + float linear; + float quadratic; +}; \ No newline at end of file diff --git a/src/material.h b/src/material.h new file mode 100644 index 0000000..a1cd10b --- /dev/null +++ b/src/material.h @@ -0,0 +1,8 @@ +#pragma once +#include + +struct Material { + glm::vec3 diffuse; + glm::vec3 specular; + float shininess; +}; \ No newline at end of file diff --git a/src/shader.cpp b/src/shader.cpp index 4285033..8d25072 100644 --- a/src/shader.cpp +++ b/src/shader.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include "shader.h" @@ -59,4 +60,48 @@ Shader::~Shader() { void Shader::use() { glUseProgram(id); +} + +void Shader::set(std::string key, int value) { + glUniform1i(glGetUniformLocation(id, key.c_str()), value); +} + +void Shader::set(std::string key, float value) { + glUniform1f(glGetUniformLocation(id, key.c_str()), value); +} + +void Shader::set(std::string key, Material value) { + set((key + ".diffuse").c_str(), value.diffuse); + set((key + ".specular").c_str(), value.specular); + set((key + ".shininess").c_str(), value.shininess); +} + +void Shader::set(std::string key, DirLight value) { + set((key + ".direction").c_str(), value.direction); + set((key + ".ambient").c_str(), value.ambient); + set((key + ".diffuse").c_str(), value.diffuse); + set((key + ".specular").c_str(), value.specular); +} + +void Shader::set(std::string key, PointLight value) { + set((key + ".position").c_str(), value.position); + set((key + ".ambient").c_str(), value.ambient); + set((key + ".diffuse").c_str(), value.diffuse); + set((key + ".specular").c_str(), value.specular); + + set((key + ".constant").c_str(), value.constant); + set((key + ".linear").c_str(), value.linear); + set((key + ".quadratic").c_str(), value.quadratic); +} + +void Shader::set(std::string key, glm::vec3 value) { + glUniform3f(glGetUniformLocation(id, key.c_str()), value.x, value.y, value.z); +} + +void Shader::set(std::string key, glm::mat3 value) { + glUniformMatrix3fv(glGetUniformLocation(id, key.c_str()), 1, GL_FALSE, glm::value_ptr(value)); +} + +void Shader::set(std::string key, glm::mat4 value) { + glUniformMatrix4fv(glGetUniformLocation(id, key.c_str()), 1, GL_FALSE, glm::value_ptr(value)); } \ No newline at end of file diff --git a/src/shader.h b/src/shader.h index e482036..77aa5b6 100644 --- a/src/shader.h +++ b/src/shader.h @@ -1,5 +1,9 @@ #pragma once +#include +#include #include +#include "material.h" +#include "light.h" class Shader { unsigned int id; @@ -8,4 +12,13 @@ public: void use(); Shader(std::string vertexShaderPath, std::string fragmentShaderPath); ~Shader(); + + void set(std::string key, int value); + void set(std::string key, float value); + void set(std::string key, Material value); + void set(std::string key, DirLight value); + void set(std::string key, PointLight value); + void set(std::string key, glm::vec3 value); + void set(std::string key, glm::mat3 value); + void set(std::string key, glm::mat4 value); }; \ No newline at end of file