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
This commit is contained in:
Nigel Barink 2022-10-18 22:57:50 +02:00
parent 71c942d88e
commit 4355a12b9a
34 changed files with 656 additions and 386 deletions

6
src/Application.h Normal file
View File

@ -0,0 +1,6 @@
#pragma once
class Application
{
virtual void Run() = 0;
};

View File

@ -1,10 +1,12 @@
#pragma once #pragma once
#include <glad/glad.h> #include <glad/glad.h>
#include "stb_image.h" #include <GLFW/glfw3.h>
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <string> #include <string>
#include "stb_image.h"
class Cubemap { class Cubemap {
public: public:

View File

@ -1,4 +1,4 @@
#include "FrameBuffer.hpp" #include "FrameBuffer.h"
void FrameBuffer::Bind() void FrameBuffer::Bind()

View File

@ -1,7 +1,6 @@
#pragma once #pragma once
#include <glad/glad.h>
#include "texture.h" #include "texture.h"
#include "RenderBuffer.hpp" #include "RenderBuffer.h"
class FrameBuffer class FrameBuffer

58
src/OutlinePass.cpp Normal file
View File

@ -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);
}

30
src/OutlinePass.h Normal file
View File

@ -0,0 +1,30 @@
#pragma once
#include <glm/glm.hpp>
#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;
};

View File

@ -1,4 +1,4 @@
#include "RenderBuffer.hpp" #include "RenderBuffer.h"
void RenderBuffer::UseDepthAndStencil (){ void RenderBuffer::UseDepthAndStencil (){
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 800, 600); /// NOTE: should be part of creating but kept seperate for now! glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 800, 600); /// NOTE: should be part of creating but kept seperate for now!

View File

@ -1,5 +1,7 @@
#pragma once #pragma once
#include <glad/glad.h> #include <glad/glad.h>
#include <GLFW/glfw3.h>
class RenderBuffer class RenderBuffer
{ {
public: public:

16
src/RenderPass.h Normal file
View File

@ -0,0 +1,16 @@
#pragma once
#include <string>
#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;
};

116
src/Renderer.cpp Normal file
View File

@ -0,0 +1,116 @@
#include "Renderer.h"
#include <iostream>
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;
}

60
src/Renderer.h Normal file
View File

@ -0,0 +1,60 @@
#pragma once
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <cmath>
#include <vector>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#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<float> 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,
};
};

32
src/ScenePass.cpp Normal file
View File

@ -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;
}

28
src/ScenePass.h Normal file
View File

@ -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;
};

25
src/Skybox.cpp Normal file
View File

@ -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(){}

59
src/Skybox.h Normal file
View File

@ -0,0 +1,59 @@
#pragma once
#include <vector>
#include "Cubemap.h"
class Skybox : public Cubemap {
public:
Skybox ();
~Skybox ();
void BuildVAO();
GLuint m_skyboxVAO;
private:
GLuint m_skyboxVBO;
std::vector<float> 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
};
};

26
src/SkyboxPass.cpp Normal file
View File

@ -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);
}

21
src/SkyboxPass.h Normal file
View File

@ -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;
};

77
src/Window.cpp Normal file
View File

@ -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);
}

32
src/Window.h Normal file
View File

@ -0,0 +1,32 @@
#pragma once
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <string>
#include <stdio.h>
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);

View File

@ -1,6 +1,4 @@
#pragma once #pragma once
#include <glad/glad.h>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>

View File

@ -1,399 +1,87 @@
#include <stdio.h>
#include <cmath>
#include <vector>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp> #include <vector>
#include <glm/gtc/type_ptr.hpp> #include <string>
#include "Window.h"
#include "Renderer.h"
#include "Skybox.h"
#include "shader.h" #include "shader.h"
#include "camera.h" #include "camera.h"
#include "model.h" #include "Application.h"
#include "FrameBuffer.hpp"
#include "RenderBuffer.hpp"
#include "Cubemap.h"
// https://learnopengl.com/Advanced-OpenGL/Framebuffers class LearnOpenGL : Application
{
float deltaTime = 0.0f; // Time between current frame and last frame public:
float lastFrame = 0.0f; // Time of last frame void Run () override{
// Create a window
Window window(800,600, "LearnOpenGL");
Camera camera(glm::vec3(0.0f, 0.0f, 8.0f)); Camera camera(glm::vec3(0.0f,0.0f,8.0f));
float lastX = 400, lastY = 300;
bool firstMouse = true;
glm::mat4 model = glm::mat4(1.0f); Renderer renderer = Renderer(camera);
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); renderer.Setup();
std::vector<float> ScreenVertices = { stbi_set_flip_vertically_on_load(true);
// 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, // Load scene resources
1.0f, -1.0f, 1.0f, 0.0f, Shader shader ("Shaders/shader.vs", "Shaders/shader.fs");
1.0f, 1.0f, 1.0f, 1.0f, Shader outlineShader("Shaders/shader.vs","Shaders/outlineshader.fs");
} ; Shader skyboxShader("Shaders/skybox.vs", "Shaders/Cubemap.fs");
std::vector<std::string> faces = { Model backpack("Models/backpack.obj");
"Textures/skybox/right.jpg", int bullshit = 0;
"Textures/skybox/left.jpg", std::vector<std::string> faces = {
"Textures/skybox/top.jpg", "Textures/skybox/right.jpg",
"Textures/skybox/bottom.jpg", "Textures/skybox/left.jpg",
"Textures/skybox/front.jpg", "Textures/skybox/top.jpg",
"Textures/skybox/back.jpg" "Textures/skybox/bottom.jpg",
"Textures/skybox/front.jpg",
"Textures/skybox/back.jpg"
};
Skybox skybox= Skybox ();
skybox.Bind();
skybox.loadCubeTextures(faces);
skybox.BuildVAO();
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
while(!window.shouldClose())
{
//window.GetInput();
renderer.Render();
window.SwapBuffers();
glfwPollEvents();
}
}
}; };
std::vector<float> 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){ void processInput( GLFWwindow* window){
if(glfwGetKey(window,GLFW_KEY_ESCAPE) == GLFW_PRESS) if(glfwGetKey(window,GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true); glfwSetWindowShouldClose(window, true);
const float CameraSpeed = 2.5f * deltaTime; const float CameraSpeed = 2.5f * Renderer::deltaTime;
if(glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) 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) 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) 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) 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); int main()
}
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{ {
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"); printf("Hello OpenGL!\n");
LearnOpenGL().Run();
return 0;
// 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();
}
delete ColourBuffer;
delete depthTexture;
glfwTerminate();
return 0;
} }

View File

@ -2,7 +2,6 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <glad/glad.h> #include <glad/glad.h>
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>

View File

@ -26,7 +26,6 @@ Shader::Shader(const char* vertextPath, const char* fragmentPath)
vertexCode = vShaderStream.str(); vertexCode = vShaderStream.str();
fragmentCode = fShaderStream.str(); fragmentCode = fShaderStream.str();
} }
catch(std::ifstream::failure e){ catch(std::ifstream::failure e){
std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl << e.what() << std::endl ; std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl << e.what() << std::endl ;
@ -35,7 +34,6 @@ Shader::Shader(const char* vertextPath, const char* fragmentPath)
const char* vShaderCode = vertexCode.c_str(); const char* vShaderCode = vertexCode.c_str();
const char* fShaderCode = fragmentCode.c_str(); const char* fShaderCode = fragmentCode.c_str();
// Compile Shaders // Compile Shaders
unsigned int vertex, fragment; unsigned int vertex, fragment;
int success; int success;
@ -86,13 +84,10 @@ Shader::Shader(const char* vertextPath, const char* fragmentPath)
} }
void Shader::use(){ void Shader::use(){
glUseProgram(ID); glUseProgram(ID);
} }
void Shader::setBool(const std::string &name, bool value) const{ void Shader::setBool(const std::string &name, bool value) const{
glUniform1i(glGetUniformLocation(ID, name.c_str()), (int) value ); glUniform1i(glGetUniformLocation(ID, name.c_str()), (int) value );
} }

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <glad/glad.h> #include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <string> #include <string>
#include <fstream> #include <fstream>

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <string>
#include <glad/glad.h> #include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <string>
struct Texture{ struct Texture{
GLuint id; GLuint id;
@ -8,5 +9,4 @@ struct Texture{
std::string path; std::string path;
}; };
Texture* CreateTexture(unsigned int width, unsigned int height); Texture* CreateTexture(unsigned int width, unsigned int height);