#pragma once #include #include #include #include #include #include "shader.hpp" #include "model.hpp" #include "shader.hpp" #include "model.hpp" #include "camera.hpp" #include "components.hpp" #include #include 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 materials; Camera camera; components::Lighting light; std::unordered_map models; std::vector 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); };