Browse Source

Ability to specify shader attribute properties fully at runtime.

There's a new DynamicAttribute class that is very similar to Attribute,
but it has the location and base type as runtime properties instead of
them being a part of template. This allows for more flexibility, but
OTOH also more typing and more responsibility on the user. See
MeshGLTest for details and usage comparison to the Attribute API.
pull/217/head
Vladimír Vondruš 9 years ago
parent
commit
f1982f2e1b
  1. 193
      src/Magnum/Attribute.h
  2. 31
      src/Magnum/Mesh.cpp
  3. 63
      src/Magnum/Mesh.h
  4. 516
      src/Magnum/Test/MeshGLTest.cpp

193
src/Magnum/Attribute.h

@ -101,6 +101,7 @@ template<UnsignedInt location, class T> class Attribute {
* Count of components passed to the shader. If passing smaller count
* of components than corresponding type has, unspecified components
* are set to default values (second and third to `0`, fourth to `1`).
* @see @ref Attribute()
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
enum class Components: GLint {
@ -307,6 +308,198 @@ template<class T> Debug& operator<<(Debug& debug, Attribute<T>::Components);
template<class T> Debug& operator<<(Debug& debug, Attribute<T>::DataType);
#endif
/**
@brief Base class for dynamic attribute location and type
Counterpart to @ref Attribute that allows runtime specification of attribute
location and base type. Note that unlike the compile-time specification, this
class doesn't do any sanity verification and leaves most of the responsibility
on the user.
*/
class DynamicAttribute {
public:
/**
* @brief Attribute kind
*
* Specifies what kind of shader type matches the attribute.
* @see @ref DynamicAttribute()
*/
enum class Kind {
/** Generic, matches single-precision floating-point shader type */
Generic,
/**
* Normalized integral, matches single-precision floating-point
* shader type
*/
GenericNormalized,
#ifndef MAGNUM_TARGET_GLES2
/** Integral, matches integral shader type */
Integral,
#ifndef MAGNUM_TARGET_GLES
/** Long, matches double-precision shader type */
Long
#endif
#endif
};
/**
* @brief Component count
*
* Count of components passed to the shader. If passing smaller count
* of components than corresponding type has, unspecified components
* are set to default values (second and third to `0`, fourth to `1`).
* @see @ref DynamicAttribute()
*/
enum class Components: GLint {
/**
* Only first component is specified. Second, third and fourth
* component are set to `0`, `0`, `1`, respectively. Only for
* scalar and vector types, not matrices.
*/
One = 1,
/**
* First two components are specified. Third and fourth component
* are set to `0`, `1`, respectively. Only for two, three and
* four-component vector types and 2x2, 3x2 and 4x2 matrix types.
*/
Two = 2,
/**
* First three components are specified. Fourth component is set to
* `1`. Only for three and four-component vector types, 2x3, 3x3
* and 4x3 matrix types.
*/
Three = 3,
/**
* All four components are specified. Only for four-component
* vector types and 2x4, 3x4 and 4x4 matrix types.
*/
Four = 4,
#ifndef MAGNUM_TARGET_GLES
/**
* Four components with BGRA ordering. Only for four-component
* float vector type. Must be used along with @ref DataType::UnsignedByte
* and @ref Kind::GenericNormalized.
* @requires_gl32 Extension @extension{ARB,vertex_array_bgra}
* @requires_gl Only RGBA component ordering is supported in OpenGL
* ES and WebGL.
*/
BGRA = GL_BGRA
#endif
};
/**
* @brief Data type
*
* Type of data passed to shader.
* @see @ref Kind, @ref DynamicAttribute()
*/
enum class DataType: GLenum {
UnsignedByte = GL_UNSIGNED_BYTE, /**< Unsigned byte */
Byte = GL_BYTE, /**< Byte */
UnsignedShort = GL_UNSIGNED_SHORT, /**< Unsigned short */
Short = GL_SHORT, /**< Short */
UnsignedInt = GL_UNSIGNED_INT, /**< Unsigned int */
Int = GL_INT, /**< Int */
#ifndef MAGNUM_TARGET_WEBGL
/**
* Half float. Only for float attribute types.
* @requires_gl30 Extension @extension{ARB,half_float_vertex}
* @requires_gles30 Extension @extension{OES,vertex_half_float}
* in OpenGL ES 2.0
* @requires_webgl20 Half float vertex attributes are not available
* in WebGL 1.0.
*/
#ifndef MAGNUM_TARGET_GLES2
HalfFloat = GL_HALF_FLOAT,
#else
HalfFloat = GL_HALF_FLOAT_OES,
#endif
#endif
/** Float. Only for float attribute types. */
Float = GL_FLOAT,
#ifndef MAGNUM_TARGET_GLES
/**
* Double. Only for float and double attribute types.
* @requires_gl Only floats are available in OpenGL ES or WebGL.
*/
Double = GL_DOUBLE,
/**
* Unsigned 10.11.11 packed float. Only for three-component float
* vector attribute type.
* @requires_gl44 Extension @extension{ARB,vertex_type_10f_11f_11f_rev}
* @requires_gl Packed float attributes are not available in OpenGL
* ES or WebGL.
*/
UnsignedInt10f11f11fRev = GL_UNSIGNED_INT_10F_11F_11F_REV,
#endif
/* GL_FIXED not supported */
#ifndef MAGNUM_TARGET_GLES2
/**
* Unsigned 2.10.10.10 packed integer. Only for four-component
* float vector attribute type.
* @todo How about (incompatible) @extension{OES,vertex_type_10_10_10_2}?
* @requires_gl33 Extension @extension{ARB,vertex_type_2_10_10_10_rev}
* @requires_gles30 Packed attributes are not available in OpenGL
* ES 2.0.
* @requires_webgl20 Packed attributes are not available in WebGL
* 1.0.
*/
UnsignedInt2101010Rev = GL_UNSIGNED_INT_2_10_10_10_REV,
/**
* Signed 2.10.10.10 packed integer. Only for four-component float
* vector attribute type.
* @requires_gl33 Extension @extension{ARB,vertex_type_2_10_10_10_rev}
* @requires_gles30 Packed attributes are not available in OpenGL
* ES 2.0.
* @requires_webgl20 Packed attributes are not available in WebGL
* 1.0.
*/
Int2101010Rev = GL_INT_2_10_10_10_REV
#endif
};
/**
* @brief Constructor
* @param kind Attribute kind
* @param location Attribute location
* @param components Component count
* @param dataType Type of passed data
*/
constexpr DynamicAttribute(Kind kind, UnsignedInt location, Components components, DataType dataType): _kind{kind}, _location{location}, _components{components}, _dataType{dataType} {}
/** @brief Attribute kind */
constexpr Kind kind() const { return _kind; }
/** @brief Attribute location */
constexpr UnsignedInt location() const { return _location; }
/** @brief Component count of passed data */
constexpr Components components() const { return _components; }
/** @brief Type of passed data */
constexpr DataType dataType() const { return _dataType; }
private:
Kind _kind;
UnsignedInt _location;
Components _components;
DataType _dataType;
};
namespace Implementation {
/* Base for sized attributes */

31
src/Magnum/Mesh.cpp

@ -45,7 +45,7 @@
namespace Magnum {
struct Mesh::AttributeLayout {
explicit AttributeLayout(const Buffer& buffer, GLuint location, GLint size, GLenum type, AttributeKind kind, GLintptr offset, GLsizei stride, GLuint divisor) noexcept: buffer{Buffer::wrap(buffer.id())}, location{location}, size{size}, type{type}, kind{kind}, offset{offset}, stride{stride}, divisor{divisor} {}
explicit AttributeLayout(const Buffer& buffer, GLuint location, GLint size, GLenum type, DynamicAttribute::Kind kind, GLintptr offset, GLsizei stride, GLuint divisor) noexcept: buffer{Buffer::wrap(buffer.id())}, location{location}, size{size}, type{type}, kind{kind}, offset{offset}, stride{stride}, divisor{divisor} {}
explicit AttributeLayout(const AttributeLayout& other): buffer{Buffer::wrap(other.buffer.id())}, location{other.location}, size{other.size}, type{other.type}, kind{other.kind}, offset{other.offset}, stride{other.stride}, divisor{other.divisor} {}
@ -53,7 +53,7 @@ struct Mesh::AttributeLayout {
GLuint location;
GLint size;
GLenum type;
AttributeKind kind;
DynamicAttribute::Kind kind;
GLintptr offset;
GLsizei stride;
GLuint divisor;
@ -227,6 +227,19 @@ Mesh& Mesh::setLabelInternal(const Containers::ArrayView<const char> label) {
}
#endif
Mesh& Mesh::addVertexBufferInstanced(Buffer& buffer, const UnsignedInt divisor, const GLintptr offset, const GLsizei stride, const DynamicAttribute& attribute) {
AttributeLayout l{buffer,
attribute.location(),
GLint(attribute.components()),
GLenum(attribute.dataType()),
attribute.kind(),
offset,
stride,
divisor};
attributePointerInternal(l);
return *this;
}
Mesh& Mesh::setIndexBuffer(Buffer& buffer, GLintptr offset, IndexType type, UnsignedInt start, UnsignedInt end) {
#if defined(CORRADE_TARGET_NACL) || defined(MAGNUM_TARGET_WEBGL)
CORRADE_ASSERT(buffer.targetHint() == Buffer::TargetHint::ElementArray,
@ -455,7 +468,7 @@ void Mesh::destroyImplementationVAO() {
#endif
}
void Mesh::attributePointerInternal(const Buffer& buffer, const GLuint location, const GLint size, const GLenum type, const AttributeKind kind, const GLintptr offset, const GLsizei stride, const GLuint divisor) {
void Mesh::attributePointerInternal(const Buffer& buffer, const GLuint location, const GLint size, const GLenum type, const DynamicAttribute::Kind kind, const GLintptr offset, const GLsizei stride, const GLuint divisor) {
AttributeLayout l{buffer, location, size, type, kind, offset, stride, divisor};
attributePointerInternal(l);
}
@ -489,16 +502,16 @@ void Mesh::attributePointerImplementationDSAEXT(AttributeLayout& attribute) {
glEnableVertexArrayAttribEXT(_id, attribute.location);
#ifndef MAGNUM_TARGET_GLES2
if(attribute.kind == AttributeKind::Integral)
if(attribute.kind == DynamicAttribute::Kind::Integral)
glVertexArrayVertexAttribIOffsetEXT(_id, attribute.buffer.id(), attribute.location, attribute.size, attribute.type, attribute.stride, attribute.offset);
#ifndef MAGNUM_TARGET_GLES
else if(attribute.kind == AttributeKind::Long)
else if(attribute.kind == DynamicAttribute::Kind::Long)
glVertexArrayVertexAttribLOffsetEXT(_id, attribute.buffer.id(), attribute.location, attribute.size, attribute.type, attribute.stride, attribute.offset);
#endif
else
#endif
{
glVertexArrayVertexAttribOffsetEXT(_id, attribute.buffer.id(), attribute.location, attribute.size, attribute.type, attribute.kind == AttributeKind::GenericNormalized, attribute.stride, attribute.offset);
glVertexArrayVertexAttribOffsetEXT(_id, attribute.buffer.id(), attribute.location, attribute.size, attribute.type, attribute.kind == DynamicAttribute::Kind::GenericNormalized, attribute.stride, attribute.offset);
}
if(attribute.divisor)
@ -511,16 +524,16 @@ void Mesh::vertexAttribPointer(AttributeLayout& attribute) {
attribute.buffer.bindInternal(Buffer::TargetHint::Array);
#ifndef MAGNUM_TARGET_GLES2
if(attribute.kind == AttributeKind::Integral)
if(attribute.kind == DynamicAttribute::Kind::Integral)
glVertexAttribIPointer(attribute.location, attribute.size, attribute.type, attribute.stride, reinterpret_cast<const GLvoid*>(attribute.offset));
#ifndef MAGNUM_TARGET_GLES
else if(attribute.kind == AttributeKind::Long)
else if(attribute.kind == DynamicAttribute::Kind::Long)
glVertexAttribLPointer(attribute.location, attribute.size, attribute.type, attribute.stride, reinterpret_cast<const GLvoid*>(attribute.offset));
#endif
else
#endif
{
glVertexAttribPointer(attribute.location, attribute.size, attribute.type, attribute.kind == AttributeKind::GenericNormalized, attribute.stride, reinterpret_cast<const GLvoid*>(attribute.offset));
glVertexAttribPointer(attribute.location, attribute.size, attribute.type, attribute.kind == DynamicAttribute::Kind::GenericNormalized, attribute.stride, reinterpret_cast<const GLvoid*>(attribute.offset));
}
if(attribute.divisor) {

63
src/Magnum/Mesh.h

@ -308,6 +308,24 @@ mesh.addVertexBuffer(colorBuffer, 0, MyShader::Color{
MyShader::Color::DataOption::Normalized});
@endcode
@anchor Mesh-configuration-dynamic
#### Dynamically specified attributes
In some cases, for example when the shader code is fully generated at runtime,
it's not possible to know attribute locations and types at compile time. In
that case, there are overloads of @ref addVertexBuffer() and
@ref addVertexBufferInstanced() that take @ref DynamicAttribute instead of
@ref Attribute typedefs. Adding a RGB attribute at location 3 normalized from
unsigned byte to float with one byte padding at the end could then look like
this:
@code
mesh.addVertexBuffer(colorBuffer, 0, 4, DynamicAttribute{
DynamicAttribute::Kind::GenericNormalized, 3,
DynamicAttribute::Components::Three,
DynamicAttribute::DataType::UnsignedByte});
});
@endcode
## Rendering meshes
Basic workflow is: bind specific framebuffer for drawing (if needed), set up
@ -794,6 +812,32 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
return *this;
}
/**
* @brief Add buffer with dynamic vertex attributes for use with given shader
* @return Reference to self (for method chaining)
*
* Equivalent to @ref addVertexBuffer(Buffer&, GLintptr, const T&...)
* but with the possibility to fully specify the attribute properties
* at runtime, including base type and location. See
* @ref Mesh-configuration-dynamic "class documentation" for usage
* example.
*/
Mesh& addVertexBuffer(Buffer& buffer, GLintptr offset, GLsizei stride, const DynamicAttribute& attribute) {
return addVertexBufferInstanced(buffer, 0, offset, stride, attribute);
}
/**
* @brief Add buffer with dynamic vertex attributes for use with given shader
* @return Reference to self (for method chaining)
*
* Equivalent to @ref addVertexBufferInstanced(Buffer&, UnsignedInt, GLintptr, const T&...)
* but with the possibility to fully specify the attribute properties
* at runtime, including base type and location. See
* @ref Mesh-configuration-dynamic "class documentation" for usage
* example.
*/
Mesh& addVertexBufferInstanced(Buffer& buffer, UnsignedInt divisor, GLintptr offset, GLsizei stride, const DynamicAttribute& attribute);
/**
* @brief Set index buffer
* @param buffer Index buffer
@ -922,17 +966,6 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
#endif
private:
enum class AttributeKind {
Generic,
GenericNormalized,
#ifndef MAGNUM_TARGET_GLES2
Integral,
#ifndef MAGNUM_TARGET_GLES
Long
#endif
#endif
};
struct MAGNUM_LOCAL AttributeLayout;
explicit Mesh(GLuint id, MeshPrimitive primitive, ObjectFlags flags);
@ -971,7 +1004,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
location+i,
GLint(attribute.components()),
GLenum(attribute.dataType()),
attribute.dataOptions() & Attribute<location, T>::DataOption::Normalized ? AttributeKind::GenericNormalized : AttributeKind::Generic,
attribute.dataOptions() & Attribute<location, T>::DataOption::Normalized ? DynamicAttribute::Kind::GenericNormalized : DynamicAttribute::Kind::Generic,
GLintptr(offset+i*attribute.vectorSize()),
stride,
divisor);
@ -983,7 +1016,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
location,
GLint(attribute.components()),
GLenum(attribute.dataType()),
AttributeKind::Integral,
DynamicAttribute::Kind::Integral,
offset,
stride,
divisor);
@ -996,7 +1029,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
location+i,
GLint(attribute.components()),
GLenum(attribute.dataType()),
AttributeKind::Long,
DynamicAttribute::Kind::Long,
GLintptr(offset+i*attribute.vectorSize()),
stride,
divisor);
@ -1027,7 +1060,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
void MAGNUM_LOCAL destroyImplementationDefault();
void MAGNUM_LOCAL destroyImplementationVAO();
void attributePointerInternal(const Buffer& buffer, GLuint location, GLint size, GLenum type, AttributeKind kind, GLintptr offset, GLsizei stride, GLuint divisor);
void attributePointerInternal(const Buffer& buffer, GLuint location, GLint size, GLenum type, DynamicAttribute::Kind kind, GLintptr offset, GLsizei stride, GLuint divisor);
void MAGNUM_LOCAL attributePointerInternal(AttributeLayout& attribute);
void MAGNUM_LOCAL attributePointerImplementationDefault(AttributeLayout& attribute);
void MAGNUM_LOCAL attributePointerImplementationVAO(AttributeLayout& attribute);

516
src/Magnum/Test/MeshGLTest.cpp

@ -147,58 +147,61 @@ MeshGLTest::MeshGLTest() {
&MeshGLTest::constructMove,
&MeshGLTest::wrap,
&MeshGLTest::label,
&MeshGLTest::label});
#ifndef MAGNUM_TARGET_GLES2
&MeshGLTest::addVertexBufferUnsignedInt,
&MeshGLTest::addVertexBufferInt,
#endif
&MeshGLTest::addVertexBufferFloat,
#ifndef MAGNUM_TARGET_GLES
&MeshGLTest::addVertexBufferDouble,
#endif
#ifndef MAGNUM_TARGET_GLES2
&MeshGLTest::addVertexBufferVectorNui,
&MeshGLTest::addVertexBufferVectorNi,
#endif
&MeshGLTest::addVertexBufferVectorN,
#ifndef MAGNUM_TARGET_GLES
&MeshGLTest::addVertexBufferVectorNd,
#endif
&MeshGLTest::addVertexBufferMatrixNxN,
#ifndef MAGNUM_TARGET_GLES
&MeshGLTest::addVertexBufferMatrixNxNd,
#endif
#ifndef MAGNUM_TARGET_GLES2
&MeshGLTest::addVertexBufferMatrixMxN,
#endif
#ifndef MAGNUM_TARGET_GLES
&MeshGLTest::addVertexBufferMatrixMxNd,
#endif
/* First instance is always using Attribute, second DynamicAttribute */
addInstancedTests({
#ifndef MAGNUM_TARGET_GLES2
&MeshGLTest::addVertexBufferUnsignedInt,
&MeshGLTest::addVertexBufferInt,
#endif
&MeshGLTest::addVertexBufferFloat,
#ifndef MAGNUM_TARGET_GLES
&MeshGLTest::addVertexBufferDouble,
#endif
#ifndef MAGNUM_TARGET_GLES2
&MeshGLTest::addVertexBufferVectorNui,
&MeshGLTest::addVertexBufferVectorNi,
#endif
&MeshGLTest::addVertexBufferVectorN,
#ifndef MAGNUM_TARGET_GLES
&MeshGLTest::addVertexBufferVectorNd,
#endif
&MeshGLTest::addVertexBufferMatrixNxN,
#ifndef MAGNUM_TARGET_GLES
&MeshGLTest::addVertexBufferMatrixNxNd,
#endif
#ifndef MAGNUM_TARGET_GLES2
&MeshGLTest::addVertexBufferMatrixMxN,
#endif
#ifndef MAGNUM_TARGET_GLES
&MeshGLTest::addVertexBufferMatrixMxNd,
#endif
#ifndef MAGNUM_TARGET_GLES2
&MeshGLTest::addVertexBufferUnsignedIntWithUnsignedShort,
&MeshGLTest::addVertexBufferUnsignedIntWithShort,
&MeshGLTest::addVertexBufferIntWithUnsignedShort,
&MeshGLTest::addVertexBufferIntWithShort,
#endif
&MeshGLTest::addVertexBufferFloatWithHalfFloat,
#ifndef MAGNUM_TARGET_GLES
&MeshGLTest::addVertexBufferFloatWithDouble,
&MeshGLTest::addVertexBufferVector3WithUnsignedInt10f11f11fRev,
#endif
#ifndef MAGNUM_TARGET_GLES2
&MeshGLTest::addVertexBufferVector4WithUnsignedInt2101010Rev,
&MeshGLTest::addVertexBufferVector4WithInt2101010Rev,
#endif
#ifndef MAGNUM_TARGET_GLES2
&MeshGLTest::addVertexBufferUnsignedIntWithUnsignedShort,
&MeshGLTest::addVertexBufferUnsignedIntWithShort,
&MeshGLTest::addVertexBufferIntWithUnsignedShort,
&MeshGLTest::addVertexBufferIntWithShort,
#endif
&MeshGLTest::addVertexBufferFloatWithHalfFloat,
#ifndef MAGNUM_TARGET_GLES
&MeshGLTest::addVertexBufferFloatWithDouble,
&MeshGLTest::addVertexBufferVector3WithUnsignedInt10f11f11fRev,
#endif
#ifndef MAGNUM_TARGET_GLES2
&MeshGLTest::addVertexBufferVector4WithUnsignedInt2101010Rev,
&MeshGLTest::addVertexBufferVector4WithInt2101010Rev,
#endif
&MeshGLTest::addVertexBufferLessVectorComponents,
&MeshGLTest::addVertexBufferNormalized,
#ifndef MAGNUM_TARGET_GLES
&MeshGLTest::addVertexBufferBGRA,
#endif
&MeshGLTest::addVertexBufferLessVectorComponents,
&MeshGLTest::addVertexBufferNormalized,
#ifndef MAGNUM_TARGET_GLES
&MeshGLTest::addVertexBufferBGRA
#endif
}, 2);
&MeshGLTest::addVertexBufferMultiple,
addTests({&MeshGLTest::addVertexBufferMultiple,
&MeshGLTest::addVertexBufferMultipleGaps,
&MeshGLTest::setIndexBuffer,
@ -545,15 +548,23 @@ void MeshGLTest::addVertexBufferUnsignedInt() {
CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available."));
#endif
typedef Attribute<0, UnsignedInt> Attribute;
constexpr UnsignedInt data[] = { 0, 157, 35681 };
Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setBaseVertex(1)
.addVertexBuffer(buffer, 4, Attribute());
mesh.setBaseVertex(1);
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 4, Attribute<0, UnsignedInt>{});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 4, 4, DynamicAttribute{
DynamicAttribute::Kind::Integral, 0,
DynamicAttribute::Components::One,
DynamicAttribute::DataType::UnsignedInt});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR();
@ -570,15 +581,23 @@ void MeshGLTest::addVertexBufferInt() {
CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available."));
#endif
typedef Attribute<0, Int> Attribute;
constexpr Int data[] = { 0, 457931, 27530 };
Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setBaseVertex(1)
.addVertexBuffer(buffer, 4, Attribute());
mesh.setBaseVertex(1);
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 4, Attribute<0, Int>{});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 4, 4, DynamicAttribute{
DynamicAttribute::Kind::Integral, 0,
DynamicAttribute::Components::One,
DynamicAttribute::DataType::Int});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR();
@ -591,15 +610,23 @@ void MeshGLTest::addVertexBufferInt() {
#endif
void MeshGLTest::addVertexBufferFloat() {
typedef Attribute<0, Float> Attribute;
const Float data[] = { 0.0f, -0.7f, Math::unpack<Float, UnsignedByte>(96) };
Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setBaseVertex(1)
.addVertexBuffer(buffer, 4, Attribute());
mesh.setBaseVertex(1);
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 4, Attribute<0, Float>{});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 4, 4, DynamicAttribute{
DynamicAttribute::Kind::Generic, 0,
DynamicAttribute::Components::One,
DynamicAttribute::DataType::Float});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR();
@ -620,15 +647,23 @@ void MeshGLTest::addVertexBufferDouble() {
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::vertex_attrib_64bit>())
CORRADE_SKIP(Extensions::GL::ARB::vertex_attrib_64bit::string() + std::string(" is not available."));
typedef Attribute<0, Double> Attribute;
const Double data[] = { 0.0, -0.7, Math::unpack<Double, UnsignedShort>(45828) };
Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setBaseVertex(1)
.addVertexBuffer(buffer, 8, Attribute());
mesh.setBaseVertex(1);
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 8, Attribute<0, Double>{});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 8, 8, DynamicAttribute{
DynamicAttribute::Kind::Long, 0,
DynamicAttribute::Components::One,
DynamicAttribute::DataType::Double});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR();
@ -647,15 +682,23 @@ void MeshGLTest::addVertexBufferVectorNui() {
CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available."));
#endif
typedef Attribute<0, Vector3ui> Attribute;
constexpr Vector3ui data[] = { {}, {37448, 547686, 156}, {27592, 157, 25} };
Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setBaseVertex(1)
.addVertexBuffer(buffer, 3*4, Attribute());
mesh.setBaseVertex(1);
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 3*4, Attribute<0, Vector3ui>{});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 3*4, 3*4, DynamicAttribute{
DynamicAttribute::Kind::Integral, 0,
DynamicAttribute::Components::Three,
DynamicAttribute::DataType::UnsignedInt});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR();
@ -672,15 +715,23 @@ void MeshGLTest::addVertexBufferVectorNi() {
CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available."));
#endif
typedef Attribute<0, Vector2i> Attribute;
constexpr Vector2i data[] = { {}, {-37448, 547686}, {27592, -157} };
Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setBaseVertex(1)
.addVertexBuffer(buffer, 2*4, Attribute());
mesh.setBaseVertex(1);
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 2*4, Attribute<0, Vector2i>{});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 2*4, 2*4, DynamicAttribute{
DynamicAttribute::Kind::Integral, 0,
DynamicAttribute::Components::Two,
DynamicAttribute::DataType::Int});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR();
@ -693,15 +744,23 @@ void MeshGLTest::addVertexBufferVectorNi() {
#endif
void MeshGLTest::addVertexBufferVectorN() {
typedef Attribute<0, Vector3> Attribute;
const Vector3 data[] = { {}, {0.0f, -0.9f, 1.0f}, Math::unpack<Vector3>(Color3ub(96, 24, 156)) };
Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setBaseVertex(1)
.addVertexBuffer(buffer, 3*4, Attribute());
mesh.setBaseVertex(1);
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 3*4, Attribute<0, Vector3>{});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 3*4, 3*4, DynamicAttribute{
DynamicAttribute::Kind::Generic, 0,
DynamicAttribute::Components::Three,
DynamicAttribute::DataType::Float});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR();
@ -722,8 +781,6 @@ void MeshGLTest::addVertexBufferVectorNd() {
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::vertex_attrib_64bit>())
CORRADE_SKIP(Extensions::GL::ARB::vertex_attrib_64bit::string() + std::string(" is not available."));
typedef Attribute<0, Vector4d> Attribute;
const Vector4d data[] = {
{}, {0.0, -0.9, 1.0, 1.25},
Math::unpack<Vector4d>(Math::Vector4<UnsignedShort>(315, 65201, 2576, 12))
@ -732,8 +789,18 @@ void MeshGLTest::addVertexBufferVectorNd() {
buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setBaseVertex(1)
.addVertexBuffer(buffer, 4*8, Attribute());
mesh.setBaseVertex(1);
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 4*8, Attribute<0, Vector4d>{});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 4*8, 4*8, DynamicAttribute{
DynamicAttribute::Kind::Long, 0,
DynamicAttribute::Components::Four,
DynamicAttribute::DataType::Double});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR();
@ -746,8 +813,6 @@ void MeshGLTest::addVertexBufferVectorNd() {
#endif
void MeshGLTest::addVertexBufferMatrixNxN() {
typedef Attribute<0, Matrix3x3> Attribute;
const Matrix3x3 data[] = {
{},
Matrix3x3::fromDiagonal({0.0f, -0.9f, 1.0f}),
@ -757,8 +822,26 @@ void MeshGLTest::addVertexBufferMatrixNxN() {
buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setBaseVertex(1)
.addVertexBuffer(buffer, 3*3*4, Attribute());
mesh.setBaseVertex(1);
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 3*3*4, Attribute<0, Matrix3x3>{});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 3*3*4, 3*3*4, DynamicAttribute{
DynamicAttribute::Kind::Generic, 0,
DynamicAttribute::Components::Three,
DynamicAttribute::DataType::Float})
.addVertexBuffer(buffer, 3*3*4 + 3*4, 3*3*4, DynamicAttribute{
DynamicAttribute::Kind::Generic, 1,
DynamicAttribute::Components::Three,
DynamicAttribute::DataType::Float})
.addVertexBuffer(buffer, 3*3*4 + 6*4, 3*3*4, DynamicAttribute{
DynamicAttribute::Kind::Generic, 2,
DynamicAttribute::Components::Three,
DynamicAttribute::DataType::Float});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR();
@ -775,8 +858,6 @@ void MeshGLTest::addVertexBufferMatrixNxNd() {
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::vertex_attrib_64bit>())
CORRADE_SKIP(Extensions::GL::ARB::vertex_attrib_64bit::string() + std::string(" is not available."));
typedef Attribute<0, Matrix3x3d> Attribute;
const Matrix3x3d data[] = {
{},
Matrix3x3d::fromDiagonal({0.0, -0.9, 1.0}),
@ -786,8 +867,26 @@ void MeshGLTest::addVertexBufferMatrixNxNd() {
buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setBaseVertex(1)
.addVertexBuffer(buffer, 3*3*8, Attribute());
mesh.setBaseVertex(1);
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 3*3*8, Attribute<0, Matrix3x3d>{});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 3*3*8, 3*3*8, DynamicAttribute{
DynamicAttribute::Kind::Long, 0,
DynamicAttribute::Components::Three,
DynamicAttribute::DataType::Double})
.addVertexBuffer(buffer, 3*3*8 + 3*8, 3*3*8, DynamicAttribute{
DynamicAttribute::Kind::Long, 1,
DynamicAttribute::Components::Three,
DynamicAttribute::DataType::Double})
.addVertexBuffer(buffer, 3*3*8 + 6*4, 3*3*8, DynamicAttribute{
DynamicAttribute::Kind::Long, 2,
DynamicAttribute::Components::Three,
DynamicAttribute::DataType::Double});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR();
@ -811,8 +910,6 @@ void MeshGLTest::addVertexBufferMatrixNxNd() {
#ifndef MAGNUM_TARGET_GLES2
void MeshGLTest::addVertexBufferMatrixMxN() {
typedef Attribute<0, Matrix3x4> Attribute;
const Matrix3x4 data[] = {
{},
Matrix3x4::fromDiagonal({0.0f, -0.9f, 1.0f}),
@ -822,8 +919,26 @@ void MeshGLTest::addVertexBufferMatrixMxN() {
buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setBaseVertex(1)
.addVertexBuffer(buffer, 3*4*4, Attribute());
mesh.setBaseVertex(1);
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 3*4*4, Attribute<0, Matrix3x4>{});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 3*4*4, 3*4*4, DynamicAttribute{
DynamicAttribute::Kind::Generic, 0,
DynamicAttribute::Components::Four,
DynamicAttribute::DataType::Float})
.addVertexBuffer(buffer, 3*4*4 + 4*4, 3*4*4, DynamicAttribute{
DynamicAttribute::Kind::Generic, 1,
DynamicAttribute::Components::Four,
DynamicAttribute::DataType::Float})
.addVertexBuffer(buffer, 3*4*4 + 8*4, 3*4*4, DynamicAttribute{
DynamicAttribute::Kind::Generic, 2,
DynamicAttribute::Components::Four,
DynamicAttribute::DataType::Float});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR();
@ -841,8 +956,6 @@ void MeshGLTest::addVertexBufferMatrixMxNd() {
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::vertex_attrib_64bit>())
CORRADE_SKIP(Extensions::GL::ARB::vertex_attrib_64bit::string() + std::string(" is not available."));
typedef Attribute<0, Matrix3x4d> Attribute;
const Matrix3x4d data[] = {
{},
Matrix3x4d::fromDiagonal({0.0f, -0.9f, 1.0f}),
@ -852,8 +965,26 @@ void MeshGLTest::addVertexBufferMatrixMxNd() {
buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setBaseVertex(1)
.addVertexBuffer(buffer, 3*4*8, Attribute());
mesh.setBaseVertex(1);
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 3*4*8, Attribute<0, Matrix3x4d>{});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 3*4*8, 3*4*8, DynamicAttribute{
DynamicAttribute::Kind::Long, 0,
DynamicAttribute::Components::Four,
DynamicAttribute::DataType::Double})
.addVertexBuffer(buffer, 3*4*8 + 4*8, 3*4*8, DynamicAttribute{
DynamicAttribute::Kind::Long, 1,
DynamicAttribute::Components::Four,
DynamicAttribute::DataType::Double})
.addVertexBuffer(buffer, 3*4*8 + 8*8, 3*4*8, DynamicAttribute{
DynamicAttribute::Kind::Long, 2,
DynamicAttribute::Components::Four,
DynamicAttribute::DataType::Double});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR();
@ -882,15 +1013,23 @@ void MeshGLTest::addVertexBufferUnsignedIntWithUnsignedShort() {
CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available."));
#endif
typedef Attribute<0, UnsignedInt> Attribute;
constexpr UnsignedShort data[] = { 0, 49563, 2128, 3821, 16583 };
Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setBaseVertex(1)
.addVertexBuffer(buffer, 2, 2, Attribute(Attribute::DataType::UnsignedShort));
mesh.setBaseVertex(1);
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 2, 2, Attribute<0, UnsignedInt>{Attribute<0, UnsignedInt>::DataType::UnsignedShort});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 4, 4, DynamicAttribute{
DynamicAttribute::Kind::Integral, 0,
DynamicAttribute::Components::One,
DynamicAttribute::DataType::UnsignedShort});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR();
@ -907,15 +1046,23 @@ void MeshGLTest::addVertexBufferUnsignedIntWithShort() {
CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available."));
#endif
typedef Attribute<0, UnsignedInt> Attribute;
constexpr Short data[] = { 0, 24563, 2128, 3821, 16583 };
Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setBaseVertex(1)
.addVertexBuffer(buffer, 2, 2, Attribute(Attribute::DataType::Short));
mesh.setBaseVertex(1);
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 2, 2, Attribute<0, UnsignedInt>{Attribute<0, UnsignedInt>::DataType::Short});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 4, 4, DynamicAttribute{
DynamicAttribute::Kind::Integral, 0,
DynamicAttribute::Components::One,
DynamicAttribute::DataType::Short});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR();
@ -932,15 +1079,23 @@ void MeshGLTest::addVertexBufferIntWithUnsignedShort() {
CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available."));
#endif
typedef Attribute<0, Int> Attribute;
constexpr UnsignedShort data[] = { 0, 49563, 2128, 3821, 16583 };
Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setBaseVertex(1)
.addVertexBuffer(buffer, 2, 2, Attribute(Attribute::DataType::UnsignedShort));
mesh.setBaseVertex(1);
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 2, 2, Attribute<0, Int>{Attribute<0, Int>::DataType::UnsignedShort});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 4, 4, DynamicAttribute{
DynamicAttribute::Kind::Integral, 0,
DynamicAttribute::Components::One,
DynamicAttribute::DataType::UnsignedShort});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR();
@ -957,15 +1112,23 @@ void MeshGLTest::addVertexBufferIntWithShort() {
CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available."));
#endif
typedef Attribute<0, Int> Attribute;
constexpr Short data[] = { 0, 24563, 2128, 3821, -16583 };
Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setBaseVertex(1)
.addVertexBuffer(buffer, 2, 2, Attribute(Attribute::DataType::Short));
mesh.setBaseVertex(1);
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 2, 2, Attribute<0, Int>{Attribute<0, Int>::DataType::Short});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 4, 4, DynamicAttribute{
DynamicAttribute::Kind::Integral, 0,
DynamicAttribute::Components::One,
DynamicAttribute::DataType::Short});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR();
@ -988,15 +1151,23 @@ void MeshGLTest::addVertexBufferFloatWithHalfFloat() {
using namespace Math::Literals;
typedef Attribute<0, Float> Attribute;
const Half data[] = { 0.0_h, -0.7_h, Half(Math::unpack<Float, UnsignedByte>(186)) };
Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setBaseVertex(1)
.addVertexBuffer(buffer, 2, Attribute(Attribute::DataType::HalfFloat));
mesh.setBaseVertex(1);
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 2, Attribute<0, Float>{Attribute<0, Float>::DataType::HalfFloat});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 2, 2, DynamicAttribute{
DynamicAttribute::Kind::Generic, 0,
DynamicAttribute::Components::One,
DynamicAttribute::DataType::HalfFloat});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR();
@ -1009,15 +1180,24 @@ void MeshGLTest::addVertexBufferFloatWithHalfFloat() {
#ifndef MAGNUM_TARGET_GLES
void MeshGLTest::addVertexBufferFloatWithDouble() {
typedef Attribute<0, Float> Attribute;
const Double data[] = { 0.0, -0.7, Math::unpack<Double, UnsignedByte>(186) };
Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setBaseVertex(1)
.addVertexBuffer(buffer, 8, Attribute(Attribute::DataType::Double));
.addVertexBuffer(buffer, 8, Attribute<0, Float>(Attribute<0, Float>::DataType::Double));
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 8, Attribute<0, Float>{Attribute<0, Float>::DataType::Double});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 8, 8, DynamicAttribute{
DynamicAttribute::Kind::Generic, 0,
DynamicAttribute::Components::One,
DynamicAttribute::DataType::Double});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR();
@ -1034,14 +1214,22 @@ void MeshGLTest::addVertexBufferVector3WithUnsignedInt10f11f11fRev() {
CORRADE_SKIP(Extensions::GL::ARB::vertex_type_10f_11f_11f_rev::string() + std::string(" is not available."));
#endif
typedef Attribute<0, Vector3> Attribute;
Buffer buffer;
buffer.setData({nullptr, 12}, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setBaseVertex(1)
.addVertexBuffer(buffer, 4, Attribute(Attribute::DataType::UnsignedInt10f11f11fRev));
mesh.setBaseVertex(1);
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 4, Attribute<0, Vector3>{Attribute<0, Vector3>::DataType::UnsignedInt10f11f11fRev});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 4, 4, DynamicAttribute{
DynamicAttribute::Kind::Generic, 0,
DynamicAttribute::Components::Three,
DynamicAttribute::DataType::UnsignedInt10f11f11fRev});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR();
/* Won't test the actual values */
@ -1055,14 +1243,22 @@ void MeshGLTest::addVertexBufferVector4WithUnsignedInt2101010Rev() {
CORRADE_SKIP(Extensions::GL::ARB::vertex_type_2_10_10_10_rev::string() + std::string(" is not available."));
#endif
typedef Attribute<0, Vector4> Attribute;
Buffer buffer;
buffer.setData({nullptr, 12}, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setBaseVertex(1)
.addVertexBuffer(buffer, 4, Attribute(Attribute::DataType::UnsignedInt2101010Rev));
mesh.setBaseVertex(1);
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 4, Attribute<0, Vector4>{Attribute<0, Vector4>::DataType::UnsignedInt2101010Rev});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 4, 4, DynamicAttribute{
DynamicAttribute::Kind::Generic, 0,
DynamicAttribute::Components::Four,
DynamicAttribute::DataType::UnsignedInt2101010Rev});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR();
/* Won't test the actual values */
@ -1074,14 +1270,22 @@ void MeshGLTest::addVertexBufferVector4WithInt2101010Rev() {
CORRADE_SKIP(Extensions::GL::ARB::vertex_type_2_10_10_10_rev::string() + std::string(" is not available."));
#endif
typedef Attribute<0, Vector4> Attribute;
Buffer buffer;
buffer.setData({nullptr, 12}, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setBaseVertex(1)
.addVertexBuffer(buffer, 4, Attribute(Attribute::DataType::Int2101010Rev));
mesh.setBaseVertex(1);
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 4, Attribute<0, Vector4>{Attribute<0, Vector4>::DataType::Int2101010Rev});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 4, 4, DynamicAttribute{
DynamicAttribute::Kind::Generic, 0,
DynamicAttribute::Components::Four,
DynamicAttribute::DataType::Int2101010Rev});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR();
/* Won't test the actual values */
@ -1089,8 +1293,6 @@ void MeshGLTest::addVertexBufferVector4WithInt2101010Rev() {
#endif
void MeshGLTest::addVertexBufferLessVectorComponents() {
typedef Attribute<0, Vector4> Attribute;
const Vector3 data[] = {
{}, {0.0f, -0.9f, 1.0f},
Math::unpack<Vector3>(Color3ub(96, 24, 156))
@ -1099,8 +1301,18 @@ void MeshGLTest::addVertexBufferLessVectorComponents() {
buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setBaseVertex(1)
.addVertexBuffer(buffer, 3*4, Attribute(Attribute::Components::Three));
mesh.setBaseVertex(1);
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 3*4, Attribute<0, Vector4>{Attribute<0, Vector4>::Components::Three});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 3*4, 3*4, DynamicAttribute{
DynamicAttribute::Kind::Generic, 0,
DynamicAttribute::Components::Three,
DynamicAttribute::DataType::Float});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR();
@ -1117,15 +1329,24 @@ void MeshGLTest::addVertexBufferLessVectorComponents() {
}
void MeshGLTest::addVertexBufferNormalized() {
typedef Attribute<0, Vector3> Attribute;
constexpr Color4ub data[] = { {}, {0, 128, 64}, {32, 156, 228} };
Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setBaseVertex(1)
.addVertexBuffer(buffer, 4, Attribute(Attribute::DataType::UnsignedByte, Attribute::DataOption::Normalized), 1);
mesh.setBaseVertex(1);
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
typedef Attribute<0, Vector3> Attribute;
mesh.addVertexBuffer(buffer, 4, Attribute(Attribute::DataType::UnsignedByte, Attribute::DataOption::Normalized), 1);
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 4, 4, DynamicAttribute{
DynamicAttribute::Kind::GenericNormalized, 0,
DynamicAttribute::Components::Three,
DynamicAttribute::DataType::UnsignedByte});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR();
@ -1148,15 +1369,24 @@ void MeshGLTest::addVertexBufferBGRA() {
CORRADE_SKIP(Extensions::GL::ARB::vertex_array_bgra::string() + std::string(" is not available."));
#endif
typedef Attribute<0, Vector4> Attribute;
constexpr Color4ub data[] = { {}, {0, 128, 64, 161}, {96, 24, 156, 225} };
Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setBaseVertex(1)
.addVertexBuffer(buffer, 4, Attribute(Attribute::Components::BGRA, Attribute::DataType::UnsignedByte, Attribute::DataOption::Normalized));
mesh.setBaseVertex(1);
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
typedef Attribute<0, Vector4> Attribute;
mesh.addVertexBuffer(buffer, 4, Attribute(Attribute::Components::BGRA, Attribute::DataType::UnsignedByte, Attribute::DataOption::Normalized));
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 4, 4, DynamicAttribute{
DynamicAttribute::Kind::GenericNormalized, 0,
DynamicAttribute::Components::BGRA,
DynamicAttribute::DataType::UnsignedByte});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR();

Loading…
Cancel
Save