* 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.
173 lines
4.6 KiB
C++
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
|