diff --git a/includes/learnopengl/shader.h b/includes/learnopengl/shader.h index 8a2b995..1fd6267 100644 --- a/includes/learnopengl/shader.h +++ b/includes/learnopengl/shader.h @@ -106,59 +106,59 @@ public: } // utility uniform functions // ------------------------------------------------------------------------ - void setBool(std::string name, bool value) const + void setBool(const std::string &name, bool value) const { glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value); } // ------------------------------------------------------------------------ - void setInt(std::string name, int value) const + void setInt(const std::string &name, int value) const { glUniform1i(glGetUniformLocation(ID, name.c_str()), value); } // ------------------------------------------------------------------------ - void setFloat(std::string name, float value) const + void setFloat(const std::string &name, float value) const { glUniform1f(glGetUniformLocation(ID, name.c_str()), value); } // ------------------------------------------------------------------------ - void setVec2(std::string name, const glm::vec2 &value) const + void setVec2(const std::string &name, const glm::vec2 &value) const { glUniform2fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]); } - void setVec2(std::string name, float x, float y) const + void setVec2(const std::string &name, float x, float y) const { glUniform2f(glGetUniformLocation(ID, name.c_str()), x, y); } // ------------------------------------------------------------------------ - void setVec3(std::string name, const glm::vec3 &value) const + void setVec3(const std::string &name, const glm::vec3 &value) const { glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]); } - void setVec3(std::string name, float x, float y, float z) const + void setVec3(const std::string &name, float x, float y, float z) const { glUniform3f(glGetUniformLocation(ID, name.c_str()), x, y, z); } // ------------------------------------------------------------------------ - void setVec4(std::string name, const glm::vec4 &value) const + void setVec4(const std::string &name, const glm::vec4 &value) const { glUniform4fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]); } - void setVec4(std::string name, float x, float y, float z, float w) + void setVec4(const std::string &name, float x, float y, float z, float w) { glUniform4f(glGetUniformLocation(ID, name.c_str()), x, y, z, w); } // ------------------------------------------------------------------------ - void setMat2(std::string name, const glm::mat2 &mat) const + void setMat2(const std::string &name, const glm::mat2 &mat) const { glUniformMatrix2fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]); } // ------------------------------------------------------------------------ - void setMat3(std::string name, const glm::mat3 &mat) const + void setMat3(const std::string &name, const glm::mat3 &mat) const { glUniformMatrix3fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]); } // ------------------------------------------------------------------------ - void setMat4(std::string name, const glm::mat4 &mat) const + void setMat4(const std::string &name, const glm::mat4 &mat) const { glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]); } diff --git a/includes/learnopengl/shader_m.h b/includes/learnopengl/shader_m.h index 2f40268..f1ad126 100644 --- a/includes/learnopengl/shader_m.h +++ b/includes/learnopengl/shader_m.h @@ -80,59 +80,59 @@ public: } // utility uniform functions // ------------------------------------------------------------------------ - void setBool(std::string name, bool value) const + void setBool(const std::string &name, bool value) const { glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value); } // ------------------------------------------------------------------------ - void setInt(std::string name, int value) const + void setInt(const std::string &name, int value) const { glUniform1i(glGetUniformLocation(ID, name.c_str()), value); } // ------------------------------------------------------------------------ - void setFloat(std::string name, float value) const + void setFloat(const std::string &name, float value) const { glUniform1f(glGetUniformLocation(ID, name.c_str()), value); } // ------------------------------------------------------------------------ - void setVec2(std::string name, const glm::vec2 &value) const + void setVec2(const std::string &name, const glm::vec2 &value) const { glUniform2fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]); } - void setVec2(std::string name, float x, float y) const + void setVec2(const std::string &name, float x, float y) const { glUniform2f(glGetUniformLocation(ID, name.c_str()), x, y); } // ------------------------------------------------------------------------ - void setVec3(std::string name, const glm::vec3 &value) const + void setVec3(const std::string &name, const glm::vec3 &value) const { glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]); } - void setVec3(std::string name, float x, float y, float z) const + void setVec3(const std::string &name, float x, float y, float z) const { glUniform3f(glGetUniformLocation(ID, name.c_str()), x, y, z); } // ------------------------------------------------------------------------ - void setVec4(std::string name, const glm::vec4 &value) const + void setVec4(const std::string &name, const glm::vec4 &value) const { glUniform4fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]); } - void setVec4(std::string name, float x, float y, float z, float w) const + void setVec4(const std::string &name, float x, float y, float z, float w) const { glUniform4f(glGetUniformLocation(ID, name.c_str()), x, y, z, w); } // ------------------------------------------------------------------------ - void setMat2(std::string name, const glm::mat2 &mat) const + void setMat2(const std::string &name, const glm::mat2 &mat) const { glUniformMatrix2fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]); } // ------------------------------------------------------------------------ - void setMat3(std::string name, const glm::mat3 &mat) const + void setMat3(const std::string &name, const glm::mat3 &mat) const { glUniformMatrix3fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]); } // ------------------------------------------------------------------------ - void setMat4(std::string name, const glm::mat4 &mat) const + void setMat4(const std::string &name, const glm::mat4 &mat) const { glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]); } diff --git a/includes/learnopengl/shader_s.h b/includes/learnopengl/shader_s.h index b22140b..0e07fe5 100644 --- a/includes/learnopengl/shader_s.h +++ b/includes/learnopengl/shader_s.h @@ -78,17 +78,17 @@ public: } // utility uniform functions // ------------------------------------------------------------------------ - void setBool(std::string name, bool value) const + void setBool(const std::string &name, bool value) const { glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value); } // ------------------------------------------------------------------------ - void setInt(std::string name, int value) const + void setInt(const std::string &name, int value) const { glUniform1i(glGetUniformLocation(ID, name.c_str()), value); } // ------------------------------------------------------------------------ - void setFloat(std::string name, float value) const + void setFloat(const std::string &name, float value) const { glUniform1f(glGetUniformLocation(ID, name.c_str()), value); } diff --git a/src/5.advanced_lighting/3.2.1.point_shadows/3.2.1.point_shadows.fs b/src/5.advanced_lighting/3.2.1.point_shadows/3.2.1.point_shadows.fs new file mode 100644 index 0000000..411cb84 --- /dev/null +++ b/src/5.advanced_lighting/3.2.1.point_shadows/3.2.1.point_shadows.fs @@ -0,0 +1,61 @@ +#version 330 core +out vec4 FragColor; + +in VS_OUT { + vec3 FragPos; + vec3 Normal; + vec2 TexCoords; +} fs_in; + +uniform sampler2D diffuseTexture; +uniform samplerCube depthMap; + +uniform vec3 lightPos; +uniform vec3 viewPos; + +uniform float far_plane; +uniform bool shadows; + +float ShadowCalculation(vec3 fragPos) +{ + // get vector between fragment position and light position + vec3 fragToLight = fragPos - lightPos; + // ise the fragment to light vector to sample from the depth map + float closestDepth = texture(depthMap, fragToLight).r; + // it is currently in linear range between [0,1], let's re-transform it back to original depth value + closestDepth *= far_plane; + // now get current linear depth as the length between the fragment and light position + float currentDepth = length(fragToLight); + // test for shadows + float bias = 0.05; // we use a much larger bias since depth is now in [near_plane, far_plane] range + float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0; + // display closestDepth as debug (to visualize depth cubemap) + // FragColor = vec4(vec3(closestDepth / far_plane), 1.0); + + return shadow; +} + +void main() +{ + vec3 color = texture(diffuseTexture, fs_in.TexCoords).rgb; + vec3 normal = normalize(fs_in.Normal); + vec3 lightColor = vec3(0.3); + // Ambient + vec3 ambient = 0.3 * color; + // Diffuse + vec3 lightDir = normalize(lightPos - fs_in.FragPos); + float diff = max(dot(lightDir, normal), 0.0); + vec3 diffuse = diff * lightColor; + // Specular + vec3 viewDir = normalize(viewPos - fs_in.FragPos); + vec3 reflectDir = reflect(-lightDir, normal); + float spec = 0.0; + vec3 halfwayDir = normalize(lightDir + viewDir); + spec = pow(max(dot(normal, halfwayDir), 0.0), 64.0); + vec3 specular = spec * lightColor; + // Calculate shadow + float shadow = shadows ? ShadowCalculation(fs_in.FragPos) : 0.0; + vec3 lighting = (ambient + (1.0 - shadow) * (diffuse + specular)) * color; + + FragColor = vec4(lighting, 1.0f); +} \ No newline at end of file diff --git a/src/5.advanced_lighting/3.2.1.point_shadows/3.2.1.point_shadows.vs b/src/5.advanced_lighting/3.2.1.point_shadows/3.2.1.point_shadows.vs new file mode 100644 index 0000000..4b15f15 --- /dev/null +++ b/src/5.advanced_lighting/3.2.1.point_shadows/3.2.1.point_shadows.vs @@ -0,0 +1,29 @@ +#version 330 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 2) in vec2 aTexCoords; + +out vec2 TexCoords; + +out VS_OUT { + vec3 FragPos; + vec3 Normal; + vec2 TexCoords; +} vs_out; + +uniform mat4 projection; +uniform mat4 view; +uniform mat4 model; + +uniform bool reverse_normals; + +void main() +{ + vs_out.FragPos = vec3(model * vec4(aPos, 1.0)); + if(reverse_normals) // a slight hack to make sure the outer large cube displays lighting from the 'inside' instead of the default 'outside'. + vs_out.Normal = transpose(inverse(mat3(model))) * (-1.0 * aNormal); + else + vs_out.Normal = transpose(inverse(mat3(model))) * aNormal; + vs_out.TexCoords = aTexCoords; + gl_Position = projection * view * model * vec4(aPos, 1.0); +} \ No newline at end of file diff --git a/src/5.advanced_lighting/3.2.2.point_shadows_soft/point_shadows_depth.frag b/src/5.advanced_lighting/3.2.1.point_shadows/3.2.1.point_shadows_depth.fs similarity index 89% rename from src/5.advanced_lighting/3.2.2.point_shadows_soft/point_shadows_depth.frag rename to src/5.advanced_lighting/3.2.1.point_shadows/3.2.1.point_shadows_depth.fs index 754b8fc..37600c6 100644 --- a/src/5.advanced_lighting/3.2.2.point_shadows_soft/point_shadows_depth.frag +++ b/src/5.advanced_lighting/3.2.1.point_shadows/3.2.1.point_shadows_depth.fs @@ -11,6 +11,6 @@ void main() // map to [0;1] range by dividing by far_plane lightDistance = lightDistance / far_plane; - // Write this as modified depth + // write this as modified depth gl_FragDepth = lightDistance; } \ No newline at end of file diff --git a/src/5.advanced_lighting/3.2.2.point_shadows_soft/point_shadows_depth.gs b/src/5.advanced_lighting/3.2.1.point_shadows/3.2.1.point_shadows_depth.gs similarity index 83% rename from src/5.advanced_lighting/3.2.2.point_shadows_soft/point_shadows_depth.gs rename to src/5.advanced_lighting/3.2.1.point_shadows/3.2.1.point_shadows_depth.gs index f61800b..96d5627 100644 --- a/src/5.advanced_lighting/3.2.2.point_shadows_soft/point_shadows_depth.gs +++ b/src/5.advanced_lighting/3.2.1.point_shadows/3.2.1.point_shadows_depth.gs @@ -2,7 +2,7 @@ layout (triangles) in; layout (triangle_strip, max_vertices=18) out; -uniform mat4 shadowTransforms[6]; +uniform mat4 shadowMatrices[6]; out vec4 FragPos; // FragPos from GS (output per emitvertex) @@ -14,7 +14,7 @@ void main() for(int i = 0; i < 3; ++i) // for each triangle's vertices { FragPos = gl_in[i].gl_Position; - gl_Position = shadowTransforms[face] * FragPos; + gl_Position = shadowMatrices[face] * FragPos; EmitVertex(); } EndPrimitive(); diff --git a/src/5.advanced_lighting/3.2.1.point_shadows/3.2.1.point_shadows_depth.vs b/src/5.advanced_lighting/3.2.1.point_shadows/3.2.1.point_shadows_depth.vs new file mode 100644 index 0000000..8c71938 --- /dev/null +++ b/src/5.advanced_lighting/3.2.1.point_shadows/3.2.1.point_shadows_depth.vs @@ -0,0 +1,9 @@ +#version 330 core +layout (location = 0) in vec3 aPos; + +uniform mat4 model; + +void main() +{ + gl_Position = model * vec4(aPos, 1.0); +} \ No newline at end of file diff --git a/src/5.advanced_lighting/3.2.1.point_shadows/point_shadows.cpp b/src/5.advanced_lighting/3.2.1.point_shadows/point_shadows.cpp index dddc3e8..b125384 100644 --- a/src/5.advanced_lighting/3.2.1.point_shadows/point_shadows.cpp +++ b/src/5.advanced_lighting/3.2.1.point_shadows/point_shadows.cpp @@ -20,11 +20,12 @@ void processInput(GLFWwindow *window); unsigned int loadTexture(const char *path); void renderScene(const Shader &shader); void renderCube(); -void renderQuad(); // settings const unsigned int SCR_WIDTH = 1280; const unsigned int SCR_HEIGHT = 720; +bool shadows = true; +bool shadowsKeyPressed = false; // camera Camera camera(glm::vec3(0.0f, 0.0f, 3.0f)); @@ -36,9 +37,6 @@ bool firstMouse = true; float deltaTime = 0.0f; float lastFrame = 0.0f; -// meshes -unsigned int planeVAO; - int main() { // glfw: initialize and configure @@ -76,38 +74,12 @@ int main() // configure global opengl state // ----------------------------- glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); // build and compile shaders // ------------------------- Shader shader("3.2.1.point_shadows.vs", "3.2.1.point_shadows.fs"); - Shader simpleDepthShader("3.2.1.point_shadows_depth.vs", "3.2.1.point_shadows_depth.fs"); - - // set up vertex data (and buffer(s)) and configure vertex attributes - // ------------------------------------------------------------------ - float planeVertices[] = { - // positions // normals // texcoords - 25.0f, -0.5f, 25.0f, 0.0f, 1.0f, 0.0f, 25.0f, 0.0f, - -25.0f, -0.5f, 25.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, - -25.0f, -0.5f, -25.0f, 0.0f, 1.0f, 0.0f, 0.0f, 25.0f, - - 25.0f, -0.5f, 25.0f, 0.0f, 1.0f, 0.0f, 25.0f, 0.0f, - -25.0f, -0.5f, -25.0f, 0.0f, 1.0f, 0.0f, 0.0f, 25.0f, - 25.0f, -0.5f, -25.0f, 0.0f, 1.0f, 0.0f, 25.0f, 25.0f - }; - // plane VAO - unsigned int planeVBO; - glGenVertexArrays(1, &planeVAO); - glGenBuffers(1, &planeVBO); - glBindVertexArray(planeVAO); - glBindBuffer(GL_ARRAY_BUFFER, planeVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(planeVertices), planeVertices, GL_STATIC_DRAW); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0); - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float))); - glEnableVertexAttribArray(2); - glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float))); - glBindVertexArray(0); + Shader simpleDepthShader("3.2.1.point_shadows_depth.vs", "3.2.1.point_shadows_depth.fs", "3.2.1.point_shadows_depth.gs"); // load textures // ------------- @@ -118,20 +90,20 @@ int main() const unsigned int SHADOW_WIDTH = 1024, SHADOW_HEIGHT = 1024; unsigned int depthMapFBO; glGenFramebuffers(1, &depthMapFBO); - // create depth texture - unsigned int depthMap; - glGenTextures(1, &depthMap); - glBindTexture(GL_TEXTURE_2D, depthMap); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, SHADOW_WIDTH, SHADOW_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); - GLfloat borderColor[] = { 1.0, 1.0, 1.0, 1.0 }; - glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); + // create depth cubemap texture + unsigned int depthCubemap; + glGenTextures(1, &depthCubemap); + glBindTexture(GL_TEXTURE_CUBE_MAP, depthCubemap); + for (unsigned int i = 0; i < 6; ++i) + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_DEPTH_COMPONENT, SHADOW_WIDTH, SHADOW_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); // attach depth texture as FBO's depth buffer glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthMap, 0); + glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthCubemap, 0); glDrawBuffer(GL_NONE); glReadBuffer(GL_NONE); glBindFramebuffer(GL_FRAMEBUFFER, 0); @@ -141,13 +113,11 @@ int main() // -------------------- shader.use(); shader.setInt("diffuseTexture", 0); - shader.setInt("shadowMap", 1); - debugDepthQuad.use(); - debugDepthQuad.setInt("depthMap", 0); + shader.setInt("depthMap", 1); // lighting info // ------------- - glm::vec3 lightPos(-2.0f, 4.0f, -1.0f); + glm::vec3 lightPos(0.0f, 0.0f, 0.0f); // render loop // ----------- @@ -163,43 +133,42 @@ int main() // ----- processInput(window); - // change light position over time - //lightPos.x = sin(glfwGetTime()) * 3.0f; - //lightPos.z = cos(glfwGetTime()) * 2.0f; - //lightPos.y = 5.0 + cos(glfwGetTime()) * 1.0f; + // move light position over time + lightPos.z = sin(glfwGetTime() * 0.5) * 3.0; // render // ------ glClearColor(0.1f, 0.1f, 0.1f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - // 1. render depth of scene to texture (from light's perspective) - // -------------------------------------------------------------- - glm::mat4 lightProjection, lightView; - glm::mat4 lightSpaceMatrix; - float near_plane = 1.0f, far_plane = 7.5f; - //lightProjection = glm::perspective(glm::radians(45.0f), (GLfloat)SHADOW_WIDTH / (GLfloat)SHADOW_HEIGHT, near_plane, far_plane); // note that if you use a perspective projection matrix you'll have to change the light position as the current light position isn't enough to reflect the whole scene - lightProjection = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, near_plane, far_plane); - lightView = glm::lookAt(lightPos, glm::vec3(0.0f), glm::vec3(0.0, 1.0, 0.0)); - lightSpaceMatrix = lightProjection * lightView; - // render scene from light's point of view - simpleDepthShader.use(); - simpleDepthShader.setMat4("lightSpaceMatrix", lightSpaceMatrix); + // 0. create depth cubemap transformation matrices + // ----------------------------------------------- + float near_plane = 1.0f; + float far_plane = 25.0f; + glm::mat4 shadowProj = glm::perspective(glm::radians(90.0f), (float)SHADOW_WIDTH / (float)SHADOW_HEIGHT, near_plane, far_plane); + std::vector shadowTransforms; + shadowTransforms.push_back(shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3( 1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f))); + shadowTransforms.push_back(shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3(-1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f))); + shadowTransforms.push_back(shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3( 0.0f, 1.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f))); + shadowTransforms.push_back(shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3( 0.0f, -1.0f, 0.0f), glm::vec3(0.0f, 0.0f, -1.0f))); + shadowTransforms.push_back(shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3( 0.0f, 0.0f, 1.0f), glm::vec3(0.0f, -1.0f, 0.0f))); + shadowTransforms.push_back(shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3( 0.0f, 0.0f, -1.0f), glm::vec3(0.0f, -1.0f, 0.0f))); + // 1. render scene to depth cubemap + // -------------------------------- glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT); glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO); - glClear(GL_DEPTH_BUFFER_BIT); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, woodTexture); - renderScene(simpleDepthShader); + glClear(GL_DEPTH_BUFFER_BIT); + simpleDepthShader.use(); + for (unsigned int i = 0; i < 6; ++i) + simpleDepthShader.setMat4("shadowMatrices[" + std::to_string(i) + "]", shadowTransforms[i]); + simpleDepthShader.setFloat("far_plane", far_plane); + simpleDepthShader.setVec3("lightPos", lightPos); + renderScene(simpleDepthShader); glBindFramebuffer(GL_FRAMEBUFFER, 0); - // reset viewport - glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - // 2. render scene as normal using the generated depth/shadow map - // -------------------------------------------------------------- + // 2. render scene as normal + // ------------------------- glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); shader.use(); @@ -207,36 +176,23 @@ int main() glm::mat4 view = camera.GetViewMatrix(); shader.setMat4("projection", projection); shader.setMat4("view", view); - // set light uniforms - shader.setVec3("viewPos", camera.Position); + // set lighting uniforms shader.setVec3("lightPos", lightPos); - shader.setMat4("lightSpaceMatrix", lightSpaceMatrix); + shader.setVec3("viewPos", camera.Position); + shader.setInt("shadows", shadows); // enable/disable shadows by pressing 'SPACE' + shader.setFloat("far_plane", far_plane); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, woodTexture); glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, depthMap); + glBindTexture(GL_TEXTURE_CUBE_MAP, depthCubemap); renderScene(shader); - // render Depth map to quad for visual debugging - // --------------------------------------------- - debugDepthQuad.use(); - debugDepthQuad.setFloat("near_plane", near_plane); - debugDepthQuad.setFloat("far_plane", far_plane); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, depthMap); - //renderQuad(); - // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.) // ------------------------------------------------------------------------------- glfwSwapBuffers(window); glfwPollEvents(); } - // optional: de-allocate all resources once they've outlived their purpose: - // ------------------------------------------------------------------------ - glDeleteVertexArrays(1, &planeVAO); - glDeleteBuffers(1, &planeVBO); - glfwTerminate(); return 0; } @@ -245,31 +201,44 @@ int main() // -------------------- void renderScene(const Shader &shader) { - // floor + // room cube glm::mat4 model; + model = glm::scale(model, glm::vec3(5.0f)); shader.setMat4("model", model); - glBindVertexArray(planeVAO); - glDrawArrays(GL_TRIANGLES, 0, 6); + glDisable(GL_CULL_FACE); // note that we disable culling here since we render 'inside' the cube instead of the usual 'outside' which throws off the normal culling methods. + shader.setInt("reverse_normals", 1); // A small little hack to invert normals when drawing cube from the inside so lighting still works. + renderCube(); + shader.setInt("reverse_normals", 0); // and of course disable it + glEnable(GL_CULL_FACE); // cubes model = glm::mat4(); - model = glm::translate(model, glm::vec3(0.0f, 1.5f, 0.0)); + model = glm::translate(model, glm::vec3(4.0f, -3.5f, 0.0)); model = glm::scale(model, glm::vec3(0.5f)); shader.setMat4("model", model); renderCube(); model = glm::mat4(); - model = glm::translate(model, glm::vec3(2.0f, 0.0f, 1.0)); + model = glm::translate(model, glm::vec3(2.0f, 3.0f, 1.0)); + model = glm::scale(model, glm::vec3(0.75f)); + shader.setMat4("model", model); + renderCube(); + model = glm::mat4(); + model = glm::translate(model, glm::vec3(-3.0f, -1.0f, 0.0)); model = glm::scale(model, glm::vec3(0.5f)); shader.setMat4("model", model); renderCube(); model = glm::mat4(); - model = glm::translate(model, glm::vec3(-1.0f, 0.0f, 2.0)); + model = glm::translate(model, glm::vec3(-1.5f, 1.0f, 1.5)); + model = glm::scale(model, glm::vec3(0.5f)); + shader.setMat4("model", model); + renderCube(); + model = glm::mat4(); + model = glm::translate(model, glm::vec3(-1.5f, 2.0f, -3.0)); model = glm::rotate(model, glm::radians(60.0f), glm::normalize(glm::vec3(1.0, 0.0, 1.0))); - model = glm::scale(model, glm::vec3(0.25)); + model = glm::scale(model, glm::vec3(0.75f)); shader.setMat4("model", model); renderCube(); } - // renderCube() renders a 1x1 3D cube in NDC. // ------------------------------------------------- unsigned int cubeVAO = 0; @@ -282,46 +251,46 @@ void renderCube() float vertices[] = { // back face -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, // bottom-left - 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, // top-right - 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, // bottom-right - 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, // top-right + 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, // top-right + 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, // bottom-right + 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, // top-right -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, // bottom-left -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, // top-left - // front face - -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom-left - 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, // bottom-right - 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // top-right - 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // top-right - -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, // top-left - -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom-left - // left face - -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-right - -1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top-left - -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-left - -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-left - -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom-right - -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-right - // right face - 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-left - 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-right - 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top-right - 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-right - 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-left - 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom-left - // bottom face - -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, // top-right - 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, // top-left - 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom-left - 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom-left - -1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, // bottom-right - -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, // top-right - // top face - -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top-left - 1.0f, 1.0f , 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom-right - 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, // top-right - 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom-right - -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top-left - -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f // bottom-left + // front face + -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom-left + 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, // bottom-right + 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // top-right + 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // top-right + -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, // top-left + -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom-left + // left face + -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-right + -1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top-left + -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-left + -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-left + -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom-right + -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-right + // right face + 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-left + 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-right + 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top-right + 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-right + 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-left + 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom-left + // bottom face + -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, // top-right + 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, // top-left + 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom-left + 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom-left + -1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, // bottom-right + -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, // top-right + // top face + -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top-left + 1.0f, 1.0f , 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom-right + 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, // top-right + 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom-right + -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top-left + -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f // bottom-left }; glGenVertexArrays(1, &cubeVAO); glGenBuffers(1, &cubeVBO); @@ -345,37 +314,6 @@ void renderCube() glBindVertexArray(0); } -// renderQuad() renders a 1x1 XY quad in NDC -// ----------------------------------------- -unsigned int quadVAO = 0; -unsigned int quadVBO; -void renderQuad() -{ - if (quadVAO == 0) - { - float quadVertices[] = { - // positions // texture Coords - -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, - -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, - 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, - 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, - }; - // setup plane VAO - glGenVertexArrays(1, &quadVAO); - glGenBuffers(1, &quadVBO); - glBindVertexArray(quadVAO); - glBindBuffer(GL_ARRAY_BUFFER, quadVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); - } - glBindVertexArray(quadVAO); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - glBindVertexArray(0); -} - // process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly // --------------------------------------------------------------------------------------------------------- void processInput(GLFWwindow *window) @@ -392,6 +330,16 @@ void processInput(GLFWwindow *window) camera.ProcessKeyboard(LEFT, deltaTime); if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) camera.ProcessKeyboard(RIGHT, deltaTime); + + if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS && !shadowsKeyPressed) + { + shadows = !shadows; + shadowsKeyPressed = true; + } + if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_RELEASE) + { + shadowsKeyPressed = false; + } } // glfw: whenever the window size changed (by OS or user resize) this callback function executes diff --git a/src/5.advanced_lighting/3.2.1.point_shadows/point_shadows.vs b/src/5.advanced_lighting/3.2.1.point_shadows/point_shadows.vs deleted file mode 100644 index 04a9ba8..0000000 --- a/src/5.advanced_lighting/3.2.1.point_shadows/point_shadows.vs +++ /dev/null @@ -1,29 +0,0 @@ -#version 330 core -layout (location = 0) in vec3 position; -layout (location = 1) in vec3 normal; -layout (location = 2) in vec2 texCoords; - -out vec2 TexCoords; - -out VS_OUT { - vec3 FragPos; - vec3 Normal; - vec2 TexCoords; -} vs_out; - -uniform mat4 projection; -uniform mat4 view; -uniform mat4 model; - -uniform bool reverse_normals; - -void main() -{ - gl_Position = projection * view * model * vec4(position, 1.0f); - vs_out.FragPos = vec3(model * vec4(position, 1.0)); - if(reverse_normals) // A slight hack to make sure the outer large cube displays lighting from the 'inside' instead of the default 'outside'. - vs_out.Normal = transpose(inverse(mat3(model))) * (-1.0 * normal); - else - vs_out.Normal = transpose(inverse(mat3(model))) * normal; - vs_out.TexCoords = texCoords; -} \ No newline at end of file diff --git a/src/5.advanced_lighting/3.2.1.point_shadows/point_shadows_depth.frag b/src/5.advanced_lighting/3.2.1.point_shadows/point_shadows_depth.frag deleted file mode 100644 index 754b8fc..0000000 --- a/src/5.advanced_lighting/3.2.1.point_shadows/point_shadows_depth.frag +++ /dev/null @@ -1,16 +0,0 @@ -#version 330 core -in vec4 FragPos; - -uniform vec3 lightPos; -uniform float far_plane; - -void main() -{ - float lightDistance = length(FragPos.xyz - lightPos); - - // map to [0;1] range by dividing by far_plane - lightDistance = lightDistance / far_plane; - - // Write this as modified depth - gl_FragDepth = lightDistance; -} \ No newline at end of file diff --git a/src/5.advanced_lighting/3.2.1.point_shadows/point_shadows_depth.gs b/src/5.advanced_lighting/3.2.1.point_shadows/point_shadows_depth.gs deleted file mode 100644 index f61800b..0000000 --- a/src/5.advanced_lighting/3.2.1.point_shadows/point_shadows_depth.gs +++ /dev/null @@ -1,22 +0,0 @@ -#version 330 core -layout (triangles) in; -layout (triangle_strip, max_vertices=18) out; - -uniform mat4 shadowTransforms[6]; - -out vec4 FragPos; // FragPos from GS (output per emitvertex) - -void main() -{ - for(int face = 0; face < 6; ++face) - { - gl_Layer = face; // built-in variable that specifies to which face we render. - for(int i = 0; i < 3; ++i) // for each triangle's vertices - { - FragPos = gl_in[i].gl_Position; - gl_Position = shadowTransforms[face] * FragPos; - EmitVertex(); - } - EndPrimitive(); - } -} \ No newline at end of file diff --git a/src/5.advanced_lighting/3.2.1.point_shadows/point_shadows_depth.vs b/src/5.advanced_lighting/3.2.1.point_shadows/point_shadows_depth.vs deleted file mode 100644 index 09fd856..0000000 --- a/src/5.advanced_lighting/3.2.1.point_shadows/point_shadows_depth.vs +++ /dev/null @@ -1,9 +0,0 @@ -#version 330 core -layout (location = 0) in vec3 position; - -uniform mat4 model; - -void main() -{ - gl_Position = model * vec4(position, 1.0); -} \ No newline at end of file diff --git a/src/5.advanced_lighting/3.2.1.point_shadows/point_shadows.frag b/src/5.advanced_lighting/3.2.2.point_shadows_soft/3.2.2.point_shadows.fs similarity index 83% rename from src/5.advanced_lighting/3.2.1.point_shadows/point_shadows.frag rename to src/5.advanced_lighting/3.2.2.point_shadows_soft/3.2.2.point_shadows.fs index 906507f..766f526 100644 --- a/src/5.advanced_lighting/3.2.1.point_shadows/point_shadows.frag +++ b/src/5.advanced_lighting/3.2.2.point_shadows_soft/3.2.2.point_shadows.fs @@ -29,16 +29,16 @@ vec3 gridSamplingDisk[20] = vec3[] float ShadowCalculation(vec3 fragPos) { - // Get vector between fragment position and light position + // get vector between fragment position and light position vec3 fragToLight = fragPos - lightPos; - // Use the fragment to light vector to sample from the depth map + // use the fragment to light vector to sample from the depth map // float closestDepth = texture(depthMap, fragToLight).r; - // It is currently in linear range between [0,1]. Let's re-transform it back to original depth value + // it is currently in linear range between [0,1], let's re-transform it back to original depth value // closestDepth *= far_plane; - // Now get current linear depth as the length between the fragment and light position + // now get current linear depth as the length between the fragment and light position float currentDepth = length(fragToLight); - // Now test for shadows - // float bias = 0.05; // We use a much larger bias since depth is now in [near_plane, far_plane] range + // test for shadows + // float bias = 0.05; // we use a much larger bias since depth is now in [near_plane, far_plane] range // float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0; // PCF // float shadow = 0.0; @@ -51,7 +51,7 @@ float ShadowCalculation(vec3 fragPos) // { // for(float z = -offset; z < offset; z += offset / (samples * 0.5)) // { - // float closestDepth = texture(depthMap, fragToLight + vec3(x, y, z)).r; // Use lightdir to lookup cubemap + // float closestDepth = texture(depthMap, fragToLight + vec3(x, y, z)).r; // use lightdir to lookup cubemap // closestDepth *= far_plane; // Undo mapping [0;1] // if(currentDepth - bias > closestDepth) // shadow += 1.0; @@ -67,16 +67,15 @@ float ShadowCalculation(vec3 fragPos) for(int i = 0; i < samples; ++i) { float closestDepth = texture(depthMap, fragToLight + gridSamplingDisk[i] * diskRadius).r; - closestDepth *= far_plane; // Undo mapping [0;1] + closestDepth *= far_plane; // undo mapping [0;1] if(currentDepth - bias > closestDepth) shadow += 1.0; } shadow /= float(samples); - // Display closestDepth as debug (to visualize depth cubemap) + // display closestDepth as debug (to visualize depth cubemap) // FragColor = vec4(vec3(closestDepth / far_plane), 1.0); - // return shadow; return shadow; } @@ -85,20 +84,20 @@ void main() vec3 color = texture(diffuseTexture, fs_in.TexCoords).rgb; vec3 normal = normalize(fs_in.Normal); vec3 lightColor = vec3(0.3); - // Ambient + // ambient vec3 ambient = 0.3 * color; - // Diffuse + // diffuse vec3 lightDir = normalize(lightPos - fs_in.FragPos); float diff = max(dot(lightDir, normal), 0.0); vec3 diffuse = diff * lightColor; - // Specular + // specular vec3 viewDir = normalize(viewPos - fs_in.FragPos); vec3 reflectDir = reflect(-lightDir, normal); float spec = 0.0; vec3 halfwayDir = normalize(lightDir + viewDir); spec = pow(max(dot(normal, halfwayDir), 0.0), 64.0); vec3 specular = spec * lightColor; - // Calculate shadow + // calculate shadow float shadow = shadows ? ShadowCalculation(fs_in.FragPos) : 0.0; vec3 lighting = (ambient + (1.0 - shadow) * (diffuse + specular)) * color; diff --git a/src/5.advanced_lighting/3.2.2.point_shadows_soft/3.2.2.point_shadows.vs b/src/5.advanced_lighting/3.2.2.point_shadows_soft/3.2.2.point_shadows.vs new file mode 100644 index 0000000..33f453b --- /dev/null +++ b/src/5.advanced_lighting/3.2.2.point_shadows_soft/3.2.2.point_shadows.vs @@ -0,0 +1,29 @@ +#version 330 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 2) in vec2 aTexCoords; + +out vec2 TexCoords; + +out VS_OUT { + vec3 FragPos; + vec3 Normal; + vec2 TexCoords; +} vs_out; + +uniform mat4 projection; +uniform mat4 view; +uniform mat4 model; + +uniform bool reverse_normals; + +void main() +{ + vs_out.FragPos = vec3(model * vec4(aPos, 1.0)); + if(reverse_normals) // a slight hack to make sure the outer large cube displays lighting from the 'inside' instead of the default 'outside'. + vs_out.Normal = transpose(inverse(mat3(model))) * (-1.0 * aNormal); + else + vs_out.Normal = transpose(inverse(mat3(model))) * aNormal; + vs_out.TexCoords = aTexCoords; + gl_Position = projection * view * model * vec4(aPos, 1.0f); +} \ No newline at end of file diff --git a/src/5.advanced_lighting/3.2.2.point_shadows_soft/point_shadows.frag b/src/5.advanced_lighting/3.2.2.point_shadows_soft/point_shadows.frag deleted file mode 100644 index 906507f..0000000 --- a/src/5.advanced_lighting/3.2.2.point_shadows_soft/point_shadows.frag +++ /dev/null @@ -1,106 +0,0 @@ -#version 330 core -out vec4 FragColor; - -in VS_OUT { - vec3 FragPos; - vec3 Normal; - vec2 TexCoords; -} fs_in; - -uniform sampler2D diffuseTexture; -uniform samplerCube depthMap; - -uniform vec3 lightPos; -uniform vec3 viewPos; - -uniform float far_plane; -uniform bool shadows; - - -// array of offset direction for sampling -vec3 gridSamplingDisk[20] = vec3[] -( - vec3(1, 1, 1), vec3(1, -1, 1), vec3(-1, -1, 1), vec3(-1, 1, 1), - vec3(1, 1, -1), vec3(1, -1, -1), vec3(-1, -1, -1), vec3(-1, 1, -1), - vec3(1, 1, 0), vec3(1, -1, 0), vec3(-1, -1, 0), vec3(-1, 1, 0), - vec3(1, 0, 1), vec3(-1, 0, 1), vec3(1, 0, -1), vec3(-1, 0, -1), - vec3(0, 1, 1), vec3(0, -1, 1), vec3(0, -1, -1), vec3(0, 1, -1) -); - -float ShadowCalculation(vec3 fragPos) -{ - // Get vector between fragment position and light position - vec3 fragToLight = fragPos - lightPos; - // Use the fragment to light vector to sample from the depth map - // float closestDepth = texture(depthMap, fragToLight).r; - // It is currently in linear range between [0,1]. Let's re-transform it back to original depth value - // closestDepth *= far_plane; - // Now get current linear depth as the length between the fragment and light position - float currentDepth = length(fragToLight); - // Now test for shadows - // float bias = 0.05; // We use a much larger bias since depth is now in [near_plane, far_plane] range - // float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0; - // PCF - // float shadow = 0.0; - // float bias = 0.05; - // float samples = 4.0; - // float offset = 0.1; - // for(float x = -offset; x < offset; x += offset / (samples * 0.5)) - // { - // for(float y = -offset; y < offset; y += offset / (samples * 0.5)) - // { - // for(float z = -offset; z < offset; z += offset / (samples * 0.5)) - // { - // float closestDepth = texture(depthMap, fragToLight + vec3(x, y, z)).r; // Use lightdir to lookup cubemap - // closestDepth *= far_plane; // Undo mapping [0;1] - // if(currentDepth - bias > closestDepth) - // shadow += 1.0; - // } - // } - // } - // shadow /= (samples * samples * samples); - float shadow = 0.0; - float bias = 0.15; - int samples = 20; - float viewDistance = length(viewPos - fragPos); - float diskRadius = (1.0 + (viewDistance / far_plane)) / 25.0; - for(int i = 0; i < samples; ++i) - { - float closestDepth = texture(depthMap, fragToLight + gridSamplingDisk[i] * diskRadius).r; - closestDepth *= far_plane; // Undo mapping [0;1] - if(currentDepth - bias > closestDepth) - shadow += 1.0; - } - shadow /= float(samples); - - // Display closestDepth as debug (to visualize depth cubemap) - // FragColor = vec4(vec3(closestDepth / far_plane), 1.0); - - // return shadow; - return shadow; -} - -void main() -{ - vec3 color = texture(diffuseTexture, fs_in.TexCoords).rgb; - vec3 normal = normalize(fs_in.Normal); - vec3 lightColor = vec3(0.3); - // Ambient - vec3 ambient = 0.3 * color; - // Diffuse - vec3 lightDir = normalize(lightPos - fs_in.FragPos); - float diff = max(dot(lightDir, normal), 0.0); - vec3 diffuse = diff * lightColor; - // Specular - vec3 viewDir = normalize(viewPos - fs_in.FragPos); - vec3 reflectDir = reflect(-lightDir, normal); - float spec = 0.0; - vec3 halfwayDir = normalize(lightDir + viewDir); - spec = pow(max(dot(normal, halfwayDir), 0.0), 64.0); - vec3 specular = spec * lightColor; - // Calculate shadow - float shadow = shadows ? ShadowCalculation(fs_in.FragPos) : 0.0; - vec3 lighting = (ambient + (1.0 - shadow) * (diffuse + specular)) * color; - - FragColor = vec4(lighting, 1.0f); -} \ No newline at end of file diff --git a/src/5.advanced_lighting/3.2.2.point_shadows_soft/point_shadows.vs b/src/5.advanced_lighting/3.2.2.point_shadows_soft/point_shadows.vs deleted file mode 100644 index 04a9ba8..0000000 --- a/src/5.advanced_lighting/3.2.2.point_shadows_soft/point_shadows.vs +++ /dev/null @@ -1,29 +0,0 @@ -#version 330 core -layout (location = 0) in vec3 position; -layout (location = 1) in vec3 normal; -layout (location = 2) in vec2 texCoords; - -out vec2 TexCoords; - -out VS_OUT { - vec3 FragPos; - vec3 Normal; - vec2 TexCoords; -} vs_out; - -uniform mat4 projection; -uniform mat4 view; -uniform mat4 model; - -uniform bool reverse_normals; - -void main() -{ - gl_Position = projection * view * model * vec4(position, 1.0f); - vs_out.FragPos = vec3(model * vec4(position, 1.0)); - if(reverse_normals) // A slight hack to make sure the outer large cube displays lighting from the 'inside' instead of the default 'outside'. - vs_out.Normal = transpose(inverse(mat3(model))) * (-1.0 * normal); - else - vs_out.Normal = transpose(inverse(mat3(model))) * normal; - vs_out.TexCoords = texCoords; -} \ No newline at end of file diff --git a/src/5.advanced_lighting/3.2.2.point_shadows_soft/point_shadows_depth.vs b/src/5.advanced_lighting/3.2.2.point_shadows_soft/point_shadows_depth.vs deleted file mode 100644 index 09fd856..0000000 --- a/src/5.advanced_lighting/3.2.2.point_shadows_soft/point_shadows_depth.vs +++ /dev/null @@ -1,9 +0,0 @@ -#version 330 core -layout (location = 0) in vec3 position; - -uniform mat4 model; - -void main() -{ - gl_Position = model * vec4(position, 1.0); -} \ No newline at end of file diff --git a/src/5.advanced_lighting/3.2.2.point_shadows_soft/point_shadows_soft.cpp b/src/5.advanced_lighting/3.2.2.point_shadows_soft/point_shadows_soft.cpp index 508ea8e..eb9796c 100644 --- a/src/5.advanced_lighting/3.2.2.point_shadows_soft/point_shadows_soft.cpp +++ b/src/5.advanced_lighting/3.2.2.point_shadows_soft/point_shadows_soft.cpp @@ -1,371 +1,359 @@ -// GLEW -#define GLEW_STATIC -#include - -// GLFW +#include #include +#include -// GL includes -#include -#include - -// GLM Mathemtics #include #include #include -// Other Libs -#include #include +#include +#include +#include -// Properties -const GLuint SCR_WIDTH = 800, SCR_HEIGHT = 600; +#include -// Function prototypes -void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode); -void scroll_callback(GLFWwindow* window, double xoffset, double yoffset); +void framebuffer_size_callback(GLFWwindow* window, int width, int height); void mouse_callback(GLFWwindow* window, double xpos, double ypos); -void Do_Movement(); -GLuint loadTexture(GLchar const * path); -void RenderScene(Shader &shader); -void RenderCube(); -void RenderQuad(); +void scroll_callback(GLFWwindow* window, double xoffset, double yoffset); +void processInput(GLFWwindow *window); +unsigned int loadTexture(const char *path); +void renderScene(const Shader &shader); +void renderCube(); -// Camera +// settings +const unsigned int SCR_WIDTH = 1280; +const unsigned int SCR_HEIGHT = 720; +bool shadows = true; +bool shadowsKeyPressed = false; + +// camera Camera camera(glm::vec3(0.0f, 0.0f, 3.0f)); +float lastX = (float)SCR_WIDTH / 2.0; +float lastY = (float)SCR_HEIGHT / 2.0; +bool firstMouse = true; -// Delta -GLfloat deltaTime = 0.0f; -GLfloat lastFrame = 0.0f; +// timing +float deltaTime = 0.0f; +float lastFrame = 0.0f; -// Options -GLboolean shadows = true; - -// Global variables -GLuint woodTexture; -GLuint planeVAO; - -// The MAIN function, from here we start our application and run our Game loop int main() { - // Init GLFW + // glfw: initialize and configure + // ------------------------------ glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); - GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", nullptr, nullptr); // Windowed + // glfw window creation + // -------------------- + GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL); glfwMakeContextCurrent(window); - - // Set the required callback functions - glfwSetKeyCallback(window, key_callback); + if (window == NULL) + { + std::cout << "Failed to create GLFW window" << std::endl; + glfwTerminate(); + return -1; + } + glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); glfwSetCursorPosCallback(window, mouse_callback); glfwSetScrollCallback(window, scroll_callback); - // Options + // tell GLFW to capture our mouse glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); - // Initialize GLEW to setup the OpenGL Function pointers - glewExperimental = GL_TRUE; - glewInit(); + // glad: load all OpenGL function pointers + // --------------------------------------- + if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) + { + std::cout << "Failed to initialize GLAD" << std::endl; + return -1; + } - // Define the viewport dimensions - glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT); - - // Setup some OpenGL options + // configure global opengl state + // ----------------------------- glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); - // Setup and compile our shaders - Shader shader("point_shadows.vs", "point_shadows.frag"); - Shader simpleDepthShader("point_shadows_depth.vs", "point_shadows_depth.frag", "point_shadows_depth.gs"); + // build and compile shaders + // ------------------------- + Shader shader("3.2.2.point_shadows.vs", "3.2.2.point_shadows.fs"); + Shader simpleDepthShader("3.2.1.point_shadows_depth.vs", "3.2.1.point_shadows_depth.fs", "3.2.1.point_shadows_depth.gs"); - // Set texture samples - shader.Use(); - glUniform1i(glGetUniformLocation(shader.Program, "diffuseTexture"), 0); - glUniform1i(glGetUniformLocation(shader.Program, "depthMap"), 1); + // load textures + // ------------- + unsigned int woodTexture = loadTexture(FileSystem::getPath("resources/textures/wood.png").c_str()); - // Light source - glm::vec3 lightPos(0.0f, 0.0f, 0.0f); - - // Load textures - woodTexture = loadTexture(FileSystem::getPath("resources/textures/wood.png").c_str()); - - // Configure depth map FBO - const GLuint SHADOW_WIDTH = 1024, SHADOW_HEIGHT = 1024; - GLuint depthMapFBO; + // configure depth map FBO + // ----------------------- + const unsigned int SHADOW_WIDTH = 1024, SHADOW_HEIGHT = 1024; + unsigned int depthMapFBO; glGenFramebuffers(1, &depthMapFBO); - // Create depth cubemap texture - GLuint depthCubemap; + // create depth cubemap texture + unsigned int depthCubemap; glGenTextures(1, &depthCubemap); glBindTexture(GL_TEXTURE_CUBE_MAP, depthCubemap); - for (GLuint i = 0; i < 6; ++i) + for (unsigned int i = 0; i < 6; ++i) glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_DEPTH_COMPONENT, SHADOW_WIDTH, SHADOW_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - // Attach cubemap as depth map FBO's color buffer + // attach depth texture as FBO's depth buffer glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO); glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthCubemap, 0); glDrawBuffer(GL_NONE); glReadBuffer(GL_NONE); - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - std::cout << "Framebuffer not complete!" << std::endl; glBindFramebuffer(GL_FRAMEBUFFER, 0); - glClearColor(0.1f, 0.1f, 0.1f, 1.0f); - // Game loop + // shader configuration + // -------------------- + shader.use(); + shader.setInt("diffuseTexture", 0); + shader.setInt("depthMap", 1); + + // lighting info + // ------------- + glm::vec3 lightPos(0.0f, 0.0f, 0.0f); + + // render loop + // ----------- while (!glfwWindowShouldClose(window)) { - // Set frame time - GLfloat currentFrame = glfwGetTime(); + // per-frame time logic + // -------------------- + float currentFrame = glfwGetTime(); deltaTime = currentFrame - lastFrame; lastFrame = currentFrame; - // Check and call events - glfwPollEvents(); - Do_Movement(); + // input + // ----- + processInput(window); - // Move light position over time - //lightPos.z = sin(glfwGetTime() * 0.5) * 3.0; + // move light position over time + lightPos.z = sin(glfwGetTime() * 0.5) * 3.0; - // 0. Create depth cubemap transformation matrices - GLfloat aspect = (GLfloat)SHADOW_WIDTH / (GLfloat)SHADOW_HEIGHT; - GLfloat near = 1.0f; - GLfloat far = 25.0f; - glm::mat4 shadowProj = glm::perspective(90.0f, aspect, near, far); + // render + // ------ + glClearColor(0.1f, 0.1f, 0.1f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // 0. create depth cubemap transformation matrices + // ----------------------------------------------- + float near_plane = 1.0f; + float far_plane = 25.0f; + glm::mat4 shadowProj = glm::perspective(glm::radians(90.0f), (float)SHADOW_WIDTH / (float)SHADOW_HEIGHT, near_plane, far_plane); std::vector shadowTransforms; - shadowTransforms.push_back(shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3( 1.0, 0.0, 0.0), glm::vec3(0.0, -1.0, 0.0))); - shadowTransforms.push_back(shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3(-1.0, 0.0, 0.0), glm::vec3(0.0, -1.0, 0.0))); - shadowTransforms.push_back(shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3( 0.0, 1.0, 0.0), glm::vec3(0.0, 0.0, 1.0))); - shadowTransforms.push_back(shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3( 0.0, -1.0, 0.0), glm::vec3(0.0, 0.0, -1.0))); - shadowTransforms.push_back(shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3( 0.0, 0.0, 1.0), glm::vec3(0.0, -1.0, 0.0))); - shadowTransforms.push_back(shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3( 0.0, 0.0, -1.0), glm::vec3(0.0, -1.0, 0.0))); + shadowTransforms.push_back(shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3(1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f))); + shadowTransforms.push_back(shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3(-1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f))); + shadowTransforms.push_back(shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f))); + shadowTransforms.push_back(shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3(0.0f, -1.0f, 0.0f), glm::vec3(0.0f, 0.0f, -1.0f))); + shadowTransforms.push_back(shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(0.0f, -1.0f, 0.0f))); + shadowTransforms.push_back(shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3(0.0f, 0.0f, -1.0f), glm::vec3(0.0f, -1.0f, 0.0f))); - // 1. Render scene to depth cubemap + // 1. render scene to depth cubemap + // -------------------------------- glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT); glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO); - glClear(GL_DEPTH_BUFFER_BIT); - simpleDepthShader.Use(); - for (GLuint i = 0; i < 6; ++i) - glUniformMatrix4fv(glGetUniformLocation(simpleDepthShader.Program, ("shadowTransforms[" + std::to_string(i) + "]").c_str()), 1, GL_FALSE, glm::value_ptr(shadowTransforms[i])); - glUniform1f(glGetUniformLocation(simpleDepthShader.Program, "far_plane"), far); - glUniform3fv(glGetUniformLocation(simpleDepthShader.Program, "lightPos"), 1, &lightPos[0]); - RenderScene(simpleDepthShader); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + glClear(GL_DEPTH_BUFFER_BIT); + simpleDepthShader.use(); + for (unsigned int i = 0; i < 6; ++i) + simpleDepthShader.setMat4("shadowMatrices[" + std::to_string(i) + "]", shadowTransforms[i]); + simpleDepthShader.setFloat("far_plane", far_plane); + simpleDepthShader.setVec3("lightPos", lightPos); + renderScene(simpleDepthShader); + glBindFramebuffer(GL_FRAMEBUFFER, 0); - // 2. Render scene as normal + // 2. render scene as normal + // ------------------------- glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - shader.Use(); + shader.use(); glm::mat4 projection = glm::perspective(camera.Zoom, (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f); glm::mat4 view = camera.GetViewMatrix(); - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view)); - // Set light uniforms - glUniform3fv(glGetUniformLocation(shader.Program, "lightPos"), 1, &lightPos[0]); - glUniform3fv(glGetUniformLocation(shader.Program, "viewPos"), 1, &camera.Position[0]); - // Enable/Disable shadows by pressing 'SPACE' - glUniform1i(glGetUniformLocation(shader.Program, "shadows"), shadows); - glUniform1f(glGetUniformLocation(shader.Program, "far_plane"), far); + shader.setMat4("projection", projection); + shader.setMat4("view", view); + // set lighting uniforms + shader.setVec3("lightPos", lightPos); + shader.setVec3("viewPos", camera.Position); + shader.setInt("shadows", shadows); // enable/disable shadows by pressing 'SPACE' + shader.setFloat("far_plane", far_plane); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, woodTexture); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_CUBE_MAP, depthCubemap); - RenderScene(shader); + renderScene(shader); - // Swap the buffers + // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.) + // ------------------------------------------------------------------------------- glfwSwapBuffers(window); + glfwPollEvents(); } glfwTerminate(); return 0; } -void RenderScene(Shader &shader) +// renders the 3D scene +// -------------------- +void renderScene(const Shader &shader) { - // Room cube + // room cube glm::mat4 model; - model = glm::scale(model, glm::vec3(10.0)); - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); - glDisable(GL_CULL_FACE); // Note that we disable culling here since we render 'inside' the cube instead of the usual 'outside' which throws off the normal culling methods. - glUniform1i(glGetUniformLocation(shader.Program, "reverse_normals"), 1); // A small little hack to invert normals when drawing cube from the inside so lighting still works. - RenderCube(); - glUniform1i(glGetUniformLocation(shader.Program, "reverse_normals"), 0); // And of course disable it + model = glm::scale(model, glm::vec3(5.0f)); + shader.setMat4("model", model); + glDisable(GL_CULL_FACE); // note that we disable culling here since we render 'inside' the cube instead of the usual 'outside' which throws off the normal culling methods. + shader.setInt("reverse_normals", 1); // A small little hack to invert normals when drawing cube from the inside so lighting still works. + renderCube(); + shader.setInt("reverse_normals", 0); // and of course disable it glEnable(GL_CULL_FACE); - // Cubes + // cubes model = glm::mat4(); model = glm::translate(model, glm::vec3(4.0f, -3.5f, 0.0)); - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); - RenderCube(); + model = glm::scale(model, glm::vec3(0.5f)); + shader.setMat4("model", model); + renderCube(); model = glm::mat4(); model = glm::translate(model, glm::vec3(2.0f, 3.0f, 1.0)); - model = glm::scale(model, glm::vec3(1.5)); - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); - RenderCube(); + model = glm::scale(model, glm::vec3(0.75f)); + shader.setMat4("model", model); + renderCube(); model = glm::mat4(); model = glm::translate(model, glm::vec3(-3.0f, -1.0f, 0.0)); - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); - RenderCube(); + model = glm::scale(model, glm::vec3(0.5f)); + shader.setMat4("model", model); + renderCube(); model = glm::mat4(); model = glm::translate(model, glm::vec3(-1.5f, 1.0f, 1.5)); - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); - RenderCube(); + model = glm::scale(model, glm::vec3(0.5f)); + shader.setMat4("model", model); + renderCube(); model = glm::mat4(); model = glm::translate(model, glm::vec3(-1.5f, 2.0f, -3.0)); - model = glm::rotate(model, 60.0f, glm::normalize(glm::vec3(1.0, 0.0, 1.0))); - model = glm::scale(model, glm::vec3(1.5)); - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); - RenderCube(); + model = glm::rotate(model, glm::radians(60.0f), glm::normalize(glm::vec3(1.0, 0.0, 1.0))); + model = glm::scale(model, glm::vec3(0.75f)); + shader.setMat4("model", model); + renderCube(); } - -// RenderCube() Renders a 1x1 3D cube in NDC. -GLuint cubeVAO = 0; -GLuint cubeVBO = 0; -void RenderCube() +// renderCube() renders a 1x1 3D cube in NDC. +// ------------------------------------------------- +unsigned int cubeVAO = 0; +unsigned int cubeVBO = 0; +void renderCube() { - // Initialize (if necessary) + // initialize (if necessary) if (cubeVAO == 0) { - GLfloat vertices[] = { - // Back face - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, // Bottom-left - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, // top-right - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, // bottom-right - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, // top-right - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, // bottom-left - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f,// top-left - // Front face - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom-left - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, // bottom-right - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // top-right - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // top-right - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, // top-left - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom-left - // Left face - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-right - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top-left - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-left - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-left - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom-right - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-right - // Right face - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-left - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-right - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top-right - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-right - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-left - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom-left - // Bottom face - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, // top-right - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, // top-left - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f,// bottom-left - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom-left - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, // bottom-right - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, // top-right - // Top face - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,// top-left - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom-right - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, // top-right - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom-right - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,// top-left - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f // bottom-left + float vertices[] = { + // back face + -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, // bottom-left + 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, // top-right + 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, // bottom-right + 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, // top-right + -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, // bottom-left + -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, // top-left + // front face + -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom-left + 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, // bottom-right + 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // top-right + 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // top-right + -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, // top-left + -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom-left + // left face + -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-right + -1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top-left + -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-left + -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-left + -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom-right + -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-right + // right face + 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-left + 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-right + 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top-right + 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-right + 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-left + 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom-left + // bottom face + -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, // top-right + 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, // top-left + 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom-left + 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom-left + -1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, // bottom-right + -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, // top-right + // top face + -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top-left + 1.0f, 1.0f , 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom-right + 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, // top-right + 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom-right + -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top-left + -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f // bottom-left }; glGenVertexArrays(1, &cubeVAO); glGenBuffers(1, &cubeVBO); - // Fill buffer + // fill buffer glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); - // Link vertex attributes + // link vertex attributes glBindVertexArray(cubeVAO); glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0); glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float))); glEnableVertexAttribArray(2); - glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat))); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float))); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); } - // Render Cube + // render Cube glBindVertexArray(cubeVAO); glDrawArrays(GL_TRIANGLES, 0, 36); glBindVertexArray(0); } -// This function loads a texture from file. Note: texture loading functions like these are usually -// managed by a 'Resource Manager' that manages all resources (like textures, models, audio). -// For learning purposes we'll just define it as a utility function. -GLuint loadTexture(GLchar const * path) +// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly +// --------------------------------------------------------------------------------------------------------- +void processInput(GLFWwindow *window) { - // Generate texture ID and load texture data - GLuint textureID; - glGenTextures(1, &textureID); - int width, height; - unsigned char* image = SOIL_load_image(path, &width, &height, 0, SOIL_LOAD_RGB); - // Assign texture to ID - glBindTexture(GL_TEXTURE_2D, textureID); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image); - glGenerateMipmap(GL_TEXTURE_2D); + if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) + glfwSetWindowShouldClose(window, true); - // Parameters - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glBindTexture(GL_TEXTURE_2D, 0); - SOIL_free_image_data(image); - return textureID; - -} - -bool keys[1024]; -bool keysPressed[1024]; -// Moves/alters the camera positions based on user input -void Do_Movement() -{ - // Camera controls - if (keys[GLFW_KEY_W]) + float cameraSpeed = 2.5 * deltaTime; + if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) camera.ProcessKeyboard(FORWARD, deltaTime); - if (keys[GLFW_KEY_S]) + if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) camera.ProcessKeyboard(BACKWARD, deltaTime); - if (keys[GLFW_KEY_A]) + if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) camera.ProcessKeyboard(LEFT, deltaTime); - if (keys[GLFW_KEY_D]) + if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) camera.ProcessKeyboard(RIGHT, deltaTime); - if (keys[GLFW_KEY_SPACE] && !keysPressed[GLFW_KEY_SPACE]) + if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS && !shadowsKeyPressed) { shadows = !shadows; - keysPressed[GLFW_KEY_SPACE] = true; + shadowsKeyPressed = true; } -} - -GLfloat lastX = 400, lastY = 300; -bool firstMouse = true; -// Is called whenever a key is pressed/released via GLFW -void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) -{ - if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) - glfwSetWindowShouldClose(window, GL_TRUE); - - if (key >= 0 && key <= 1024) + if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_RELEASE) { - if (action == GLFW_PRESS) - keys[key] = true; - else if (action == GLFW_RELEASE) - { - keys[key] = false; - keysPressed[key] = false; - } + shadowsKeyPressed = false; } } +// glfw: whenever the window size changed (by OS or user resize) this callback function executes +// --------------------------------------------------------------------------------------------- +void framebuffer_size_callback(GLFWwindow* window, int width, int height) +{ + // make sure the viewport matches the new window dimensions; note that width and + // height will be significantly larger than specified on retina displays. + glViewport(0, 0, width, height); +} + + +// glfw: whenever the mouse moves, this callback is called +// ------------------------------------------------------- void mouse_callback(GLFWwindow* window, double xpos, double ypos) { if (firstMouse) @@ -375,8 +363,8 @@ void mouse_callback(GLFWwindow* window, double xpos, double ypos) firstMouse = false; } - GLfloat xoffset = xpos - lastX; - GLfloat yoffset = lastY - ypos; + float xoffset = xpos - lastX; + float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top lastX = xpos; lastY = ypos; @@ -384,7 +372,48 @@ void mouse_callback(GLFWwindow* window, double xpos, double ypos) camera.ProcessMouseMovement(xoffset, yoffset); } +// glfw: whenever the mouse scroll wheel scrolls, this callback is called +// ---------------------------------------------------------------------- void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) { camera.ProcessMouseScroll(yoffset); +} + +// utility function for loading a 2D texture from file +// --------------------------------------------------- +unsigned int loadTexture(char const * path) +{ + unsigned int textureID; + glGenTextures(1, &textureID); + + int width, height, nrComponents; + unsigned char *data = stbi_load(path, &width, &height, &nrComponents, 0); + if (data) + { + GLenum format; + if (nrComponents == 1) + format = GL_RED; + else if (nrComponents == 3) + format = GL_RGB; + else if (nrComponents == 4) + format = GL_RGBA; + + glBindTexture(GL_TEXTURE_2D, textureID); + glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data); + glGenerateMipmap(GL_TEXTURE_2D); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, format == GL_RGBA ? GL_CLAMP_TO_EDGE : GL_REPEAT); // for this tutorial: use GL_CLAMP_TO_EDGE to prevent semi-transparent borders. Due to interpolation it takes texels from next repeat + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, format == GL_RGBA ? GL_CLAMP_TO_EDGE : GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + stbi_image_free(data); + } + else + { + std::cout << "Texture failed to load at path: " << path << std::endl; + stbi_image_free(data); + } + + return textureID; } \ No newline at end of file