All checks were successful
Build (Arch Linux) / build (push) Successful in 3m10s
164 lines
5.5 KiB
C++
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
|