#include "Renderer.h" #include #include #include #include #include #include #include #include #include #include "../Primitives/Scene.h" #include "../model.h" #include "../Utils.h" static enum class RenderPass { NONE = 0, SKYBOX, HDR_SKYBOX, DEFAULT, PBR }; const int num_passes = static_cast(RenderPass::DEFAULT) ; Texture* colourAttachment; glm::vec3 lightPositions[] = { glm::vec3(-10.0f, 10.0f, 10.0f), glm::vec3(10.0f, 10.0f, 10.0f), glm::vec3(-10.0f, -10.0f, 10.0f), glm::vec3(10.0f, -10.0f, 10.0f) }; glm::vec3 lightColors[] = { glm::vec3(300.0f, 300.0f, 300.0f), glm::vec3(300.0f, 300.0f, 300.0f), glm::vec3(300.0f, 300.0f, 300.0f), glm::vec3(300.0f, 300.0f, 300.0f) }; int nrRows = 7; int nrColumns = 7; float spacing = 2.5; unsigned int albedo; unsigned int normal; unsigned int metallic; unsigned int roughness; unsigned int ao; unsigned int cubeVAO = 0; unsigned int cubeVBO = 0; void renderCube() { 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); } unsigned int envCubemap; unsigned int envMapVAO; void Renderer::Setup() { // Create ScreenVAO glGenVertexArrays(1, &ScreenVAO); glBindVertexArray(ScreenVAO); glGenBuffers(1, &VBO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, ScreenVertices.size() * sizeof(float), &ScreenVertices[0], GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float))); glBindVertexArray(0); // Enable features glEnable(GL_DEPTH_TEST); glEnable(GL_STENCIL_TEST); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); glEnable(GL_MULTISAMPLE); // Load shaders shaders[static_cast(RenderPass::SKYBOX)] = Shader(); shaders[static_cast(RenderPass::SKYBOX)].Load("../Shaders/skybox.vs", "../Shaders/Cubemap.fs"); shaders[static_cast(RenderPass::HDR_SKYBOX)] = Shader(); shaders[static_cast(RenderPass::HDR_SKYBOX)].Load("../Shaders/HDRSkybox.vs", "../Shaders/HDRSkybox.fs"); shaders[static_cast(RenderPass::DEFAULT)] = Shader(); shaders[static_cast(RenderPass::DEFAULT)].Load("../Shaders/shader.vs", "../Shaders/shader.fs"); shaders[static_cast(RenderPass::PBR)] = Shader(); shaders[static_cast(RenderPass::PBR)].Load("../Shaders/pbr.vs", "../Shaders/pbr.fs"); albedo = TextureFromFile("../Textures/rusted_iron/albedo.png", "."); normal = TextureFromFile("../Textures/rusted_iron/normal.png", "."); metallic = TextureFromFile("../Textures/rusted_iron/metallic.png", "."); roughness = TextureFromFile("../Textures/rusted_iron/roughness.png", "."); ao = TextureFromFile("../Textures/rusted_iron/ao.png","."); // Create the skybox from an HDR equirectangular environment map unsigned int captureFBO, captureRBO; glGenFramebuffers(1, &captureFBO); glGenRenderbuffers(1, &captureRBO); glBindFramebuffer(GL_FRAMEBUFFER, captureFBO); glBindRenderbuffer(GL_RENDERBUFFER, captureRBO); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, 512, 512); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, captureRBO); glGenTextures(1, &envCubemap); glBindTexture(GL_TEXTURE_CUBE_MAP, envCubemap); for (unsigned int i = 0; i < 6; ++i) { glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, 512, 512, 0, GL_RGB, GL_FLOAT, nullptr); } glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glm::mat4 captureProjection = glm::perspective(glm::radians(90.0f), 1.0f, 0.1f, 10.0f); glm::mat4 captureViews[] = { glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f)), glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(-1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f)), glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)), glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f), glm::vec3(0.0f, 0.0f, -1.0f)), glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(0.0f, -1.0f, 0.0f)), glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, -1.0f), glm::vec3(0.0f, -1.0f, 0.0f)) }; auto eqShader = Shader(); eqShader.Load("../Shaders/HDRMap.vs", "../Shaders/HDRMap.fs"); auto hdrTexture = LoadIBL("../Textures/photostudio.hdr"); eqShader.use(); eqShader.setInt("equirectangularMap", 0); eqShader.setMat4("projection", captureProjection); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, hdrTexture); glViewport(0, 0, 512, 512); glBindFramebuffer(GL_FRAMEBUFFER, captureFBO); for (unsigned int i = 0; i < 6; ++i) { eqShader.setMat4("view", captureViews[i]); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, envCubemap, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); renderCube(); } glBindFramebuffer(GL_FRAMEBUFFER, 0); glViewport(0, 0, 800, 600); // restore viewport; std::vector m_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 }; unsigned int envMapVBO; glGenVertexArrays(1, &envMapVAO); glBindVertexArray(envMapVAO); glGenBuffers(1, &envMapVBO); glBindBuffer(GL_ARRAY_BUFFER, envMapVBO); glBufferData(GL_ARRAY_BUFFER, m_skyboxVertices.size() * sizeof(float), &m_skyboxVertices[0], GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); glBindVertexArray(0); } void Renderer::resize(int width, int height ) { framebuffer = FrameBuffer(); framebuffer.Bind(); ColourBuffer = CreateTexture(width, height); framebuffer.Attach(*ColourBuffer); renderbufferObject = RenderBuffer(); renderbufferObject.Bind(); renderbufferObject.UseDepthAndStencil(width, height); framebuffer.Attach(renderbufferObject); if (framebuffer.IsComplete() == false) { std::cout << "ERROR::FRAMEBUFFER::Framebuffer is not complete! " << std::endl; } renderbufferObject.Unbind(); OutlineEffect = FrameBuffer(); OutlineEffect.Bind(); colourAttachment = CreateTexture(width, height); OutlineEffect.Attach(*colourAttachment); auto renderBuffer = RenderBuffer(); renderBuffer.Bind(); renderBuffer.UseDepthAndStencil(width, height); renderBuffer.Unbind(); glad_glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, renderBuffer.id); OutlineEffect.Unbind(); } unsigned int sphereVAO = 0; unsigned int indexCount; void renderSphere() { if (sphereVAO == 0) { glGenVertexArrays(1, &sphereVAO); unsigned int vbo, ebo; glGenBuffers(1, &vbo); glGenBuffers(1, &ebo); std::vector positions; std::vector uv; std::vector normals; std::vector indices; const unsigned int X_SEGMENTS = 64; const unsigned int Y_SEGMENTS = 64; const float PI = 3.14159265359f; for (unsigned int x = 0; x <= X_SEGMENTS; ++x) { for (unsigned int y = 0; y <= Y_SEGMENTS; ++y) { float xSegment = (float)x / (float)X_SEGMENTS; float ySegment = (float)y / (float)Y_SEGMENTS; float xPos = std::cos(xSegment * 2.0f * PI) * std::sin(ySegment * PI); float yPos = std::cos(ySegment * PI); float zPos = std::sin(xSegment * 2.0f * PI) * std::sin(ySegment * PI); positions.push_back(glm::vec3(xPos, yPos, zPos)); uv.push_back(glm::vec2(xSegment, ySegment)); normals.push_back(glm::vec3(xPos, yPos, zPos)); } } bool oddRow = false; for (unsigned int y = 0; y < Y_SEGMENTS; ++y) { if (!oddRow) // even rows: y == 0, y == 2; and so on { for (unsigned int x = 0; x <= X_SEGMENTS; ++x) { indices.push_back(y * (X_SEGMENTS + 1) + x); indices.push_back((y + 1) * (X_SEGMENTS + 1) + x); } } else { for (int x = X_SEGMENTS; x >= 0; --x) { indices.push_back((y + 1) * (X_SEGMENTS + 1) + x); indices.push_back(y * (X_SEGMENTS + 1) + x); } } oddRow = !oddRow; } indexCount = static_cast(indices.size()); std::vector data; for (unsigned int i = 0; i < positions.size(); ++i) { data.push_back(positions[i].x); data.push_back(positions[i].y); data.push_back(positions[i].z); if (normals.size() > 0) { data.push_back(normals[i].x); data.push_back(normals[i].y); data.push_back(normals[i].z); } if (uv.size() > 0) { data.push_back(uv[i].x); data.push_back(uv[i].y); } } glBindVertexArray(sphereVAO); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(float), &data[0], GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW); unsigned int stride = (3 + 2 + 3) * sizeof(float); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, (void*)0); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, stride, (void*)(3 * sizeof(float))); glEnableVertexAttribArray(2); glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, stride, (void*)(6 * sizeof(float))); } glBindVertexArray(sphereVAO); glDrawElements(GL_TRIANGLE_STRIP, indexCount, GL_UNSIGNED_INT, 0); } void Renderer::Render(Scene& scene) { glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glm::mat4 projection = glm::perspective(glm::radians(scene.MainCamera.Zoom), (float)800 / (float)600, 0.1f, 100.0f); auto view = scene.MainCamera.GetViewMatrix(); auto model = glm::mat4(1.0f); // Skybox #if false glDepthMask(GL_FALSE); Shader shader = shaders.at(static_cast(RenderPass::SKYBOX)); shader.use(); shader.setMat4("projection", projection); auto centeredView = glm::mat4(glm::mat3(scene.MainCamera.GetViewMatrix())); shader.setMat4("view", centeredView); glActiveTexture(GL_TEXTURE0); scene.skybox.Bind(); glDrawArrays(GL_TRIANGLES, 0, 36); scene.skybox.Unbind(); glDepthMask(GL_TRUE); #endif //HDR Environment Skybox Shader shader = shaders.at(static_cast(RenderPass::HDR_SKYBOX)); glDepthFunc(GL_LEQUAL); shader.use(); shader.setMat4("projection", projection); shader.setMat4("view", scene.MainCamera.GetViewMatrix()); glBindVertexArray(envMapVAO); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_CUBE_MAP, envCubemap); glDrawArrays(GL_TRIANGLES, 0, 36); glBindTexture(GL_TEXTURE_CUBE_MAP, 0); glBindVertexArray(0); glDepthFunc(GL_LESS); // Phong lighting shader = shaders.at(static_cast(RenderPass::DEFAULT)); shader.use(); shader.setVec3("cameraPos", scene.MainCamera.Position); shader.setInt("skybox", 11); glActiveTexture(GL_TEXTURE11); scene.skybox.Bind(); glActiveTexture(GL_TEXTURE0); model = glm::translate(model, glm::vec3(20.0f, 0.0f, 0.0f)); shader.setMat4("model", model); shader.setMat4("view", view); shader.setMat4("projection", projection); for (auto entity : scene.entities) { entity.Draw(shader); } scene.skybox.Unbind(); // PBR shader = shaders.at(static_cast(RenderPass::PBR)); shader.use(); shader.setInt("albedoMap", 0); shader.setInt("normalMap", 1); shader.setInt("metallicMap", 2); shader.setInt("roughnessMap", 3); shader.setInt("aoMap", 4); shader.setMat4("projection", projection); view = scene.MainCamera.GetViewMatrix(); shader.setMat4("view", view); shader.setVec3("camPos", scene.MainCamera.Position); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, albedo); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, normal); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, metallic); glActiveTexture(GL_TEXTURE3); glBindTexture(GL_TEXTURE_2D, roughness); glActiveTexture(GL_TEXTURE4); glBindTexture(GL_TEXTURE_2D, ao); // Render Spheres model = glm::mat4(1.0f); for (int row = 0; row < nrRows; ++row) { for (int col = 0; col < nrColumns; ++col) { model = glm::mat4(1.0f); model = glm::translate(model, glm::vec3( (col - (nrColumns / 2)) * spacing, (row - (nrRows / 2)) * spacing, 0.0f )); shader.setMat4("model", model); shader.setMat3("normalMatrix", glm::transpose(glm::inverse(glm::mat3(model)))); renderSphere(); } } // Render light source for (unsigned int i = 0; i < sizeof(lightPositions) / sizeof(lightPositions[0]); ++i) { glm::vec3 newPos = lightPositions[i] + glm::vec3(sin(glfwGetTime() * 5.0) * 5.0, 0.0, 0.0); newPos = lightPositions[i]; shader.setVec3("lightPositions[" + std::to_string(i)+"]", newPos); shader.setVec3("lightColors[" + std::to_string(i) + "]", lightColors[i]); model = glm::mat4(1.0f); model = glm::translate(model, newPos); model = glm::scale(model, glm::vec3(0.5f)); shader.setMat4("model", model); shader.setMat3("normalMatrix", glm::transpose(glm::inverse(glm::mat3(model)))); renderSphere(); } /* Shader OutlineShader; OutlineShader.Load("../Shaders/shader.vs", "../Shaders/outlineshader.fs"); glStencilFunc(GL_NOTEQUAL, 1, 0xFF); glStencilMask(0x00); glDisable(GL_DEPTH_TEST); //OutlineEffect.Bind(); //glClearColor(0.1f, 0.1f, 0.1f, 1.0f); //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); OutlineShader.use(); OutlineShader.setMat4("model", glm::scale(glm::mat4(1.0f), glm::vec3(1.05f, 1.05f, 1.05f))); OutlineShader.setMat4("view", view); OutlineShader.setMat4("projection", projection); OutlineShader.setVec3("outlineColor", glm::vec3(0.28f, 0.10f, 0.26f)); for (auto entity : scene.entities) { entity.Draw(OutlineShader); } glStencilFunc(GL_ALWAYS, 1, 0xFF); glStencilMask(0xFF); */ // 4. draw result to screen /* glBindFramebuffer(GL_FRAMEBUFFER, 0); glDisable(GL_DEPTH_TEST); Shader shader; shader.Load("../Shaders/Framebuffers.vs", "../Shaders/Framebuffers.fs"); shader.use(); shader.setInt("screenTexture",0); glBindVertexArray(ScreenVAO); glBindTexture(GL_TEXTURE_2D, ColourBuffer->id); glDrawArrays(GL_TRIANGLES, 0, 6); // Reset stencil glEnable(GL_DEPTH_TEST); */ } void Renderer::Shutdown() { framebuffer.Unbind(); }