Code re-work: shadow mapping.

This commit is contained in:
Joey de Vries
2017-04-22 20:40:35 +02:00
parent 33dd340549
commit 85530ab997
25 changed files with 1030 additions and 1074 deletions

View File

@@ -106,40 +106,40 @@ public:
} }
// utility uniform functions // utility uniform functions
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void setBool(std::string name, bool value) void setBool(std::string name, bool value) const
{ {
glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value); glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value);
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void setInt(std::string name, int value) void setInt(std::string name, int value) const
{ {
glUniform1i(glGetUniformLocation(ID, name.c_str()), value); glUniform1i(glGetUniformLocation(ID, name.c_str()), value);
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void setFloat(std::string name, float value) void setFloat(std::string name, float value) const
{ {
glUniform1f(glGetUniformLocation(ID, name.c_str()), value); glUniform1f(glGetUniformLocation(ID, name.c_str()), value);
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void setVec2(std::string name, const glm::vec2 &value) void setVec2(std::string name, const glm::vec2 &value) const
{ {
glUniform2fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]); glUniform2fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
} }
void setVec2(std::string name, float x, float y) void setVec2(std::string name, float x, float y) const
{ {
glUniform2f(glGetUniformLocation(ID, name.c_str()), x, y); glUniform2f(glGetUniformLocation(ID, name.c_str()), x, y);
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void setVec3(std::string name, const glm::vec3 &value) void setVec3(std::string name, const glm::vec3 &value) const
{ {
glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]); glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
} }
void setVec3(std::string name, float x, float y, float z) void setVec3(std::string name, float x, float y, float z) const
{ {
glUniform3f(glGetUniformLocation(ID, name.c_str()), x, y, z); glUniform3f(glGetUniformLocation(ID, name.c_str()), x, y, z);
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void setVec4(std::string name, const glm::vec4 &value) void setVec4(std::string name, const glm::vec4 &value) const
{ {
glUniform4fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]); glUniform4fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
} }
@@ -148,17 +148,17 @@ public:
glUniform4f(glGetUniformLocation(ID, name.c_str()), x, y, z, w); glUniform4f(glGetUniformLocation(ID, name.c_str()), x, y, z, w);
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void setMat2(std::string name, const glm::mat2 &mat) void setMat2(std::string name, const glm::mat2 &mat) const
{ {
glUniformMatrix2fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]); glUniformMatrix2fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]);
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void setMat3(std::string name, const glm::mat3 &mat) void setMat3(std::string name, const glm::mat3 &mat) const
{ {
glUniformMatrix3fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]); glUniformMatrix3fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]);
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void setMat4(std::string name, const glm::mat4 &mat) void setMat4(std::string name, const glm::mat4 &mat) const
{ {
glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]); glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]);
} }

View File

@@ -74,65 +74,65 @@ public:
} }
// activate the shader // activate the shader
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void use() void use() const
{ {
glUseProgram(ID); glUseProgram(ID);
} }
// utility uniform functions // utility uniform functions
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void setBool(std::string name, bool value) void setBool(std::string name, bool value) const
{ {
glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value); glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value);
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void setInt(std::string name, int value) void setInt(std::string name, int value) const
{ {
glUniform1i(glGetUniformLocation(ID, name.c_str()), value); glUniform1i(glGetUniformLocation(ID, name.c_str()), value);
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void setFloat(std::string name, float value) void setFloat(std::string name, float value) const
{ {
glUniform1f(glGetUniformLocation(ID, name.c_str()), value); glUniform1f(glGetUniformLocation(ID, name.c_str()), value);
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void setVec2(std::string name, const glm::vec2 &value) void setVec2(std::string name, const glm::vec2 &value) const
{ {
glUniform2fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]); glUniform2fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
} }
void setVec2(std::string name, float x, float y) void setVec2(std::string name, float x, float y) const
{ {
glUniform2f(glGetUniformLocation(ID, name.c_str()), x, y); glUniform2f(glGetUniformLocation(ID, name.c_str()), x, y);
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void setVec3(std::string name, const glm::vec3 &value) void setVec3(std::string name, const glm::vec3 &value) const
{ {
glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]); glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
} }
void setVec3(std::string name, float x, float y, float z) void setVec3(std::string name, float x, float y, float z) const
{ {
glUniform3f(glGetUniformLocation(ID, name.c_str()), x, y, z); glUniform3f(glGetUniformLocation(ID, name.c_str()), x, y, z);
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void setVec4(std::string name, const glm::vec4 &value) void setVec4(std::string name, const glm::vec4 &value) const
{ {
glUniform4fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]); glUniform4fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
} }
void setVec4(std::string name, float x, float y, float z, float w) void setVec4(std::string name, float x, float y, float z, float w) const
{ {
glUniform4f(glGetUniformLocation(ID, name.c_str()), x, y, z, w); glUniform4f(glGetUniformLocation(ID, name.c_str()), x, y, z, w);
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void setMat2(std::string name, const glm::mat2 &mat) void setMat2(std::string name, const glm::mat2 &mat) const
{ {
glUniformMatrix2fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]); glUniformMatrix2fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]);
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void setMat3(std::string name, const glm::mat3 &mat) void setMat3(std::string name, const glm::mat3 &mat) const
{ {
glUniformMatrix3fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]); glUniformMatrix3fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]);
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void setMat4(std::string name, const glm::mat4 &mat) void setMat4(std::string name, const glm::mat4 &mat) const
{ {
glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]); glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]);
} }

View File

@@ -78,17 +78,17 @@ public:
} }
// utility uniform functions // utility uniform functions
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void setBool(std::string name, bool value) void setBool(std::string name, bool value) const
{ {
glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value); glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value);
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void setInt(std::string name, int value) void setInt(std::string name, int value) const
{ {
glUniform1i(glGetUniformLocation(ID, name.c_str()), value); glUniform1i(glGetUniformLocation(ID, name.c_str()), value);
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void setFloat(std::string name, float value) void setFloat(std::string name, float value) const
{ {
glUniform1f(glGetUniformLocation(ID, name.c_str()), value); glUniform1f(glGetUniformLocation(ID, name.c_str()), value);
} }

View File

@@ -7,7 +7,7 @@
#include <glm/gtc/type_ptr.hpp> #include <glm/gtc/type_ptr.hpp>
#include <learnopengl/filesystem.h> #include <learnopengl/filesystem.h>
#include <learnopengl/shader_m.h> #include <learnopengl/shader.h>
#include <learnopengl/camera.h> #include <learnopengl/camera.h>
#include <learnopengl/model.h> #include <learnopengl/model.h>

View File

@@ -7,7 +7,7 @@
#include <glm/gtc/type_ptr.hpp> #include <glm/gtc/type_ptr.hpp>
#include <learnopengl/filesystem.h> #include <learnopengl/filesystem.h>
#include <learnopengl/shader_m.h> #include <learnopengl/shader.h>
#include <learnopengl/camera.h> #include <learnopengl/camera.h>
#include <learnopengl/model.h> #include <learnopengl/model.h>

View File

@@ -1,11 +1,11 @@
#version 330 core #version 330 core
layout (location = 0) in vec3 position; layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 texCoords; layout (location = 1) in vec2 aTexCoords;
out vec2 TexCoords; out vec2 TexCoords;
void main() void main()
{ {
gl_Position = vec4(position, 1.0f); TexCoords = aTexCoords;
TexCoords = texCoords; gl_Position = vec4(aPos, 1.0);
} }

View File

@@ -1,11 +1,13 @@
#version 330 core #version 330 core
out vec4 color; out vec4 FragColor;
in vec2 TexCoords; in vec2 TexCoords;
uniform sampler2D depthMap; uniform sampler2D depthMap;
uniform float near_plane; uniform float near_plane;
uniform float far_plane; uniform float far_plane;
// required when using a perspective projection matrix
float LinearizeDepth(float depth) float LinearizeDepth(float depth)
{ {
float z = depth * 2.0 - 1.0; // Back to NDC float z = depth * 2.0 - 1.0; // Back to NDC
@@ -16,5 +18,5 @@ void main()
{ {
float depthValue = texture(depthMap, TexCoords).r; float depthValue = texture(depthMap, TexCoords).r;
// color = vec4(vec3(LinearizeDepth(depthValue) / far_plane), 1.0); // perspective // color = vec4(vec3(LinearizeDepth(depthValue) / far_plane), 1.0); // perspective
color = vec4(vec3(depthValue), 1.0); // orthographic FragColor = vec4(vec3(depthValue), 1.0); // orthographic
} }

View File

@@ -1,10 +1,10 @@
#version 330 core #version 330 core
layout (location = 0) in vec3 position; layout (location = 0) in vec3 aPos;
uniform mat4 lightSpaceMatrix; uniform mat4 lightSpaceMatrix;
uniform mat4 model; uniform mat4 model;
void main() void main()
{ {
gl_Position = lightSpaceMatrix * model * vec4(position, 1.0f); gl_Position = lightSpaceMatrix * model * vec4(aPos, 1.0f);
} }

View File

@@ -1,416 +1,381 @@
// GLEW #include <glad/glad.h>
#define GLEW_STATIC
#include <GL/glew.h>
// GLFW
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <stb_image.h>
// GL includes
#include <learnopengl/shader.h>
#include <learnopengl/camera.h>
// GLM Mathemtics
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp> #include <glm/gtc/type_ptr.hpp>
// Other Libs
#include <SOIL.h>
#include <learnopengl/filesystem.h> #include <learnopengl/filesystem.h>
#include <learnopengl/shader.h>
#include <learnopengl/camera.h>
#include <learnopengl/model.h>
// Properties #include <iostream>
const GLuint SCR_WIDTH = 800, SCR_HEIGHT = 600;
// Function prototypes void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
void mouse_callback(GLFWwindow* window, double xpos, double ypos); void mouse_callback(GLFWwindow* window, double xpos, double ypos);
void Do_Movement(); void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
GLuint loadTexture(GLchar const * path); void processInput(GLFWwindow *window);
void RenderScene(Shader &shader); unsigned int loadTexture(const char *path);
void RenderCube(); void renderScene(const Shader &shader);
void RenderQuad(); void renderCube();
void renderQuad();
// Camera // settings
const unsigned int SCR_WIDTH = 1280;
const unsigned int SCR_HEIGHT = 720;
// camera
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f)); 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 // timing
GLfloat deltaTime = 0.0f; float deltaTime = 0.0f;
GLfloat lastFrame = 0.0f; float lastFrame = 0.0f;
// Options // meshes
GLboolean shadows = true; unsigned int planeVAO;
// Global variables
GLuint woodTexture;
GLuint planeVAO;
// The MAIN function, from here we start our application and run our Game loop
int main() int main()
{ {
// Init GLFW // glfw: initialize and configure
// ------------------------------
glfwInit(); glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 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); glfwMakeContextCurrent(window);
if (window == NULL)
// Set the required callback functions {
glfwSetKeyCallback(window, key_callback); std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
glfwSetCursorPosCallback(window, mouse_callback); glfwSetCursorPosCallback(window, mouse_callback);
glfwSetScrollCallback(window, scroll_callback); glfwSetScrollCallback(window, scroll_callback);
// Options // tell GLFW to capture our mouse
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
// Initialize GLEW to setup the OpenGL Function pointers // glad: load all OpenGL function pointers
glewExperimental = GL_TRUE; // ---------------------------------------
glewInit(); if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
// Define the viewport dimensions // configure global opengl state
glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT); // -----------------------------
// Setup some OpenGL options
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
// Setup and compile our shaders // build and compile shaders
Shader shader("shadow_mapping.vs", "shadow_mapping.frag"); // -------------------------
Shader simpleDepthShader("shadow_mapping_depth.vs", "shadow_mapping_depth.frag"); Shader simpleDepthShader("3.1.1.shadow_mapping_depth.vs", "3.1.1.shadow_mapping_depth.fs");
Shader debugDepthQuad("debug_quad.vs", "debug_quad_depth.frag"); Shader debugDepthQuad("3.1.1.debug_quad.vs", "3.1.1.debug_quad_depth.fs");
// Set texture samples // set up vertex data (and buffer(s)) and configure vertex attributes
shader.Use(); // ------------------------------------------------------------------
glUniform1i(glGetUniformLocation(shader.Program, "diffuseTexture"), 0); float planeVertices[] = {
glUniform1i(glGetUniformLocation(shader.Program, "shadowMap"), 1); // 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,
GLfloat planeVertices[] = { 25.0f, -0.5f, 25.0f, 0.0f, 1.0f, 0.0f, 25.0f, 0.0f,
// Positions // Normals // Texture Coords -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, 25.0f, 10.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, 0.0f, 0.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, 25.0f, 25.0f,
-25.0f, -0.5f, -25.0f, 0.0f, 1.0f, 0.0f, 0.0f, 25.0f
}; };
// Setup plane VAO // plane VAO
GLuint planeVBO; unsigned int planeVBO;
glGenVertexArrays(1, &planeVAO); glGenVertexArrays(1, &planeVAO);
glGenBuffers(1, &planeVBO); glGenBuffers(1, &planeVBO);
glBindVertexArray(planeVAO); glBindVertexArray(planeVAO);
glBindBuffer(GL_ARRAY_BUFFER, planeVBO); glBindBuffer(GL_ARRAY_BUFFER, planeVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(planeVertices), &planeVertices, GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER, sizeof(planeVertices), planeVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0); 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); 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); 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)));
glBindVertexArray(0); glBindVertexArray(0);
// Light source // load textures
glm::vec3 lightPos(-2.0f, 4.0f, -1.0f); // -------------
unsigned int woodTexture = loadTexture(FileSystem::getPath("resources/textures/wood.png").c_str());
// Load textures // configure depth map FBO
woodTexture = loadTexture(FileSystem::getPath("resources/textures/wood.png").c_str()); // -----------------------
const unsigned int SHADOW_WIDTH = 1024, SHADOW_HEIGHT = 1024;
// Configure depth map FBO unsigned int depthMapFBO;
const GLuint SHADOW_WIDTH = 1024, SHADOW_HEIGHT = 1024;
GLuint depthMapFBO;
glGenFramebuffers(1, &depthMapFBO); glGenFramebuffers(1, &depthMapFBO);
// - Create depth texture // create depth texture
GLuint depthMap; unsigned int depthMap;
glGenTextures(1, &depthMap); glGenTextures(1, &depthMap);
glBindTexture(GL_TEXTURE_2D, 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); 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_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
GLfloat borderColor[] = { 1.0, 1.0, 1.0, 1.0 }; // attach depth texture as FBO's depth buffer
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO); glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthMap, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthMap, 0);
glDrawBuffer(GL_NONE); glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE); glReadBuffer(GL_NONE);
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
// Game loop // shader configuration
// --------------------
debugDepthQuad.use();
debugDepthQuad.setInt("depthMap", 0);
// lighting info
// -------------
glm::vec3 lightPos(-2.0f, 4.0f, -1.0f);
// render loop
// -----------
while (!glfwWindowShouldClose(window)) while (!glfwWindowShouldClose(window))
{ {
// Set frame time // per-frame time logic
GLfloat currentFrame = glfwGetTime(); // --------------------
float currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame; deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame; lastFrame = currentFrame;
// Check and call events // input
glfwPollEvents(); // -----
Do_Movement(); processInput(window);
// Change light position over time // render
lightPos.z = cos(glfwGetTime()) * 2.0f; // ------
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) // 1. render depth of scene to texture (from light's perspective)
// - Get light projection/view matrix. // --------------------------------------------------------------
glm::mat4 lightProjection, lightView; glm::mat4 lightProjection, lightView;
glm::mat4 lightSpaceMatrix; glm::mat4 lightSpaceMatrix;
GLfloat near_plane = 1.0f, far_plane = 7.5f; float near_plane = 1.0f, far_plane = 7.5f;
lightProjection = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, near_plane, far_plane); lightProjection = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, near_plane, far_plane);
//lightProjection = glm::perspective(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.
lightView = glm::lookAt(lightPos, glm::vec3(0.0f), glm::vec3(0.0, 1.0, 0.0)); lightView = glm::lookAt(lightPos, glm::vec3(0.0f), glm::vec3(0.0, 1.0, 0.0));
lightSpaceMatrix = lightProjection * lightView; lightSpaceMatrix = lightProjection * lightView;
// - now render scene from light's point of view // render scene from light's point of view
simpleDepthShader.Use(); simpleDepthShader.use();
glUniformMatrix4fv(glGetUniformLocation(simpleDepthShader.Program, "lightSpaceMatrix"), 1, GL_FALSE, glm::value_ptr(lightSpaceMatrix)); simpleDepthShader.setMat4("lightSpaceMatrix", lightSpaceMatrix);
glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT); glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);
glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO); glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO);
glClear(GL_DEPTH_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT);
RenderScene(simpleDepthShader); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, woodTexture);
renderScene(simpleDepthShader);
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
// 2. Render scene as normal // reset viewport
glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT); glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
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]);
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "lightSpaceMatrix"), 1, GL_FALSE, glm::value_ptr(lightSpaceMatrix));
// Enable/Disable shadows by pressing 'SPACE'
glUniform1i(glGetUniformLocation(shader.Program, "shadows"), shadows);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, woodTexture);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, depthMap);
RenderScene(shader);
// 3. DEBUG: visualize depth map by rendering it to plane // render Depth map to quad for visual debugging
debugDepthQuad.Use(); // ---------------------------------------------
glUniform1f(glGetUniformLocation(debugDepthQuad.Program, "near_plane"), near_plane); debugDepthQuad.use();
glUniform1f(glGetUniformLocation(debugDepthQuad.Program, "far_plane"), far_plane); debugDepthQuad.setFloat("near_plane", near_plane);
debugDepthQuad.setFloat("far_plane", far_plane);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, depthMap); glBindTexture(GL_TEXTURE_2D, depthMap);
//RenderQuad(); // uncomment this line to see depth map renderQuad();
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
// Swap the buffers // -------------------------------------------------------------------------------
glfwSwapBuffers(window); glfwSwapBuffers(window);
glfwPollEvents();
} }
// optional: de-allocate all resources once they've outlived their purpose:
// ------------------------------------------------------------------------
glDeleteVertexArrays(1, &planeVAO);
glDeleteBuffers(1, &planeVBO);
glfwTerminate(); glfwTerminate();
return 0; return 0;
} }
void RenderScene(Shader &shader) // renders the 3D scene
// --------------------
void renderScene(const Shader &shader)
{ {
// Floor // floor
glm::mat4 model; glm::mat4 model;
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); shader.setMat4("model", model);
glBindVertexArray(planeVAO); glBindVertexArray(planeVAO);
glDrawArrays(GL_TRIANGLES, 0, 6); glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0); // cubes
// Cubes
model = glm::mat4(); model = glm::mat4();
model = glm::translate(model, glm::vec3(0.0f, 1.5f, 0.0)); model = glm::translate(model, glm::vec3(0.0f, 1.5f, 0.0));
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); model = glm::scale(model, glm::vec3(0.5f));
RenderCube(); shader.setMat4("model", model);
renderCube();
model = glm::mat4(); model = glm::mat4();
model = glm::translate(model, glm::vec3(2.0f, 0.0f, 1.0)); model = glm::translate(model, glm::vec3(2.0f, 0.0f, 1.0));
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); model = glm::scale(model, glm::vec3(0.5f));
RenderCube(); shader.setMat4("model", model);
renderCube();
model = glm::mat4(); model = glm::mat4();
model = glm::translate(model, glm::vec3(-1.0f, 0.0f, 2.0)); model = glm::translate(model, glm::vec3(-1.0f, 0.0f, 2.0));
model = glm::rotate(model, 60.0f, glm::normalize(glm::vec3(1.0, 0.0, 1.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.5)); model = glm::scale(model, glm::vec3(0.25));
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); shader.setMat4("model", model);
RenderCube(); renderCube();
} }
// RenderQuad() Renders a 1x1 quad in NDC, best used for framebuffer color targets // renderCube() renders a 1x1 3D cube in NDC.
// and post-processing effects. // -------------------------------------------------
GLuint quadVAO = 0; unsigned int cubeVAO = 0;
GLuint quadVBO; unsigned int cubeVBO = 0;
void RenderQuad() void renderCube()
{
// initialize (if necessary)
if (cubeVAO == 0)
{
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
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// link vertex attributes
glBindVertexArray(cubeVAO);
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)));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
// render Cube
glBindVertexArray(cubeVAO);
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
}
// renderQuad() renders a 1x1 XY quad in NDC
// -----------------------------------------
unsigned int quadVAO = 0;
unsigned int quadVBO;
void renderQuad()
{ {
if (quadVAO == 0) if (quadVAO == 0)
{ {
GLfloat quadVertices[] = { float quadVertices[] = {
// Positions // Texture Coords // positions // texture Coords
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f, -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, 0.0f, 0.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
}; };
// Setup plane VAO // setup plane VAO
glGenVertexArrays(1, &quadVAO); glGenVertexArrays(1, &quadVAO);
glGenBuffers(1, &quadVBO); glGenBuffers(1, &quadVBO);
glBindVertexArray(quadVAO); glBindVertexArray(quadVAO);
glBindBuffer(GL_ARRAY_BUFFER, quadVBO); glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0); glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(1); glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
} }
glBindVertexArray(quadVAO); glBindVertexArray(quadVAO);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0); glBindVertexArray(0);
} }
// RenderCube() Renders a 1x1 3D cube in NDC. // process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
GLuint cubeVAO = 0; // ---------------------------------------------------------------------------------------------------------
GLuint cubeVBO = 0; void processInput(GLFWwindow *window)
void RenderCube()
{ {
// Initialize (if necessary) if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
if (cubeVAO == 0) glfwSetWindowShouldClose(window, true);
{
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
};
glGenVertexArrays(1, &cubeVAO);
glGenBuffers(1, &cubeVBO);
// Fill buffer
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// Link vertex attributes
glBindVertexArray(cubeVAO);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
// 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 float cameraSpeed = 2.5 * deltaTime;
// managed by a 'Resource Manager' that manages all resources (like textures, models, audio). if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
// For learning purposes we'll just define it as a utility function.
GLuint loadTexture(GLchar const * path)
{
// 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);
// 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])
camera.ProcessKeyboard(FORWARD, deltaTime); camera.ProcessKeyboard(FORWARD, deltaTime);
if (keys[GLFW_KEY_S]) if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
camera.ProcessKeyboard(BACKWARD, deltaTime); camera.ProcessKeyboard(BACKWARD, deltaTime);
if (keys[GLFW_KEY_A]) if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
camera.ProcessKeyboard(LEFT, deltaTime); camera.ProcessKeyboard(LEFT, deltaTime);
if (keys[GLFW_KEY_D]) if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
camera.ProcessKeyboard(RIGHT, deltaTime); camera.ProcessKeyboard(RIGHT, deltaTime);
if (keys[GLFW_KEY_SPACE] && !keysPressed[GLFW_KEY_SPACE])
{
shadows = !shadows;
keysPressed[GLFW_KEY_SPACE] = true;
}
} }
GLfloat lastX = 400, lastY = 300; // glfw: whenever the window size changed (by OS or user resize) this callback function executes
bool firstMouse = true; // ---------------------------------------------------------------------------------------------
// Is called whenever a key is pressed/released via GLFW void framebuffer_size_callback(GLFWwindow* window, int width, int height)
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{ {
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) // make sure the viewport matches the new window dimensions; note that width and
glfwSetWindowShouldClose(window, GL_TRUE); // height will be significantly larger than specified on retina displays.
glViewport(0, 0, width, height);
if (key >= 0 && key <= 1024)
{
if (action == GLFW_PRESS)
keys[key] = true;
else if (action == GLFW_RELEASE)
{
keys[key] = false;
keysPressed[key] = false;
}
}
} }
// glfw: whenever the mouse moves, this callback is called
// -------------------------------------------------------
void mouse_callback(GLFWwindow* window, double xpos, double ypos) void mouse_callback(GLFWwindow* window, double xpos, double ypos)
{ {
if (firstMouse) if (firstMouse)
@@ -420,8 +385,8 @@ void mouse_callback(GLFWwindow* window, double xpos, double ypos)
firstMouse = false; firstMouse = false;
} }
GLfloat xoffset = xpos - lastX; float xoffset = xpos - lastX;
GLfloat yoffset = lastY - ypos; float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top
lastX = xpos; lastX = xpos;
lastY = ypos; lastY = ypos;
@@ -429,7 +394,48 @@ void mouse_callback(GLFWwindow* window, double xpos, double ypos)
camera.ProcessMouseMovement(xoffset, yoffset); camera.ProcessMouseMovement(xoffset, yoffset);
} }
// glfw: whenever the mouse scroll wheel scrolls, this callback is called
// ----------------------------------------------------------------------
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{ {
camera.ProcessMouseScroll(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;
}

View File

@@ -14,8 +14,6 @@ uniform sampler2D shadowMap;
uniform vec3 lightPos; uniform vec3 lightPos;
uniform vec3 viewPos; uniform vec3 viewPos;
uniform bool shadows;
float ShadowCalculation(vec4 fragPosLightSpace) float ShadowCalculation(vec4 fragPosLightSpace)
{ {
// perform perspective divide // perform perspective divide
@@ -26,29 +24,9 @@ float ShadowCalculation(vec4 fragPosLightSpace)
float closestDepth = texture(shadowMap, projCoords.xy).r; float closestDepth = texture(shadowMap, projCoords.xy).r;
// Get depth of current fragment from light's perspective // Get depth of current fragment from light's perspective
float currentDepth = projCoords.z; float currentDepth = projCoords.z;
// Calculate bias (based on depth map resolution and slope)
vec3 normal = normalize(fs_in.Normal);
vec3 lightDir = normalize(lightPos - fs_in.FragPos);
float bias = max(0.05 * (1.0 - dot(normal, lightDir)), 0.005);
// Check whether current frag pos is in shadow // Check whether current frag pos is in shadow
// float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0; float shadow = currentDepth > closestDepth ? 1.0 : 0.0;
// PCF
float shadow = 0.0;
vec2 texelSize = 1.0 / textureSize(shadowMap, 0);
for(int x = -1; x <= 1; ++x)
{
for(int y = -1; y <= 1; ++y)
{
float pcfDepth = texture(shadowMap, projCoords.xy + vec2(x, y) * texelSize).r;
shadow += currentDepth - bias > pcfDepth ? 1.0 : 0.0;
}
}
shadow /= 9.0;
// Keep the shadow at 0.0 when outside the far_plane region of the light's frustum.
if(projCoords.z > 1.0)
shadow = 0.0;
return shadow; return shadow;
} }
@@ -57,22 +35,22 @@ void main()
vec3 color = texture(diffuseTexture, fs_in.TexCoords).rgb; vec3 color = texture(diffuseTexture, fs_in.TexCoords).rgb;
vec3 normal = normalize(fs_in.Normal); vec3 normal = normalize(fs_in.Normal);
vec3 lightColor = vec3(0.3); vec3 lightColor = vec3(0.3);
// Ambient // ambient
vec3 ambient = 0.3 * color; vec3 ambient = 0.3 * color;
// Diffuse // diffuse
vec3 lightDir = normalize(lightPos - fs_in.FragPos); vec3 lightDir = normalize(lightPos - fs_in.FragPos);
float diff = max(dot(lightDir, normal), 0.0); float diff = max(dot(lightDir, normal), 0.0);
vec3 diffuse = diff * lightColor; vec3 diffuse = diff * lightColor;
// Specular // specular
vec3 viewDir = normalize(viewPos - fs_in.FragPos); vec3 viewDir = normalize(viewPos - fs_in.FragPos);
vec3 reflectDir = reflect(-lightDir, normal); vec3 reflectDir = reflect(-lightDir, normal);
float spec = 0.0; float spec = 0.0;
vec3 halfwayDir = normalize(lightDir + viewDir); vec3 halfwayDir = normalize(lightDir + viewDir);
spec = pow(max(dot(normal, halfwayDir), 0.0), 64.0); spec = pow(max(dot(normal, halfwayDir), 0.0), 64.0);
vec3 specular = spec * lightColor; vec3 specular = spec * lightColor;
// Calculate shadow // calculate shadow
float shadow = shadows ? ShadowCalculation(fs_in.FragPosLightSpace) : 0.0; float shadow = ShadowCalculation(fs_in.FragPosLightSpace);
vec3 lighting = (ambient + (1.0 - shadow) * (diffuse + specular)) * color; vec3 lighting = (ambient + (1.0 - shadow) * (diffuse + specular)) * color;
FragColor = vec4(lighting, 1.0f); FragColor = vec4(lighting, 1.0);
} }

View File

@@ -0,0 +1,27 @@
#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;
vec4 FragPosLightSpace;
} vs_out;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
uniform mat4 lightSpaceMatrix;
void main()
{
vs_out.FragPos = vec3(model * vec4(aPos, 1.0));
vs_out.Normal = transpose(inverse(mat3(model))) * aNormal;
vs_out.TexCoords = aTexCoords;
vs_out.FragPosLightSpace = lightSpaceMatrix * vec4(vs_out.FragPos, 1.0);
gl_Position = projection * view * model * vec4(aPos, 1.0f);
}

View File

@@ -1,11 +0,0 @@
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texCoords;
out vec2 TexCoords;
void main()
{
gl_Position = vec4(position, 1.0f);
TexCoords = texCoords;
}

View File

@@ -1,20 +0,0 @@
#version 330 core
out vec4 color;
in vec2 TexCoords;
uniform sampler2D depthMap;
uniform float near_plane;
uniform float far_plane;
float LinearizeDepth(float depth)
{
float z = depth * 2.0 - 1.0; // Back to NDC
return (2.0 * near_plane * far_plane) / (far_plane + near_plane - z * (far_plane - near_plane));
}
void main()
{
float depthValue = texture(depthMap, TexCoords).r;
// color = vec4(vec3(LinearizeDepth(depthValue) / far_plane), 1.0); // perspective
color = vec4(vec3(depthValue), 1.0); // orthographic
}

View File

@@ -1,27 +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;
vec4 FragPosLightSpace;
} vs_out;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
uniform mat4 lightSpaceMatrix;
void main()
{
gl_Position = projection * view * model * vec4(position, 1.0f);
vs_out.FragPos = vec3(model * vec4(position, 1.0));
vs_out.Normal = transpose(inverse(mat3(model))) * normal;
vs_out.TexCoords = texCoords;
vs_out.FragPosLightSpace = lightSpaceMatrix * vec4(vs_out.FragPos, 1.0);
}

View File

@@ -1,416 +1,404 @@
// GLEW #include <glad/glad.h>
#define GLEW_STATIC
#include <GL/glew.h>
// GLFW
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <stb_image.h>
// GL includes
#include <learnopengl/shader.h>
#include <learnopengl/camera.h>
// GLM Mathemtics
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp> #include <glm/gtc/type_ptr.hpp>
// Other Libs
#include <SOIL.h>
#include <learnopengl/filesystem.h> #include <learnopengl/filesystem.h>
#include <learnopengl/shader.h>
#include <learnopengl/camera.h>
#include <learnopengl/model.h>
// Properties #include <iostream>
const GLuint SCR_WIDTH = 800, SCR_HEIGHT = 600;
// Function prototypes void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
void mouse_callback(GLFWwindow* window, double xpos, double ypos); void mouse_callback(GLFWwindow* window, double xpos, double ypos);
void Do_Movement(); void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
GLuint loadTexture(GLchar const * path); void processInput(GLFWwindow *window);
void RenderScene(Shader &shader); unsigned int loadTexture(const char *path);
void RenderCube(); void renderScene(const Shader &shader);
void RenderQuad(); void renderCube();
void renderQuad();
// Camera // settings
const unsigned int SCR_WIDTH = 1280;
const unsigned int SCR_HEIGHT = 720;
// camera
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f)); 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 // timing
GLfloat deltaTime = 0.0f; float deltaTime = 0.0f;
GLfloat lastFrame = 0.0f; float lastFrame = 0.0f;
// Options // meshes
GLboolean shadows = true; unsigned int planeVAO;
// Global variables
GLuint woodTexture;
GLuint planeVAO;
// The MAIN function, from here we start our application and run our Game loop
int main() int main()
{ {
// Init GLFW // glfw: initialize and configure
// ------------------------------
glfwInit(); glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 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); glfwMakeContextCurrent(window);
if (window == NULL)
// Set the required callback functions {
glfwSetKeyCallback(window, key_callback); std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
glfwSetCursorPosCallback(window, mouse_callback); glfwSetCursorPosCallback(window, mouse_callback);
glfwSetScrollCallback(window, scroll_callback); glfwSetScrollCallback(window, scroll_callback);
// Options // tell GLFW to capture our mouse
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
// Initialize GLEW to setup the OpenGL Function pointers // glad: load all OpenGL function pointers
glewExperimental = GL_TRUE; // ---------------------------------------
glewInit(); if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
// Define the viewport dimensions // configure global opengl state
glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT); // -----------------------------
// Setup some OpenGL options
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
// Setup and compile our shaders // build and compile shaders
Shader shader("shadow_mapping.vs", "shadow_mapping.frag"); // -------------------------
Shader simpleDepthShader("shadow_mapping_depth.vs", "shadow_mapping_depth.frag"); Shader shader("3.1.2.shadow_mapping.vs", "3.1.2.shadow_mapping.fs");
Shader debugDepthQuad("debug_quad.vs", "debug_quad_depth.frag"); Shader simpleDepthShader("3.1.1.shadow_mapping_depth.vs", "3.1.1.shadow_mapping_depth.fs");
Shader debugDepthQuad("3.1.1.debug_quad.vs", "3.1.1.debug_quad_depth.fs");
// Set texture samples // set up vertex data (and buffer(s)) and configure vertex attributes
shader.Use(); // ------------------------------------------------------------------
glUniform1i(glGetUniformLocation(shader.Program, "diffuseTexture"), 0); float planeVertices[] = {
glUniform1i(glGetUniformLocation(shader.Program, "shadowMap"), 1); // 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,
GLfloat planeVertices[] = { 25.0f, -0.5f, 25.0f, 0.0f, 1.0f, 0.0f, 25.0f, 0.0f,
// Positions // Normals // Texture Coords -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, 25.0f, 25.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, 0.0f, 0.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, 25.0f, 25.0f,
-25.0f, -0.5f, -25.0f, 0.0f, 1.0f, 0.0f, 0.0f, 25.0f
}; };
// Setup plane VAO // plane VAO
GLuint planeVBO; unsigned int planeVBO;
glGenVertexArrays(1, &planeVAO); glGenVertexArrays(1, &planeVAO);
glGenBuffers(1, &planeVBO); glGenBuffers(1, &planeVBO);
glBindVertexArray(planeVAO); glBindVertexArray(planeVAO);
glBindBuffer(GL_ARRAY_BUFFER, planeVBO); glBindBuffer(GL_ARRAY_BUFFER, planeVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(planeVertices), &planeVertices, GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER, sizeof(planeVertices), planeVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0); 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); 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); 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)));
glBindVertexArray(0); glBindVertexArray(0);
// Light source // load textures
glm::vec3 lightPos(-2.0f, 4.0f, -1.0f); // -------------
unsigned int woodTexture = loadTexture(FileSystem::getPath("resources/textures/wood.png").c_str());
// Load textures // configure depth map FBO
woodTexture = loadTexture(FileSystem::getPath("resources/textures/wood.png").c_str()); // -----------------------
const unsigned int SHADOW_WIDTH = 1024, SHADOW_HEIGHT = 1024;
// Configure depth map FBO unsigned int depthMapFBO;
const GLuint SHADOW_WIDTH = 1024, SHADOW_HEIGHT = 1024;
GLuint depthMapFBO;
glGenFramebuffers(1, &depthMapFBO); glGenFramebuffers(1, &depthMapFBO);
// - Create depth texture // create depth texture
GLuint depthMap; unsigned int depthMap;
glGenTextures(1, &depthMap); glGenTextures(1, &depthMap);
glBindTexture(GL_TEXTURE_2D, 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); 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_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
GLfloat borderColor[] = { 1.0, 1.0, 1.0, 1.0 }; // attach depth texture as FBO's depth buffer
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO); glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthMap, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthMap, 0);
glDrawBuffer(GL_NONE); glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE); glReadBuffer(GL_NONE);
glBindFramebuffer(GL_FRAMEBUFFER, 0); 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("shadowMap", 1);
debugDepthQuad.use();
debugDepthQuad.setInt("depthMap", 0);
// lighting info
// -------------
glm::vec3 lightPos(-2.0f, 4.0f, -1.0f);
// render loop
// -----------
while (!glfwWindowShouldClose(window)) while (!glfwWindowShouldClose(window))
{ {
// Set frame time // per-frame time logic
GLfloat currentFrame = glfwGetTime(); // --------------------
float currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame; deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame; lastFrame = currentFrame;
// Check and call events // input
glfwPollEvents(); // -----
Do_Movement(); processInput(window);
// Change light position over time // render
lightPos.z = cos(glfwGetTime()) * 2.0f; // ------
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) // 1. render depth of scene to texture (from light's perspective)
// - Get light projection/view matrix. // --------------------------------------------------------------
glm::mat4 lightProjection, lightView; glm::mat4 lightProjection, lightView;
glm::mat4 lightSpaceMatrix; glm::mat4 lightSpaceMatrix;
GLfloat near_plane = 1.0f, far_plane = 7.5f; float near_plane = 1.0f, far_plane = 7.5f;
lightProjection = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, near_plane, far_plane); lightProjection = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, near_plane, far_plane);
//lightProjection = glm::perspective(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.
lightView = glm::lookAt(lightPos, glm::vec3(0.0f), glm::vec3(0.0, 1.0, 0.0)); lightView = glm::lookAt(lightPos, glm::vec3(0.0f), glm::vec3(0.0, 1.0, 0.0));
lightSpaceMatrix = lightProjection * lightView; lightSpaceMatrix = lightProjection * lightView;
// - now render scene from light's point of view // render scene from light's point of view
simpleDepthShader.Use(); simpleDepthShader.use();
glUniformMatrix4fv(glGetUniformLocation(simpleDepthShader.Program, "lightSpaceMatrix"), 1, GL_FALSE, glm::value_ptr(lightSpaceMatrix)); simpleDepthShader.setMat4("lightSpaceMatrix", lightSpaceMatrix);
glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT); glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);
glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO); glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO);
glClear(GL_DEPTH_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT);
RenderScene(simpleDepthShader); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, woodTexture);
renderScene(simpleDepthShader);
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
// 2. Render scene as normal // reset viewport
glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT); glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shader.Use();
// 2. render scene as normal using the generated depth/shadow map
// --------------------------------------------------------------
glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shader.use();
glm::mat4 projection = glm::perspective(camera.Zoom, (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f); glm::mat4 projection = glm::perspective(camera.Zoom, (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
glm::mat4 view = camera.GetViewMatrix(); glm::mat4 view = camera.GetViewMatrix();
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); shader.setMat4("projection", projection);
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view)); shader.setMat4("view", view);
// Set light uniforms // set light uniforms
glUniform3fv(glGetUniformLocation(shader.Program, "lightPos"), 1, &lightPos[0]); shader.setVec3("viewPos", camera.Position);
glUniform3fv(glGetUniformLocation(shader.Program, "viewPos"), 1, &camera.Position[0]); shader.setVec3("lightPos", lightPos);
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "lightSpaceMatrix"), 1, GL_FALSE, glm::value_ptr(lightSpaceMatrix)); shader.setMat4("lightSpaceMatrix", lightSpaceMatrix);
// Enable/Disable shadows by pressing 'SPACE'
glUniform1i(glGetUniformLocation(shader.Program, "shadows"), shadows);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, woodTexture); glBindTexture(GL_TEXTURE_2D, woodTexture);
glActiveTexture(GL_TEXTURE1); glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, depthMap); glBindTexture(GL_TEXTURE_2D, depthMap);
RenderScene(shader); renderScene(shader);
// 3. DEBUG: visualize depth map by rendering it to plane // render Depth map to quad for visual debugging
debugDepthQuad.Use(); // ---------------------------------------------
glUniform1f(glGetUniformLocation(debugDepthQuad.Program, "near_plane"), near_plane); debugDepthQuad.use();
glUniform1f(glGetUniformLocation(debugDepthQuad.Program, "far_plane"), far_plane); debugDepthQuad.setFloat("near_plane", near_plane);
debugDepthQuad.setFloat("far_plane", far_plane);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, depthMap); glBindTexture(GL_TEXTURE_2D, depthMap);
//RenderQuad(); // uncomment this line to see depth map //renderQuad();
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
// Swap the buffers // -------------------------------------------------------------------------------
glfwSwapBuffers(window); glfwSwapBuffers(window);
glfwPollEvents();
} }
// optional: de-allocate all resources once they've outlived their purpose:
// ------------------------------------------------------------------------
glDeleteVertexArrays(1, &planeVAO);
glDeleteBuffers(1, &planeVBO);
glfwTerminate(); glfwTerminate();
return 0; return 0;
} }
void RenderScene(Shader &shader) // renders the 3D scene
// --------------------
void renderScene(const Shader &shader)
{ {
// Floor // floor
glm::mat4 model; glm::mat4 model;
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); shader.setMat4("model", model);
glBindVertexArray(planeVAO); glBindVertexArray(planeVAO);
glDrawArrays(GL_TRIANGLES, 0, 6); glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0); // cubes
// Cubes
model = glm::mat4(); model = glm::mat4();
model = glm::translate(model, glm::vec3(0.0f, 1.5f, 0.0)); model = glm::translate(model, glm::vec3(0.0f, 1.5f, 0.0));
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); model = glm::scale(model, glm::vec3(0.5f));
RenderCube(); shader.setMat4("model", model);
renderCube();
model = glm::mat4(); model = glm::mat4();
model = glm::translate(model, glm::vec3(2.0f, 0.0f, 1.0)); model = glm::translate(model, glm::vec3(2.0f, 0.0f, 1.0));
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); model = glm::scale(model, glm::vec3(0.5f));
RenderCube(); shader.setMat4("model", model);
renderCube();
model = glm::mat4(); model = glm::mat4();
model = glm::translate(model, glm::vec3(-1.0f, 0.0f, 2.0)); model = glm::translate(model, glm::vec3(-1.0f, 0.0f, 2.0));
model = glm::rotate(model, 60.0f, glm::normalize(glm::vec3(1.0, 0.0, 1.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.5)); model = glm::scale(model, glm::vec3(0.25));
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); shader.setMat4("model", model);
RenderCube(); renderCube();
} }
// RenderQuad() Renders a 1x1 quad in NDC, best used for framebuffer color targets // renderCube() renders a 1x1 3D cube in NDC.
// and post-processing effects. // -------------------------------------------------
GLuint quadVAO = 0; unsigned int cubeVAO = 0;
GLuint quadVBO; unsigned int cubeVBO = 0;
void RenderQuad() void renderCube()
{
// initialize (if necessary)
if (cubeVAO == 0)
{
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
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// link vertex attributes
glBindVertexArray(cubeVAO);
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)));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
// render Cube
glBindVertexArray(cubeVAO);
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
}
// renderQuad() renders a 1x1 XY quad in NDC
// -----------------------------------------
unsigned int quadVAO = 0;
unsigned int quadVBO;
void renderQuad()
{ {
if (quadVAO == 0) if (quadVAO == 0)
{ {
GLfloat quadVertices[] = { float quadVertices[] = {
// Positions // Texture Coords // positions // texture Coords
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f, -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, 0.0f, 0.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
}; };
// Setup plane VAO // setup plane VAO
glGenVertexArrays(1, &quadVAO); glGenVertexArrays(1, &quadVAO);
glGenBuffers(1, &quadVBO); glGenBuffers(1, &quadVBO);
glBindVertexArray(quadVAO); glBindVertexArray(quadVAO);
glBindBuffer(GL_ARRAY_BUFFER, quadVBO); glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0); glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(1); glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
} }
glBindVertexArray(quadVAO); glBindVertexArray(quadVAO);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0); glBindVertexArray(0);
} }
// RenderCube() Renders a 1x1 3D cube in NDC. // process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
GLuint cubeVAO = 0; // ---------------------------------------------------------------------------------------------------------
GLuint cubeVBO = 0; void processInput(GLFWwindow *window)
void RenderCube()
{ {
// Initialize (if necessary) if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
if (cubeVAO == 0) glfwSetWindowShouldClose(window, true);
{
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
};
glGenVertexArrays(1, &cubeVAO);
glGenBuffers(1, &cubeVBO);
// Fill buffer
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// Link vertex attributes
glBindVertexArray(cubeVAO);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
// 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 float cameraSpeed = 2.5 * deltaTime;
// managed by a 'Resource Manager' that manages all resources (like textures, models, audio). if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
// For learning purposes we'll just define it as a utility function.
GLuint loadTexture(GLchar const * path)
{
// 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);
// 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])
camera.ProcessKeyboard(FORWARD, deltaTime); camera.ProcessKeyboard(FORWARD, deltaTime);
if (keys[GLFW_KEY_S]) if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
camera.ProcessKeyboard(BACKWARD, deltaTime); camera.ProcessKeyboard(BACKWARD, deltaTime);
if (keys[GLFW_KEY_A]) if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
camera.ProcessKeyboard(LEFT, deltaTime); camera.ProcessKeyboard(LEFT, deltaTime);
if (keys[GLFW_KEY_D]) if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
camera.ProcessKeyboard(RIGHT, deltaTime); camera.ProcessKeyboard(RIGHT, deltaTime);
if (keys[GLFW_KEY_SPACE] && !keysPressed[GLFW_KEY_SPACE])
{
shadows = !shadows;
keysPressed[GLFW_KEY_SPACE] = true;
}
} }
GLfloat lastX = 400, lastY = 300; // glfw: whenever the window size changed (by OS or user resize) this callback function executes
bool firstMouse = true; // ---------------------------------------------------------------------------------------------
// Is called whenever a key is pressed/released via GLFW void framebuffer_size_callback(GLFWwindow* window, int width, int height)
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{ {
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) // make sure the viewport matches the new window dimensions; note that width and
glfwSetWindowShouldClose(window, GL_TRUE); // height will be significantly larger than specified on retina displays.
glViewport(0, 0, width, height);
if (key >= 0 && key <= 1024)
{
if (action == GLFW_PRESS)
keys[key] = true;
else if (action == GLFW_RELEASE)
{
keys[key] = false;
keysPressed[key] = false;
}
}
} }
// glfw: whenever the mouse moves, this callback is called
// -------------------------------------------------------
void mouse_callback(GLFWwindow* window, double xpos, double ypos) void mouse_callback(GLFWwindow* window, double xpos, double ypos)
{ {
if (firstMouse) if (firstMouse)
@@ -420,8 +408,8 @@ void mouse_callback(GLFWwindow* window, double xpos, double ypos)
firstMouse = false; firstMouse = false;
} }
GLfloat xoffset = xpos - lastX; float xoffset = xpos - lastX;
GLfloat yoffset = lastY - ypos; float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top
lastX = xpos; lastX = xpos;
lastY = ypos; lastY = ypos;
@@ -429,7 +417,48 @@ void mouse_callback(GLFWwindow* window, double xpos, double ypos)
camera.ProcessMouseMovement(xoffset, yoffset); camera.ProcessMouseMovement(xoffset, yoffset);
} }
// glfw: whenever the mouse scroll wheel scrolls, this callback is called
// ----------------------------------------------------------------------
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{ {
camera.ProcessMouseScroll(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;
}

View File

@@ -1,6 +0,0 @@
#version 330 core
void main()
{
// gl_FragDepth = gl_FragCoord.z;
}

View File

@@ -1,10 +0,0 @@
#version 330 core
layout (location = 0) in vec3 position;
uniform mat4 lightSpaceMatrix;
uniform mat4 model;
void main()
{
gl_Position = lightSpaceMatrix * model * vec4(position, 1.0f);
}

View File

@@ -14,23 +14,21 @@ uniform sampler2D shadowMap;
uniform vec3 lightPos; uniform vec3 lightPos;
uniform vec3 viewPos; uniform vec3 viewPos;
uniform bool shadows;
float ShadowCalculation(vec4 fragPosLightSpace) float ShadowCalculation(vec4 fragPosLightSpace)
{ {
// perform perspective divide // perform perspective divide
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w; vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
// Transform to [0,1] range // transform to [0,1] range
projCoords = projCoords * 0.5 + 0.5; projCoords = projCoords * 0.5 + 0.5;
// Get closest depth value from light's perspective (using [0,1] range fragPosLight as coords) // get closest depth value from light's perspective (using [0,1] range fragPosLight as coords)
float closestDepth = texture(shadowMap, projCoords.xy).r; float closestDepth = texture(shadowMap, projCoords.xy).r;
// Get depth of current fragment from light's perspective // get depth of current fragment from light's perspective
float currentDepth = projCoords.z; float currentDepth = projCoords.z;
// Calculate bias (based on depth map resolution and slope) // calculate bias (based on depth map resolution and slope)
vec3 normal = normalize(fs_in.Normal); vec3 normal = normalize(fs_in.Normal);
vec3 lightDir = normalize(lightPos - fs_in.FragPos); vec3 lightDir = normalize(lightPos - fs_in.FragPos);
float bias = max(0.05 * (1.0 - dot(normal, lightDir)), 0.005); float bias = max(0.05 * (1.0 - dot(normal, lightDir)), 0.005);
// Check whether current frag pos is in shadow // check whether current frag pos is in shadow
// float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0; // float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0;
// PCF // PCF
float shadow = 0.0; float shadow = 0.0;
@@ -45,7 +43,7 @@ float ShadowCalculation(vec4 fragPosLightSpace)
} }
shadow /= 9.0; shadow /= 9.0;
// Keep the shadow at 0.0 when outside the far_plane region of the light's frustum. // keep the shadow at 0.0 when outside the far_plane region of the light's frustum.
if(projCoords.z > 1.0) if(projCoords.z > 1.0)
shadow = 0.0; shadow = 0.0;
@@ -57,22 +55,22 @@ void main()
vec3 color = texture(diffuseTexture, fs_in.TexCoords).rgb; vec3 color = texture(diffuseTexture, fs_in.TexCoords).rgb;
vec3 normal = normalize(fs_in.Normal); vec3 normal = normalize(fs_in.Normal);
vec3 lightColor = vec3(0.3); vec3 lightColor = vec3(0.3);
// Ambient // ambient
vec3 ambient = 0.3 * color; vec3 ambient = 0.3 * color;
// Diffuse // diffuse
vec3 lightDir = normalize(lightPos - fs_in.FragPos); vec3 lightDir = normalize(lightPos - fs_in.FragPos);
float diff = max(dot(lightDir, normal), 0.0); float diff = max(dot(lightDir, normal), 0.0);
vec3 diffuse = diff * lightColor; vec3 diffuse = diff * lightColor;
// Specular // specular
vec3 viewDir = normalize(viewPos - fs_in.FragPos); vec3 viewDir = normalize(viewPos - fs_in.FragPos);
vec3 reflectDir = reflect(-lightDir, normal); vec3 reflectDir = reflect(-lightDir, normal);
float spec = 0.0; float spec = 0.0;
vec3 halfwayDir = normalize(lightDir + viewDir); vec3 halfwayDir = normalize(lightDir + viewDir);
spec = pow(max(dot(normal, halfwayDir), 0.0), 64.0); spec = pow(max(dot(normal, halfwayDir), 0.0), 64.0);
vec3 specular = spec * lightColor; vec3 specular = spec * lightColor;
// Calculate shadow // calculate shadow
float shadow = shadows ? ShadowCalculation(fs_in.FragPosLightSpace) : 0.0; float shadow = ShadowCalculation(fs_in.FragPosLightSpace);
vec3 lighting = (ambient + (1.0 - shadow) * (diffuse + specular)) * color; vec3 lighting = (ambient + (1.0 - shadow) * (diffuse + specular)) * color;
FragColor = vec4(lighting, 1.0f); FragColor = vec4(lighting, 1.0);
} }

View File

@@ -0,0 +1,27 @@
#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;
vec4 FragPosLightSpace;
} vs_out;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
uniform mat4 lightSpaceMatrix;
void main()
{
vs_out.FragPos = vec3(model * vec4(aPos, 1.0));
vs_out.Normal = transpose(inverse(mat3(model))) * aNormal;
vs_out.TexCoords = aTexCoords;
vs_out.FragPosLightSpace = lightSpaceMatrix * vec4(vs_out.FragPos, 1.0);
gl_Position = projection * view * model * vec4(aPos, 1.0f);
}

View File

@@ -1,11 +0,0 @@
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texCoords;
out vec2 TexCoords;
void main()
{
gl_Position = vec4(position, 1.0f);
TexCoords = texCoords;
}

View File

@@ -1,20 +0,0 @@
#version 330 core
out vec4 color;
in vec2 TexCoords;
uniform sampler2D depthMap;
uniform float near_plane;
uniform float far_plane;
float LinearizeDepth(float depth)
{
float z = depth * 2.0 - 1.0; // Back to NDC
return (2.0 * near_plane * far_plane) / (far_plane + near_plane - z * (far_plane - near_plane));
}
void main()
{
float depthValue = texture(depthMap, TexCoords).r;
// color = vec4(vec3(LinearizeDepth(depthValue) / far_plane), 1.0); // perspective
color = vec4(vec3(depthValue), 1.0); // orthographic
}

View File

@@ -1,131 +1,128 @@
// GLEW #include <glad/glad.h>
#define GLEW_STATIC
#include <GL/glew.h>
// GLFW
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <stb_image.h>
// GL includes
#include <learnopengl/shader.h>
#include <learnopengl/camera.h>
// GLM Mathemtics
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp> #include <glm/gtc/type_ptr.hpp>
// Other Libs
#include <SOIL.h>
#include <learnopengl/filesystem.h> #include <learnopengl/filesystem.h>
#include <learnopengl/shader.h>
#include <learnopengl/camera.h>
#include <learnopengl/model.h>
// Properties #include <iostream>
const GLuint SCR_WIDTH = 800, SCR_HEIGHT = 600;
// Function prototypes void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
void mouse_callback(GLFWwindow* window, double xpos, double ypos); void mouse_callback(GLFWwindow* window, double xpos, double ypos);
void Do_Movement(); void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
GLuint loadTexture(GLchar const * path); void processInput(GLFWwindow *window);
void RenderScene(Shader &shader); unsigned int loadTexture(const char *path);
void RenderCube(); void renderScene(const Shader &shader);
void RenderQuad(); void renderCube();
void renderQuad();
// Camera // settings
const unsigned int SCR_WIDTH = 1280;
const unsigned int SCR_HEIGHT = 720;
// camera
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f)); 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 // timing
GLfloat deltaTime = 0.0f; float deltaTime = 0.0f;
GLfloat lastFrame = 0.0f; float lastFrame = 0.0f;
// Options // meshes
GLboolean shadows = true; unsigned int planeVAO;
// Global variables
GLuint woodTexture;
GLuint planeVAO;
// The MAIN function, from here we start our application and run our Game loop
int main() int main()
{ {
// Init GLFW // glfw: initialize and configure
// ------------------------------
glfwInit(); glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 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); glfwMakeContextCurrent(window);
if (window == NULL)
// Set the required callback functions {
glfwSetKeyCallback(window, key_callback); std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
glfwSetCursorPosCallback(window, mouse_callback); glfwSetCursorPosCallback(window, mouse_callback);
glfwSetScrollCallback(window, scroll_callback); glfwSetScrollCallback(window, scroll_callback);
// Options // tell GLFW to capture our mouse
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
// Initialize GLEW to setup the OpenGL Function pointers // glad: load all OpenGL function pointers
glewExperimental = GL_TRUE; // ---------------------------------------
glewInit(); if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
// Define the viewport dimensions // configure global opengl state
glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT); // -----------------------------
// Setup some OpenGL options
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
// Setup and compile our shaders // build and compile shaders
Shader shader("shadow_mapping.vs", "shadow_mapping.frag"); // -------------------------
Shader simpleDepthShader("shadow_mapping_depth.vs", "shadow_mapping_depth.frag"); Shader shader("3.1.3.shadow_mapping.vs", "3.1.3.shadow_mapping.fs");
Shader debugDepthQuad("debug_quad.vs", "debug_quad_depth.frag"); Shader simpleDepthShader("3.1.1.shadow_mapping_depth.vs", "3.1.1.shadow_mapping_depth.fs");
Shader debugDepthQuad("3.1.1.debug_quad.vs", "3.1.1.debug_quad_depth.fs");
// Set texture samples // set up vertex data (and buffer(s)) and configure vertex attributes
shader.Use(); // ------------------------------------------------------------------
glUniform1i(glGetUniformLocation(shader.Program, "diffuseTexture"), 0); float planeVertices[] = {
glUniform1i(glGetUniformLocation(shader.Program, "shadowMap"), 1); // 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,
GLfloat planeVertices[] = { 25.0f, -0.5f, 25.0f, 0.0f, 1.0f, 0.0f, 25.0f, 0.0f,
// Positions // Normals // Texture Coords -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, 25.0f, 25.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, 0.0f, 0.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, 25.0f, 25.0f,
-25.0f, -0.5f, -25.0f, 0.0f, 1.0f, 0.0f, 0.0f, 25.0f
}; };
// Setup plane VAO // plane VAO
GLuint planeVBO; unsigned int planeVBO;
glGenVertexArrays(1, &planeVAO); glGenVertexArrays(1, &planeVAO);
glGenBuffers(1, &planeVBO); glGenBuffers(1, &planeVBO);
glBindVertexArray(planeVAO); glBindVertexArray(planeVAO);
glBindBuffer(GL_ARRAY_BUFFER, planeVBO); glBindBuffer(GL_ARRAY_BUFFER, planeVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(planeVertices), &planeVertices, GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER, sizeof(planeVertices), planeVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0); 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); 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); 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)));
glBindVertexArray(0); glBindVertexArray(0);
// Light source // load textures
glm::vec3 lightPos(-2.0f, 4.0f, -1.0f); // -------------
unsigned int woodTexture = loadTexture(FileSystem::getPath("resources/textures/wood.png").c_str());
// Load textures // configure depth map FBO
woodTexture = loadTexture(FileSystem::getPath("resources/textures/wood.png").c_str()); // -----------------------
const unsigned int SHADOW_WIDTH = 1024, SHADOW_HEIGHT = 1024;
// Configure depth map FBO unsigned int depthMapFBO;
const GLuint SHADOW_WIDTH = 1024, SHADOW_HEIGHT = 1024;
GLuint depthMapFBO;
glGenFramebuffers(1, &depthMapFBO); glGenFramebuffers(1, &depthMapFBO);
// - Create depth texture // create depth texture
GLuint depthMap; unsigned int depthMap;
glGenTextures(1, &depthMap); glGenTextures(1, &depthMap);
glBindTexture(GL_TEXTURE_2D, 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); 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_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@@ -133,284 +130,283 @@ int main()
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 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 }; GLfloat borderColor[] = { 1.0, 1.0, 1.0, 1.0 };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
// attach depth texture as FBO's depth buffer
glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO); glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthMap, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthMap, 0);
glDrawBuffer(GL_NONE); glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE); glReadBuffer(GL_NONE);
glBindFramebuffer(GL_FRAMEBUFFER, 0); 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("shadowMap", 1);
debugDepthQuad.use();
debugDepthQuad.setInt("depthMap", 0);
// lighting info
// -------------
glm::vec3 lightPos(-2.0f, 4.0f, -1.0f);
// render loop
// -----------
while (!glfwWindowShouldClose(window)) while (!glfwWindowShouldClose(window))
{ {
// Set frame time // per-frame time logic
GLfloat currentFrame = glfwGetTime(); // --------------------
float currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame; deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame; lastFrame = currentFrame;
// Check and call events // input
glfwPollEvents(); // -----
Do_Movement(); processInput(window);
// Change light position over time // change light position over time
lightPos.z = cos(glfwGetTime()) * 2.0f; //lightPos.x = sin(glfwGetTime()) * 3.0f;
//lightPos.z = cos(glfwGetTime()) * 2.0f;
//lightPos.y = 5.0 + cos(glfwGetTime()) * 1.0f;
// 1. Render depth of scene to texture (from light's perspective) // render
// - Get light projection/view matrix. // ------
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 lightProjection, lightView;
glm::mat4 lightSpaceMatrix; glm::mat4 lightSpaceMatrix;
GLfloat near_plane = 1.0f, far_plane = 7.5f; 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); lightProjection = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, near_plane, far_plane);
//lightProjection = glm::perspective(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.
lightView = glm::lookAt(lightPos, glm::vec3(0.0f), glm::vec3(0.0, 1.0, 0.0)); lightView = glm::lookAt(lightPos, glm::vec3(0.0f), glm::vec3(0.0, 1.0, 0.0));
lightSpaceMatrix = lightProjection * lightView; lightSpaceMatrix = lightProjection * lightView;
// - now render scene from light's point of view // render scene from light's point of view
simpleDepthShader.Use(); simpleDepthShader.use();
glUniformMatrix4fv(glGetUniformLocation(simpleDepthShader.Program, "lightSpaceMatrix"), 1, GL_FALSE, glm::value_ptr(lightSpaceMatrix)); simpleDepthShader.setMat4("lightSpaceMatrix", lightSpaceMatrix);
glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT); glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);
glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO); glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO);
glClear(GL_DEPTH_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT);
RenderScene(simpleDepthShader); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, woodTexture);
renderScene(simpleDepthShader);
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
// 2. Render scene as normal // reset viewport
glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT); glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shader.Use();
// 2. render scene as normal using the generated depth/shadow map
// --------------------------------------------------------------
glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shader.use();
glm::mat4 projection = glm::perspective(camera.Zoom, (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f); glm::mat4 projection = glm::perspective(camera.Zoom, (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
glm::mat4 view = camera.GetViewMatrix(); glm::mat4 view = camera.GetViewMatrix();
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); shader.setMat4("projection", projection);
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view)); shader.setMat4("view", view);
// Set light uniforms // set light uniforms
glUniform3fv(glGetUniformLocation(shader.Program, "lightPos"), 1, &lightPos[0]); shader.setVec3("viewPos", camera.Position);
glUniform3fv(glGetUniformLocation(shader.Program, "viewPos"), 1, &camera.Position[0]); shader.setVec3("lightPos", lightPos);
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "lightSpaceMatrix"), 1, GL_FALSE, glm::value_ptr(lightSpaceMatrix)); shader.setMat4("lightSpaceMatrix", lightSpaceMatrix);
// Enable/Disable shadows by pressing 'SPACE'
glUniform1i(glGetUniformLocation(shader.Program, "shadows"), shadows);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, woodTexture); glBindTexture(GL_TEXTURE_2D, woodTexture);
glActiveTexture(GL_TEXTURE1); glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, depthMap); glBindTexture(GL_TEXTURE_2D, depthMap);
RenderScene(shader); renderScene(shader);
// 3. DEBUG: visualize depth map by rendering it to plane // render Depth map to quad for visual debugging
debugDepthQuad.Use(); // ---------------------------------------------
glUniform1f(glGetUniformLocation(debugDepthQuad.Program, "near_plane"), near_plane); debugDepthQuad.use();
glUniform1f(glGetUniformLocation(debugDepthQuad.Program, "far_plane"), far_plane); debugDepthQuad.setFloat("near_plane", near_plane);
debugDepthQuad.setFloat("far_plane", far_plane);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, depthMap); glBindTexture(GL_TEXTURE_2D, depthMap);
//RenderQuad(); // uncomment this line to see depth map //renderQuad();
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
// Swap the buffers // -------------------------------------------------------------------------------
glfwSwapBuffers(window); glfwSwapBuffers(window);
glfwPollEvents();
} }
// optional: de-allocate all resources once they've outlived their purpose:
// ------------------------------------------------------------------------
glDeleteVertexArrays(1, &planeVAO);
glDeleteBuffers(1, &planeVBO);
glfwTerminate(); glfwTerminate();
return 0; return 0;
} }
void RenderScene(Shader &shader) // renders the 3D scene
// --------------------
void renderScene(const Shader &shader)
{ {
// Floor // floor
glm::mat4 model; glm::mat4 model;
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); shader.setMat4("model", model);
glBindVertexArray(planeVAO); glBindVertexArray(planeVAO);
glDrawArrays(GL_TRIANGLES, 0, 6); glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0); // cubes
// Cubes
model = glm::mat4(); model = glm::mat4();
model = glm::translate(model, glm::vec3(0.0f, 1.5f, 0.0)); model = glm::translate(model, glm::vec3(0.0f, 1.5f, 0.0));
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); model = glm::scale(model, glm::vec3(0.5f));
RenderCube(); shader.setMat4("model", model);
renderCube();
model = glm::mat4(); model = glm::mat4();
model = glm::translate(model, glm::vec3(2.0f, 0.0f, 1.0)); model = glm::translate(model, glm::vec3(2.0f, 0.0f, 1.0));
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); model = glm::scale(model, glm::vec3(0.5f));
RenderCube(); shader.setMat4("model", model);
renderCube();
model = glm::mat4(); model = glm::mat4();
model = glm::translate(model, glm::vec3(-1.0f, 0.0f, 2.0)); model = glm::translate(model, glm::vec3(-1.0f, 0.0f, 2.0));
model = glm::rotate(model, 60.0f, glm::normalize(glm::vec3(1.0, 0.0, 1.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.5)); model = glm::scale(model, glm::vec3(0.25));
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); shader.setMat4("model", model);
RenderCube(); renderCube();
} }
// RenderQuad() Renders a 1x1 quad in NDC, best used for framebuffer color targets // renderCube() renders a 1x1 3D cube in NDC.
// and post-processing effects. // -------------------------------------------------
GLuint quadVAO = 0; unsigned int cubeVAO = 0;
GLuint quadVBO; unsigned int cubeVBO = 0;
void RenderQuad() void renderCube()
{
// initialize (if necessary)
if (cubeVAO == 0)
{
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
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// link vertex attributes
glBindVertexArray(cubeVAO);
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)));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
// render Cube
glBindVertexArray(cubeVAO);
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
}
// renderQuad() renders a 1x1 XY quad in NDC
// -----------------------------------------
unsigned int quadVAO = 0;
unsigned int quadVBO;
void renderQuad()
{ {
if (quadVAO == 0) if (quadVAO == 0)
{ {
GLfloat quadVertices[] = { float quadVertices[] = {
// Positions // Texture Coords // positions // texture Coords
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f, -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, 0.0f, 0.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
}; };
// Setup plane VAO // setup plane VAO
glGenVertexArrays(1, &quadVAO); glGenVertexArrays(1, &quadVAO);
glGenBuffers(1, &quadVBO); glGenBuffers(1, &quadVBO);
glBindVertexArray(quadVAO); glBindVertexArray(quadVAO);
glBindBuffer(GL_ARRAY_BUFFER, quadVBO); glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0); glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(1); glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
} }
glBindVertexArray(quadVAO); glBindVertexArray(quadVAO);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0); glBindVertexArray(0);
} }
// RenderCube() Renders a 1x1 3D cube in NDC. // process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
GLuint cubeVAO = 0; // ---------------------------------------------------------------------------------------------------------
GLuint cubeVBO = 0; void processInput(GLFWwindow *window)
void RenderCube()
{ {
// Initialize (if necessary) if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
if (cubeVAO == 0) glfwSetWindowShouldClose(window, true);
{
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
};
glGenVertexArrays(1, &cubeVAO);
glGenBuffers(1, &cubeVBO);
// Fill buffer
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// Link vertex attributes
glBindVertexArray(cubeVAO);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
// 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 float cameraSpeed = 2.5 * deltaTime;
// managed by a 'Resource Manager' that manages all resources (like textures, models, audio). if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
// For learning purposes we'll just define it as a utility function.
GLuint loadTexture(GLchar const * path)
{
// 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);
// 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])
camera.ProcessKeyboard(FORWARD, deltaTime); camera.ProcessKeyboard(FORWARD, deltaTime);
if (keys[GLFW_KEY_S]) if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
camera.ProcessKeyboard(BACKWARD, deltaTime); camera.ProcessKeyboard(BACKWARD, deltaTime);
if (keys[GLFW_KEY_A]) if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
camera.ProcessKeyboard(LEFT, deltaTime); camera.ProcessKeyboard(LEFT, deltaTime);
if (keys[GLFW_KEY_D]) if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
camera.ProcessKeyboard(RIGHT, deltaTime); camera.ProcessKeyboard(RIGHT, deltaTime);
if (keys[GLFW_KEY_SPACE] && !keysPressed[GLFW_KEY_SPACE])
{
shadows = !shadows;
keysPressed[GLFW_KEY_SPACE] = true;
}
} }
GLfloat lastX = 400, lastY = 300; // glfw: whenever the window size changed (by OS or user resize) this callback function executes
bool firstMouse = true; // ---------------------------------------------------------------------------------------------
// Is called whenever a key is pressed/released via GLFW void framebuffer_size_callback(GLFWwindow* window, int width, int height)
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{ {
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) // make sure the viewport matches the new window dimensions; note that width and
glfwSetWindowShouldClose(window, GL_TRUE); // height will be significantly larger than specified on retina displays.
glViewport(0, 0, width, height);
if (key >= 0 && key <= 1024)
{
if (action == GLFW_PRESS)
keys[key] = true;
else if (action == GLFW_RELEASE)
{
keys[key] = false;
keysPressed[key] = false;
}
}
} }
// glfw: whenever the mouse moves, this callback is called
// -------------------------------------------------------
void mouse_callback(GLFWwindow* window, double xpos, double ypos) void mouse_callback(GLFWwindow* window, double xpos, double ypos)
{ {
if (firstMouse) if (firstMouse)
@@ -420,8 +416,8 @@ void mouse_callback(GLFWwindow* window, double xpos, double ypos)
firstMouse = false; firstMouse = false;
} }
GLfloat xoffset = xpos - lastX; float xoffset = xpos - lastX;
GLfloat yoffset = lastY - ypos; float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top
lastX = xpos; lastX = xpos;
lastY = ypos; lastY = ypos;
@@ -429,7 +425,48 @@ void mouse_callback(GLFWwindow* window, double xpos, double ypos)
camera.ProcessMouseMovement(xoffset, yoffset); camera.ProcessMouseMovement(xoffset, yoffset);
} }
// glfw: whenever the mouse scroll wheel scrolls, this callback is called
// ----------------------------------------------------------------------
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{ {
camera.ProcessMouseScroll(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;
}

View File

@@ -1,27 +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;
vec4 FragPosLightSpace;
} vs_out;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
uniform mat4 lightSpaceMatrix;
void main()
{
gl_Position = projection * view * model * vec4(position, 1.0f);
vs_out.FragPos = vec3(model * vec4(position, 1.0));
vs_out.Normal = transpose(inverse(mat3(model))) * normal;
vs_out.TexCoords = texCoords;
vs_out.FragPosLightSpace = lightSpaceMatrix * vec4(vs_out.FragPos, 1.0);
}

View File

@@ -1,6 +0,0 @@
#version 330 core
void main()
{
// gl_FragDepth = gl_FragCoord.z;
}

View File

@@ -1,10 +0,0 @@
#version 330 core
layout (location = 0) in vec3 position;
uniform mat4 lightSpaceMatrix;
uniform mat4 model;
void main()
{
gl_Position = lightSpaceMatrix * model * vec4(position, 1.0f);
}