Refactor mesh setup & properly disable old attribs on re-setup
This commit is contained in:
parent
e9af93b747
commit
d807d5c74b
1 changed files with 64 additions and 54 deletions
|
|
@ -267,46 +267,50 @@ namespace psemek::gfx
|
|||
}
|
||||
};
|
||||
|
||||
template <bool IsInstanced, bool InstanceSetup, typename ... Attribs>
|
||||
struct mesh_setup_base;
|
||||
|
||||
template <bool IsInstanced, bool InstanceSetup>
|
||||
struct mesh_setup_base<IsInstanced, InstanceSetup>
|
||||
struct mesh_setup_result
|
||||
{
|
||||
static std::size_t setup()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void setup_impl(int, std::size_t, std::size_t)
|
||||
{}
|
||||
std::size_t stride;
|
||||
std::size_t max_index;
|
||||
};
|
||||
|
||||
template <bool IsInstanced, bool InstanceSetup, typename Attr1, typename ... Attribs>
|
||||
struct mesh_setup_base<IsInstanced, InstanceSetup, Attr1, Attribs...>
|
||||
template <bool InstanceSetup, typename ... Attribs>
|
||||
struct mesh_setup_base;
|
||||
|
||||
template <bool InstanceSetup>
|
||||
struct mesh_setup_base<InstanceSetup>
|
||||
{
|
||||
static std::size_t setup()
|
||||
static mesh_setup_result setup()
|
||||
{
|
||||
std::size_t const stride = stride_helper<InstanceSetup, Attr1, Attribs...>::stride();
|
||||
setup_impl(0, 0, stride);
|
||||
return stride;
|
||||
return {0, 0};
|
||||
}
|
||||
|
||||
static void setup_impl(int index, std::size_t offset, std::size_t stride)
|
||||
static std::size_t setup_impl(std::size_t index, std::size_t, std::size_t)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
};
|
||||
|
||||
template <bool InstanceSetup, typename Attr1, typename ... Attribs>
|
||||
struct mesh_setup_base<InstanceSetup, Attr1, Attribs...>
|
||||
{
|
||||
static mesh_setup_result setup()
|
||||
{
|
||||
std::size_t const stride = stride_helper<InstanceSetup, Attr1, Attribs...>::stride();
|
||||
auto const max_index = setup_impl(0, 0, stride);
|
||||
return {stride, max_index};
|
||||
}
|
||||
|
||||
static std::size_t setup_impl(std::size_t index, std::size_t offset, std::size_t stride)
|
||||
{
|
||||
if constexpr (std::is_same_v<Attr1, skip>)
|
||||
{
|
||||
mesh_setup_base<IsInstanced, InstanceSetup, Attribs...>::setup_impl(index + 1, offset, stride);
|
||||
return mesh_setup_base<InstanceSetup, Attribs...>::setup_impl(index + 1, offset, stride);
|
||||
}
|
||||
else if constexpr (is_padding<Attr1>::value)
|
||||
{
|
||||
mesh_setup_base<IsInstanced, InstanceSetup, Attribs...>::setup_impl(index, offset + Attr1::size, stride);
|
||||
return mesh_setup_base<InstanceSetup, Attribs...>::setup_impl(index, offset + Attr1::size, stride);
|
||||
}
|
||||
else if constexpr (!IsInstanced && is_instanced<Attr1>::value)
|
||||
{
|
||||
static_assert("cannot use instanced attribute for non-instanced mesh");
|
||||
}
|
||||
else if constexpr (!IsInstanced || (is_instanced<Attr1>::value == InstanceSetup))
|
||||
else if constexpr (is_instanced<Attr1>::value == InstanceSetup)
|
||||
{
|
||||
using attr = typename remove_instanced<Attr1>::type;
|
||||
|
||||
|
|
@ -324,7 +328,7 @@ namespace psemek::gfx
|
|||
gl::VertexAttribDivisor(index + row, 1);
|
||||
}
|
||||
|
||||
mesh_setup_base<IsInstanced, InstanceSetup, Attribs...>::setup_impl(index + attr::rows, offset + attr_size<Attr1>(), stride);
|
||||
return mesh_setup_base<InstanceSetup, Attribs...>::setup_impl(index + attr::rows, offset + attr_size<Attr1>(), stride);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -336,7 +340,7 @@ namespace psemek::gfx
|
|||
gl::EnableVertexAttribArray(index);
|
||||
gl::VertexAttribPointer(index, traits::size, traits::type, traits::normalized, stride, reinterpret_cast<char const *>(offset));
|
||||
|
||||
mesh_setup_base<IsInstanced, InstanceSetup, Attribs...>::setup_impl(index + 1, offset + attr_size<Attr1>(), stride);
|
||||
return mesh_setup_base<InstanceSetup, Attribs...>::setup_impl(index + 1, offset + attr_size<Attr1>(), stride);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -345,24 +349,39 @@ namespace psemek::gfx
|
|||
|
||||
if constexpr (is_matrix<attr>::value)
|
||||
{
|
||||
mesh_setup_base<IsInstanced, InstanceSetup, Attribs...>::setup_impl(index + attr::rows, offset, stride);
|
||||
return mesh_setup_base<InstanceSetup, Attribs...>::setup_impl(index + attr::rows, offset, stride);
|
||||
}
|
||||
else
|
||||
{
|
||||
mesh_setup_base<IsInstanced, InstanceSetup, Attribs...>::setup_impl(index + 1, offset, stride);
|
||||
return mesh_setup_base<InstanceSetup, Attribs...>::setup_impl(index + 1, offset, stride);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ... Attribs>
|
||||
using mesh_setup = mesh_setup_base<false, false, Attribs...>;
|
||||
using mesh_vertex_setup = mesh_setup_base<false, Attribs...>;
|
||||
|
||||
template <typename ... Attribs>
|
||||
using instanced_mesh_vertex_setup = mesh_setup_base<true, false, Attribs...>;
|
||||
using mesh_instance_setup = mesh_setup_base<true, Attribs...>;
|
||||
|
||||
template <typename ... Attribs>
|
||||
using instanced_mesh_instance_setup = mesh_setup_base<true, true, Attribs...>;
|
||||
template <typename ... Args>
|
||||
struct has_instanced_attribs_impl
|
||||
: std::false_type
|
||||
{};
|
||||
|
||||
template <typename T, typename ... Args>
|
||||
struct has_instanced_attribs_impl<T, Args...>
|
||||
: has_instanced_attribs_impl<Args...>
|
||||
{};
|
||||
|
||||
template <typename T, typename ... Args>
|
||||
struct has_instanced_attribs_impl<instanced<T>, Args...>
|
||||
: std::true_type
|
||||
{};
|
||||
|
||||
template <typename ... Args>
|
||||
constexpr bool has_instanced_attribs = has_instanced_attribs_impl<Args...>::value;
|
||||
|
||||
template <typename T>
|
||||
struct gl_type;
|
||||
|
|
@ -433,24 +452,6 @@ namespace psemek::gfx
|
|||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename ... Args>
|
||||
struct has_instanced_attribs_impl
|
||||
: std::false_type
|
||||
{};
|
||||
|
||||
template <typename T, typename ... Args>
|
||||
struct has_instanced_attribs_impl<T, Args...>
|
||||
: has_instanced_attribs_impl<Args...>
|
||||
{};
|
||||
|
||||
template <typename T, typename ... Args>
|
||||
struct has_instanced_attribs_impl<instanced<T>, Args...>
|
||||
: std::true_type
|
||||
{};
|
||||
|
||||
template <typename ... Args>
|
||||
constexpr bool has_instanced_attribs = has_instanced_attribs_impl<Args...>::value;
|
||||
}
|
||||
|
||||
/* A generic mesh class
|
||||
|
|
@ -549,6 +550,8 @@ namespace psemek::gfx
|
|||
|
||||
GLenum primitive_type_;
|
||||
GLenum index_type_;
|
||||
|
||||
std::size_t max_attribute_index_ = 0;
|
||||
};
|
||||
|
||||
mesh_info info_;
|
||||
|
|
@ -559,16 +562,23 @@ namespace psemek::gfx
|
|||
{
|
||||
array_.bind();
|
||||
|
||||
for (std::size_t i = 0; i < info_.max_attribute_index_; ++i)
|
||||
gl::DisableVertexAttribArray(i);
|
||||
|
||||
if (!vertex_buffer_) vertex_buffer_ = buffer{};
|
||||
vertex_buffer_.bind();
|
||||
info_.stride_ = detail::instanced_mesh_vertex_setup<Attribs...>::setup();
|
||||
auto vertex_setup = detail::mesh_vertex_setup<Attribs...>::setup();
|
||||
info_.stride_ = vertex_setup.stride;
|
||||
info_.max_attribute_index_ = vertex_setup.max_index;
|
||||
|
||||
if constexpr (detail::has_instanced_attribs<Attribs...>)
|
||||
{
|
||||
if (!instance_buffer_) instance_buffer_ = buffer{};
|
||||
instance_buffer_.bind();
|
||||
info_.instance_stride_ = detail::instanced_mesh_instance_setup<Attribs...>::setup();
|
||||
auto instance_setup = detail::mesh_instance_setup<Attribs...>::setup();
|
||||
info_.instance_stride_ = instance_setup.stride;
|
||||
info_.instanced_ = true;
|
||||
info_.max_attribute_index_ = std::max(info_.max_attribute_index_, instance_setup.max_index);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue