From 4355a12b9a9151147121807ed65ea18e6e63db01 Mon Sep 17 00:00:00 2001 From: Nigel Date: Tue, 18 Oct 2022 22:57:50 +0200 Subject: [PATCH] Architecture redesign PART 1: - Added a Renderer class - Added a Application interface - Added a RenderPass interface - Added multiple RenderPass classes - Added a Window class - Moved Shaders into a Shader folder The idea behind this redesign is to make more abstractions. These abstraction are then supposedly going to make it easier to focus on the next couple tutorials main elements --- Cubemap.fs => Shaders/Cubemap.fs | 0 Framebuffers.fs => Shaders/Framebuffers.fs | 0 Framebuffers.vs => Shaders/Framebuffers.vs | 0 lightsource.fs => Shaders/lightsource.fs | 0 lightsource.vs => Shaders/lightsource.vs | 0 outlineshader.fs => Shaders/outlineshader.fs | 0 shader.fs => Shaders/shader.fs | 0 shader.vs => Shaders/shader.vs | 0 skybox.vs => Shaders/skybox.vs | 0 src/Application.h | 6 + src/Cubemap.h | 4 +- src/FrameBuffer.cpp | 2 +- src/{FrameBuffer.hpp => FrameBuffer.h} | 3 +- src/OutlinePass.cpp | 58 +++ src/OutlinePass.h | 30 ++ src/RenderBuffer.cpp | 2 +- src/{RenderBuffer.hpp => RenderBuffer.h} | 2 + src/RenderPass.h | 16 + src/Renderer.cpp | 116 +++++ src/Renderer.h | 60 +++ src/ScenePass.cpp | 32 ++ src/ScenePass.h | 28 ++ src/Skybox.cpp | 25 ++ src/Skybox.h | 59 +++ src/SkyboxPass.cpp | 26 ++ src/SkyboxPass.h | 21 + src/Window.cpp | 77 ++++ src/Window.h | 32 ++ src/camera.h | 2 - src/main.cpp | 430 +++---------------- src/mesh.h | 1 - src/shader.cpp | 5 - src/shader.h | 1 + src/texture.h | 4 +- 34 files changed, 656 insertions(+), 386 deletions(-) rename Cubemap.fs => Shaders/Cubemap.fs (100%) rename Framebuffers.fs => Shaders/Framebuffers.fs (100%) rename Framebuffers.vs => Shaders/Framebuffers.vs (100%) rename lightsource.fs => Shaders/lightsource.fs (100%) rename lightsource.vs => Shaders/lightsource.vs (100%) rename outlineshader.fs => Shaders/outlineshader.fs (100%) rename shader.fs => Shaders/shader.fs (100%) rename shader.vs => Shaders/shader.vs (100%) rename skybox.vs => Shaders/skybox.vs (100%) create mode 100644 src/Application.h rename src/{FrameBuffer.hpp => FrameBuffer.h} (84%) create mode 100644 src/OutlinePass.cpp create mode 100644 src/OutlinePass.h rename src/{RenderBuffer.hpp => RenderBuffer.h} (88%) create mode 100644 src/RenderPass.h create mode 100644 src/Renderer.cpp create mode 100644 src/Renderer.h create mode 100644 src/ScenePass.cpp create mode 100644 src/ScenePass.h create mode 100644 src/Skybox.cpp create mode 100644 src/Skybox.h create mode 100644 src/SkyboxPass.cpp create mode 100644 src/SkyboxPass.h create mode 100644 src/Window.cpp create mode 100644 src/Window.h diff --git a/Cubemap.fs b/Shaders/Cubemap.fs similarity index 100% rename from Cubemap.fs rename to Shaders/Cubemap.fs diff --git a/Framebuffers.fs b/Shaders/Framebuffers.fs similarity index 100% rename from Framebuffers.fs rename to Shaders/Framebuffers.fs diff --git a/Framebuffers.vs b/Shaders/Framebuffers.vs similarity index 100% rename from Framebuffers.vs rename to Shaders/Framebuffers.vs diff --git a/lightsource.fs b/Shaders/lightsource.fs similarity index 100% rename from lightsource.fs rename to Shaders/lightsource.fs diff --git a/lightsource.vs b/Shaders/lightsource.vs similarity index 100% rename from lightsource.vs rename to Shaders/lightsource.vs diff --git a/outlineshader.fs b/Shaders/outlineshader.fs similarity index 100% rename from outlineshader.fs rename to Shaders/outlineshader.fs diff --git a/shader.fs b/Shaders/shader.fs similarity index 100% rename from shader.fs rename to Shaders/shader.fs diff --git a/shader.vs b/Shaders/shader.vs similarity index 100% rename from shader.vs rename to Shaders/shader.vs diff --git a/skybox.vs b/Shaders/skybox.vs similarity index 100% rename from skybox.vs rename to Shaders/skybox.vs diff --git a/src/Application.h b/src/Application.h new file mode 100644 index 0000000..86c828d --- /dev/null +++ b/src/Application.h @@ -0,0 +1,6 @@ +#pragma once + +class Application +{ + virtual void Run() = 0; +}; \ No newline at end of file diff --git a/src/Cubemap.h b/src/Cubemap.h index b480a30..071db44 100644 --- a/src/Cubemap.h +++ b/src/Cubemap.h @@ -1,10 +1,12 @@ #pragma once #include -#include "stb_image.h" +#include #include #include #include +#include "stb_image.h" + class Cubemap { public: diff --git a/src/FrameBuffer.cpp b/src/FrameBuffer.cpp index 779f499..05379c0 100644 --- a/src/FrameBuffer.cpp +++ b/src/FrameBuffer.cpp @@ -1,4 +1,4 @@ -#include "FrameBuffer.hpp" +#include "FrameBuffer.h" void FrameBuffer::Bind() diff --git a/src/FrameBuffer.hpp b/src/FrameBuffer.h similarity index 84% rename from src/FrameBuffer.hpp rename to src/FrameBuffer.h index e1cd659..7544bef 100644 --- a/src/FrameBuffer.hpp +++ b/src/FrameBuffer.h @@ -1,7 +1,6 @@ #pragma once -#include #include "texture.h" -#include "RenderBuffer.hpp" +#include "RenderBuffer.h" class FrameBuffer diff --git a/src/OutlinePass.cpp b/src/OutlinePass.cpp new file mode 100644 index 0000000..819f102 --- /dev/null +++ b/src/OutlinePass.cpp @@ -0,0 +1,58 @@ +#include "OutlinePass.h" +#include "Renderer.h" +OutlinePass::OutlinePass(Shader& shader, Model& sceneObject, glm::mat4& model, glm::mat4& projection, Camera& camera) +: RenderPass("Renderpass - Outline", shader ) , m_model(sceneObject), model(model), projection(projection), camera(camera) +{ +} + +OutlinePass::~OutlinePass(){ + + delete m_depthTexture; +} + +void OutlinePass::Setup() +{ + // Framebuffer outline effect + m_outlineFrameBuffer = FrameBuffer(); + m_outlineFrameBuffer.Bind(); + + // Create a texture attachment (colour attachment) + m_depthTexture = CreateTexture(800,600); + + // attach texture to the frame buffer as a colour attachment + m_outlineFrameBuffer.Attach(*m_depthTexture); + + // Add depth buffer attachment + m_outlineRenderBuffer = RenderBuffer(); + m_outlineRenderBuffer.Bind(); + + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 800, 600); + m_outlineRenderBuffer.Unbind(); + + // attach depth buffer to our framebuffer + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_outlineRenderBuffer.id); + m_outlineFrameBuffer.Unbind(); + +} + +void OutlinePass::Render() +{ + glStencilFunc(GL_NOTEQUAL, 1, 0xFF); + glStencilMask(0x00); + glDisable(GL_DEPTH_TEST); + + m_shader.use(); + m_shader.setMat4("model", model); + m_shader.setMat4("view", camera.GetViewMatrix()); + m_shader.setMat4("projection", projection); + m_shader.setVec3("outlineColor", glm::vec3(0.28, 0.10, 0.26)); + + model = glm::scale(model, glm::vec3(1.05f,1.05f, 1.05f)); + m_shader.setMat4("model", model); + + m_model.Draw(m_shader); + + glStencilFunc(GL_ALWAYS, 1, 0xff); + glStencilMask(0xFF); + +} \ No newline at end of file diff --git a/src/OutlinePass.h b/src/OutlinePass.h new file mode 100644 index 0000000..7c9e957 --- /dev/null +++ b/src/OutlinePass.h @@ -0,0 +1,30 @@ +#pragma once +#include +#include "RenderPass.h" +#include "FrameBuffer.h" +#include "RenderBuffer.h" +#include "texture.h" +#include "model.h" +#include "camera.h" + +class OutlinePass : RenderPass { + +public: + void Setup() override; + void Render() override; + + OutlinePass (Shader& shader, Model& sceneObject, glm::mat4& model , glm::mat4& projection, Camera& camera) ; + ~OutlinePass(); + +private: + FrameBuffer m_outlineFrameBuffer; + RenderBuffer m_outlineRenderBuffer; + Texture* m_depthTexture; + + glm::mat4 model; + glm::mat4 projection; + + Model& m_model; + Camera& camera; + +}; \ No newline at end of file diff --git a/src/RenderBuffer.cpp b/src/RenderBuffer.cpp index c13e1f7..c5c5c43 100644 --- a/src/RenderBuffer.cpp +++ b/src/RenderBuffer.cpp @@ -1,4 +1,4 @@ -#include "RenderBuffer.hpp" +#include "RenderBuffer.h" void RenderBuffer::UseDepthAndStencil (){ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 800, 600); /// NOTE: should be part of creating but kept seperate for now! diff --git a/src/RenderBuffer.hpp b/src/RenderBuffer.h similarity index 88% rename from src/RenderBuffer.hpp rename to src/RenderBuffer.h index 2b2765f..dcc7007 100644 --- a/src/RenderBuffer.hpp +++ b/src/RenderBuffer.h @@ -1,5 +1,7 @@ #pragma once #include +#include + class RenderBuffer { public: diff --git a/src/RenderPass.h b/src/RenderPass.h new file mode 100644 index 0000000..6f34d2e --- /dev/null +++ b/src/RenderPass.h @@ -0,0 +1,16 @@ +#pragma once +#include +#include "shader.h" + +class RenderPass { +public : + virtual void Render() = 0; + virtual void Setup() = 0; + + RenderPass(const std::string& name, Shader& shader) : m_name(name), m_shader(shader) {} + ~RenderPass(){} + +protected: + const std::string& m_name; + Shader& m_shader; +}; \ No newline at end of file diff --git a/src/Renderer.cpp b/src/Renderer.cpp new file mode 100644 index 0000000..309cfdf --- /dev/null +++ b/src/Renderer.cpp @@ -0,0 +1,116 @@ +#include "Renderer.h" +#include + +void Renderer::Setup() +{ + framebuffer = new FrameBuffer(); + framebuffer->Bind(); + + ColourBuffer = CreateTexture(800,600); + framebuffer->Attach(*ColourBuffer); + + renderbufferObject = new RenderBuffer(); + renderbufferObject->Bind(); + renderbufferObject->UseDepthAndStencil(); + renderbufferObject->Unbind(); + + framebuffer->Attach(*renderbufferObject); + + if(framebuffer->IsComplete() == false ){ + std::cout << "ERROR::FRAMEBUFFER::Framebuffer is not complete! " << std::endl; + } + + framebuffer->Unbind(); +} + +void Renderer::Render() +{ + float currentFrame = glfwGetTime(); + deltaTime = currentFrame - lastFrame; + lastFrame = currentFrame; + + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + + // Recalculate the Camera's view matrix + view = camera.GetViewMatrix(); + // Reset the model matrix to an identity matrix + model = glm::mat4(1.0f); + + + framebuffer->Bind(); + std::cout << "Starting Render passes :" << std::endl; + + // Outline of render steps + + // 1. Skybox pass + // 2. Scene pass + // 3. outline pass + // SKIP for now! + + glClearColor(0.1f, 0.1f, 0.1f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // 4. draw result to screen + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + glDisable(GL_DEPTH_TEST); + + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + + m_shader->use(); + m_shader->setInt("screenTexture",0); + glBindVertexArray(ScreenVAO); + glBindTexture(GL_TEXTURE_2D, ColourBuffer->id); + glDrawArrays(GL_TRIANGLES, 0, 6); + + + // Reset stencil + glStencilMask(0xFF); + glStencilFunc(GL_ALWAYS, 1, 0xFF); + glEnable(GL_DEPTH_TEST); + +} + + + +Renderer::Renderer(Camera& camera) +: camera(camera) +{ + deltaTime = 0.0f; + /// Create and compile the screen shader + m_shader = new Shader ("Shaders/Framebuffers.vs", "Shaders/Framebuffers.fs" ); + + // 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); +} + +Renderer::~Renderer() +{ + delete framebuffer; + delete renderbufferObject; + delete m_shader; + delete ColourBuffer; +} \ No newline at end of file diff --git a/src/Renderer.h b/src/Renderer.h new file mode 100644 index 0000000..a0ce4d8 --- /dev/null +++ b/src/Renderer.h @@ -0,0 +1,60 @@ +#pragma once +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "camera.h" +#include "shader.h" +#include "model.h" +#include "FrameBuffer.h" +#include "RenderBuffer.h" +#include "Cubemap.h" +#include "SkyboxPass.h" +#include "ScenePass.h" + +class Renderer +{ + public: + void Render(); + void Setup(); + + Renderer(Camera& camera); + ~Renderer(); + + private: + Camera& camera; + float deltaTime; // Time between current frame and last frame + float lastFrame = 0.0f; // Time of last frame + GLuint ScreenVAO, VBO; + FrameBuffer* framebuffer; + RenderBuffer* renderbufferObject; + Texture* ColourBuffer; + + Shader* m_shader; + + glm::mat4 model = glm::mat4(1.0f); + glm::mat4 view; + glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)800 / (float)600, 0.1f, 100.0f); + + glm::vec3 lightpos = glm::vec3(-0.2f, -1.0f, -0.3f); + + std::vector ScreenVertices = { + // vertex , uv + -1.0f, 1.0f, 0.0f, 1.0f, + -1.0f,-1.0f, 0.0f, 0.0f, + 1.0f, -1.0f, 1.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, + }; + + + +}; diff --git a/src/ScenePass.cpp b/src/ScenePass.cpp new file mode 100644 index 0000000..6109b81 --- /dev/null +++ b/src/ScenePass.cpp @@ -0,0 +1,32 @@ +#include "ScenePass.h" + +void ScenePass::Render() +{ + m_shader.use(); + m_shader.setVec3("cameraPos", camera.Position); + + if (m_skybox) + { + glActiveTexture(GL_TEXTURE11); + m_skybox->Bind(); + glActiveTexture(GL_TEXTURE0); + + m_shader.setInt("skybox",11); + } + + m_shader.setMat4("model", model); + m_shader.setMat4("view", camera.GetViewMatrix()); + m_shader.setMat4("projection", projection); + + + m_scene.Draw(m_shader); +} + +void ScenePass::Setup() +{ +} + +void ScenePass::SetSkybox(Skybox& skybox) +{ + m_skybox = &skybox; +} \ No newline at end of file diff --git a/src/ScenePass.h b/src/ScenePass.h new file mode 100644 index 0000000..a88c0a3 --- /dev/null +++ b/src/ScenePass.h @@ -0,0 +1,28 @@ +#pragma once +#include "RenderPass.h" +#include "Renderer.h" +#include "Skybox.h" +#include "shader.h" +#include "camera.h" +#include "model.h" +class ScenePass : RenderPass { + + public: + void Setup() override; + void Render() override; + + ScenePass(Shader& shader, Model& scene, glm::mat4& model, glm::mat4& projection, Camera& camera) + : RenderPass("RenderPass - Scene", shader), m_scene(scene), model(model), projection(projection), camera(camera) {} + ~ScenePass(); + + void SetSkybox(Skybox& skybox); + + private: + Skybox* m_skybox; + Model& m_scene; + glm::mat4& model; + glm::mat4& projection; + Camera& camera; + + +}; \ No newline at end of file diff --git a/src/Skybox.cpp b/src/Skybox.cpp new file mode 100644 index 0000000..b2b00ba --- /dev/null +++ b/src/Skybox.cpp @@ -0,0 +1,25 @@ +#include "Skybox.h" + +void Skybox::BuildVAO(){ + // Create SkyboxVAO + + glGenVertexArrays(1, &m_skyboxVAO); + glBindVertexArray(m_skyboxVAO); + + glGenBuffers(1, &m_skyboxVBO); + glBindBuffer(GL_ARRAY_BUFFER, m_skyboxVBO); + + 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); +} + +Skybox::Skybox() : Cubemap() +{ + +} + +Skybox::~Skybox(){} diff --git a/src/Skybox.h b/src/Skybox.h new file mode 100644 index 0000000..4537825 --- /dev/null +++ b/src/Skybox.h @@ -0,0 +1,59 @@ +#pragma once +#include +#include "Cubemap.h" + + +class Skybox : public Cubemap { +public: + Skybox (); + ~Skybox (); + + void BuildVAO(); + GLuint m_skyboxVAO; +private: + GLuint m_skyboxVBO; + 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 + }; +}; diff --git a/src/SkyboxPass.cpp b/src/SkyboxPass.cpp new file mode 100644 index 0000000..87088c8 --- /dev/null +++ b/src/SkyboxPass.cpp @@ -0,0 +1,26 @@ +#include "SkyboxPass.h" + + +SkyboxPass::~SkyboxPass() +{ +} + +void SkyboxPass::Setup() +{ +} + +void SkyboxPass::Render() +{ + glDepthMask(GL_FALSE); + + m_shader.use(); + m_shader.setMat4("projection", projection); + + glm::mat4 centeredView = glm::mat4(glm::mat3(camera.GetViewMatrix())); + m_shader.setMat4("view", centeredView); + + glBindVertexArray(skybox.m_skyboxVAO); + skybox.Bind(); + glDrawArrays(GL_TRIANGLES, 0, 36); + glDepthMask(GL_TRUE); +} \ No newline at end of file diff --git a/src/SkyboxPass.h b/src/SkyboxPass.h new file mode 100644 index 0000000..35c22aa --- /dev/null +++ b/src/SkyboxPass.h @@ -0,0 +1,21 @@ +#pragma once +#include "RenderPass.h" +#include "Renderer.h" +#include "Skybox.h" +#include "shader.h" + +class SkyboxPass : RenderPass { + public: + void Render() override; + void Setup() override; + + SkyboxPass(Shader& shader, glm::mat4& projection, Skybox& skybox, Camera& camera) + : RenderPass("Render Pass - Skybox", shader), projection(projection), skybox(skybox), camera(camera){} + ~SkyboxPass(); + + private: + Skybox skybox; + glm::mat4& projection; + Camera& camera; + +}; \ No newline at end of file diff --git a/src/Window.cpp b/src/Window.cpp new file mode 100644 index 0000000..fc4d378 --- /dev/null +++ b/src/Window.cpp @@ -0,0 +1,77 @@ +#include "Window.h" + +bool firstMouse = true; +float lastx = 400, lasty = 300; + + +Window::Window(int initialWidth, int initialHeight, const std::string& WindowName) +: m_width(initialWidth), m_height(initialHeight), m_WindowName(WindowName) +{ + glfwInit(); + + // setup the window + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + + // Enable window based multisampling + glfwWindowHint(GLFW_SAMPLES, 4); + + m_window = glfwCreateWindow(m_width, m_height, m_WindowName.c_str(), NULL, NULL); + + if(m_window == NULL) + { + printf("Failed to create GLFW window!\n"); + glfwTerminate(); + return; + } + + glfwMakeContextCurrent(m_window); + + if(!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){ + printf("Failed to initialize GLAD!\n"); + return; + } + + glViewport(0,0, m_width, m_height); + + // Setup Callbacks + glfwSetFramebufferSizeCallback(m_window, framebuffer_size_callback); + //glfwSetInputMode(m_window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); + glfwSetCursorPosCallback(m_window, mouse_callback); + glfwSetScrollCallback(m_window, scroll_callback); +} + + +Window::~Window() +{ + glfwDestroyWindow(m_window); + glfwTerminate(); +} + +void mouse_callback(GLFWwindow* window, double xpos, double ypos) +{ + if(firstMouse){ + lastx = xpos; + lasty = ypos; + firstMouse = false; + } + + float xoffset = xpos - lastx; + float yoffset = ypos - lasty; + + lastx = xpos; + lasty - ypos; + + // camera.ProcessMouseMovement(xoffset, yoffset); +} + +void framebuffer_size_callback(GLFWwindow* window, int width, int height) +{ + glViewport(0,0, width,height); +} + +void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) +{ + // camera.ProcessMouseScroll(yoffset); +} \ No newline at end of file diff --git a/src/Window.h b/src/Window.h new file mode 100644 index 0000000..b497d2f --- /dev/null +++ b/src/Window.h @@ -0,0 +1,32 @@ +#pragma once +#include +#include +#include +#include + +class Window +{ + public: + Window (int initialWidth, int initialHeight, const std::string& WindowName); + ~Window(); + + void setWidth(int width){this->m_width = width;} + void setHeight(int height){this->m_height = height;} + + int getWidth(){return this->m_width;} + int getHeight(){return this->m_height;} + double getRatio(){return (this->m_width / this->m_height);} + + bool shouldClose(){ return glfwWindowShouldClose(m_window);} + //void GetInput(){ processInput(m_window);} + void SwapBuffers(){ glfwSwapBuffers(m_window);} + private: + int m_width, m_height; + const std::string& m_WindowName; + GLFWwindow* m_window; +}; + + +void framebuffer_size_callback(GLFWwindow* window, int width, int height); +void mouse_callback(GLFWwindow* window, double xpos, double ypos); +void scroll_callback(GLFWwindow* window, double xoffset, double yoffset); \ No newline at end of file diff --git a/src/camera.h b/src/camera.h index d2e0bfc..a14da10 100644 --- a/src/camera.h +++ b/src/camera.h @@ -1,6 +1,4 @@ #pragma once - -#include #include #include diff --git a/src/main.cpp b/src/main.cpp index bdcca61..6d32e39 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,399 +1,87 @@ -#include -#include -#include - -#include -#include - #include -#include -#include - +#include +#include +#include "Window.h" +#include "Renderer.h" +#include "Skybox.h" #include "shader.h" #include "camera.h" -#include "model.h" -#include "FrameBuffer.hpp" -#include "RenderBuffer.hpp" -#include "Cubemap.h" +#include "Application.h" -// https://learnopengl.com/Advanced-OpenGL/Framebuffers +class LearnOpenGL : Application +{ + +public: + void Run () override{ + // Create a window + Window window(800,600, "LearnOpenGL"); -float deltaTime = 0.0f; // Time between current frame and last frame -float lastFrame = 0.0f; // Time of last frame + Camera camera(glm::vec3(0.0f,0.0f,8.0f)); + + Renderer renderer = Renderer(camera); + + renderer.Setup(); + + stbi_set_flip_vertically_on_load(true); -Camera camera(glm::vec3(0.0f, 0.0f, 8.0f)); -float lastX = 400, lastY = 300; -bool firstMouse = true; + // Load scene resources + Shader shader ("Shaders/shader.vs", "Shaders/shader.fs"); + Shader outlineShader("Shaders/shader.vs","Shaders/outlineshader.fs"); + Shader skyboxShader("Shaders/skybox.vs", "Shaders/Cubemap.fs"); -glm::mat4 model = glm::mat4(1.0f); -glm::mat4 view; -glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)800 / (float)600, 0.1f, 100.0f); - -glm::vec3 lightpos(-0.2f, -1.0f, -0.3f); + Model backpack("Models/backpack.obj"); + int bullshit = 0; + std::vector faces = { + "Textures/skybox/right.jpg", + "Textures/skybox/left.jpg", + "Textures/skybox/top.jpg", + "Textures/skybox/bottom.jpg", + "Textures/skybox/front.jpg", + "Textures/skybox/back.jpg" + }; -std::vector ScreenVertices = { - // vertex , uv - -1.0f, 1.0f, 0.0f, 1.0f, - -1.0f,-1.0f, 0.0f, 0.0f, - 1.0f, -1.0f, 1.0f, 0.0f, + Skybox skybox= Skybox (); + skybox.Bind(); + skybox.loadCubeTextures(faces); + skybox.BuildVAO(); - -1.0f, 1.0f, 0.0f, 1.0f, - 1.0f, -1.0f, 1.0f, 0.0f, - 1.0f, 1.0f, 1.0f, 1.0f, -} ; + //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + while(!window.shouldClose()) + { + //window.GetInput(); -std::vector faces = { - "Textures/skybox/right.jpg", - "Textures/skybox/left.jpg", - "Textures/skybox/top.jpg", - "Textures/skybox/bottom.jpg", - "Textures/skybox/front.jpg", - "Textures/skybox/back.jpg" + renderer.Render(); + + window.SwapBuffers(); + glfwPollEvents(); + } + + } }; -std::vector 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 -}; - -void framebuffer_size_callback(GLFWwindow* window, int width, int height) { - glViewport(0,0, width, height); -} +/* void processInput( GLFWwindow* window){ if(glfwGetKey(window,GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true); - const float CameraSpeed = 2.5f * deltaTime; + const float CameraSpeed = 2.5f * Renderer::deltaTime; if(glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) - camera.ProcessKeyboard(FORWARD, deltaTime); + Renderer::camera.ProcessKeyboard(FORWARD, Renderer::deltaTime); if(glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) - camera.ProcessKeyboard(BACKWARD, deltaTime); + Renderer::camera.ProcessKeyboard(BACKWARD, Renderer::deltaTime); if(glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) - camera.ProcessKeyboard(LEFT, deltaTime); + Renderer::camera.ProcessKeyboard(LEFT, Renderer::deltaTime); if(glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) - camera.ProcessKeyboard(RIGHT,deltaTime); + Renderer::camera.ProcessKeyboard(RIGHT,Renderer::deltaTime); } -void mouse_callback(GLFWwindow* window, double xpos, double ypos){ - if (firstMouse) // initially set to true - { - lastX = xpos; - lastY = ypos; - firstMouse = false; - } - float xoffset = xpos - lastX; - float yoffset = lastY - ypos; // reversed since y-coordinates range from bottom to top - - lastX = xpos; - lastY = ypos; +*/ - camera.ProcessMouseMovement(xoffset,yoffset); -} -void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) +int main() { - camera.ProcessMouseScroll(yoffset); -} - -GLFWwindow* CreateWindowWithOpenGLContext() -{ - glfwInit(); - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - - // multisampling - glfwWindowHint(GLFW_SAMPLES, 4); - - GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL); - if( window == NULL){ - printf("Failed to create GLFW window!\n"); - glfwTerminate(); - return nullptr; - } - glfwMakeContextCurrent(window); - - if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){ - printf("Failed to initialize GLAD!\n"); - return nullptr; - } - - glViewport(0,0, 800, 600); - glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); - glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); - glfwSetCursorPosCallback(window, mouse_callback); - glfwSetScrollCallback(window, scroll_callback); - - return window; - -} - -void Skybox_pass (GLuint& SkyboxVAO, Shader& skyboxShader, Cubemap& skycubemap) -{ - glDepthMask(GL_FALSE); - - skyboxShader.use(); - skyboxShader.setMat4("projection", projection); - - glm::mat4 centeredView = glm::mat4(glm::mat3(camera.GetViewMatrix())); - skyboxShader.setMat4("view", centeredView); - - glBindVertexArray(SkyboxVAO); - skycubemap.Bind(); - glDrawArrays(GL_TRIANGLES, 0, 36); - glDepthMask(GL_TRUE); -} - -void drawScene_pass(Shader& shader, Model& Object, Cubemap& skybox) -{ - shader.use(); - shader.setVec3("cameraPos", camera.Position); - - glActiveTexture(GL_TEXTURE11); - skybox.Bind(); - glActiveTexture(GL_TEXTURE0); - - - shader.setMat4("model", model); - shader.setMat4("view", view); - shader.setMat4("projection", projection); - shader.setInt("skybox",11); - - Object.Draw(shader); -} - -void outline_pass( Shader& shader, Model& Object) -{ - - - glStencilFunc(GL_NOTEQUAL, 1, 0xFF); - glStencilMask(0x00); - glDisable(GL_DEPTH_TEST); - - shader.use(); - shader.setMat4("model", model); - shader.setMat4("view", view); - shader.setMat4("projection", projection); - shader.setVec3("outlineColor", glm::vec3(0.28, 0.10, 0.26)); - - model = glm::scale(model, glm::vec3(1.05f,1.05f, 1.05f)); - shader.setMat4("model", model); - - Object.Draw(shader); - - glStencilFunc(GL_ALWAYS, 1, 0xff); - glStencilMask(0xFF); -} - -void DrawToScreen( GLuint& VAO, GLuint& ScreenTexture, Shader& shader) -{ - // draw to screen - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - glDisable(GL_DEPTH_TEST); - - glClearColor(1.0f, 1.0f, 1.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - - - shader.use(); - shader.setInt("screenTexture",0); - glBindVertexArray(VAO); - glBindTexture(GL_TEXTURE_2D, ScreenTexture); - glDrawArrays(GL_TRIANGLES, 0, 6); -} - -int main() { printf("Hello OpenGL!\n"); - - - // Setup OpenGL Context - GLFWwindow* window = CreateWindowWithOpenGLContext(); - - if(window == nullptr) - return -1; - - glEnable(GL_DEPTH_TEST); - stbi_set_flip_vertically_on_load(true); - - // Load scene resources - Shader shader ("shader.vs", "shader.fs"); - Shader outlineShader("shader.vs","outlineshader.fs"); - Shader framebufferShader("Framebuffers.vs", "Framebuffers.fs" ); - Shader skyboxShader("skybox.vs", "Cubemap.fs"); - - Model backpack("Models/backpack.obj"); - - // Framebuffer outline effect - FrameBuffer outlineFrameBuffer = FrameBuffer(); - outlineFrameBuffer.Bind(); - - // Create a texture attachment (colour attachment) - Texture* depthTexture = CreateTexture(800,600); - - // attach texture to the frame buffer as a colour attachment - outlineFrameBuffer.Attach(*depthTexture); - - // Add depth buffer attachment - RenderBuffer outlineRenderBuffer = RenderBuffer(); - outlineRenderBuffer.Bind(); - - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 800, 600); - outlineRenderBuffer.Unbind(); - - // attach depth buffer to our framebuffer - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, outlineRenderBuffer.id); - outlineFrameBuffer.Unbind(); - - // Post processing - FrameBuffer framebuffer = FrameBuffer(); - framebuffer.Bind(); - - Texture* ColourBuffer = CreateTexture(800,600); - framebuffer.Attach(*ColourBuffer); - - RenderBuffer renderbufferObject = RenderBuffer(); - renderbufferObject.Bind(); - renderbufferObject.UseDepthAndStencil(); - renderbufferObject.Unbind(); - - framebuffer.Attach(renderbufferObject); - - if(framebuffer.IsComplete() == false ){ - std::cout << "ERROR::FRAMEBUFFER::Framebuffer is not complete! " << std::endl; - } - - framebuffer.Unbind(); - - Cubemap skybox= Cubemap (); - skybox.Bind(); - skybox.loadCubeTextures(faces); - - // Create ScreenVAO - GLuint ScreenVAO, VBO; - 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); - - // Create SkyboxVAO - GLuint SkyboxVAO, SkyboxVBO; - glGenVertexArrays(1, &SkyboxVAO); - glBindVertexArray(SkyboxVAO); - - glGenBuffers(1, &SkyboxVBO); - glBindBuffer(GL_ARRAY_BUFFER, SkyboxVBO); - - glBufferData(GL_ARRAY_BUFFER, skyboxVertices.size() * sizeof(float), &skyboxVertices[0], GL_STATIC_DRAW); - - glEnableVertexAttribArray(0); - glVertexAttribPointer(0,3, GL_FLOAT,GL_FALSE, 3 * sizeof(float),(void*) 0); - - glBindVertexArray(0); - - - glEnable(GL_DEPTH_TEST); - glEnable(GL_STENCIL_TEST); - glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - glEnable(GL_MULTISAMPLE); - -//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); -while(!glfwWindowShouldClose(window)) -{ - float currentFrame = glfwGetTime(); - deltaTime = currentFrame - lastFrame; - lastFrame = currentFrame; - - processInput(window); - - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - - // Recalculate the Camera's view matrix - view = camera.GetViewMatrix(); - // Reset the model matrix to an identity matrix - model = glm::mat4(1.0f); - - - framebuffer.Bind(); - - glClearColor(0.1f, 0.1f, 0.1f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - Skybox_pass(SkyboxVAO, skyboxShader, skybox); - - drawScene_pass(shader, backpack, skybox); - - outline_pass(outlineShader, backpack); - - DrawToScreen(ScreenVAO, ColourBuffer->id, framebufferShader); - - // Reset stencil - glStencilMask(0xFF); - glStencilFunc(GL_ALWAYS, 1, 0xFF); - glEnable(GL_DEPTH_TEST); - - glfwSwapBuffers(window); - glfwPollEvents(); + LearnOpenGL().Run(); + return 0; } - - -delete ColourBuffer; -delete depthTexture; -glfwTerminate(); - -return 0; - - -} \ No newline at end of file diff --git a/src/mesh.h b/src/mesh.h index e07a8a4..4aab197 100644 --- a/src/mesh.h +++ b/src/mesh.h @@ -2,7 +2,6 @@ #include #include - #include #include diff --git a/src/shader.cpp b/src/shader.cpp index be948b6..6ffc138 100644 --- a/src/shader.cpp +++ b/src/shader.cpp @@ -25,7 +25,6 @@ Shader::Shader(const char* vertextPath, const char* fragmentPath) vertexCode = vShaderStream.str(); fragmentCode = fShaderStream.str(); - } catch(std::ifstream::failure e){ @@ -35,7 +34,6 @@ Shader::Shader(const char* vertextPath, const char* fragmentPath) const char* vShaderCode = vertexCode.c_str(); const char* fShaderCode = fragmentCode.c_str(); - // Compile Shaders unsigned int vertex, fragment; int success; @@ -86,13 +84,10 @@ Shader::Shader(const char* vertextPath, const char* fragmentPath) } - void Shader::use(){ glUseProgram(ID); } - - void Shader::setBool(const std::string &name, bool value) const{ glUniform1i(glGetUniformLocation(ID, name.c_str()), (int) value ); } diff --git a/src/shader.h b/src/shader.h index da94717..e936833 100644 --- a/src/shader.h +++ b/src/shader.h @@ -1,5 +1,6 @@ #pragma once #include +#include #include #include #include diff --git a/src/texture.h b/src/texture.h index f915b98..6020e1b 100644 --- a/src/texture.h +++ b/src/texture.h @@ -1,6 +1,7 @@ #pragma once -#include #include +#include +#include struct Texture{ GLuint id; @@ -8,5 +9,4 @@ struct Texture{ std::string path; }; - Texture* CreateTexture(unsigned int width, unsigned int height); \ No newline at end of file