From f95da5cccd50c5f33987ff0c0ac2dc0a56a4cbc6 Mon Sep 17 00:00:00 2001 From: Joey de Vries Date: Mon, 24 Apr 2017 22:57:05 +0200 Subject: [PATCH] Code re-work: SSAO --- src/5.advanced_lighting/9.ssao/9.ssao.fs | 11 +- src/5.advanced_lighting/9.ssao/9.ssao.vs | 8 +- src/5.advanced_lighting/9.ssao/9.ssao_blur.fs | 8 +- .../9.ssao/9.ssao_geometry.fs | 10 +- .../9.ssao/9.ssao_geometry.vs | 17 +- .../9.ssao/9.ssao_lighting.fs | 25 +- src/5.advanced_lighting/9.ssao/ssao.cpp | 558 +++++++++--------- 7 files changed, 306 insertions(+), 331 deletions(-) diff --git a/src/5.advanced_lighting/9.ssao/9.ssao.fs b/src/5.advanced_lighting/9.ssao/9.ssao.fs index e496924..7d31bfe 100644 --- a/src/5.advanced_lighting/9.ssao/9.ssao.fs +++ b/src/5.advanced_lighting/9.ssao/9.ssao.fs @@ -1,5 +1,6 @@ #version 330 core out float FragColor; + in vec2 TexCoords; uniform sampler2D gPosition; @@ -20,20 +21,20 @@ uniform mat4 projection; void main() { - // Get input for SSAO algorithm + // get input for SSAO algorithm vec3 fragPos = texture(gPosition, TexCoords).xyz; vec3 normal = normalize(texture(gNormal, TexCoords).rgb); vec3 randomVec = normalize(texture(texNoise, TexCoords * noiseScale).xyz); - // Create TBN change-of-basis matrix: from tangent-space to view-space + // create TBN change-of-basis matrix: from tangent-space to view-space vec3 tangent = normalize(randomVec - normal * dot(randomVec, normal)); vec3 bitangent = cross(normal, tangent); mat3 TBN = mat3(tangent, bitangent, normal); - // Iterate over the sample kernel and calculate occlusion factor + // iterate over the sample kernel and calculate occlusion factor float occlusion = 0.0; for(int i = 0; i < kernelSize; ++i) { // get sample position - vec3 sample = TBN * samples[i]; // From tangent to view-space + vec3 sample = TBN * samples[i]; // from tangent to view-space sample = fragPos + sample * radius; // project sample position (to sample texture) (to get position on screen/texture) @@ -43,7 +44,7 @@ void main() offset.xyz = offset.xyz * 0.5 + 0.5; // transform to range 0.0 - 1.0 // get sample depth - float sampleDepth = texture(gPosition, offset.xy).z; // Get depth value of kernel sample + float sampleDepth = texture(gPosition, offset.xy).z; // get depth value of kernel sample // range check & accumulate float rangeCheck = smoothstep(0.0, 1.0, radius / abs(fragPos.z - sampleDepth)); diff --git a/src/5.advanced_lighting/9.ssao/9.ssao.vs b/src/5.advanced_lighting/9.ssao/9.ssao.vs index 819c18d..9f93e29 100644 --- a/src/5.advanced_lighting/9.ssao/9.ssao.vs +++ b/src/5.advanced_lighting/9.ssao/9.ssao.vs @@ -1,11 +1,11 @@ #version 330 core -layout (location = 0) in vec3 position; -layout (location = 1) in vec2 texCoords; +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec2 aTexCoords; out vec2 TexCoords; void main() { - gl_Position = vec4(position, 1.0f); - TexCoords = texCoords; + TexCoords = aTexCoords; + gl_Position = vec4(aPos, 1.0); } \ No newline at end of file diff --git a/src/5.advanced_lighting/9.ssao/9.ssao_blur.fs b/src/5.advanced_lighting/9.ssao/9.ssao_blur.fs index d4d802e..5b28d84 100644 --- a/src/5.advanced_lighting/9.ssao/9.ssao_blur.fs +++ b/src/5.advanced_lighting/9.ssao/9.ssao_blur.fs @@ -1,10 +1,12 @@ #version 330 core +out float FragColor; + in vec2 TexCoords; -out float fragColor; uniform sampler2D ssaoInput; -void main() { +void main() +{ vec2 texelSize = 1.0 / vec2(textureSize(ssaoInput, 0)); float result = 0.0; for (int x = -2; x < 2; ++x) @@ -15,5 +17,5 @@ void main() { result += texture(ssaoInput, TexCoords + offset).r; } } - fragColor = result / (4.0 * 4.0); + FragColor = result / (4.0 * 4.0); } \ No newline at end of file diff --git a/src/5.advanced_lighting/9.ssao/9.ssao_geometry.fs b/src/5.advanced_lighting/9.ssao/9.ssao_geometry.fs index 3213cc4..b4c0fb8 100644 --- a/src/5.advanced_lighting/9.ssao/9.ssao_geometry.fs +++ b/src/5.advanced_lighting/9.ssao/9.ssao_geometry.fs @@ -1,7 +1,7 @@ #version 330 core layout (location = 0) out vec3 gPosition; layout (location = 1) out vec3 gNormal; -layout (location = 2) out vec4 gAlbedoSpec; +layout (location = 2) out vec3 gAlbedo; in vec2 TexCoords; in vec3 FragPos; @@ -9,10 +9,10 @@ in vec3 Normal; void main() { - // Store the fragment position vector in the first gbuffer texture + // store the fragment position vector in the first gbuffer texture gPosition = FragPos; - // Also store the per-fragment normals into the gbuffer + // also store the per-fragment normals into the gbuffer gNormal = normalize(Normal); - // And the diffuse per-fragment color - gAlbedoSpec.rgb = vec3(0.95); + // and the diffuse per-fragment color + gAlbedo.rgb = vec3(0.95); } \ No newline at end of file diff --git a/src/5.advanced_lighting/9.ssao/9.ssao_geometry.vs b/src/5.advanced_lighting/9.ssao/9.ssao_geometry.vs index 14d8450..e69c065 100644 --- a/src/5.advanced_lighting/9.ssao/9.ssao_geometry.vs +++ b/src/5.advanced_lighting/9.ssao/9.ssao_geometry.vs @@ -1,23 +1,26 @@ #version 330 core -layout (location = 0) in vec3 position; -layout (location = 1) in vec3 normal; -layout (location = 2) in vec2 texCoords; +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 2) in vec2 aTexCoords; out vec3 FragPos; out vec2 TexCoords; out vec3 Normal; +uniform bool invertedNormals; + uniform mat4 model; uniform mat4 view; uniform mat4 projection; void main() { - vec4 viewPos = view * model * vec4(position, 1.0f); + vec4 viewPos = view * model * vec4(aPos, 1.0); FragPos = viewPos.xyz; - gl_Position = projection * viewPos; - TexCoords = texCoords; + TexCoords = aTexCoords; mat3 normalMatrix = transpose(inverse(mat3(view * model))); - Normal = normalMatrix * normal; + Normal = normalMatrix * (invertedNormals ? -aNormal : aNormal); + + gl_Position = projection * viewPos; } \ No newline at end of file diff --git a/src/5.advanced_lighting/9.ssao/9.ssao_lighting.fs b/src/5.advanced_lighting/9.ssao/9.ssao_lighting.fs index 74156b2..f0dbc1b 100644 --- a/src/5.advanced_lighting/9.ssao/9.ssao_lighting.fs +++ b/src/5.advanced_lighting/9.ssao/9.ssao_lighting.fs @@ -1,5 +1,6 @@ #version 330 core out vec4 FragColor; + in vec2 TexCoords; uniform sampler2D gPosition; @@ -13,44 +14,34 @@ struct Light { float Linear; float Quadratic; - float Radius; }; uniform Light light; -uniform int draw_mode; void main() { - // Retrieve data from gbuffer + // retrieve data from gbuffer vec3 FragPos = texture(gPosition, TexCoords).rgb; vec3 Normal = texture(gNormal, TexCoords).rgb; vec3 Diffuse = texture(gAlbedo, TexCoords).rgb; float AmbientOcclusion = texture(ssao, TexCoords).r; - // Then calculate lighting as usual + // then calculate lighting as usual vec3 ambient = vec3(0.3 * Diffuse * AmbientOcclusion); vec3 lighting = ambient; - vec3 viewDir = normalize(-FragPos); // Viewpos is (0.0.0) - // Diffuse + vec3 viewDir = normalize(-FragPos); // viewpos is (0.0.0) + // diffuse vec3 lightDir = normalize(light.Position - FragPos); vec3 diffuse = max(dot(Normal, lightDir), 0.0) * Diffuse * light.Color; - // Specular + // specular vec3 halfwayDir = normalize(lightDir + viewDir); float spec = pow(max(dot(Normal, halfwayDir), 0.0), 8.0); vec3 specular = light.Color * spec; - // Attenuation + // attenuation float distance = length(light.Position - FragPos); float attenuation = 1.0 / (1.0 + light.Linear * distance + light.Quadratic * distance * distance); diffuse *= attenuation; specular *= attenuation; lighting += diffuse + specular; - // Based on which of the 1-5 keys we pressed, show specific buffer values - if(draw_mode == 1) - FragColor = vec4(lighting, 1.0); - else if(draw_mode == 2) - FragColor = vec4(FragPos, 1.0); - else if(draw_mode == 3) - FragColor = vec4(Normal, 1.0); - else if(draw_mode == 4) - FragColor = vec4(vec3(AmbientOcclusion), 1.0); + FragColor = vec4(lighting, 1.0); } diff --git a/src/5.advanced_lighting/9.ssao/ssao.cpp b/src/5.advanced_lighting/9.ssao/ssao.cpp index 4937927..f9175b5 100644 --- a/src/5.advanced_lighting/9.ssao/ssao.cpp +++ b/src/5.advanced_lighting/9.ssao/ssao.cpp @@ -1,118 +1,101 @@ -// GLEW -#define GLEW_STATIC -#include - -// GLFW +#include #include -// GL includes -#include -#include -#include - -// GLM Mathemtics #include #include #include -// Other Libs -#include - -#include // necessary for generation of random floats (for sample kernel and noise texture) #include +#include +#include +#include -// Properties -const GLuint SCR_WIDTH = 1280, SCR_HEIGHT = 720; +#include +#include -// Function prototypes -void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode); -void scroll_callback(GLFWwindow* window, double xoffset, double yoffset); +void framebuffer_size_callback(GLFWwindow* window, int width, int height); void mouse_callback(GLFWwindow* window, double xpos, double ypos); -void Do_Movement(); -void RenderCube(); -void RenderQuad(); +void scroll_callback(GLFWwindow* window, double xoffset, double yoffset); +void processInput(GLFWwindow *window); +unsigned int loadTexture(const char *path, bool gammaCorrection); +void renderQuad(); +void renderCube(); -// Camera +// settings +const unsigned int SCR_WIDTH = 1280; +const unsigned int SCR_HEIGHT = 720; + +// camera Camera camera(glm::vec3(0.0f, 0.0f, 5.0f)); +float lastX = (float)SCR_WIDTH / 2.0; +float lastY = (float)SCR_HEIGHT / 2.0; +bool firstMouse = true; -// Delta -GLfloat deltaTime = 0.0f; -GLfloat lastFrame = 0.0f; +// timing +float deltaTime = 0.0f; +float lastFrame = 0.0f; -// Options -GLuint draw_mode = 1; - -GLfloat lerp(GLfloat a, GLfloat b, GLfloat f) +float lerp(float a, float b, float f) { return a + f * (b - a); } -// The MAIN function, from here we start our application and run our Game loop int main() { - // Init GLFW + // glfw: initialize and configure + // ------------------------------ glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); - GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", nullptr, nullptr); // Windowed + // glfw window creation + // -------------------- + GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL); glfwMakeContextCurrent(window); - - // Set the required callback functions - glfwSetKeyCallback(window, key_callback); + if (window == NULL) + { + std::cout << "Failed to create GLFW window" << std::endl; + glfwTerminate(); + return -1; + } + glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); glfwSetCursorPosCallback(window, mouse_callback); glfwSetScrollCallback(window, scroll_callback); - // Options + // tell GLFW to capture our mouse glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); - // Initialize GLEW to setup the OpenGL Function pointers - glewExperimental = GL_TRUE; - glewInit(); - glGetError(); + // glad: load all OpenGL function pointers + // --------------------------------------- + if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) + { + std::cout << "Failed to initialize GLAD" << std::endl; + return -1; + } - // Define the viewport dimensions - glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT); - - // Setup some OpenGL options + // configure global opengl state + // ----------------------------- glEnable(GL_DEPTH_TEST); - // Setup and compile our shaders - Shader shaderGeometryPass("ssao_geometry.vs", "ssao_geometry.frag"); - Shader shaderLightingPass("ssao.vs", "ssao_lighting.frag"); - Shader shaderSSAO("ssao.vs", "ssao.frag"); - Shader shaderSSAOBlur("ssao.vs", "ssao_blur.frag"); + // build and compile shaders + // ------------------------- + Shader shaderGeometryPass("9.ssao_geometry.vs", "9.ssao_geometry.fs"); + Shader shaderLightingPass("9.ssao.vs", "9.ssao_lighting.fs"); + Shader shaderSSAO("9.ssao.vs", "9.ssao.fs"); + Shader shaderSSAOBlur("9.ssao.vs", "9.ssao_blur.fs"); - // Set samplers - shaderLightingPass.Use(); - glUniform1i(glGetUniformLocation(shaderLightingPass.Program, "gPosition"), 0); - glUniform1i(glGetUniformLocation(shaderLightingPass.Program, "gNormal"), 1); - glUniform1i(glGetUniformLocation(shaderLightingPass.Program, "gAlbedo"), 2); - glUniform1i(glGetUniformLocation(shaderLightingPass.Program, "ssao"), 3); - shaderSSAO.Use(); - glUniform1i(glGetUniformLocation(shaderSSAO.Program, "gPosition"), 0); - glUniform1i(glGetUniformLocation(shaderSSAO.Program, "gNormal"), 1); - glUniform1i(glGetUniformLocation(shaderSSAO.Program, "texNoise"), 2); + // load models + // ----------- + Model nanosuit(FileSystem::getPath("resources/objects/nanosuit/nanosuit.obj")); - // Objects - Model nanosuit(FileSystem::getPath("resources/objects/nanosuit/nanosuit.obj").c_str()); - - // Lights - glm::vec3 lightPos = glm::vec3(2.0, 4.0, -2.0); - glm::vec3 lightColor = glm::vec3(0.2, 0.2, 0.7); - - // Set up G-Buffer - // 3 textures: - // 1. Positions (RGB) - // 2. Color (RGB) - // 3. Normals (RGB) - GLuint gBuffer; + // configure g-buffer framebuffer + // ------------------------------ + unsigned int gBuffer; glGenFramebuffers(1, &gBuffer); glBindFramebuffer(GL_FRAMEBUFFER, gBuffer); - GLuint gPosition, gNormal, gAlbedo; - // - Position buffer + unsigned int gPosition, gNormal, gAlbedo; + // position color buffer glGenTextures(1, &gPosition); glBindTexture(GL_TEXTURE_2D, gPosition); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_FLOAT, NULL); @@ -121,39 +104,41 @@ int main() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gPosition, 0); - // - Normal color buffer + // normal color buffer glGenTextures(1, &gNormal); glBindTexture(GL_TEXTURE_2D, gNormal); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, gNormal, 0); - // - Albedo color buffer + // color + specular color buffer glGenTextures(1, &gAlbedo); glBindTexture(GL_TEXTURE_2D, gAlbedo); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGBA, GL_FLOAT, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, gAlbedo, 0); - // - Tell OpenGL which color attachments we'll use (of this framebuffer) for rendering - GLuint attachments[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 }; + // tell OpenGL which color attachments we'll use (of this framebuffer) for rendering + unsigned int attachments[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 }; glDrawBuffers(3, attachments); - // - Create and attach depth buffer (renderbuffer) - GLuint rboDepth; + // create and attach depth buffer (renderbuffer) + unsigned int rboDepth; glGenRenderbuffers(1, &rboDepth); glBindRenderbuffer(GL_RENDERBUFFER, rboDepth); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, SCR_WIDTH, SCR_HEIGHT); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboDepth); - // - Finally check if framebuffer is complete + // finally check if framebuffer is complete if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - std::cout << "GBuffer Framebuffer not complete!" << std::endl; + std::cout << "Framebuffer not complete!" << std::endl; + glBindFramebuffer(GL_FRAMEBUFFER, 0); - // Also create framebuffer to hold SSAO processing stage - GLuint ssaoFBO, ssaoBlurFBO; + // also create framebuffer to hold SSAO processing stage + // ----------------------------------------------------- + unsigned int ssaoFBO, ssaoBlurFBO; glGenFramebuffers(1, &ssaoFBO); glGenFramebuffers(1, &ssaoBlurFBO); glBindFramebuffer(GL_FRAMEBUFFER, ssaoFBO); - GLuint ssaoColorBuffer, ssaoColorBufferBlur; - // - SSAO color buffer + unsigned int ssaoColorBuffer, ssaoColorBufferBlur; + // SSAO color buffer glGenTextures(1, &ssaoColorBuffer); glBindTexture(GL_TEXTURE_2D, ssaoColorBuffer); glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_FLOAT, NULL); @@ -162,7 +147,7 @@ int main() glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ssaoColorBuffer, 0); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) std::cout << "SSAO Framebuffer not complete!" << std::endl; - // - and blur stage + // and blur stage glBindFramebuffer(GL_FRAMEBUFFER, ssaoBlurFBO); glGenTextures(1, &ssaoColorBufferBlur); glBindTexture(GL_TEXTURE_2D, ssaoColorBufferBlur); @@ -174,31 +159,33 @@ int main() std::cout << "SSAO Blur Framebuffer not complete!" << std::endl; glBindFramebuffer(GL_FRAMEBUFFER, 0); - // Sample kernel + // generate sample kernel + // ---------------------- std::uniform_real_distribution randomFloats(0.0, 1.0); // generates random floats between 0.0 and 1.0 std::default_random_engine generator; std::vector ssaoKernel; - for (GLuint i = 0; i < 64; ++i) + for (unsigned int i = 0; i < 64; ++i) { glm::vec3 sample(randomFloats(generator) * 2.0 - 1.0, randomFloats(generator) * 2.0 - 1.0, randomFloats(generator)); sample = glm::normalize(sample); sample *= randomFloats(generator); - GLfloat scale = GLfloat(i) / 64.0; + float scale = float(i) / 64.0; - // Scale samples s.t. they're more aligned to center of kernel + // scale samples s.t. they're more aligned to center of kernel scale = lerp(0.1f, 1.0f, scale * scale); sample *= scale; ssaoKernel.push_back(sample); } - // Noise texture + // generate noise texture + // ---------------------- std::vector ssaoNoise; - for (GLuint i = 0; i < 16; i++) + for (unsigned int i = 0; i < 16; i++) { glm::vec3 noise(randomFloats(generator) * 2.0 - 1.0, randomFloats(generator) * 2.0 - 1.0, 0.0f); // rotate around z-axis (in tangent space) ssaoNoise.push_back(noise); } - GLuint noiseTexture; glGenTextures(1, &noiseTexture); + unsigned int noiseTexture; glGenTextures(1, &noiseTexture); glBindTexture(GL_TEXTURE_2D, noiseTexture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, 4, 4, 0, GL_RGB, GL_FLOAT, &ssaoNoise[0]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -206,285 +193,274 @@ int main() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + // lighting info + // ------------- + glm::vec3 lightPos = glm::vec3(2.0, 4.0, -2.0); + glm::vec3 lightColor = glm::vec3(0.2, 0.2, 0.7); - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + // shader configuration + // -------------------- + shaderLightingPass.use(); + shaderLightingPass.setInt("gPosition", 0); + shaderLightingPass.setInt("gNormal", 1); + shaderLightingPass.setInt("gAlbedo", 2); + shaderLightingPass.setInt("ssao", 3); + shaderSSAO.use(); + shaderSSAO.setInt("gPosition", 0); + shaderSSAO.setInt("gNormal", 1); + shaderSSAO.setInt("texNoise", 2); + shaderSSAOBlur.use(); + shaderSSAOBlur.setInt("ssaoInput", 0); - // Game loop + // render loop + // ----------- while (!glfwWindowShouldClose(window)) { - // Set frame time - GLfloat currentFrame = glfwGetTime(); + // per-frame time logic + // -------------------- + float currentFrame = glfwGetTime(); deltaTime = currentFrame - lastFrame; lastFrame = currentFrame; - // Check and call events - glfwPollEvents(); - Do_Movement(); + // input + // ----- + processInput(window); - // 1. Geometry Pass: render scene's geometry/color data into gbuffer + // render + // ------ + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // 1. geometry pass: render scene's geometry/color data into gbuffer + // ----------------------------------------------------------------- glBindFramebuffer(GL_FRAMEBUFFER, gBuffer); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (GLfloat)SCR_WIDTH / (GLfloat)SCR_HEIGHT, 0.1f, 50.0f); + glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 50.0f); glm::mat4 view = camera.GetViewMatrix(); glm::mat4 model; - shaderGeometryPass.Use(); - glUniformMatrix4fv(glGetUniformLocation(shaderGeometryPass.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); - glUniformMatrix4fv(glGetUniformLocation(shaderGeometryPass.Program, "view"), 1, GL_FALSE, glm::value_ptr(view)); - // Background cubes - // Note that AO doesn't work too well on flat surfaces so simply scaling the cube as the background room wouldn't work - // as the resulting faces of the cube are completely flat. - model = glm::translate(model, glm::vec3(10.0f, 0.0f, 0.0f)); - model = glm::scale(model, glm::vec3(1.0f, 20.0f, 20.0f)); - glUniformMatrix4fv(glGetUniformLocation(shaderGeometryPass.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); - RenderCube(); + shaderGeometryPass.use(); + shaderGeometryPass.setMat4("projection", projection); + shaderGeometryPass.setMat4("view", view); + // room cube model = glm::mat4(); - model = glm::translate(model, glm::vec3(-10.0f, 0.0f, 0.0f)); - model = glm::scale(model, glm::vec3(1.0f, 20.0f, 20.0f)); - glUniformMatrix4fv(glGetUniformLocation(shaderGeometryPass.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); - RenderCube(); - model = glm::mat4(); - model = glm::translate(model, glm::vec3(0.0f, 0.0f, 10.0f)); - model = glm::scale(model, glm::vec3(20.0f, 20.0f, 1.0f)); - glUniformMatrix4fv(glGetUniformLocation(shaderGeometryPass.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); - RenderCube(); - model = glm::mat4(); - model = glm::translate(model, glm::vec3(0.0f, 0.0f, -10.0f)); - model = glm::scale(model, glm::vec3(20.0f, 20.0f, 1.0f)); - glUniformMatrix4fv(glGetUniformLocation(shaderGeometryPass.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); - RenderCube(); - model = glm::mat4(); - model = glm::translate(model, glm::vec3(0.0f, 10.0f, 0.0f)); - model = glm::scale(model, glm::vec3(20.0f, 1.0f, 20.0f)); - glUniformMatrix4fv(glGetUniformLocation(shaderGeometryPass.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); - RenderCube(); - // Floor cube - model = glm::mat4(); - model = glm::translate(model, glm::vec3(0.0, -1.0f, 0.0f)); - model = glm::scale(model, glm::vec3(20.0f, 1.0f, 20.0f)); - glUniformMatrix4fv(glGetUniformLocation(shaderGeometryPass.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); - RenderCube(); - // Nanosuit model on the floor + model = glm::translate(model, glm::vec3(0.0, 7.0f, 0.0f)); + model = glm::scale(model, glm::vec3(7.5f, 7.5f, 7.5f)); + shaderGeometryPass.setMat4("model", model); + shaderGeometryPass.setInt("invertedNormals", 1); // invert normals as we're inside the cube + renderCube(); + shaderGeometryPass.setInt("invertedNormals", 0); + // nanosuit model on the floor model = glm::mat4(); model = glm::translate(model, glm::vec3(0.0f, 0.0f, 5.0)); model = glm::rotate(model, glm::radians(-90.0f), glm::vec3(1.0, 0.0, 0.0)); model = glm::scale(model, glm::vec3(0.5f)); - glUniformMatrix4fv(glGetUniformLocation(shaderGeometryPass.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); + shaderGeometryPass.setMat4("model", model); nanosuit.Draw(shaderGeometryPass); glBindFramebuffer(GL_FRAMEBUFFER, 0); - // 2. Create SSAO texture + // 2. generate SSAO texture + // ------------------------ glBindFramebuffer(GL_FRAMEBUFFER, ssaoFBO); glClear(GL_COLOR_BUFFER_BIT); - shaderSSAO.Use(); + shaderSSAO.use(); + // Send kernel + rotation + for (unsigned int i = 0; i < 64; ++i) + shaderSSAO.setVec3("samples[" + std::to_string(i) + "]", ssaoKernel[i]); + shaderSSAO.setMat4("projection", projection); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, gPosition); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, gNormal); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, noiseTexture); - // Send kernel + rotation - for (GLuint i = 0; i < 64; ++i) - glUniform3fv(glGetUniformLocation(shaderSSAO.Program, ("samples[" + std::to_string(i) + "]").c_str()), 1, &ssaoKernel[i][0]); - glUniformMatrix4fv(glGetUniformLocation(shaderSSAO.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); - RenderQuad(); + renderQuad(); glBindFramebuffer(GL_FRAMEBUFFER, 0); - // 3. Blur SSAO texture to remove noise + // 3. blur SSAO texture to remove noise + // ------------------------------------ glBindFramebuffer(GL_FRAMEBUFFER, ssaoBlurFBO); glClear(GL_COLOR_BUFFER_BIT); - shaderSSAOBlur.Use(); + shaderSSAOBlur.use(); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, ssaoColorBuffer); - RenderQuad(); + renderQuad(); glBindFramebuffer(GL_FRAMEBUFFER, 0); - // 4. Lighting Pass: traditional deferred Blinn-Phong lighting now with added screen-space ambient occlusion + // 4. lighting pass: traditional deferred Blinn-Phong lighting with added screen-space ambient occlusion + // ----------------------------------------------------------------------------------------------------- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - shaderLightingPass.Use(); + shaderLightingPass.use(); + // send light relevant uniforms + glm::vec3 lightPosView = glm::vec3(camera.GetViewMatrix() * glm::vec4(lightPos, 1.0)); + shaderLightingPass.setVec3("light.Position", lightPosView); + shaderLightingPass.setVec3("light.Color", lightColor); + // Update attenuation parameters + const float constant = 1.0; // note that we don't send this to the shader, we assume it is always 1.0 (in our case) + const float linear = 0.09; + const float quadratic = 0.032; + shaderLightingPass.setFloat("light.Linear", linear); + shaderLightingPass.setFloat("light.Quadratic", quadratic); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, gPosition); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, gNormal); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, gAlbedo); - glActiveTexture(GL_TEXTURE3); // Add extra SSAO texture to lighting pass + glActiveTexture(GL_TEXTURE3); // add extra SSAO texture to lighting pass glBindTexture(GL_TEXTURE_2D, ssaoColorBufferBlur); - // Also send light relevant uniforms - glm::vec3 lightPosView = glm::vec3(camera.GetViewMatrix() * glm::vec4(lightPos, 1.0)); - glUniform3fv(glGetUniformLocation(shaderLightingPass.Program, "light.Position"), 1, &lightPosView[0]); - glUniform3fv(glGetUniformLocation(shaderLightingPass.Program, "light.Color"), 1, &lightColor[0]); - // Update attenuation parameters - const GLfloat constant = 1.0; // Note that we don't send this to the shader, we assume it is always 1.0 (in our case) - const GLfloat linear = 0.09; - const GLfloat quadratic = 0.032; - glUniform1f(glGetUniformLocation(shaderLightingPass.Program, "light.Linear"), linear); - glUniform1f(glGetUniformLocation(shaderLightingPass.Program, "light.Quadratic"), quadratic); - glUniform1i(glGetUniformLocation(shaderLightingPass.Program, "draw_mode"), draw_mode); - RenderQuad(); + renderQuad(); - // Swap the buffers + // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.) + // ------------------------------------------------------------------------------- glfwSwapBuffers(window); + glfwPollEvents(); } glfwTerminate(); return 0; } +// renderCube() renders a 1x1 3D cube in NDC. +// ------------------------------------------------- +unsigned int cubeVAO = 0; +unsigned int cubeVBO = 0; +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 quad in NDC, best used for framebuffer color targets -// and post-processing effects. -GLuint quadVAO = 0; -GLuint quadVBO; -void RenderQuad() + +// renderQuad() renders a 1x1 XY quad in NDC +// ----------------------------------------- +unsigned int quadVAO = 0; +unsigned int quadVBO; +void renderQuad() { if (quadVAO == 0) { - GLfloat quadVertices[] = { - // Positions // Texture Coords + float quadVertices[] = { + // positions // texture Coords -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, }; - // Setup plane VAO + // setup plane VAO glGenVertexArrays(1, &quadVAO); glGenBuffers(1, &quadVBO); glBindVertexArray(quadVAO); glBindBuffer(GL_ARRAY_BUFFER, quadVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW); glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); 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); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glBindVertexArray(0); } -// RenderCube() Renders a 1x1 3D cube in NDC. -GLuint cubeVAO = 0; -GLuint cubeVBO = 0; -void RenderCube() +// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly +// --------------------------------------------------------------------------------------------------------- +void processInput(GLFWwindow *window) { - // Initialize (if necessary) - if (cubeVAO == 0) - { - GLfloat vertices[] = { - // Back face - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, // Bottom-left - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, // top-right - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, // bottom-right - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, // top-right - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, // bottom-left - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f,// top-left - // Front face - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom-left - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, // bottom-right - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // top-right - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // top-right - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, // top-left - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom-left - // Left face - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-right - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top-left - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-left - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-left - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom-right - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-right - // Right face - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-left - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-right - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top-right - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-right - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-left - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom-left - // Bottom face - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, // top-right - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, // top-left - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f,// bottom-left - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom-left - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, // bottom-right - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, // top-right - // Top face - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,// top-left - 0.5f, 0.5f , 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom-right - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, // top-right - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom-right - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,// top-left - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f // bottom-left - }; - 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); -} + if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) + glfwSetWindowShouldClose(window, true); -bool keys[1024]; -bool keysPressed[1024]; -// Moves/alters the camera positions based on user input -void Do_Movement() -{ - // Camera controls - if (keys[GLFW_KEY_W]) + float cameraSpeed = 2.5 * deltaTime; + if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) camera.ProcessKeyboard(FORWARD, deltaTime); - if (keys[GLFW_KEY_S]) + if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) camera.ProcessKeyboard(BACKWARD, deltaTime); - if (keys[GLFW_KEY_A]) + if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) camera.ProcessKeyboard(LEFT, deltaTime); - if (keys[GLFW_KEY_D]) + if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) camera.ProcessKeyboard(RIGHT, deltaTime); - - if (keys[GLFW_KEY_1]) - draw_mode = 1; - if (keys[GLFW_KEY_2]) - draw_mode = 2; - if (keys[GLFW_KEY_3]) - draw_mode = 3; - if (keys[GLFW_KEY_4]) - draw_mode = 4; } -GLfloat lastX = 400, lastY = 300; -bool firstMouse = true; -// Is called whenever a key is pressed/released via GLFW -void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) +// glfw: whenever the window size changed (by OS or user resize) this callback function executes +// --------------------------------------------------------------------------------------------- +void framebuffer_size_callback(GLFWwindow* window, int width, int height) { - if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) - glfwSetWindowShouldClose(window, GL_TRUE); - - if (key >= 0 && key <= 1024) - { - if (action == GLFW_PRESS) - keys[key] = true; - else if (action == GLFW_RELEASE) - { - keys[key] = false; - keysPressed[key] = false; - } - } + // make sure the viewport matches the new window dimensions; note that width and + // height will be significantly larger than specified on retina displays. + glViewport(0, 0, width, height); } + +// glfw: whenever the mouse moves, this callback is called +// ------------------------------------------------------- void mouse_callback(GLFWwindow* window, double xpos, double ypos) { if (firstMouse) @@ -494,8 +470,8 @@ void mouse_callback(GLFWwindow* window, double xpos, double ypos) firstMouse = false; } - GLfloat xoffset = xpos - lastX; - GLfloat yoffset = lastY - ypos; + float xoffset = xpos - lastX; + float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top lastX = xpos; lastY = ypos; @@ -503,6 +479,8 @@ void mouse_callback(GLFWwindow* window, double xpos, double ypos) camera.ProcessMouseMovement(xoffset, yoffset); } +// glfw: whenever the mouse scroll wheel scrolls, this callback is called +// ---------------------------------------------------------------------- void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) { camera.ProcessMouseScroll(yoffset);