Files
MapLibreParticleLab/src/mbgl/gl/attribute.hpp
John Firebaugh 1db2ffbc1b [core] Use gl::Program to resolve some rough edges in the GL binding types
* Extract `ignore` util to separate header.
* `Segment` now tracks offset and length of indices, rather than primitives. This is more natural.
* Introduce `VertexVector` and `IndexVector` types. These types carry information about the intended draw mode (`Triangles`, `LineStrip`, etc.), and ensure that elements are always appended in a group size appropriate for that draw mode, for both indexed and unindexed rendering.
* `Program`, rather than `Drawable`, is now the unifying object for draw calls. `Program` is the best place to type check the draw call, because it is typed to carry information about the intended primitive, vertex type, attributes, and uniforms.
* Use the debug shaders for debug tile rendering, like gl-js.
* Fix the draw mode for background. It was drawing triangle strips with a triangles array. Surprised this didn’t cause issues. Now it’s type checked.
2016-11-08 08:09:29 -08:00

173 lines
4.6 KiB
C++

#pragma once
#include <mbgl/gl/types.hpp>
#include <mbgl/util/ignore.hpp>
#include <cstddef>
#include <functional>
#include <tuple>
#include <utility>
namespace mbgl {
namespace gl {
template <class Tag, class T, std::size_t N>
class Attribute {
public:
using Type = T[N];
class State {
public:
AttributeLocation location;
static constexpr std::size_t count = N;
static constexpr DataType type = DataTypeOf<T>::value;
};
};
#define MBGL_DEFINE_ATTRIBUTE(type_, n_, name_) \
struct name_ : ::mbgl::gl::Attribute<name_, type_, n_> { static constexpr auto name = #name_; }
namespace detail {
// Attribute binding requires member offsets. The only standard way to
// obtain an offset is the offsetof macro. The offsetof macro has defined
// behavior only for standard layout types. That rules out std::tuple and
// any other solution that relies on chained inheritance. Manually implemented
// variadic specialization looks like the only solution. Fortunately, we
// only use a maximum of five attributes.
template <class... As>
class Vertex;
template <class A1>
class Vertex<A1> {
public:
typename A1::Type a1;
using VertexType = Vertex<A1>;
static const std::size_t attributeOffsets[1];
};
template <class A1, class A2>
class Vertex<A1, A2> {
public:
typename A1::Type a1;
typename A2::Type a2;
using VertexType = Vertex<A1, A2>;
static const std::size_t attributeOffsets[2];
};
template <class A1, class A2, class A3>
class Vertex<A1, A2, A3> {
public:
typename A1::Type a1;
typename A2::Type a2;
typename A3::Type a3;
using VertexType = Vertex<A1, A2, A3>;
static const std::size_t attributeOffsets[3];
};
template <class A1, class A2, class A3, class A4>
class Vertex<A1, A2, A3, A4> {
public:
typename A1::Type a1;
typename A2::Type a2;
typename A3::Type a3;
typename A4::Type a4;
using VertexType = Vertex<A1, A2, A3, A4>;
static const std::size_t attributeOffsets[4];
};
template <class A1, class A2, class A3, class A4, class A5>
class Vertex<A1, A2, A3, A4, A5> {
public:
typename A1::Type a1;
typename A2::Type a2;
typename A3::Type a3;
typename A4::Type a4;
typename A5::Type a5;
using VertexType = Vertex<A1, A2, A3, A4, A5>;
static const std::size_t attributeOffsets[5];
};
template <class A1>
const std::size_t Vertex<A1>::attributeOffsets[1] = {
offsetof(VertexType, a1)
};
template <class A1, class A2>
const std::size_t Vertex<A1, A2>::attributeOffsets[2] = {
offsetof(VertexType, a1),
offsetof(VertexType, a2)
};
template <class A1, class A2, class A3>
const std::size_t Vertex<A1, A2, A3>::attributeOffsets[3] = {
offsetof(VertexType, a1),
offsetof(VertexType, a2),
offsetof(VertexType, a3)
};
template <class A1, class A2, class A3, class A4>
const std::size_t Vertex<A1, A2, A3, A4>::attributeOffsets[4] = {
offsetof(VertexType, a1),
offsetof(VertexType, a2),
offsetof(VertexType, a3),
offsetof(VertexType, a4)
};
template <class A1, class A2, class A3, class A4, class A5>
const std::size_t Vertex<A1, A2, A3, A4, A5>::attributeOffsets[5] = {
offsetof(VertexType, a1),
offsetof(VertexType, a2),
offsetof(VertexType, a3),
offsetof(VertexType, a4),
offsetof(VertexType, a5)
};
} // namespace detail
AttributeLocation attributeLocation(ProgramID, const char * name);
void bindAttribute(AttributeLocation location,
std::size_t count,
DataType type,
std::size_t vertexSize,
std::size_t vertexOffset,
std::size_t attributeOffset);
template <class... As>
class Attributes {
public:
using State = std::tuple<typename As::State...>;
using Vertex = detail::Vertex<As...>;
static State state(const ProgramID& id) {
return State { { attributeLocation(id, As::name) }... };
}
static std::function<void (std::size_t)> binder(const State& state) {
return binder(state, std::index_sequence_for<As...>());
}
private:
template <std::size_t... Is>
static std::function<void (std::size_t)> binder(const State& state, std::index_sequence<Is...>) {
return [&state] (std::size_t vertexOffset) {
ignore((bindAttribute(std::get<Is>(state).location,
std::get<Is>(state).count,
std::get<Is>(state).type,
sizeof(Vertex),
vertexOffset,
Vertex::attributeOffsets[Is]), 0)...);
};
}
};
} // namespace gl
} // namespace mbgl