int main() { _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); // ======================================================= // INITIALIZE // ======================================================= 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(800, 600, "OpenGl Program", nullptr, nullptr); if (window == nullptr) { printf("Failed to create GLFW window\n"); glfwTerminate(); return false; } glfwMakeContextCurrent(window); glewExperimental = GL_TRUE; if (glewInit() != GLEW_OK) { printf("Failed to initialize GLEW\n"); return false; } glViewport(0, 0, WIDTH, HEIGHT); glEnable(GL_DEPTH_TEST); glfwSetKeyCallback(window, Key_callback); glfwSetCursorPosCallback(window, mouse_callback); glfwSetScrollCallback(window, scroll_callback); // Build and compile our shader program Shader lightingShader("../Data/Shaders/vertexShaderLighting_nano.vs", "../Data/Shaders/fragmentShaderLighting_nano.frag", 2); Shader lampShader("../Data/Shaders/vertexShaderLighting_Lamp.vs", "../Data/Shaders/fragmentShaderLighting_Lamp.frag", 0); // set the application to capture the cursor glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); glm::vec3 pointLightPositions[] = { glm::vec3(2.0f, 0.0f, 2.0f), glm::vec3(-2.0f, 0.0f, -2.0f), }; DirLight dirlight(lightingShader, vect3(-0.2f, -1.0f, -0.3f), vect3(255, 255, 255), 0.5f); PointLight pointLight1(lightingShader, pointLightPositions[0], vect3(255, 255, 255), 0.5f); PointLight pointLight2(lightingShader, pointLightPositions[1], vect3(255, 255, 255), 0.5f); //PointLight pointLight3(lightingShader, pointLightPositions[2], vect3(255, 255, 255), 1.0f); //PointLight pointLight4(lightingShader, pointLightPositions[3], vect3(255, 255, 255), 1.0f); SpotLight spotLight(lightingShader, MainCamera.Position, MainCamera.Front, vect3(255, 255, 255), 1.0f); GLfloat time = glfwGetTime(); Model nanosuit("../Data/Models/Box/OutPutModel.txt"); time = glfwGetTime() - time; printf("Time to load: %f", time); nanosuit.SetPosition(glm::vec3(0.0f, 0.0f, 0.0f)); // ======================================================= // MAIN UPDATE LOOP // ======================================================= //float count = 0; //GLfloat time = 0; while (!glfwWindowShouldClose(window)) { // Update deltaTime GLfloat currentFrame = glfwGetTime(); deltaTime = currentFrame - lastFrame; lastFrame = currentFrame; // FPS check //if (time >= 1.0f) //{ // printf("FPS: %f", count); // time = 0; // count = 0; //} // check and call events glfwPollEvents(); UpdateCamera(); // Rendering commands here //glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClearColor(0.1f, 0.1f, 0.1f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // draw triangle lightingShader.Use(); GLint viewPosLoc = lightingShader.GetUniformLocation("viewPos"); glUniform3f(viewPosLoc, MainCamera.Position.x, MainCamera.Position.y, MainCamera.Position.z); // Directional light dirlight.Update(); // Point lights pointLight1.Update(0); pointLight2.Update(1); // SpotLight spotLight.SetPosDir(MainCamera.Position, MainCamera.Front); spotLight.Update(); // Camera/View transformation glm::mat4 view; view = MainCamera.GetViewMatrix(); // set the projection matrix (perspective) glm::mat4 projectionMatrix; // FOV, aspect ratio, near plane, far plane projectionMatrix = glm::perspective(glm::radians(MainCamera.Zoom), (GLfloat)WIDTH / (GLfloat)HEIGHT, 0.1f, farPlane); // specify matrices GLint modelLoc = lightingShader.GetUniformLocation("modelMat"); GLint viewLoc = lightingShader.GetUniformLocation("viewMat"); glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view)); GLint projLoc = lightingShader.GetUniformLocation("projectionMat"); glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projectionMatrix)); //glm::mat4 model; //model = glm::translate(model, glm::vec3(0, -1.75f, 0.0f)); // Translate it down a bit so it's at the center of the scene //model += glm::translate(model, glm::vec3(0.2f, 0.0f, 0.0f)); //model = glm::scale(model, glm::vec3(0.2f, 0.2f, 0.2f)); // It's a bit too big for our scene, so scale it down //glUniformMatrix4fv(glGetUniformLocation(lightingShader.Program, "modelMat"), 1, GL_FALSE, glm::value_ptr(model)); nanosuit.Draw(lightingShader); // Swap the buffers glfwSwapBuffers(window); } // ======================================================= // CLEANUP // ======================================================= glfwTerminate(); return 0; }
int main() { // 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); // glfw window creation // -------------------- GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL); if (window == NULL) { std::cout << "Failed to create GLFW window" << std::endl; glfwTerminate(); return -1; } glfwMakeContextCurrent(window); glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); glfwSetCursorPosCallback(window, mouse_callback); glfwSetScrollCallback(window, scroll_callback); // tell GLFW to capture our mouse glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); // glad: load all OpenGL function pointers // --------------------------------------- if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { std::cout << "Failed to initialize GLAD" << std::endl; return -1; } // configure global opengl state // ----------------------------- glEnable(GL_DEPTH_TEST); // build and compile shaders // ------------------------- Shader shader("9.2.geometry_shader.vs", "9.2.geometry_shader.fs", "9.2.geometry_shader.gs"); // load models // ----------- Model nanosuit(FileSystem::getPath("resources/objects/nanosuit/nanosuit.obj")); // render loop // ----------- while (!glfwWindowShouldClose(window)) { // per-frame time logic // -------------------- float currentFrame = glfwGetTime(); deltaTime = currentFrame - lastFrame; lastFrame = currentFrame; // input // ----- processInput(window); // render // ------ glClearColor(0.1f, 0.1f, 0.1f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // configure transformation matrices glm::mat4 projection = glm::perspective(glm::radians(45.0f), (float)SCR_WIDTH / (float)SCR_HEIGHT, 1.0f, 100.0f); glm::mat4 view = camera.GetViewMatrix();; glm::mat4 model; shader.use(); shader.setMat4("projection", projection); shader.setMat4("view", view); shader.setMat4("model", model); // add time component to geometry shader in the form of a uniform shader.setFloat("time", glfwGetTime()); // draw model nanosuit.Draw(shader); // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.) // ------------------------------------------------------------------------------- glfwSwapBuffers(window); glfwPollEvents(); } glfwTerminate(); return 0; }
// The MAIN function, from here we start our application and run our Game loop int main() { if(!glfwInit()){ return -1; } glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); auto window = glfwCreateWindow(WIDTH, HEIGHT, "Cube maps", nullptr, nullptr); if (nullptr == window) { std::cout << "Failed to create GLFW windows" << std::endl; glfwTerminate(); return -1; } glfwMakeContextCurrent(window); int actualWidth; int actualHeight; glfwGetFramebufferSize(window, &actualWidth, &actualHeight); glViewport(0, 0, actualWidth, actualHeight); // Set the required callback functions glfwSetKeyCallback(window, key_callback); glfwSetCursorPosCallback(window, mouse_callback); glfwSetScrollCallback(window, scroll_callback); // Options // glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); // Setup some OpenGL options glEnable(GL_DEPTH_TEST); // Setup and compile our shaders Shader shader("vertex.vsh", "fragment.fsh"); // Load models Model nanosuit("nanosuit/nanosuit.obj"); vector<const GLchar*> faces; faces.push_back("right.jpg"); faces.push_back("left.jpg"); faces.push_back("top.jpg"); faces.push_back("bottom.jpg"); faces.push_back("back.jpg"); faces.push_back("front.jpg"); GLuint cubemapTexture = loadCubemap(faces); GLfloat skyboxVertices[] = { // Positions -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f }; GLuint skyboxVAO; glGenVertexArrays(1, &skyboxVAO); glBindVertexArray(skyboxVAO); GLuint skyboxVBO; glGenBuffers(1, &skyboxVBO); glBindBuffer(GL_ARRAY_BUFFER, skyboxVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(0); glBindVertexArray(0); Shader skyboxShader("skybox.vsh", "skybox.fsh"); // Draw in wireframe //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // Game loop while(!glfwWindowShouldClose(window)) { // Set frame time GLfloat currentFrame = glfwGetTime(); deltaTime = currentFrame - lastFrame; lastFrame = currentFrame; // Check and call events glfwPollEvents(); Do_Movement(); // Clear the colorbuffer glClearColor(0.05f, 0.05f, 0.05f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Draw scene as normal shader.Use(); glm::mat4 model; model = glm::translate(model, glm::vec3(0.0f, -1.75f, 0.0f)); // Translate it down a bit so it's at the center of the scene model = glm::scale(model, glm::vec3(0.2f, 0.2f, 0.2f)); // It's a bit too big for our scene, so scale it down glm::mat4 view = camera.GetViewMatrix(); glm::mat4 projection = glm::perspective(camera.Zoom, (float)screenWidth/(float)screenHeight, 0.1f, 100.0f); glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); glUniformMatrix4fv(glGetUniformLocation(shader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view)); glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); glUniform3f(glGetUniformLocation(shader.Program, "cameraPos"), camera.Position.x, camera.Position.y, camera.Position.z); glActiveTexture(GL_TEXTURE3); // We already have 3 texture units active (in this shader) so set the skybox as the 4th texture unit (texture units are 0 based so index number 3) glUniform1i(glGetUniformLocation(shader.Program, "skybox"), 3); // Now draw the nanosuit glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexture); nanosuit.Draw(shader); glDepthFunc(GL_LEQUAL); skyboxShader.Use(); // Transformation matrices glUniformMatrix4fv(glGetUniformLocation(skyboxShader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); view = glm::mat4(glm::mat3(camera.GetViewMatrix())); glUniformMatrix4fv(glGetUniformLocation(skyboxShader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view)); glBindVertexArray(skyboxVAO); glActiveTexture(GL_TEXTURE0); glUniform1i(glGetUniformLocation(skyboxShader.Program, "skybox"), 0); glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexture); glDrawArrays(GL_TRIANGLES, 0, 36); glBindVertexArray(0); glDepthFunc(GL_LESS); // Swap the buffers glfwSwapBuffers(window); } glfwTerminate(); return 0; }
// The MAIN function, from here we start our application and run our Game loop int main() { // Init GLFW 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 glfwMakeContextCurrent(window); // Set the required callback functions glfwSetKeyCallback(window, key_callback); glfwSetCursorPosCallback(window, mouse_callback); glfwSetScrollCallback(window, scroll_callback); // Options glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); // Initialize GLEW to setup the OpenGL Function pointers glewExperimental = GL_TRUE; glewInit(); glGetError(); // Define the viewport dimensions glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT); // Setup some OpenGL options 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"); // Set samplers shaderLightingPass.Use(); glUniform1i(glGetUniformLocation(shaderLightingPass.Program, "gPositionDepth"), 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, "gPositionDepth"), 0); glUniform1i(glGetUniformLocation(shaderSSAO.Program, "gNormal"), 1); glUniform1i(glGetUniformLocation(shaderSSAO.Program, "texNoise"), 2); // 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 + depth (RGBA) // 2. Color (RGB) // 3. Normals (RGB) GLuint gBuffer; glGenFramebuffers(1, &gBuffer); glBindFramebuffer(GL_FRAMEBUFFER, gBuffer); GLuint gPositionDepth, gNormal, gAlbedo; // - Position + linear depth color buffer glGenTextures(1, &gPositionDepth); glBindTexture(GL_TEXTURE_2D, gPositionDepth); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, 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); 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, gPositionDepth, 0); // - Normal color buffer glGenTextures(1, &gNormal); glBindTexture(GL_TEXTURE_2D, gNormal); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 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 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); 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 }; glDrawBuffers(3, attachments); // - Create and attach depth buffer (renderbuffer) GLuint 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 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) std::cout << "GBuffer Framebuffer not complete!" << std::endl; // Also create framebuffer to hold SSAO processing stage GLuint ssaoFBO, ssaoBlurFBO; glGenFramebuffers(1, &ssaoFBO); glGenFramebuffers(1, &ssaoBlurFBO); glBindFramebuffer(GL_FRAMEBUFFER, ssaoFBO); GLuint 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); 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_ATTACHMENT0, GL_TEXTURE_2D, ssaoColorBuffer, 0); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) std::cout << "SSAO Framebuffer not complete!" << std::endl; // - and blur stage glBindFramebuffer(GL_FRAMEBUFFER, ssaoBlurFBO); glGenTextures(1, &ssaoColorBufferBlur); glBindTexture(GL_TEXTURE_2D, ssaoColorBufferBlur); glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 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_ATTACHMENT0, GL_TEXTURE_2D, ssaoColorBufferBlur, 0); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) std::cout << "SSAO Blur Framebuffer not complete!" << std::endl; glBindFramebuffer(GL_FRAMEBUFFER, 0); // Sample kernel std::uniform_real_distribution<GLfloat> randomFloats(0.0, 1.0); // generates random floats between 0.0 and 1.0 std::default_random_engine generator; std::vector<glm::vec3> ssaoKernel; for (GLuint 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; // 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 std::vector<glm::vec3> ssaoNoise; for (GLuint 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); glBindTexture(GL_TEXTURE_2D, noiseTexture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, 4, 4, 0, GL_RGB, GL_FLOAT, &ssaoNoise[0]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Game loop while (!glfwWindowShouldClose(window)) { // Set frame time GLfloat currentFrame = glfwGetTime(); deltaTime = currentFrame - lastFrame; lastFrame = currentFrame; // Check and call events glfwPollEvents(); Do_Movement(); // 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(camera.Zoom, (GLfloat)SCR_WIDTH / (GLfloat)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)); // Floor cube 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::mat4(); model = glm::translate(model, glm::vec3(0.0f, 0.0f, 5.0)); model = glm::rotate(model, -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)); nanosuit.Draw(shaderGeometryPass); glBindFramebuffer(GL_FRAMEBUFFER, 0); // 2. Create SSAO texture glBindFramebuffer(GL_FRAMEBUFFER, ssaoFBO); glClear(GL_COLOR_BUFFER_BIT); shaderSSAO.Use(); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, gPositionDepth); 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(); glBindFramebuffer(GL_FRAMEBUFFER, 0); // 3. Blur SSAO texture to remove noise glBindFramebuffer(GL_FRAMEBUFFER, ssaoBlurFBO); glClear(GL_COLOR_BUFFER_BIT); shaderSSAOBlur.Use(); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, ssaoColorBuffer); RenderQuad(); glBindFramebuffer(GL_FRAMEBUFFER, 0); // 4. Lighting Pass: traditional deferred Blinn-Phong lighting now with added screen-space ambient occlusion glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); shaderLightingPass.Use(); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, gPositionDepth); 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 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(); // Swap the buffers glfwSwapBuffers(window); } glfwTerminate(); return 0; }