diff --git a/FinalProject/FinalProject.vcxproj b/FinalProject/FinalProject.vcxproj index f3f0de1..2df4171 100644 --- a/FinalProject/FinalProject.vcxproj +++ b/FinalProject/FinalProject.vcxproj @@ -108,6 +108,7 @@ + @@ -142,6 +143,8 @@ + + diff --git a/FinalProject/FinalProject.vcxproj.filters b/FinalProject/FinalProject.vcxproj.filters index 7638a20..6a5c503 100644 --- a/FinalProject/FinalProject.vcxproj.filters +++ b/FinalProject/FinalProject.vcxproj.filters @@ -165,6 +165,9 @@ Source Files\Qt Widgets\Pages\Scene Editor\Object Selector + + Source Files\OpenGL Abstractions + @@ -206,6 +209,12 @@ Header Files\Qt Widgets\Pages\Scene Editor\Object Setter + + Header Files\OpenGL Abstractions + + + Header Files\OpenGL Abstractions + diff --git a/FinalProject/fragmentshader.fs b/FinalProject/fragmentshader.fs index 556286e..5dbf34b 100644 --- a/FinalProject/fragmentshader.fs +++ b/FinalProject/fragmentshader.fs @@ -1,13 +1,148 @@ #version 430 core out vec4 FragColor; +struct Material { + sampler2D texture_diffuse1; + sampler2D texture_specular1; + float shininess; +}; + +struct DirLight { + vec3 direction; + + vec3 ambient; + vec3 diffuse; + vec3 specular; +}; + +struct PointLight { + vec3 position; + + float constant; + float linear; + float quadratic; + + vec3 ambient; + vec3 diffuse; + vec3 specular; +}; + +struct SpotLight { + vec3 position; + vec3 direction; + float cutOff; + float outerCutOff; + + float constant; + float linear; + float quadratic; + + vec3 ambient; + vec3 diffuse; + vec3 specular; +}; + +#define NR_POINT_LIGHTS 4 + +in vec3 FragPos; +in vec3 Normal; in vec2 TexCoords; -uniform sampler2D texture_diffuse1; -uniform sampler2D texture_specular1; + +uniform vec3 viewPos; +uniform DirLight dirLight; +uniform PointLight pointLights[NR_POINT_LIGHTS]; +uniform SpotLight spotLight; +uniform Material material; + +// function prototypes +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() { - FragColor = texture(texture_specular1, TexCoords); - FragColor = texture(texture_diffuse1, TexCoords); + // properties + vec3 norm = normalize(Normal); + vec3 viewDir = normalize(viewPos - FragPos); + + // == ===================================================== + // Our lighting is set up in 3 phases: directional, point lights and an optional flashlight + // For each phase, a calculate function is defined that calculates the corresponding color + // per lamp. In the main() function we take all the calculated colors and sum them up for + // this fragment's final color. + // == ===================================================== + // phase 1: directional lighting + vec3 result = CalcDirLight(dirLight, norm, viewDir); + // phase 2: point lights + for(int i = 0; i < NR_POINT_LIGHTS; i++) + result += CalcPointLight(pointLights[i], norm, FragPos, viewDir); + // phase 3: spot light + 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.texture_diffuse1, TexCoords)); + vec3 diffuse = light.diffuse * diff * vec3(texture(material.texture_diffuse1, TexCoords)); + vec3 specular = light.specular * spec * vec3(texture(material.texture_specular1, 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.texture_diffuse1, TexCoords)); + vec3 diffuse = light.diffuse * diff * vec3(texture(material.texture_diffuse1, TexCoords)); + vec3 specular = light.specular * spec * vec3(texture(material.texture_specular1, 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.texture_diffuse1, TexCoords)); + vec3 diffuse = light.diffuse * diff * vec3(texture(material.texture_diffuse1, TexCoords)); + vec3 specular = light.specular * spec * vec3(texture(material.texture_specular1, TexCoords)); + ambient *= attenuation * intensity; + diffuse *= attenuation * intensity; + specular *= attenuation * intensity; + return (ambient + diffuse + specular); } \ No newline at end of file diff --git a/FinalProject/illuminant.fs b/FinalProject/illuminant.fs new file mode 100644 index 0000000..e69de29 diff --git a/FinalProject/illuminant.h b/FinalProject/illuminant.h new file mode 100644 index 0000000..0eda181 --- /dev/null +++ b/FinalProject/illuminant.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include +#include + +#include "shader.h" +#include "logger.h" + +class Illuminant { + +}; + +class DirLight : public Illuminant { + +}; + +class SpotLight : public Illuminant { + +}; + +class PointLight : public Illuminant { + +}; \ No newline at end of file diff --git a/FinalProject/illuminant.vs b/FinalProject/illuminant.vs new file mode 100644 index 0000000..c875a90 --- /dev/null +++ b/FinalProject/illuminant.vs @@ -0,0 +1,11 @@ +#version 430 core +layout (location = 0) in vec3 aPos; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + +void main() +{ + gl_Position = projection * view * model * vec4(aPos, 1.0); +} \ No newline at end of file diff --git a/FinalProject/lightCaster.cpp b/FinalProject/lightCaster.cpp new file mode 100644 index 0000000..8fddfa1 --- /dev/null +++ b/FinalProject/lightCaster.cpp @@ -0,0 +1,232 @@ +#include"lightCaster.h" + +ShaderProgram* lastShader = NULL; + +queue available = queue(); + +Illuminant::Illuminant(){ + Logger::debug("We do not recommend to construct illuminant without parameter"); +} +// white color by default +Illuminant::Illuminant(glm::vec3 position, LightType lightType){ + _position = position; + setType(lightType); + Logger::info("55555555555"); +} +// set up with one color +Illuminant::Illuminant(glm::vec3 position, glm::vec3 color, LightType lightType){ + _position = position; + _ambient = color * 0.05f; + _diffuse = color * 0.8f; + _specular = color; + setType(lightType); + Logger::info("4444444444444444444"); +} +//set up by assign all colors +Illuminant::Illuminant(glm::vec3 position, glm::vec3 ambient, + glm::vec3 diffuse, glm::vec3 specular, LightType lightType){ + _position = position; + _ambient = ambient; + _diffuse = diffuse; + _specular = specular; + setType(lightType); + Logger::info("333333333333333"); +} + +// set up with one color,建议平行光源使用这个 +Illuminant::Illuminant(LightType lightType, glm::vec3 direction, glm::vec3 color) { + _direction = direction; + _ambient = color * 0.05f; + _diffuse = color * 0.8f; + _specular = color; + setType(lightType); + Logger::info("22222222222222222"); +} + +// set up with one color,建议聚光灯光源使用这个 +Illuminant::Illuminant(glm::vec3 position, glm::vec3 direction, glm::vec3 color, LightType lightType) { + _direction = direction; + _position = position; + _ambient = color * 0.05f; + _diffuse = color * 0.8f; + _specular = color; + setType(lightType); + Logger::info("1111111111111111111"); +} + +Illuminant::~Illuminant() { + switchOff(); + if (_lightType == point) { + available.push(this->pointID); + } + +} + +void Illuminant::setAttenuation(float constant, float linear, float quadratic){ + _constant = constant; + _linear = linear; + _quadratic = quadratic; +} + +glm::vec3 Illuminant::direction(){ + return _direction; +} +glm::vec3 Illuminant::position(){ + return _position; +} +glm::vec3 Illuminant::ambient(){ + return _ambient; +} +glm::vec3 Illuminant::diffuse(){ + return _diffuse; +} +glm::vec3 Illuminant::specular(){ + return _specular; +} + +Illuminant::LightType Illuminant::type(){ + return _lightType; +} + +void Illuminant::move(glm::vec3 deltaPos){ + _position += deltaPos; +} +void Illuminant::setPosition(glm::vec3 Pos){ + _position = Pos; +} + +void Illuminant::setColor(glm::vec3 ambient, glm::vec3 diffuse, glm::vec3 specular){ + _ambient = ambient; + _diffuse = diffuse; + _specular = specular; +} + +// 使用默认的分配系数 +void Illuminant::setColor(glm::vec3 color){ + _ambient = color * 0.05f; + _diffuse = color * 0.8f; + _specular = color; +} +void Illuminant::setDirection(glm::vec3 direction) { + _direction = direction; +} + +void Illuminant::setType(LightType type){ + + if (available.size() == 0 and type == point) { + Logger::error("Point light number exceed!\n"); + return; + } + _lightType = type; + if (type == point) { + pointID = available.front(); + available.pop(); + } +} + +void Illuminant::updateLight(ShaderProgram& shader) { + lastShader = &shader; + if (_lightType == dir) { + // directional light + shader.setUniform("dirLight.direction", _direction); + shader.setUniform("dirLight.ambient", _ambient); + shader.setUniform("dirLight.diffuse", _diffuse); + shader.setUniform("dirLight.specular",_specular); + } + else if (_lightType == point) + { // point light 1 + string prefix = "pointLights[" + std::to_string(pointID) + "]."; + + shader.setUniform(prefix+"position", _position); + shader.setUniform(prefix + "ambient", _ambient); + shader.setUniform(prefix + "diffuse", _diffuse); + shader.setUniform(prefix + "specular", _specular); + shader.setUniform(prefix + "constant",_constant); + shader.setUniform(prefix + "linear", _linear); + shader.setUniform(prefix + "quadratic", _quadratic); + + } + else { + // spotLight + shader.setUniform("spotLight.position", _position); + shader.setUniform("spotLight.direction", _direction); + shader.setUniform("spotLight.ambient", _ambient); + shader.setUniform("spotLight.diffuse", _diffuse); + shader.setUniform("spotLight.specular", _specular); + shader.setUniform("spotLight.constant", _constant); + shader.setUniform("spotLight.linear", _linear); + shader.setUniform("spotLight.quadratic", _quadratic); + shader.setUniform("spotLight.cutOff", glm::cos(glm::radians(12.5f))); + shader.setUniform("spotLight.outerCutOff", glm::cos(glm::radians(15.0f))); + } + + +} + +void Illuminant::switchOff() { + // 只要没有颜色就行了 + setColor(glm::vec3(0.0f, 0.0f, 0.0f)); + if (lastShader != NULL) { + updateLight(*lastShader); + } +} + +void init_queue() { + for (int i = 0; i < Illuminant::MAXPOINTLIGHT; i++) { + available.push(i); + Logger::info("23533423q543"); + } +} + +// 如果uniform变量没有被设置,可能会出现不可预知的后果! +void setAllLigntUniform(ShaderProgram& shader) { + + shader.setUniform("dirLight.direction",0,0,-1); + shader.setUniform("dirLight.ambient", 0.1f, 0.1f, 0.1f); + shader.setUniform("dirLight.diffuse", 0.0f, 0.0f, 0.0f); + shader.setUniform("dirLight.specular", 0.0f, 0.0f, 0.0f); + // point light 1 + + shader.setUniform("pointLights[0].position", 0, 0, 0); + shader.setUniform("pointLights[0].ambient", 0.0f, 0.0f, 0.0f); + shader.setUniform("pointLights[0].diffuse", 0.0f, 0.0f, 0.0f); + shader.setUniform("pointLights[0].specular", 0.0f, 0.0f, 0.0f); + shader.setUniform("pointLights[0].constant", 1.0f); + shader.setUniform("pointLights[0].linear", 0.09f); + shader.setUniform("pointLights[0].quadratic", 0.032f); + // point light 2 + shader.setUniform("pointLights[1].position", 0.0f, 0.0f, 0.0f); + shader.setUniform("pointLights[1].ambient", 0.0f, 0.0f, 0.0f); + shader.setUniform("pointLights[1].diffuse", 0.0f, 0.0f, 0.0f); + shader.setUniform("pointLights[1].specular", 0.0f, 0.0f, 0.0f); + shader.setUniform("pointLights[1].constant", 1.0f); + shader.setUniform("pointLights[1].linear", 0.09f); + shader.setUniform("pointLights[1].quadratic", 0.032f); + // point light 3 + shader.setUniform("pointLights[2].position", 0.0f, 0.0f, 0.0f); + shader.setUniform("pointLights[2].ambient", 0.0f, 0.0f, 0.0f); + shader.setUniform("pointLights[2].diffuse", 0.0f, 0.0f, 0.0f); + shader.setUniform("pointLights[2].specular", 0.0f, 0.0f, 0.0f); + shader.setUniform("pointLights[2].constant", 1.0f); + shader.setUniform("pointLights[2].linear", 0.09f); + shader.setUniform("pointLights[2].quadratic", 0.032f); + // point light 4 + shader.setUniform("pointLights[3].position", 0.0f, 0.0f, 0.0f); + shader.setUniform("pointLights[3].ambient", 0.0f, 0.0f, 0.0f); + shader.setUniform("pointLights[3].diffuse", 0.0f, 0.0f, 0.0f); + shader.setUniform("pointLights[3].specular", 0.0f, 0.0f, 0.0f); + shader.setUniform("pointLights[3].constant", 1.0f); + shader.setUniform("pointLights[3].linear", 0.09f); + shader.setUniform("pointLights[3].quadratic", 0.032f); + // spotLight + shader.setUniform("spotLight.position", 0.0f, 0.0f, 3.0f); + shader.setUniform("spotLight.direction", -0.0f,-0.0f, -1.0f); + shader.setUniform("spotLight.ambient", 0.0f, 0.0f, 0.0f); + shader.setUniform("spotLight.diffuse", 0.0f, 0.0f, 0.0f); + shader.setUniform("spotLight.specular", 0.0f, 0.0f, 0.0f); + shader.setUniform("spotLight.constant", 1.0f); + shader.setUniform("spotLight.linear", 0.09f); + shader.setUniform("spotLight.quadratic", 0.032f); + shader.setUniform("spotLight.cutOff", glm::cos(glm::radians(12.5f))); + shader.setUniform("spotLight.outerCutOff", glm::cos(glm::radians(15.0f))); +} \ No newline at end of file diff --git a/FinalProject/lightCaster.h b/FinalProject/lightCaster.h new file mode 100644 index 0000000..5a53e4a --- /dev/null +++ b/FinalProject/lightCaster.h @@ -0,0 +1,86 @@ +#pragma once +#include"shader.h" +#include +#include +#include"logger.h" +#include + +using std::queue; +using std::string; +// 发光物不需要纹理,所以说需要另外的shader +// 在sceneviewer中被包含 +class Illuminant { +public: + enum LightType { dir, spot, point }; + int pointID = -1; +private: + LightType _lightType = dir; + + glm::vec3 _direction = glm::vec3(0,0,-1); + glm::vec3 _position = glm::vec3(0.0f); + glm::vec3 _ambient = glm::vec3(0.05f, 0.05f, 0.05f); + glm::vec3 _diffuse = glm::vec3(0.8f, 0.8f, 0.8f); + glm::vec3 _specular = glm::vec3(0.8f, 0.8f, 0.8f); + + float _constant = 1.0f; + float _linear = 0.09f; + float _quadratic = 0.032f; + + +public: + // 修改此处必须同步修改fragment shader的数组定义语句,目前此值最大为4 + const static int MAXPOINTLIGHT = 4; + + Illuminant(); + // white color by default, + Illuminant(glm::vec3 position, LightType lightType); + // set up with one color,建议点光源使用这个 + Illuminant(glm::vec3 position,glm::vec3 color, LightType lightType); + + // set up with one color,建议平行光源使用这个 + Illuminant(LightType lightType,glm::vec3 direction, glm::vec3 color); + + // set up with one color,建议聚光灯光源使用这个 + Illuminant(glm::vec3 position, glm::vec3 direction,glm::vec3 color, LightType lightType); + + //set up by assign all colors + Illuminant(glm::vec3 position, glm::vec3 ambient, glm::vec3 diffuse, glm::vec3 specular, LightType lightType); + + // 析构函数中,如果是点光源,应该增加可用点光源数目。不过暂时没有实现,在上层进行控制 + // 无论如何,将此函数置为黑色 + ~Illuminant(); + void setAttenuation(float constant, float linear, float quadratic); + + glm::vec3 direction(); + glm::vec3 position(); + glm::vec3 ambient(); + glm::vec3 diffuse(); + glm::vec3 specular(); + LightType type(); + + void move(glm::vec3 deltaPos); + void setPosition(glm::vec3 Pos); + // 平行光与手电筒必须设置此项 + void setDirection(glm::vec3 direction); + + void setColor(glm::vec3 ambient, glm::vec3 diffuse, glm::vec3 specular); + // 使用默认的分配系数 + void setColor(glm::vec3 color); + // 将本光源的信息传递给着色器 + void updateLight(ShaderProgram& shader); + + + +private: + // 只能在最初设定光源类型,没有必要在期间修改 + void setType(LightType type); + + // 懒惰删除 + void switchOff(); + +}; + +// 初始设置所有变量 +void setAllLigntUniform(ShaderProgram& lightingShader); + +void init_queue(); \ No newline at end of file diff --git a/FinalProject/mesh.cpp b/FinalProject/mesh.cpp index 0f70513..bcd149e 100644 --- a/FinalProject/mesh.cpp +++ b/FinalProject/mesh.cpp @@ -22,11 +22,14 @@ Mesh::Mesh(const std::vector& vertices, const std::vector& text void Mesh::render(const ShaderProgram& shader) const { unsigned int diffuseNr = 1; unsigned int specularNr = 1; + shader.setUniform("material.shininess",_shininess); for (int i = 0; i < _textures.size(); i++) { OPENGL_EXTRA_FUNCTIONS->glActiveTexture(GL_TEXTURE0 + i); // activate proper texture unit before binding // retrieve texture number (the N in diffuse_textureN) std::string number; std::string name = _textures[i].type() == TextureType::DIFFUSE ? "texture_diffuse" : "texture_specular"; + name = "material." + name; + if (_textures[i].type() == TextureType::DIFFUSE) number = std::to_string(diffuseNr++); else if (_textures[i].type() == TextureType::SPECULAR) diff --git a/FinalProject/mesh.h b/FinalProject/mesh.h index 56e07c5..86390ce 100644 --- a/FinalProject/mesh.h +++ b/FinalProject/mesh.h @@ -13,6 +13,9 @@ private: std::vector _indices; std::vector _textures; + // we can control shininess in mesh + float _shininess = 32.0f; + VertexArrayObject _vao = VertexArrayObject::empty(); public: @@ -23,6 +26,9 @@ public: inline std::vector vertices() const { return _vertices; } inline std::vector indices() const { return _indices; } inline std::vector textures() const { return _textures; } + + inline float shininess() const { return _shininess; } + inline void setShininess(float shininess) { _shininess = shininess; } inline VertexArrayObject vao() const { return _vao; } @@ -31,4 +37,4 @@ public: private: void setupMesh(); -}; \ No newline at end of file +}; diff --git a/FinalProject/renderable.cpp b/FinalProject/renderable.cpp index e6fedfd..289a8c5 100644 --- a/FinalProject/renderable.cpp +++ b/FinalProject/renderable.cpp @@ -42,6 +42,7 @@ void Renderable::render(ShaderProgram shader) { } // Set model matrix shader.setUniform("model", modelMatrix()); + // Render _model->render(shader); } diff --git a/FinalProject/sceneviewer.cpp b/FinalProject/sceneviewer.cpp index ede88ab..8f39eab 100644 --- a/FinalProject/sceneviewer.cpp +++ b/FinalProject/sceneviewer.cpp @@ -1,18 +1,13 @@ #include "sceneviewer.h" -#include #include #include #include #include +#include -#include "vbo.h" -#include "vao.h" -#include "shader.h" -#include "logger.h" -#include "model.h" +#include "lightCaster.h" -using std::vector; SceneViewer::SceneViewer(QWidget* parent) : QOpenGLWidget(parent) @@ -22,38 +17,50 @@ SceneViewer::SceneViewer(QWidget* parent) format.setProfile(QSurfaceFormat::CoreProfile); format.setVersion(4, 3); setFormat(format); - - // Create a folder - QDir dir("./temp/shaders"); - if (!dir.exists()) { - dir.mkpath("."); + + // Create temp folder + QDir dir; + if (!dir.exists("./temp")) + { + dir.mkdir("./temp"); + } + if (!dir.exists("./temp/shaders")) + { + dir.mkdir("./temp/shaders"); } - // Copy the shaders to the folder - if (QFile::exists("./temp/shaders/vertexshader.vs")) { - QFile::remove("./temp/shaders/vertexshader.vs"); - } - QFile::copy(":/shaders/vertexshader.vs", "./temp/shaders/vertexshader.vs"); - QFile::setPermissions("./temp/shaders/vertexshader.vs", QFileDevice::ReadOwner | QFileDevice::WriteOwner); - if (QFile::exists("./temp/shaders/fragmentshader.fs")) { - QFile::remove("./temp/shaders/fragmentshader.fs"); - } - QFile::copy(":/shaders/fragmentshader.fs", "./temp/shaders/fragmentshader.fs"); - QFile::setPermissions("./temp/shaders/fragmentshader.fs", QFile::ReadOwner | QFile::WriteOwner); + // Copy the shaders to the temp folder + extractShaderResorce("vertexshader.vs"); + extractShaderResorce("fragmentshader.fs"); + extractShaderResorce("illuminant.vs"); + extractShaderResorce("illuminant.fs"); } SceneViewer::~SceneViewer() { + +} +void SceneViewer::extractShaderResorce(const QString& shaderName) { + QString shaderResourcePath = ":/shaders/" + shaderName; + QString shaderTempPath = "./temp/shaders/" + shaderName; + + if (QFile::exists(shaderTempPath)) + { + QFile::remove(shaderTempPath); + } + QFile::copy(shaderResourcePath, shaderTempPath); + QFile::setPermissions(shaderTempPath, QFile::ReadOwner | QFile::WriteOwner); } void SceneViewer::initializeGL() { initializeOpenGLFunctions(); - + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); - + glEnable(GL_FRAMEBUFFER_SRGB); + Logger::info("Currently running on OpenGL version: " + std::string((const char*)glGetString(GL_VERSION))); _shaderProgram.ensureInitialized(); @@ -65,8 +72,16 @@ void SceneViewer::initializeGL() { _shaderProgram.attachShader(fragmentShader); vertexShader.dispose(); fragmentShader.dispose(); + + setAllLigntUniform(_shaderProgram); + init_queue(); + + addDirLight(glm::vec3(0.3, 0.5, -1), glm::vec3(0.2, 0.1, 0.2)); + addSpotLight(glm::vec3(0.3, 0.5, -1), glm::vec3(-0.3, -0.5, 3), glm::vec3(0.2, 1, 0.1)); + addPointLight(glm::vec3(0.5, 0.9, 0.4), glm::vec3(1, 0.2, 0.4)); + addPointLight(glm::vec3(-0.3, -0.9, 0.4), glm::vec3(0, 0.2, 0.9)); - _camera.setPosition(glm::vec3(0.0f, 0.0f, 10.0f)); + _camera.setPosition(glm::vec3(0.0f, 0.0f, 5.0f)); } void SceneViewer::resizeGL(int w, int h) { @@ -85,6 +100,8 @@ void SceneViewer::paintGL() { glm::mat4 projection = glm::perspective(glm::radians(_camera.zoomVal()), (float)width() / (float)height(), 0.1f, 100.0f); _shaderProgram.setUniform("view", view); _shaderProgram.setUniform("projection", projection); + + update_light(); for (auto object : _objects) { object.render(_shaderProgram); @@ -193,3 +210,24 @@ void SceneViewer::resizeEvent(QResizeEvent* event) { //mask.addRoundedRect(rect(), _cornerRadius, _cornerRadius); //setMask(mask.toFillPolygon().toPolygon()); } + + +void SceneViewer::update_light() { + setAllLigntUniform(_shaderProgram); + for (int i = 0; i < _illuminants.size(); i++) { + _illuminants[i].updateLight(_shaderProgram); + } +} + +void SceneViewer::addDirLight(glm::vec3 direction, glm::vec3 color) { + _illuminants.push_back(Illuminant(Illuminant::LightType::dir, direction,color)); +} +void SceneViewer::addPointLight(glm::vec3 position, glm::vec3 color) { + _illuminants.push_back(Illuminant(position, color, Illuminant::LightType::point)); +} +void SceneViewer::addSpotLight(glm::vec3 direction, glm::vec3 position, glm::vec3 color) { + _illuminants.push_back(Illuminant(position,direction, color, Illuminant::LightType::spot)); +} +void SceneViewer::deleteLight(int index) { + _illuminants.erase(_illuminants.begin() + index); +} \ No newline at end of file diff --git a/FinalProject/sceneviewer.h b/FinalProject/sceneviewer.h index 5d2460e..c97a399 100644 --- a/FinalProject/sceneviewer.h +++ b/FinalProject/sceneviewer.h @@ -4,7 +4,6 @@ #include #include #include - #include #include "camera.h" @@ -12,6 +11,11 @@ #include "renderable.h" #include "vao.h" #include "utils.h" +#include "lightCaster.h" +#include "vbo.h" +#include "logger.h" +#include "model.h" + class SceneViewer : public QOpenGLWidget, protected QOpenGLFunctions { @@ -21,6 +25,8 @@ private: // OpenGL section------------------------------------- // List of objects currently in the scene std::vector _objects; + // List of light casters in the scene + std::vector _illuminants; // Shader program for objects ShaderProgram _shaderProgram = ShaderProgram::empty(); // Main camera @@ -42,6 +48,14 @@ private: public: SceneViewer(QWidget* parent = 0); ~SceneViewer(); + void update_light(); + void addDirLight(glm::vec3 direction, glm::vec3 color); + void addPointLight(glm::vec3 position, glm::vec3 color); + void addSpotLight(glm::vec3 direction,glm::vec3 position, glm::vec3 color); + void deleteLight(int index); + +private: + void extractShaderResorce(const QString& shaderName); protected: // OpenGL functions diff --git a/FinalProject/vertexshader.vs b/FinalProject/vertexshader.vs index 73091f6..056e569 100644 --- a/FinalProject/vertexshader.vs +++ b/FinalProject/vertexshader.vs @@ -3,6 +3,8 @@ layout (location = 0) in vec3 aPos; layout (location = 1) in vec3 aNormal; layout (location = 2) in vec2 aTexCoords; +out vec3 FragPos; +out vec3 Normal; out vec2 TexCoords; uniform mat4 model; @@ -11,6 +13,9 @@ uniform mat4 projection; void main() { - TexCoords = aTexCoords; - gl_Position = projection * view * model * vec4(aPos, 1.0); + FragPos = vec3(model * vec4(aPos, 1.0)); + Normal = mat3(transpose(inverse(model))) * aNormal; + TexCoords = aTexCoords; + + gl_Position = projection * view * vec4(FragPos, 1.0); } \ No newline at end of file