kuiper-engine/include/renderer/gl_renderer.hpp
Adam Macdonald a8d8b9b9ab
All checks were successful
Build (Arch Linux) / build (push) Successful in 3m10s
initial commit
2025-04-16 01:58:29 +01:00

164 lines
5.5 KiB
C++

#pragma once
#include "components/camera.hpp"
#include "components/lights.hpp"
#include "graphics/opengl/buffer.hpp"
#include "graphics/opengl/framebuffer.hpp"
#include "graphics/opengl/program.hpp"
#include "graphics/opengl/vertex_array.hpp"
#include "maths/transform.hpp"
#include "resources/material.hpp"
#include "resources/model.hpp"
#include "resources/primitive.hpp"
#include <glad/gl.h>
#include <array>
#include <glm/ext/matrix_transform.hpp>
#include <glm/mat4x4.hpp>
#include <glm/vec3.hpp>
#include <glm/vec4.hpp>
#include <cstddef>
#include <cstdint>
#include <limits>
#include <utility>
#include <vector>
namespace kuiper
{
namespace gl
{
static constexpr std::size_t MAX_NUM_LIGHTS = 100;
static constexpr std::size_t LIGHT_SSBO_INIT_SIZE = 1000;
static constexpr std::uint32_t NUM_CLUSTERS_X = 12;
static constexpr std::uint32_t NUM_CLUSTERS_Y = 12;
static constexpr std::uint32_t NUM_CLUSTERS_Z = 24;
static constexpr std::uint32_t NUM_CLUSTERS = NUM_CLUSTERS_X * NUM_CLUSTERS_Y * NUM_CLUSTERS_Z;
static constexpr std::uint32_t LOCAL_SIZE = 128;
static constexpr float NEAR_Z_DEPTH = 0.1f;
static constexpr float FAR_Z_DEPTH = std::numeric_limits<std::uint16_t>::max();
struct gl_state {
// Vertex & element buffers
vertex_array::s_ptr vao {nullptr};
buffer::s_ptr vertex_buffer {nullptr};
buffer::s_ptr index_buffer {nullptr};
// Indirect & model matrix buffer
buffer::s_ptr indirect_buffer {nullptr};
buffer::s_ptr matrix_buffer {nullptr};
// Shaders
program::s_ptr pbr_shader {nullptr};
program::s_ptr clustering_shader {nullptr};
program::s_ptr light_culling_shader {nullptr};
// Lighting buffers
buffer::s_ptr cluster_buffer {nullptr};
buffer::s_ptr lights_buffer {nullptr};
// Configuration
std::uint32_t max_texture_units {32};
std::vector<std::int32_t> texture_unit_slots {};
};
struct renderer_metrics {
std::size_t n_vertices {};
std::size_t n_indices {};
std::size_t n_draw_cmds {};
std::size_t n_matrices {};
std::size_t n_materials {};
std::size_t n_lights {};
};
class renderer {
public:
using vertex_t = vertex;
using index_t = std::uint32_t;
struct draw_elements_indirect_cmd {
std::uint32_t count {0};
std::uint32_t instance_count {0};
std::uint32_t first_index {0};
std::uint32_t base_vertex {0};
std::uint32_t base_instance {0};
};
struct alignas(4) render_matrices {
glm::mat4 model_matrix;
glm::mat3 normal_matrix;
};
struct alignas(16) cluster {
glm::vec4 min_point;
glm::vec4 max_point;
std::uint32_t count;
std::uint32_t light_indices[MAX_NUM_LIGHTS];
};
struct alignas(16) point_light {
glm::vec4 position;
glm::vec4 colour;
float intensity;
float radius;
};
private:
using vertex_storage_t = std::vector<vertex_t>;
using index_storage_t = std::vector<index_t>;
using draw_cmd_storage_t = std::vector<draw_elements_indirect_cmd>;
using matrix_storage_t = std::vector<render_matrices>;
using material_storage_t = std::vector<resource::material>;
using light_storage_t = std::vector<point_light>;
public:
renderer(gl_state&& state)
: m_state(std::move(state)) {}
~renderer() = default;
renderer(const renderer&) = delete;
renderer& operator=(const renderer&) = delete;
renderer(renderer&&) noexcept = delete;
renderer& operator=(renderer&&) noexcept = delete;
static renderer init();
void render(const framebuffer::s_ptr& framebuffer,
const glm::vec3& cam_pos,
const component::camera_props& cam_props) noexcept;
void flush() noexcept;
renderer_metrics metrics() const noexcept;
void draw_model(const resource::model& model, const maths::transform_euler& transform);
void draw_mesh(const resource::mesh& mesh,
const std::vector<resource::material>& materials,
const glm::mat4& transform);
void draw_primitive(const resource::primitive& primitive,
const resource::material& material,
const maths::transform_euler& transform);
void draw_primitive(const resource::primitive& primitive,
const resource::material& material,
const glm::mat4& transform);
void add_light(const glm::vec3& pos, const component::point_light& light) noexcept;
private:
void update_and_upload() noexcept;
private:
gl_state m_state {};
vertex_storage_t m_vertices {};
index_storage_t m_indices {};
draw_cmd_storage_t m_draw_cmds {};
matrix_storage_t m_matrices {};
material_storage_t m_materials {};
light_storage_t m_lights {};
};
} // namespace gl
} // namespace kuiper