learn-opengl/21-framebuffers/src/scene.hpp

134 lines
4.4 KiB
C++

#pragma once
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include "shader.hpp"
#include "model.hpp"
#include "shader.hpp"
#include "model.hpp"
#include "camera.hpp"
#include "components.hpp"
#include <vector>
#include <unordered_map>
struct Thing {
std::string name;
Model& model;
Material& material;
components::Position position;
components::Rotation rotation;
float scale;
float distance = 0;
};
struct Scene {
Shader shader;
Shader screen_shader;
std::unordered_map<std::string, components::Material> materials;
Camera camera;
components::Lighting light;
std::unordered_map<std::string, Model> models;
std::vector<Thing> things;
float deltaTime = 0.0f;
float lastFrame = 0.0f;
unsigned int framebuffer = 0;
unsigned int textureColorBuffer = 0;
unsigned int quadVAO = 0;
unsigned int quadVBO = 0;
unsigned int rbo = 0;
float quadVertices[24] = {
// vertex attributes for a quad that fills the entire screen in Normalized Device Coordinates.
// positions // texCoords
-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
};
Scene(components::Scene& config):
shader{config.shader.vertex_path, config.shader.frag_path},
screen_shader{config.screen_shader.vertex_path, config.shader.frag_path},
materials{config.materials},
camera{
.position=config.camera.position,
.front=config.camera.front,
.up=config.camera.up,
.direction=config.camera.direction,
.movement_speed=config.camera.movement_speed,
},
light{config.light}
{
for(auto& [name, model] : config.models) {
models.try_emplace(name, model.directory, model.model_path);
}
for(auto& thing : config.things) {
things.emplace_back(
thing.model,
models.at(thing.model),
materials.at(thing.material),
thing.position,
thing.rotation,
thing.scale);
}
glGenVertexArrays(1, &quadVAO);
glGenBuffers(1, &quadVBO);
glBindVertexArray(quadVAO);
glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 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)));
shader.use();
shader.setInt("texture1", 0);
shader.apply_lighting(light);
screen_shader.use();
screen_shader.setInt("screenTexture", 0);
// framebuffer config
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
// framebuffer configuration
// -------------------------
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
// create a color attachment texture
glGenTextures(1, &textureColorBuffer);
glBindTexture(GL_TEXTURE_2D, textureColorBuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureColorBuffer, 0);
// create a renderbuffer object for depth and stencil attachment (we won't be sampling these)
glGenRenderbuffers(1, &rbo);
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, SCR_WIDTH, SCR_HEIGHT); // use a single renderbuffer object for both a depth AND stencil buffer.
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo); // now actually attach it
// now that we actually created the framebuffer and added all attachments we want to check if it is actually complete now
dbc::check(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, "Frame buffer not complete.");
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
void update();
void draw_thing(Shader& with_shader, Thing& thing);
void render(GLFWwindow* window);
void cleanup();
void spawn(const std::string& name, components::Position& position, components::Rotation& rotation);
};