fixes
This commit is contained in:
341
source/rendering/batch_renderers/mesh_batch_renderer.cpp
Normal file
341
source/rendering/batch_renderers/mesh_batch_renderer.cpp
Normal file
@@ -0,0 +1,341 @@
|
||||
#include "rendering/batch_renderers/mesh_batch_renderer.hpp"
|
||||
|
||||
#include "shader_program/uniforms/mesh_uniforms.hpp"
|
||||
#include "util/unroll_bool_template.hpp"
|
||||
#include "util/logger.hpp" // TODO remove
|
||||
#include <bitset> // TODOE remove
|
||||
|
||||
namespace rendering
|
||||
{
|
||||
|
||||
mesh_batch_renderer::mesh_batch_renderer(int render_mode_count)
|
||||
: m_render_mode_count{ render_mode_count } {};
|
||||
|
||||
std::pair<std::size_t, bool> mesh_batch_renderer::lookup_batch(
|
||||
const batch_components_type& batch_components
|
||||
) const {
|
||||
|
||||
const auto component_it = std::upper_bound(
|
||||
m_component_lookup.begin(), m_component_lookup.end(),
|
||||
batch_components,
|
||||
[](const auto& components, const auto& entry)
|
||||
{
|
||||
return components < entry.first;
|
||||
}
|
||||
);
|
||||
|
||||
const auto index = component_it - m_component_lookup.begin();
|
||||
|
||||
const auto match = (
|
||||
index != 0 and m_component_lookup[index - 1].first == batch_components
|
||||
);
|
||||
|
||||
return { index - static_cast<std::size_t>(match), match };
|
||||
}
|
||||
|
||||
std::optional<mesh_batch_renderer::id_type> mesh_batch_renderer::add(
|
||||
const batch_components_type& batch_component,
|
||||
const zgl::mesh_handle& mesh,
|
||||
const aabb& bounding_box,
|
||||
const zgl::model_matrix_handle& transform,
|
||||
const zgl::material_handle& material,
|
||||
const shader_program_lookups::mesh_lookup& shader_program_lookup
|
||||
) {
|
||||
const auto [ lookup_index, lookup_match ] = lookup_batch(batch_component);
|
||||
|
||||
std::size_t batch_index;
|
||||
batch_id_type batch_id;
|
||||
|
||||
if (lookup_match)
|
||||
{
|
||||
batch_index = m_component_lookup[lookup_index].second;
|
||||
batch_id = m_id_lookup[batch_index];
|
||||
}
|
||||
else
|
||||
{
|
||||
auto base_requirements = requirements::mesh::flags::position;
|
||||
|
||||
const auto [ vertex_comps, material_comps ] = batch_component;
|
||||
|
||||
// If no texture is provided, the uniform color is provided by ambient light.
|
||||
if ((material_comps & material_component::flags::texture) == material_component::flags::none)
|
||||
{
|
||||
base_requirements |= requirements::mesh::flags::uniform_color;
|
||||
}
|
||||
|
||||
ztu::logger::debug("vertex_comps: %", std::bitset<32>{ static_cast<unsigned long long>(static_cast<int>(vertex_comps)) });
|
||||
ztu::logger::debug("material_comps: %", std::bitset<32>{ static_cast<unsigned long long>(static_cast<int>(material_comps)) });
|
||||
ztu::logger::debug("lit reqs: %", std::bitset<32>{ static_cast<unsigned long long>(static_cast<int>(shader_program::capabilities::mesh::lit.uniforms)) });
|
||||
|
||||
|
||||
for (std::size_t i{}; i != requirements::mesh::all.size(); ++i)
|
||||
{
|
||||
const auto& requirement = requirements::mesh::all[i];
|
||||
|
||||
if (
|
||||
(
|
||||
requirement.vertex_requirements != components::mesh_vertex::flags::none and
|
||||
(vertex_comps & requirement.vertex_requirements) == requirement.vertex_requirements
|
||||
)
|
||||
and
|
||||
(
|
||||
requirement.material_requirements != material_component::flags::none and
|
||||
(material_comps & requirement.material_requirements) == requirement.material_requirements
|
||||
)
|
||||
) {
|
||||
base_requirements |= requirements::mesh::flags{ 1 << i };
|
||||
}
|
||||
}
|
||||
|
||||
ztu::logger::debug("base reqs: %", std::bitset<32>{ static_cast<unsigned long long>(static_cast<int>(base_requirements)) });
|
||||
|
||||
|
||||
const auto base_shader = shader_program_lookup.find(base_requirements);
|
||||
if (not base_shader)
|
||||
{
|
||||
ztu::logger::warn("Could not find base shader!");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const auto point_shader = shader_program_lookup.find(base_requirements | requirements::mesh::flags::point);
|
||||
if (not point_shader)
|
||||
{
|
||||
ztu::logger::warn("Could not find point shader!");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const auto lit_shader = shader_program_lookup.find(base_requirements | requirements::mesh::flags::lit);
|
||||
if (not lit_shader)
|
||||
{
|
||||
ztu::logger::warn("Could not find lit shader!");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto shader_programs = std::array{
|
||||
*base_shader,
|
||||
*point_shader,
|
||||
*base_shader,
|
||||
*lit_shader
|
||||
};
|
||||
|
||||
ztu::logger::debug(
|
||||
"shaders: % % %",
|
||||
base_shader->program_id,
|
||||
point_shader->program_id,
|
||||
lit_shader->program_id
|
||||
);
|
||||
|
||||
batch_index = m_batches.size();
|
||||
batch_id = m_next_batch_id++;
|
||||
m_batches.emplace_back(batch_type{}, batch_component);
|
||||
m_id_lookup.push_back(batch_id);
|
||||
m_component_lookup.emplace(m_component_lookup.begin() + lookup_index, batch_component, batch_index);
|
||||
m_shader_programs.insert(
|
||||
m_shader_programs.begin() + lookup_index,
|
||||
shader_programs.begin(), shader_programs.end()
|
||||
);
|
||||
}
|
||||
|
||||
auto& batch = m_batches[batch_index].first;
|
||||
|
||||
const auto mesh_id = batch.add(mesh, bounding_box, transform, material);
|
||||
|
||||
return id_type{ batch_id, mesh_id };
|
||||
}
|
||||
|
||||
std::optional<aabb> mesh_batch_renderer::bounding_box(id_type id)
|
||||
{
|
||||
const auto lookup_it = std::ranges::find(m_id_lookup, id.first);
|
||||
|
||||
if (lookup_it == m_id_lookup.end())
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const auto batch_index = lookup_it - m_id_lookup.begin();
|
||||
auto& batch = m_batches[batch_index].first;
|
||||
|
||||
return batch.bounding_box(id.second);
|
||||
}
|
||||
|
||||
bool mesh_batch_renderer::remove(const id_type id)
|
||||
{
|
||||
const auto lookup_it = std::ranges::find(m_id_lookup, id.first);
|
||||
|
||||
if (lookup_it == m_id_lookup.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto batch_index = lookup_it - m_id_lookup.begin();
|
||||
auto& batch = m_batches[batch_index].first;
|
||||
|
||||
// If batches can be removed the indices in m_component_lookup need to be changed.
|
||||
return batch.remove(id.second);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<bool Textured, bool Lit, bool Alpha>
|
||||
void render_mesh_batch(
|
||||
const zgl::shader_program_handle& shader_program,
|
||||
const mesh_batch& batch,
|
||||
const glm::mat4& vp_matrix,
|
||||
const glm::mat4& view_matrix,
|
||||
const GLenum draw_mode
|
||||
) {
|
||||
const auto meshes = batch.meshes();
|
||||
const auto transforms = batch.transforms();
|
||||
const auto textures = batch.textures();
|
||||
const auto surface_properties = batch.surface_properties();
|
||||
const auto alphas = batch.alphas();
|
||||
|
||||
/*ztu::logger::debug("meshes: %", meshes.size());
|
||||
ztu::logger::debug("transforms: %", transforms.size());
|
||||
ztu::logger::debug("textures: %", textures.size());
|
||||
ztu::logger::debug("surface_properties: %", surface_properties.size());
|
||||
ztu::logger::debug("alphas: %", alphas.size());
|
||||
|
||||
ztu::logger::debug("textured: % alpha: % lit: %", Textured, Alpha, Lit);*/
|
||||
|
||||
namespace uniforms = shader_program::uniforms::mesh;
|
||||
|
||||
for (std::size_t i{}; i != meshes.size(); ++i)
|
||||
{
|
||||
//ztu::logger::debug("Mesh: %", i);
|
||||
|
||||
const auto& mesh = meshes[i];
|
||||
const auto& model_matrix = transforms[i];
|
||||
|
||||
const auto mvp_matrix = vp_matrix * model_matrix;
|
||||
|
||||
shader_program.set_uniform<uniforms::mvp.info>(mvp_matrix);
|
||||
|
||||
if constexpr (Textured)
|
||||
{
|
||||
textures[i].bind();
|
||||
}
|
||||
|
||||
if constexpr (Lit)
|
||||
{
|
||||
shader_program.set_uniform<uniforms::model_matrix.info>(model_matrix);
|
||||
|
||||
// TODO more efficient set
|
||||
const auto& properties = surface_properties[i];
|
||||
shader_program.set_uniform<uniforms::ambient_filter.info>(properties.ambient_filter);
|
||||
shader_program.set_uniform<uniforms::diffuse_filter.info>(properties.diffuse_filter);
|
||||
shader_program.set_uniform<uniforms::specular_filter.info>(properties.specular_filter);
|
||||
shader_program.set_uniform<uniforms::shininess.info>(properties.shininess);
|
||||
}
|
||||
|
||||
if constexpr (Alpha)
|
||||
{
|
||||
|
||||
shader_program.set_uniform<uniforms::alpha.info>(alphas[i]);
|
||||
}
|
||||
|
||||
//ztu::logger::debug("vao: % valid: %%", mesh.vao_id, std::boolalpha, (bool)glIsVertexArray(mesh.vao_id));
|
||||
|
||||
mesh.bind();
|
||||
|
||||
//ztu::logger::debug("glDrawElements(%, %)", draw_mode, mesh.index_count);
|
||||
|
||||
glDrawElements(draw_mode, mesh.index_count, GL_UNSIGNED_INT, nullptr);
|
||||
|
||||
//ztu::logger::debug("done");
|
||||
}
|
||||
}
|
||||
|
||||
void mesh_batch_renderer::render(
|
||||
const modes::mesh render_mode,
|
||||
const glm::mat4& vp_matrix,
|
||||
const glm::mat4& view_matrix,
|
||||
const glm::vec3& view_pos,
|
||||
const lighting_setup& lights
|
||||
) {
|
||||
|
||||
namespace uniforms = shader_program::uniforms::mesh;
|
||||
|
||||
const auto render_mode_index = static_cast<int>(render_mode);
|
||||
|
||||
const auto lines = render_mode == modes::mesh::wire_frame;
|
||||
const auto points = render_mode == modes::mesh::points;
|
||||
const auto lit = render_mode == modes::mesh::lit_faces;
|
||||
|
||||
for (std::size_t i{}; i != m_batches.size(); ++i) {
|
||||
|
||||
//ztu::logger::debug("batch: %", i);
|
||||
|
||||
const auto& [ batch, batch_components ] = m_batches[i];
|
||||
|
||||
const auto [ vertex_components, material_components ] = batch_components;
|
||||
|
||||
const auto textured = (
|
||||
(vertex_components & components::mesh_vertex::flags::tex_coord) != components::mesh_vertex::flags::none
|
||||
and (material_components & material_component::flags::texture) != material_component::flags::none
|
||||
);
|
||||
|
||||
const auto alpha = (
|
||||
(material_components & material_component::flags::transparency) != material_component::flags::none
|
||||
);
|
||||
|
||||
const auto draw_mode = points ? GLenum{ GL_POINTS } : GLenum{ GL_TRIANGLES };
|
||||
|
||||
const auto& shader_program = m_shader_programs[i * m_render_mode_count + render_mode_index];
|
||||
|
||||
//ztu::logger::debug("shader_program: % valid: %%", shader_program.program_id, std::boolalpha, (bool)glIsProgram(shader_program.program_id));
|
||||
|
||||
shader_program.bind();
|
||||
|
||||
if (lit)
|
||||
{
|
||||
// TODO set more efficiently
|
||||
shader_program.set_uniform<uniforms::view_pos.info>(view_pos);
|
||||
shader_program.set_uniform<uniforms::point_light_direction.info>(lights.point_light_direction);
|
||||
shader_program.set_uniform<uniforms::point_light_color.info>(lights.point_light_color);
|
||||
shader_program.set_uniform<uniforms::ambient_light_color.info>(lights.ambient_light_color);
|
||||
}
|
||||
|
||||
if (textured)
|
||||
{
|
||||
constexpr auto texture_unit = 0;
|
||||
glActiveTexture(GL_TEXTURE0 + texture_unit);
|
||||
shader_program.set_uniform<uniforms::tex.info>(texture_unit);
|
||||
}
|
||||
else
|
||||
{
|
||||
shader_program.set_uniform<uniforms::color.info>(glm::vec4(lights.ambient_light_color, 1.0f));
|
||||
}
|
||||
|
||||
if (lines)
|
||||
{
|
||||
glPolygonMode(GL_FRONT, GL_LINE);
|
||||
glPolygonMode(GL_BACK, GL_LINE);
|
||||
}
|
||||
|
||||
unroll_bool_function_template(
|
||||
[&]<bool Textured, bool Lit, bool Alpha>() {
|
||||
render_mesh_batch<Textured, Lit, Alpha>(
|
||||
shader_program,
|
||||
batch,
|
||||
vp_matrix,
|
||||
view_matrix,
|
||||
draw_mode
|
||||
);
|
||||
},
|
||||
textured, lit, alpha
|
||||
);
|
||||
|
||||
if (lines)
|
||||
{
|
||||
glPolygonMode(GL_FRONT, GL_FILL);
|
||||
glPolygonMode(GL_BACK, GL_FILL);
|
||||
}
|
||||
}
|
||||
|
||||
zgl::texture_handle::unbind();
|
||||
zgl::mesh_handle::unbind();
|
||||
zgl::shader_program_handle::unbind();
|
||||
}
|
||||
|
||||
}
|
||||
243
source/rendering/batch_renderers/point_cloud_batch_renderer.cpp
Normal file
243
source/rendering/batch_renderers/point_cloud_batch_renderer.cpp
Normal file
@@ -0,0 +1,243 @@
|
||||
#include "rendering/batch_renderers/point_cloud_batch_renderer.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "rendering/requirements/point_cloud_requirements.hpp"
|
||||
#include "shader_program/uniforms/point_cloud_uniforms.hpp"
|
||||
#include "util/unroll_bool_template.hpp"
|
||||
|
||||
namespace rendering
|
||||
{
|
||||
|
||||
point_cloud_batch_renderer::point_cloud_batch_renderer(int render_mode_count)
|
||||
: m_render_mode_count{ render_mode_count } {};
|
||||
|
||||
std::pair<std::size_t, bool> point_cloud_batch_renderer::lookup_batch(
|
||||
const batch_components_type& batch_component
|
||||
) const {
|
||||
const auto component_it = std::upper_bound(
|
||||
m_component_lookup.begin(), m_component_lookup.end(),
|
||||
batch_component,
|
||||
[](const auto& batch_component, const auto& entry)
|
||||
{
|
||||
return batch_component < entry.first;
|
||||
}
|
||||
);
|
||||
|
||||
const auto index = component_it - m_component_lookup.begin();
|
||||
|
||||
const auto match = (
|
||||
index == 0 or m_component_lookup[index - 1].first == batch_component
|
||||
);
|
||||
|
||||
return { index - static_cast<std::size_t>(match), match };
|
||||
}
|
||||
|
||||
std::optional<point_cloud_batch_renderer::id_type> point_cloud_batch_renderer::add(
|
||||
batch_components_type batch_components,
|
||||
const zgl::point_cloud_handle& point_cloud,
|
||||
const aabb& bounding_box,
|
||||
const zgl::model_matrix_handle& transform,
|
||||
const shader_program_lookups::point_cloud_lookup& shader_program_lookup
|
||||
) {
|
||||
const auto [ lookup_index, lookup_match ] = lookup_batch(batch_components);
|
||||
|
||||
std::size_t batch_index;
|
||||
batch_id_type batch_id;
|
||||
|
||||
if (lookup_match) {
|
||||
batch_index = m_component_lookup[lookup_index].second;
|
||||
batch_id = m_id_lookup[batch_index];
|
||||
}
|
||||
else
|
||||
{
|
||||
auto base_requirements = requirements::point_cloud::flags{};
|
||||
|
||||
const auto vertex_comps = batch_components;
|
||||
|
||||
for (std::size_t i{}; i != requirements::point_cloud::all.size(); ++i)
|
||||
{
|
||||
const auto& requirement = requirements::point_cloud::all[i];
|
||||
|
||||
if (
|
||||
(vertex_comps & requirement.vertex_requirements) != components::point_cloud_vertex::flags::none
|
||||
) {
|
||||
base_requirements |= requirements::point_cloud::flags{ 1 << i };
|
||||
}
|
||||
}
|
||||
|
||||
const auto uniform_color_shader = shader_program_lookup.find(
|
||||
base_requirements | requirements::point_cloud::flags::uniform_color
|
||||
);
|
||||
|
||||
if (not uniform_color_shader)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const auto rainbow_shader = shader_program_lookup.find(
|
||||
base_requirements | requirements::point_cloud::flags::rainbow
|
||||
);
|
||||
|
||||
if (not rainbow_shader)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto shader_programs = std::array{
|
||||
*uniform_color_shader,
|
||||
*rainbow_shader
|
||||
};
|
||||
|
||||
batch_index = m_batches.size();
|
||||
batch_id = m_next_batch_id++;
|
||||
m_batches.emplace_back(batch_type{}, batch_components);
|
||||
m_id_lookup.push_back(batch_id);
|
||||
m_component_lookup.emplace(m_component_lookup.begin() + lookup_index, batch_components, batch_index);
|
||||
m_shader_programs.insert(
|
||||
m_shader_programs.begin() + lookup_index,
|
||||
shader_programs.begin(), shader_programs.end()
|
||||
);
|
||||
}
|
||||
|
||||
auto& batch = m_batches[batch_index].first;
|
||||
|
||||
const auto mesh_id = batch.add(point_cloud, bounding_box, transform);
|
||||
|
||||
return id_type{ batch_id, mesh_id };
|
||||
}
|
||||
|
||||
std::optional<aabb> point_cloud_batch_renderer::bounding_box(id_type id)
|
||||
{
|
||||
const auto lookup_it = std::ranges::find(m_id_lookup, id.first);
|
||||
|
||||
if (lookup_it == m_id_lookup.end())
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const auto batch_index = lookup_it - m_id_lookup.begin();
|
||||
auto& batch = m_batches[batch_index].first;
|
||||
|
||||
return batch.bounding_box(id.second);
|
||||
}
|
||||
|
||||
bool point_cloud_batch_renderer::remove(const id_type id)
|
||||
{
|
||||
const auto lookup_it = std::ranges::find(m_id_lookup, id.first);
|
||||
|
||||
if (lookup_it == m_id_lookup.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto batch_index = lookup_it - m_id_lookup.begin();
|
||||
auto& batch = m_batches[batch_index].first;
|
||||
|
||||
// If batches can be removed the indices in m_component_lookup need to be changed.
|
||||
return batch.remove(id.second);
|
||||
}
|
||||
|
||||
|
||||
template<bool Normals>
|
||||
void render_point_cloud_batch(
|
||||
const zgl::shader_program_handle& shader_program,
|
||||
const point_cloud_batch& batch,
|
||||
const glm::mat4& vp_matrix,
|
||||
const glm::vec3& camera_position
|
||||
) {
|
||||
const auto point_clouds = batch.point_clouds();
|
||||
const auto transforms = batch.transforms();
|
||||
|
||||
namespace uniforms = shader_program::uniforms::point_cloud;
|
||||
|
||||
for (std::size_t i{}; i != point_clouds.size(); ++i)
|
||||
{
|
||||
const auto& point_cloud = point_clouds[i];
|
||||
const auto& model_matrix = transforms[i];
|
||||
|
||||
// TODO check order
|
||||
const auto mvp_matrix = vp_matrix * model_matrix;
|
||||
|
||||
shader_program.set_uniform<uniforms::mvp.info>(mvp_matrix);
|
||||
|
||||
if constexpr (Normals)
|
||||
{
|
||||
shader_program.set_uniform<uniforms::model.info>(model_matrix);
|
||||
shader_program.set_uniform<uniforms::camera_position.info>(camera_position);
|
||||
}
|
||||
|
||||
point_cloud.bind();
|
||||
|
||||
using block_index_type = ztu::u16;
|
||||
static constexpr auto block_size = static_cast<std::size_t>(
|
||||
std::numeric_limits<block_index_type>::max()
|
||||
);
|
||||
|
||||
for (GLsizei j{}; j < point_cloud.point_count; j += block_size)
|
||||
{
|
||||
const auto points_left = static_cast<std::size_t>(point_cloud.point_count) - j;
|
||||
const auto points_in_block = std::min(points_left, block_size);
|
||||
glDrawArrays(
|
||||
GL_POINTS,
|
||||
j,
|
||||
static_cast<block_index_type>(points_in_block)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void point_cloud_batch_renderer::render(
|
||||
const modes::point_cloud render_mode,
|
||||
const glm::mat4& vp_matrix,
|
||||
const glm::vec3& camera_position,
|
||||
const lighting_setup&
|
||||
) {
|
||||
|
||||
namespace uniforms = shader_program::uniforms::point_cloud;
|
||||
|
||||
const auto render_mode_index = static_cast<std::size_t>(render_mode);
|
||||
|
||||
glEnable(GL_PROGRAM_POINT_SIZE);
|
||||
glEnable(GL_POINT_SMOOTH);
|
||||
|
||||
const auto rainbow = render_mode == modes::point_cloud::rainbow;
|
||||
|
||||
|
||||
for (std::size_t i{}; i != m_batches.size(); ++i) {
|
||||
|
||||
const auto& [ batch, vertex_components ] = m_batches[i];
|
||||
|
||||
const auto normals = static_cast<bool>(vertex_components & components::point_cloud_vertex::flags::normal);
|
||||
|
||||
const auto& shader_program = m_shader_programs[i * m_render_mode_count + render_mode_index];
|
||||
|
||||
shader_program.bind();
|
||||
|
||||
if (rainbow)
|
||||
{
|
||||
shader_program.set_uniform<uniforms::rainbow_offset_y.info>(0.0f); // TODO fix
|
||||
shader_program.set_uniform<uniforms::rainbow_scale_y.info>(0.0f); // TODO fix
|
||||
}
|
||||
|
||||
unroll_bool_function_template(
|
||||
[&]<bool Normals>() {
|
||||
render_point_cloud_batch<Normals>(
|
||||
shader_program,
|
||||
batch,
|
||||
vp_matrix,
|
||||
camera_position
|
||||
);
|
||||
},
|
||||
normals
|
||||
);
|
||||
}
|
||||
|
||||
glDisable(GL_PROGRAM_POINT_SIZE);
|
||||
glDisable(GL_POINT_SMOOTH);
|
||||
|
||||
zgl::point_cloud_handle::unbind();
|
||||
zgl::shader_program_handle::unbind();
|
||||
}
|
||||
|
||||
}
|
||||
147
source/rendering/batches/mesh_batch.ipp
Normal file
147
source/rendering/batches/mesh_batch.ipp
Normal file
@@ -0,0 +1,147 @@
|
||||
#ifndef INCLUDE_MESH_BATCH_IMPLEMENTATION
|
||||
# error Never include this file directly include 'mesh_batch.hpp'
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
inline mesh_batch::id_type mesh_batch::add(
|
||||
const zgl::mesh_handle& mesh,
|
||||
const aabb& bounding_box,
|
||||
const zgl::model_matrix_handle& transform,
|
||||
const zgl::material_handle& material
|
||||
) {
|
||||
std::size_t index;
|
||||
if (material.texture)
|
||||
{
|
||||
// Sort by texture id if possible, so meshes the same texture are rendered consecutively.
|
||||
const auto texture_it = std::ranges::upper_bound(
|
||||
m_textures,
|
||||
*material.texture,
|
||||
[](const auto& lhs, const auto& rhs)
|
||||
{
|
||||
return lhs.texture_id < rhs.texture_id;
|
||||
}
|
||||
);
|
||||
index = texture_it - m_textures.begin();
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO inserting by vao might split up texture sequence, this needs more attention
|
||||
// Otherwise, sort by vao, so meshes with the same vertices are rendered consecutively.
|
||||
const auto mesh_it = std::ranges::upper_bound(
|
||||
m_meshes,
|
||||
mesh,
|
||||
[](const auto& lhs, const auto& rhs)
|
||||
{
|
||||
return lhs.vao_id < rhs.vao_id;
|
||||
}
|
||||
);
|
||||
index = mesh_it - m_meshes.begin();
|
||||
}
|
||||
|
||||
m_meshes.insert(m_meshes.begin() + index, mesh);
|
||||
m_bounding_boxes.insert(m_bounding_boxes.begin() + index, bounding_box);
|
||||
m_transforms.insert(m_transforms.begin() + index, transform);
|
||||
|
||||
if (material.texture)
|
||||
{
|
||||
m_textures.insert(m_textures.begin() + index, *material.texture);
|
||||
}
|
||||
|
||||
if (material.surface_properties)
|
||||
{
|
||||
m_surface_properties.insert(m_surface_properties.begin() + index, *material.surface_properties);
|
||||
}
|
||||
|
||||
if (material.alpha)
|
||||
{
|
||||
m_alphas.insert(m_alphas.begin() + index, *material.alpha);
|
||||
}
|
||||
|
||||
const auto mesh_id = m_next_mesh_id++;
|
||||
|
||||
m_id_lookup.insert(m_id_lookup.begin() + index, mesh_id);
|
||||
|
||||
return mesh_id;
|
||||
}
|
||||
|
||||
std::optional<aabb> mesh_batch::bounding_box(id_type id)
|
||||
{
|
||||
const auto lookup_it = std::ranges::find(m_id_lookup, id);
|
||||
|
||||
if (lookup_it == m_id_lookup.end())
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const auto index = lookup_it - m_id_lookup.begin();
|
||||
|
||||
const auto& base_bounding_box = m_bounding_boxes[index];
|
||||
const auto& transform = m_transforms[index];
|
||||
|
||||
return base_bounding_box.transformed(transform);
|
||||
}
|
||||
|
||||
inline bool mesh_batch::remove(const id_type id)
|
||||
{
|
||||
const auto lookup_it = std::ranges::find(m_id_lookup, id);
|
||||
|
||||
if (lookup_it == m_id_lookup.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto index = lookup_it - m_id_lookup.begin();
|
||||
|
||||
m_id_lookup.erase(m_id_lookup.begin() + index);
|
||||
m_meshes.erase(m_meshes.begin() + index);
|
||||
m_bounding_boxes.erase(m_bounding_boxes.begin() + index);
|
||||
m_transforms.erase(m_transforms.begin() + index);
|
||||
|
||||
if (not m_textures.empty())
|
||||
{
|
||||
m_textures.erase(m_textures.begin() + index);
|
||||
}
|
||||
|
||||
if (not m_surface_properties.empty())
|
||||
{
|
||||
m_surface_properties.erase(m_surface_properties.begin() + index);
|
||||
}
|
||||
|
||||
if (not m_alphas.empty())
|
||||
{
|
||||
m_alphas.erase(m_alphas.begin() + index);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline std::span<const zgl::mesh_handle> mesh_batch::meshes() const
|
||||
{
|
||||
return m_meshes;
|
||||
}
|
||||
|
||||
inline std::span<const aabb> mesh_batch::bounding_boxes() const
|
||||
{
|
||||
return m_bounding_boxes;
|
||||
}
|
||||
|
||||
inline std::span<const zgl::model_matrix_handle> mesh_batch::transforms() const
|
||||
{
|
||||
return m_transforms;
|
||||
}
|
||||
|
||||
inline std::span<const zgl::texture_handle> mesh_batch::textures() const
|
||||
{
|
||||
return m_textures;
|
||||
}
|
||||
|
||||
inline std::span<const zgl::surface_properties_handle> mesh_batch::surface_properties() const
|
||||
{
|
||||
return m_surface_properties;
|
||||
}
|
||||
|
||||
inline std::span<const zgl::alpha_handle> mesh_batch::alphas() const
|
||||
{
|
||||
return m_alphas;
|
||||
}
|
||||
69
source/rendering/batches/point_cloud_batch.ipp
Normal file
69
source/rendering/batches/point_cloud_batch.ipp
Normal file
@@ -0,0 +1,69 @@
|
||||
#ifndef INCLUDE_POINT_CLOUD_BATCH_IMPLEMENTATION
|
||||
# error Never include this file directly include 'point_cloud_batch.hpp'
|
||||
#endif
|
||||
|
||||
|
||||
inline point_cloud_batch::id_type point_cloud_batch::add(
|
||||
const zgl::point_cloud_handle& point_cloud,
|
||||
const aabb& bounding_box,
|
||||
const zgl::model_matrix_handle& transform
|
||||
) {
|
||||
const auto new_id = m_next_id++;
|
||||
|
||||
m_point_clouds.push_back(point_cloud);
|
||||
m_transforms.push_back(transform);
|
||||
m_bounding_boxes.push_back(bounding_box);
|
||||
m_id_lookup.push_back(new_id);
|
||||
|
||||
return new_id;
|
||||
}
|
||||
|
||||
std::optional<aabb> point_cloud_batch::bounding_box(id_type id)
|
||||
{
|
||||
const auto lookup_it = std::ranges::find(m_id_lookup, id);
|
||||
|
||||
if (lookup_it == m_id_lookup.end())
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const auto index = lookup_it - m_id_lookup.begin();
|
||||
|
||||
const auto& base_bounding_box = m_bounding_boxes[index];
|
||||
const auto& transform = m_transforms[index];
|
||||
|
||||
return base_bounding_box.transformed(transform);
|
||||
}
|
||||
|
||||
inline bool point_cloud_batch::remove(id_type id)
|
||||
{
|
||||
const auto lookup_it = std::ranges::find(m_id_lookup, id);
|
||||
|
||||
if (lookup_it == m_id_lookup.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto index = lookup_it - m_id_lookup.begin();
|
||||
|
||||
m_id_lookup.erase(m_id_lookup.begin() + index);
|
||||
m_point_clouds.erase(m_point_clouds.begin() + index);
|
||||
m_transforms.erase(m_transforms.begin() + index);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline std::span<const zgl::point_cloud_handle> point_cloud_batch::point_clouds() const
|
||||
{
|
||||
return m_point_clouds;
|
||||
}
|
||||
|
||||
inline std::span<const zgl::model_matrix_handle> point_cloud_batch::transforms() const
|
||||
{
|
||||
return m_transforms;
|
||||
}
|
||||
|
||||
inline std::span<const aabb> point_cloud_batch::bounding_boxes() const
|
||||
{
|
||||
return m_bounding_boxes;
|
||||
}
|
||||
58
source/rendering/shader_program_lookups/mesh_lookup.cpp
Normal file
58
source/rendering/shader_program_lookups/mesh_lookup.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
#include "rendering/shader_program_lookups/mesh_lookup.hpp"
|
||||
|
||||
#include "util/logger.hpp" // TODO remove
|
||||
#include <bitset> // TODO remove
|
||||
|
||||
namespace rendering::shader_program_lookups
|
||||
{
|
||||
|
||||
void mesh_lookup::add(
|
||||
const zgl::shader_program_handle& shader_program_handle
|
||||
) {
|
||||
m_shader_program_lookup.add(
|
||||
shader_program_handle,
|
||||
shader_program::attributes::mesh::all,
|
||||
shader_program::uniforms::mesh::all
|
||||
);
|
||||
}
|
||||
|
||||
std::optional<zgl::shader_program_handle> mesh_lookup::find(
|
||||
requirements::mesh::flags requirements
|
||||
) const {
|
||||
auto capability = shader_program::capabilities::mesh::type{};
|
||||
|
||||
auto index = std::size_t{};
|
||||
|
||||
auto requirement_flags = static_cast<ztu::u32>(requirements);
|
||||
|
||||
while (requirement_flags)
|
||||
{
|
||||
if (requirement_flags & 1)
|
||||
{
|
||||
const auto shader_requirements_index = requirements::mesh::all[index].shader_program_requirement_index;
|
||||
const auto& [ attributes, uniforms ] = shader_program::capabilities::mesh::all[shader_requirements_index];
|
||||
capability.attributes |= attributes;
|
||||
capability.uniforms |= uniforms;
|
||||
}
|
||||
|
||||
requirement_flags >>= 1;
|
||||
++index;
|
||||
}
|
||||
|
||||
// TODO if not textured and not colored add ucolor "for free"
|
||||
|
||||
ztu::logger::debug("attributes reqs: %", std::bitset<32>{ static_cast<unsigned long long>(static_cast<int>(capability.attributes)) });
|
||||
ztu::logger::debug("uniforms reqs: %", std::bitset<32>{ static_cast<unsigned long long>(static_cast<int>(capability.uniforms)) });
|
||||
|
||||
return m_shader_program_lookup.find(
|
||||
static_cast<ztu::u32>(capability.attributes),
|
||||
static_cast<ztu::u32>(capability.uniforms),
|
||||
shader_program::attributes::mesh::all
|
||||
);
|
||||
}
|
||||
|
||||
void mesh_lookup::print() {
|
||||
m_shader_program_lookup.print();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
#include "rendering/shader_program_lookups/point_cloud_lookup.hpp"
|
||||
|
||||
namespace rendering::shader_program_lookups
|
||||
{
|
||||
|
||||
void point_cloud_lookup::add(
|
||||
const zgl::shader_program_handle& shader_program_handle
|
||||
) {
|
||||
m_program_lookup.add(
|
||||
shader_program_handle,
|
||||
shader_program::attributes::point_cloud::all,
|
||||
shader_program::uniforms::point_cloud::all
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
std::optional<zgl::shader_program_handle> point_cloud_lookup::find(
|
||||
requirements::point_cloud::flags requirements
|
||||
) const {
|
||||
auto capability = shader_program::capabilities::point_cloud::type{};
|
||||
|
||||
auto index = std::size_t{};
|
||||
|
||||
auto requirement_flags = static_cast<ztu::u32>(requirements);
|
||||
|
||||
while (requirement_flags)
|
||||
{
|
||||
if (requirement_flags & 1)
|
||||
{
|
||||
const auto shader_requirements_index = requirements::point_cloud::all[index].shader_program_requirement_index;
|
||||
const auto& [ attributes, uniforms ] = shader_program::capabilities::point_cloud::all[shader_requirements_index];
|
||||
capability.attributes |= attributes;
|
||||
capability.uniforms |= uniforms;
|
||||
}
|
||||
|
||||
requirement_flags >>= 1;
|
||||
++index;
|
||||
}
|
||||
|
||||
return m_program_lookup.find(
|
||||
static_cast<ztu::u32>(capability.attributes),
|
||||
static_cast<ztu::u32>(capability.uniforms),
|
||||
shader_program::attributes::point_cloud::all
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user