Browse Source

Moved Attribute class out of AbstractShaderProgram enum.

No backward compatibility issues should exist, as the class is in most
(if not all) cases used with unscoped name:

    class MyShader: public AbstractShaderProgram {
        public:
            typedef Attribute<0, Vector3> Position;
        // ...
    };
pull/77/head
Vladimír Vondruš 12 years ago
parent
commit
1cfb5b0eaf
  1. 301
      src/Magnum/AbstractShaderProgram.cpp
  2. 549
      src/Magnum/AbstractShaderProgram.h
  3. 329
      src/Magnum/Attribute.cpp
  4. 582
      src/Magnum/Attribute.h
  5. 2
      src/Magnum/CMakeLists.txt
  6. 1
      src/Magnum/DebugTools/ResourceManager.cpp
  7. 2
      src/Magnum/Implementation/MeshState.h
  8. 2
      src/Magnum/Magnum.h
  9. 27
      src/Magnum/Mesh.cpp
  10. 59
      src/Magnum/Mesh.h
  11. 4
      src/Magnum/MeshTools/FullScreenTriangle.cpp
  12. 1
      src/Magnum/MeshView.cpp
  13. 14
      src/Magnum/Shaders/Generic.h
  14. 28
      src/Magnum/Test/AbstractShaderProgramTest.cpp
  15. 61
      src/Magnum/Test/MeshGLTest.cpp
  16. 4
      src/Magnum/Test/SampleQueryGLTest.cpp

301
src/Magnum/AbstractShaderProgram.cpp

@ -1070,305 +1070,4 @@ void AbstractShaderProgram::uniformImplementationDSAEXT(const GLint location, co
} }
#endif #endif
namespace Implementation {
UnsignedInt FloatAttribute::size(GLint components, DataType dataType) {
switch(dataType) {
case DataType::UnsignedByte:
case DataType::Byte:
return components;
case DataType::UnsignedShort:
case DataType::Short:
case DataType::HalfFloat:
return 2*components;
case DataType::UnsignedInt:
case DataType::Int:
case DataType::Float:
return 4*components;
#ifndef MAGNUM_TARGET_GLES
case DataType::Double:
return 8*components;
#endif
}
CORRADE_ASSERT_UNREACHABLE();
}
#ifndef MAGNUM_TARGET_GLES2
UnsignedInt IntAttribute::size(GLint components, DataType dataType) {
switch(dataType) {
case DataType::UnsignedByte:
case DataType::Byte:
return components;
case DataType::UnsignedShort:
case DataType::Short:
return 2*components;
case DataType::UnsignedInt:
case DataType::Int:
return 4*components;
}
CORRADE_ASSERT_UNREACHABLE();
}
#endif
#ifndef MAGNUM_TARGET_GLES
UnsignedInt DoubleAttribute::size(GLint components, DataType dataType) {
switch(dataType) {
case DataType::Double:
return 8*components;
}
CORRADE_ASSERT_UNREACHABLE();
}
#endif
UnsignedInt Attribute<Math::Vector<3, Float>>::size(GLint components, DataType dataType) {
switch(dataType) {
case DataType::UnsignedByte:
case DataType::Byte:
return components;
case DataType::UnsignedShort:
case DataType::Short:
case DataType::HalfFloat:
return 2*components;
case DataType::UnsignedInt:
case DataType::Int:
case DataType::Float:
return 4*components;
#ifndef MAGNUM_TARGET_GLES
case DataType::Double:
return 8*components;
case DataType::UnsignedInt10f11f11fRev:
CORRADE_INTERNAL_ASSERT(components == 3);
return 4;
#endif
}
CORRADE_ASSERT_UNREACHABLE();
}
UnsignedInt Attribute<Math::Vector<4, Float>>::size(GLint components, DataType dataType) {
#ifndef MAGNUM_TARGET_GLES
if(components == GL_BGRA) components = 4;
#endif
switch(dataType) {
case DataType::UnsignedByte:
case DataType::Byte:
return components;
case DataType::UnsignedShort:
case DataType::Short:
case DataType::HalfFloat:
return 2*components;
case DataType::UnsignedInt:
case DataType::Int:
case DataType::Float:
return 4*components;
#ifndef MAGNUM_TARGET_GLES
case DataType::Double:
return 8*components;
#endif
#ifndef MAGNUM_TARGET_GLES2
case DataType::UnsignedInt2101010Rev:
case DataType::Int2101010Rev:
CORRADE_INTERNAL_ASSERT(components == 4);
return 4;
#endif
}
CORRADE_ASSERT_UNREACHABLE();
}
Debug operator<<(Debug debug, SizedAttribute<1, 1>::Components value) {
switch(value) {
case SizedAttribute<1, 1>::Components::One:
return debug << "AbstractShaderProgram::Attribute::Components::One";
}
return debug << "AbstractShaderProgram::Attribute::Components::(invalid)";
}
Debug operator<<(Debug debug, SizedAttribute<1, 2>::Components value) {
switch(value) {
case SizedAttribute<1, 2>::Components::One:
return debug << "AbstractShaderProgram::Attribute::Components::One";
case SizedAttribute<1, 2>::Components::Two:
return debug << "AbstractShaderProgram::Attribute::Components::Two";
}
return debug << "AbstractShaderProgram::Attribute::Components::(invalid)";
}
Debug operator<<(Debug debug, SizedAttribute<1, 3>::Components value) {
switch(value) {
case SizedAttribute<1, 3>::Components::One:
return debug << "AbstractShaderProgram::Attribute::Components::One";
case SizedAttribute<1, 3>::Components::Two:
return debug << "AbstractShaderProgram::Attribute::Components::Two";
case SizedAttribute<1, 3>::Components::Three:
return debug << "AbstractShaderProgram::Attribute::Components::Three";
}
return debug << "AbstractShaderProgram::Attribute::Components::(invalid)";
}
Debug operator<<(Debug debug, SizedAttribute<1, 4>::Components value) {
switch(value) {
case SizedAttribute<1, 4>::Components::One:
return debug << "AbstractShaderProgram::Attribute::Components::One";
case SizedAttribute<1, 4>::Components::Two:
return debug << "AbstractShaderProgram::Attribute::Components::Two";
case SizedAttribute<1, 4>::Components::Three:
return debug << "AbstractShaderProgram::Attribute::Components::Three";
case SizedAttribute<1, 4>::Components::Four:
return debug << "AbstractShaderProgram::Attribute::Components::Four";
}
return debug << "AbstractShaderProgram::Attribute::Components::(invalid)";
}
Debug operator<<(Debug debug, SizedMatrixAttribute<2>::Components value) {
switch(value) {
case SizedMatrixAttribute<2>::Components::Two:
return debug << "AbstractShaderProgram::Attribute::Components::Two";
}
return debug << "AbstractShaderProgram::Attribute::Components::(invalid)";
}
Debug operator<<(Debug debug, SizedMatrixAttribute<3>::Components value) {
switch(value) {
case SizedMatrixAttribute<3>::Components::Three:
return debug << "AbstractShaderProgram::Attribute::Components::Three";
}
return debug << "AbstractShaderProgram::Attribute::Components::(invalid)";
}
Debug operator<<(Debug debug, SizedMatrixAttribute<4>::Components value) {
switch(value) {
case SizedMatrixAttribute<4>::Components::Four:
return debug << "AbstractShaderProgram::Attribute::Components::Four";
}
return debug << "AbstractShaderProgram::Attribute::Components::(invalid)";
}
Debug operator<<(Debug debug, Attribute<Math::Vector<4, Float>>::Components value) {
switch(value) {
case Attribute<Math::Vector<4, Float>>::Components::One:
return debug << "AbstractShaderProgram::Attribute::Components::One";
case Attribute<Math::Vector<4, Float>>::Components::Two:
return debug << "AbstractShaderProgram::Attribute::Components::Two";
case Attribute<Math::Vector<4, Float>>::Components::Three:
return debug << "AbstractShaderProgram::Attribute::Components::Three";
case Attribute<Math::Vector<4, Float>>::Components::Four:
return debug << "AbstractShaderProgram::Attribute::Components::Four";
#ifndef MAGNUM_TARGET_GLES
case Attribute<Math::Vector<4, Float>>::Components::BGRA:
return debug << "AbstractShaderProgram::Attribute::Components::BGRA";
#endif
}
return debug << "AbstractShaderProgram::Attribute::Components::(invalid)";
}
Debug operator<<(Debug debug, FloatAttribute::DataType value) {
switch(value) {
#define _c(value) case FloatAttribute::DataType::value: return debug << "AbstractShaderProgram::Attribute::DataType::" #value;
_c(UnsignedByte)
_c(Byte)
_c(UnsignedShort)
_c(Short)
_c(UnsignedInt)
_c(Int)
_c(HalfFloat)
_c(Float)
#ifndef MAGNUM_TARGET_GLES
_c(Double)
#endif
#undef _c
}
return debug << "AbstractShaderProgram::Attribute::DataType::(invalid)";
}
#ifndef MAGNUM_TARGET_GLES2
Debug operator<<(Debug debug, IntAttribute::DataType value) {
switch(value) {
#define _c(value) case IntAttribute::DataType::value: return debug << "AbstractShaderProgram::Attribute::DataType::" #value;
_c(UnsignedByte)
_c(Byte)
_c(UnsignedShort)
_c(Short)
_c(UnsignedInt)
_c(Int)
#undef _c
}
return debug << "AbstractShaderProgram::Attribute::DataType::(invalid)";
}
#endif
#ifndef MAGNUM_TARGET_GLES
Debug operator<<(Debug debug, DoubleAttribute::DataType value) {
switch(value) {
#define _c(value) case DoubleAttribute::DataType::value: return debug << "AbstractShaderProgram::Attribute::DataType::" #value;
_c(Double)
#undef _c
}
return debug << "AbstractShaderProgram::Attribute::DataType::(invalid)";
}
#endif
Debug operator<<(Debug debug, Attribute<Math::Vector<3, Float>>::DataType value) {
switch(value) {
#define _c(value) case Attribute<Math::Vector<3, Float>>::DataType::value: return debug << "AbstractShaderProgram::Attribute::DataType::" #value;
_c(UnsignedByte)
_c(Byte)
_c(UnsignedShort)
_c(Short)
_c(UnsignedInt)
_c(Int)
_c(HalfFloat)
_c(Float)
#ifndef MAGNUM_TARGET_GLES
_c(Double)
_c(UnsignedInt10f11f11fRev)
#endif
#undef _c
}
return debug << "AbstractShaderProgram::Attribute::DataType::(invalid)";
}
Debug operator<<(Debug debug, Attribute<Math::Vector<4, Float>>::DataType value) {
switch(value) {
#define _c(value) case Attribute<Math::Vector<4, Float>>::DataType::value: return debug << "AbstractShaderProgram::Attribute::DataType::" #value;
_c(UnsignedByte)
_c(Byte)
_c(UnsignedShort)
_c(Short)
_c(UnsignedInt)
_c(Int)
_c(HalfFloat)
_c(Float)
#ifndef MAGNUM_TARGET_GLES
_c(Double)
#endif
#ifndef MAGNUM_TARGET_GLES2
_c(UnsignedInt2101010Rev)
_c(Int2101010Rev)
#endif
#undef _c
}
return debug << "AbstractShaderProgram::Attribute::DataType::(invalid)";
}
}
} }

549
src/Magnum/AbstractShaderProgram.h

@ -32,17 +32,13 @@
#include <functional> #include <functional>
#include <string> #include <string>
#include <Corrade/Containers/Array.h> #include <Corrade/Containers/Array.h>
#include <Corrade/Containers/EnumSet.h>
#include "Magnum/AbstractObject.h" #include "Magnum/AbstractObject.h"
#include "Magnum/Magnum.h" #include "Magnum/Attribute.h"
namespace Magnum { namespace Magnum {
namespace Implementation { namespace Implementation { struct ShaderProgramState; }
template<class> struct Attribute;
struct ShaderProgramState;
}
/** /**
@brief Base for shader program implementations @brief Base for shader program implementations
@ -338,16 +334,13 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
friend struct Implementation::ShaderProgramState; friend struct Implementation::ShaderProgramState;
public: public:
template<UnsignedInt, class> class Attribute;
/** /**
* @brief Max supported vertex attribute count * @brief Max supported vertex attribute count
* *
* The result is cached, repeated queries don't result in repeated * The result is cached, repeated queries don't result in repeated
* OpenGL calls. * OpenGL calls.
* @see @ref Mesh::maxVertexAttributes(), * @see @ref Mesh::maxVertexAttributes(),
* @ref AbstractShaderProgram::Attribute, @fn_gl{Get} with * @ref Attribute, @fn_gl{Get} with @def_gl{MAX_VERTEX_ATTRIBS}
* @def_gl{MAX_VERTEX_ATTRIBS}
*/ */
static Int maxVertexAttributes(); static Int maxVertexAttributes();
@ -1019,542 +1012,6 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
GLuint _id; GLuint _id;
}; };
/**
@brief Base struct for attribute location and type
Template parameter @p location is vertex attribute location, number between `0`
and @ref maxVertexAttributes(). To ensure compatibility, you should always have
vertex attribute with location `0`.
Template parameter @p T is the type which is used for shader attribute, e.g.
@ref Vector4i for `ivec4`. DataType is type of passed data when adding vertex
buffers to mesh. By default it is the same as type used in shader (e.g.
@ref DataType::Int for @ref Vector4i). It's also possible to pass integer data
to floating-point shader inputs. In this case you may want to normalize the
values (e.g. color components from 0-255 to 0.0f - 1.0f) -- see @ref DataOption::Normalized.
Only some types are allowed as attribute types, see @ref AbstractShaderProgram-types
for more information.
See @ref AbstractShaderProgram-subclassing for example usage in shaders and
@ref Mesh-configuration for example usage when adding vertex buffers to mesh.
*/
template<UnsignedInt location, class T> class AbstractShaderProgram::Attribute {
public:
enum: UnsignedInt {
Location = location, /**< Location to which the attribute is bound */
/**
* Count of vectors in this type
*
* @see @ref vectorSize()
*/
VectorCount = Implementation::Attribute<T>::VectorCount
};
/**
* @brief Type
*
* Type used in shader code.
* @see @ref ScalarType, @ref DataType
*/
typedef T Type;
/**
* @brief Scalar type
*
* The underlying scalar type of the attribute.
* @see @ref Type, @ref DataType
*/
typedef typename Implementation::Attribute<T>::ScalarType ScalarType;
/**
* @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`).
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
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 DataOption::Normalized.
* @requires_gl32 %Extension @extension{ARB,vertex_array_bgra}
* @requires_gl Only RGBA component ordering is supported in OpenGL
* ES.
*/
BGRA = GL_BGRA
#endif
};
#else
typedef typename Implementation::Attribute<T>::Components Components;
#endif
/**
* @brief Data type
*
* Type of data passed to shader.
* @see @ref Type, @ref DataOptions, @ref Attribute()
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
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 */
/**
* Half float. Only for float attribute types.
* @requires_gl30 %Extension @extension{ARB,half_float_vertex}
* @requires_gles30 %Extension @es_extension{OES,vertex_half_float}
* in OpenGL ES 2.0
*/
HalfFloat = GL_HALF_FLOAT,
/** 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.
*/
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.
*/
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) @es_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
*/
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
*/
Int2101010Rev = GL_INT_2_10_10_10_REV
#endif
};
#else
typedef typename Implementation::Attribute<T>::DataType DataType;
#endif
/**
* @brief Data option
* @see @ref DataOptions, @ref Attribute()
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
enum class DataOption: UnsignedByte {
/**
* Normalize integer components. Only for float attribute types.
* Default is to not normalize.
*/
Normalized = 1 << 0
};
#else
typedef typename Implementation::Attribute<T>::DataOption DataOption;
#endif
/**
* @brief Data options
* @see @ref Attribute()
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
typedef typename Containers::EnumSet<DataOption> DataOptions;
#else
typedef typename Implementation::Attribute<T>::DataOptions DataOptions;
#endif
/**
* @brief Constructor
* @param components Component count
* @param dataType Type of passed data. Default is the same as
* type used in shader (e.g. @ref DataType::Int for @ref Vector4i).
* @param dataOptions Data options. Default is no options.
*/
constexpr Attribute(Components components, DataType dataType = Implementation::Attribute<T>::DefaultDataType, DataOptions dataOptions = DataOptions()): _components(components), _dataType(dataType), _dataOptions(dataOptions) {}
/**
* @brief Constructor
* @param dataType Type of passed data. Default is the same as
* type used in shader (e.g. @ref DataType::Int for @ref Vector4i).
* @param dataOptions Data options. Default is no options.
*
* Component count is set to the same value as in type used in shader
* (e.g. @ref Components::Three for @ref Vector3).
*/
constexpr Attribute(DataType dataType = Implementation::Attribute<T>::DefaultDataType, DataOptions dataOptions = DataOptions()): _components(Implementation::Attribute<T>::DefaultComponents), _dataType(dataType), _dataOptions(dataOptions) {}
/** @brief Component count of passed data */
constexpr Components components() const { return _components; }
/** @brief Type of passed data */
constexpr DataType dataType() const { return _dataType; }
/**
* @brief Size of each vector in passed data
*
* @see @ref VectorCount
*/
UnsignedInt vectorSize() const {
return Implementation::Attribute<T>::size(GLint(_components), _dataType);
}
/** @brief Data options */
constexpr DataOptions dataOptions() const { return _dataOptions; }
private:
Components _components;
DataType _dataType;
DataOptions _dataOptions;
};
#ifdef DOXYGEN_GENERATING_OUTPUT
/** @debugoperatorclassenum{Magnum::AbstractShaderProgram::Attribute,Magnum::AbstractShaderProgram::Attribute::Components} */
template<class T> Debug operator<<(Debug debug, AbstractShaderProgram::Attribute<T>::Components);
/** @debugoperatorclassenum{Magnum::AbstractShaderProgram::Attribute,Magnum::AbstractShaderProgram::Attribute::DataType} */
template<class T> Debug operator<<(Debug debug, AbstractShaderProgram::Attribute<T>::DataType);
#endif
namespace Implementation {
/* Base for sized attributes */
template<std::size_t cols, std::size_t rows> struct SizedAttribute;
/* Vector attribute sizes */
template<std::size_t cols> struct SizedVectorAttribute {
enum: UnsignedInt { VectorCount = UnsignedInt(cols) };
};
template<> struct SizedAttribute<1, 1>: SizedVectorAttribute<1> {
enum class Components: GLint { One = 1 };
constexpr static Components DefaultComponents = Components::One;
};
template<> struct SizedAttribute<1, 2>: SizedVectorAttribute<1> {
enum class Components: GLint { One = 1, Two = 2 };
constexpr static Components DefaultComponents = Components::Two;
};
template<> struct SizedAttribute<1, 3>: SizedVectorAttribute<1> {
enum class Components: GLint { One = 1, Two = 2, Three = 3 };
constexpr static Components DefaultComponents = Components::Three;
};
template<> struct SizedAttribute<1, 4>: SizedVectorAttribute<1> {
enum class Components: GLint { One = 1, Two = 2, Three = 3, Four = 4 };
constexpr static Components DefaultComponents = Components::Four;
};
Debug MAGNUM_EXPORT operator<<(Debug debug, SizedAttribute<1, 1>::Components value);
Debug MAGNUM_EXPORT operator<<(Debug debug, SizedAttribute<1, 2>::Components value);
Debug MAGNUM_EXPORT operator<<(Debug debug, SizedAttribute<1, 3>::Components value);
Debug MAGNUM_EXPORT operator<<(Debug debug, SizedAttribute<1, 4>::Components value);
/* Matrix attribute sizes */
template<std::size_t rows> struct SizedMatrixAttribute;
template<> struct SizedMatrixAttribute<2> {
enum class Components: GLint { Two = 2 };
constexpr static Components DefaultComponents = Components::Two;
};
template<> struct SizedMatrixAttribute<3> {
enum class Components: GLint { Three = 3 };
constexpr static Components DefaultComponents = Components::Three;
};
template<> struct SizedMatrixAttribute<4> {
enum class Components: GLint { Four = 4 };
constexpr static Components DefaultComponents = Components::Four;
};
Debug MAGNUM_EXPORT operator<<(Debug debug, SizedMatrixAttribute<2>::Components value);
Debug MAGNUM_EXPORT operator<<(Debug debug, SizedMatrixAttribute<3>::Components value);
Debug MAGNUM_EXPORT operator<<(Debug debug, SizedMatrixAttribute<4>::Components value);
template<> struct SizedAttribute<2, 2>: SizedVectorAttribute<2>, SizedMatrixAttribute<2> {};
template<> struct SizedAttribute<3, 3>: SizedVectorAttribute<3>, SizedMatrixAttribute<3> {};
template<> struct SizedAttribute<4, 4>: SizedVectorAttribute<4>, SizedMatrixAttribute<4> {};
#ifndef MAGNUM_TARGET_GLES2
template<> struct SizedAttribute<2, 3>: SizedVectorAttribute<2>, SizedMatrixAttribute<3> {};
template<> struct SizedAttribute<3, 2>: SizedVectorAttribute<3>, SizedMatrixAttribute<2> {};
template<> struct SizedAttribute<2, 4>: SizedVectorAttribute<2>, SizedMatrixAttribute<4> {};
template<> struct SizedAttribute<4, 2>: SizedVectorAttribute<4>, SizedMatrixAttribute<2> {};
template<> struct SizedAttribute<3, 4>: SizedVectorAttribute<3>, SizedMatrixAttribute<4> {};
template<> struct SizedAttribute<4, 3>: SizedVectorAttribute<4>, SizedMatrixAttribute<3> {};
#endif
/* Base for attributes */
template<class> struct Attribute;
/* Base for float attributes */
struct FloatAttribute {
typedef Float ScalarType;
enum class DataType: GLenum {
UnsignedByte = GL_UNSIGNED_BYTE,
Byte = GL_BYTE,
UnsignedShort = GL_UNSIGNED_SHORT,
Short = GL_SHORT,
UnsignedInt = GL_UNSIGNED_INT,
Int = GL_INT,
#ifndef MAGNUM_TARGET_GLES2
HalfFloat = GL_HALF_FLOAT,
#else
HalfFloat = GL_HALF_FLOAT_OES,
#endif
Float = GL_FLOAT
#ifndef MAGNUM_TARGET_GLES
,
Double = GL_DOUBLE
#endif
};
constexpr static DataType DefaultDataType = DataType::Float;
enum class DataOption: UnsignedByte {
Normalized = 1 << 0
};
typedef Containers::EnumSet<DataOption> DataOptions;
static UnsignedInt MAGNUM_EXPORT size(GLint components, DataType dataType);
};
CORRADE_ENUMSET_OPERATORS(FloatAttribute::DataOptions)
Debug MAGNUM_EXPORT operator<<(Debug debug, FloatAttribute::DataType value);
#ifndef MAGNUM_TARGET_GLES2
/* Base for int attributes */
struct IntAttribute {
typedef Int ScalarType;
enum class DataType: GLenum {
UnsignedByte = GL_UNSIGNED_BYTE,
Byte = GL_BYTE,
UnsignedShort = GL_UNSIGNED_SHORT,
Short = GL_SHORT,
UnsignedInt = GL_UNSIGNED_INT,
Int = GL_INT
};
constexpr static DataType DefaultDataType = DataType::Int;
enum class DataOption: UnsignedByte {};
typedef Containers::EnumSet<DataOption> DataOptions;
static UnsignedInt MAGNUM_EXPORT size(GLint components, DataType dataType);
};
CORRADE_ENUMSET_OPERATORS(IntAttribute::DataOptions)
Debug MAGNUM_EXPORT operator<<(Debug debug, IntAttribute::DataType value);
/* Base for unsigned int attributes */
struct UnsignedIntAttribute {
typedef UnsignedInt ScalarType;
typedef IntAttribute::DataType DataType;
constexpr static DataType DefaultDataType = DataType::UnsignedInt;
typedef IntAttribute::DataOption DataOption;
typedef IntAttribute::DataOptions DataOptions;
static UnsignedInt size(GLint components, DataType dataType) {
return IntAttribute::size(components, dataType);
}
};
#endif
#ifndef MAGNUM_TARGET_GLES
/* Base for double attributes */
struct DoubleAttribute {
typedef Double ScalarType;
enum class DataType: GLenum {
Double = GL_DOUBLE
};
constexpr static DataType DefaultDataType = DataType::Double;
typedef IntAttribute::DataOption DataOption;
typedef IntAttribute::DataOptions DataOptions;
static UnsignedInt MAGNUM_EXPORT size(GLint components, DataType dataType);
};
Debug MAGNUM_EXPORT operator<<(Debug debug, DoubleAttribute::DataType value);
#endif
/* Floating-point three-component vector has additional data type compared to
classic floats */
template<> struct Attribute<Math::Vector<3, Float>>: SizedAttribute<1, 3> {
typedef Float ScalarType;
enum class DataType: GLenum {
UnsignedByte = GL_UNSIGNED_BYTE,
Byte = GL_BYTE,
UnsignedShort = GL_UNSIGNED_SHORT,
Short = GL_SHORT,
UnsignedInt = GL_UNSIGNED_INT,
Int = GL_INT,
#ifndef MAGNUM_TARGET_GLES2
HalfFloat = GL_HALF_FLOAT,
#else
HalfFloat = GL_HALF_FLOAT_OES,
#endif
Float = GL_FLOAT
#ifndef MAGNUM_TARGET_GLES
,
Double = GL_DOUBLE,
UnsignedInt10f11f11fRev = GL_UNSIGNED_INT_10F_11F_11F_REV
#endif
};
constexpr static DataType DefaultDataType = DataType::Float;
typedef FloatAttribute::DataOption DataOption;
typedef FloatAttribute::DataOptions DataOptions;
static UnsignedInt MAGNUM_EXPORT size(GLint components, DataType dataType);
};
Debug MAGNUM_EXPORT operator<<(Debug debug, Attribute<Math::Vector<3, Float>>::DataType value);
/* Floating-point four-component vector is absolutely special case */
template<> struct Attribute<Math::Vector<4, Float>> {
typedef Float ScalarType;
enum class Components: GLint {
One = 1,
Two = 2,
Three = 3,
Four = 4
#ifndef MAGNUM_TARGET_GLES
,
BGRA = GL_BGRA
#endif
};
constexpr static Components DefaultComponents = Components::Four;
enum class DataType: GLenum {
UnsignedByte = GL_UNSIGNED_BYTE,
Byte = GL_BYTE,
UnsignedShort = GL_UNSIGNED_SHORT,
Short = GL_SHORT,
UnsignedInt = GL_UNSIGNED_INT,
Int = GL_INT,
#ifndef MAGNUM_TARGET_GLES2
HalfFloat = GL_HALF_FLOAT,
#else
HalfFloat = GL_HALF_FLOAT_OES,
#endif
Float = GL_FLOAT
#ifndef MAGNUM_TARGET_GLES
,
Double = GL_DOUBLE
#endif
#ifndef MAGNUM_TARGET_GLES2
,
UnsignedInt2101010Rev = GL_UNSIGNED_INT_2_10_10_10_REV,
Int2101010Rev = GL_INT_2_10_10_10_REV
#endif
};
constexpr static DataType DefaultDataType = DataType::Float;
typedef FloatAttribute::DataOption DataOption;
typedef FloatAttribute::DataOptions DataOptions;
enum: UnsignedInt { VectorCount = 1 };
static UnsignedInt MAGNUM_EXPORT size(GLint components, DataType dataType);
};
Debug MAGNUM_EXPORT operator<<(Debug debug, Attribute<Math::Vector<4, Float>>::Components value);
Debug MAGNUM_EXPORT operator<<(Debug debug, Attribute<Math::Vector<4, Float>>::DataType value);
/* Common float, int, unsigned int and double scalar attributes */
template<> struct Attribute<Float>: FloatAttribute, SizedAttribute<1, 1> {};
#ifndef MAGNUM_TARGET_GLES2
template<> struct Attribute<Int>: IntAttribute, SizedAttribute<1, 1> {};
template<> struct Attribute<UnsignedInt>: UnsignedIntAttribute, SizedAttribute<1, 1> {};
#ifndef MAGNUM_TARGET_GLES
template<> struct Attribute<Double>: DoubleAttribute, SizedAttribute<1, 1> {};
#endif
#endif
/* Common float, int, unsigned int and double vector attributes */
template<std::size_t size_> struct Attribute<Math::Vector<size_, Float>>: FloatAttribute, SizedAttribute<1, size_> {};
#ifndef MAGNUM_TARGET_GLES2
template<std::size_t size_> struct Attribute<Math::Vector<size_, Int>>: IntAttribute, SizedAttribute<1, size_> {};
template<std::size_t size_> struct Attribute<Math::Vector<size_, UnsignedInt>>: UnsignedIntAttribute, SizedAttribute<1, size_> {};
#ifndef MAGNUM_TARGET_GLES
template<std::size_t size_> struct Attribute<Math::Vector<size_, Double>>: DoubleAttribute, SizedAttribute<1, size_> {};
#endif
#endif
template<class T> struct Attribute<Math::Vector2<T>>: Attribute<Math::Vector<2, T>> {};
template<class T> struct Attribute<Math::Vector3<T>>: Attribute<Math::Vector<3, T>> {};
template<class T> struct Attribute<Math::Vector4<T>>: Attribute<Math::Vector<4, T>> {};
template<class T> struct Attribute<BasicColor3<T>>: Attribute<Math::Vector3<T>> {};
template<class T> struct Attribute<BasicColor4<T>>: Attribute<Math::Vector4<T>> {};
/* Common float and double rectangular matrix attributes */
template<std::size_t cols, std::size_t rows> struct Attribute<Math::RectangularMatrix<cols, rows, Float>>: FloatAttribute, SizedAttribute<cols, rows> {};
#ifndef MAGNUM_TARGET_GLES
template<std::size_t cols, std::size_t rows> struct Attribute<Math::RectangularMatrix<cols, rows, Double>>: DoubleAttribute, SizedAttribute<cols, rows> {};
#endif
/* Common float and double square matrix attributes */
template<std::size_t size_> struct Attribute<Math::Matrix<size_, Float>>: Attribute<Math::RectangularMatrix<size_, size_, Float>> {};
#ifndef MAGNUM_TARGET_GLES
template<std::size_t size_> struct Attribute<Math::Matrix<size_, Double>>: Attribute<Math::RectangularMatrix<size_, size_, Double>> {};
#endif
template<class T> struct Attribute<Math::Matrix3<T>>: Attribute<Math::Matrix<3, T>> {};
template<class T> struct Attribute<Math::Matrix4<T>>: Attribute<Math::Matrix<4, T>> {};
}
} }
#endif #endif

329
src/Magnum/Attribute.cpp

@ -0,0 +1,329 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include "Attribute.h"
#include <Corrade/Utility/Assert.h>
namespace Magnum { namespace Implementation {
UnsignedInt FloatAttribute::size(GLint components, DataType dataType) {
switch(dataType) {
case DataType::UnsignedByte:
case DataType::Byte:
return components;
case DataType::UnsignedShort:
case DataType::Short:
case DataType::HalfFloat:
return 2*components;
case DataType::UnsignedInt:
case DataType::Int:
case DataType::Float:
return 4*components;
#ifndef MAGNUM_TARGET_GLES
case DataType::Double:
return 8*components;
#endif
}
CORRADE_ASSERT_UNREACHABLE();
}
#ifndef MAGNUM_TARGET_GLES2
UnsignedInt IntAttribute::size(GLint components, DataType dataType) {
switch(dataType) {
case DataType::UnsignedByte:
case DataType::Byte:
return components;
case DataType::UnsignedShort:
case DataType::Short:
return 2*components;
case DataType::UnsignedInt:
case DataType::Int:
return 4*components;
}
CORRADE_ASSERT_UNREACHABLE();
}
#endif
#ifndef MAGNUM_TARGET_GLES
UnsignedInt DoubleAttribute::size(GLint components, DataType dataType) {
switch(dataType) {
case DataType::Double:
return 8*components;
}
CORRADE_ASSERT_UNREACHABLE();
}
#endif
UnsignedInt Attribute<Math::Vector<3, Float>>::size(GLint components, DataType dataType) {
switch(dataType) {
case DataType::UnsignedByte:
case DataType::Byte:
return components;
case DataType::UnsignedShort:
case DataType::Short:
case DataType::HalfFloat:
return 2*components;
case DataType::UnsignedInt:
case DataType::Int:
case DataType::Float:
return 4*components;
#ifndef MAGNUM_TARGET_GLES
case DataType::Double:
return 8*components;
case DataType::UnsignedInt10f11f11fRev:
CORRADE_INTERNAL_ASSERT(components == 3);
return 4;
#endif
}
CORRADE_ASSERT_UNREACHABLE();
}
UnsignedInt Attribute<Math::Vector<4, Float>>::size(GLint components, DataType dataType) {
#ifndef MAGNUM_TARGET_GLES
if(components == GL_BGRA) components = 4;
#endif
switch(dataType) {
case DataType::UnsignedByte:
case DataType::Byte:
return components;
case DataType::UnsignedShort:
case DataType::Short:
case DataType::HalfFloat:
return 2*components;
case DataType::UnsignedInt:
case DataType::Int:
case DataType::Float:
return 4*components;
#ifndef MAGNUM_TARGET_GLES
case DataType::Double:
return 8*components;
#endif
#ifndef MAGNUM_TARGET_GLES2
case DataType::UnsignedInt2101010Rev:
case DataType::Int2101010Rev:
CORRADE_INTERNAL_ASSERT(components == 4);
return 4;
#endif
}
CORRADE_ASSERT_UNREACHABLE();
}
Debug operator<<(Debug debug, SizedAttribute<1, 1>::Components value) {
switch(value) {
case SizedAttribute<1, 1>::Components::One:
return debug << "Attribute::Components::One";
}
return debug << "Attribute::Components::(invalid)";
}
Debug operator<<(Debug debug, SizedAttribute<1, 2>::Components value) {
switch(value) {
case SizedAttribute<1, 2>::Components::One:
return debug << "Attribute::Components::One";
case SizedAttribute<1, 2>::Components::Two:
return debug << "Attribute::Components::Two";
}
return debug << "Attribute::Components::(invalid)";
}
Debug operator<<(Debug debug, SizedAttribute<1, 3>::Components value) {
switch(value) {
case SizedAttribute<1, 3>::Components::One:
return debug << "Attribute::Components::One";
case SizedAttribute<1, 3>::Components::Two:
return debug << "Attribute::Components::Two";
case SizedAttribute<1, 3>::Components::Three:
return debug << "Attribute::Components::Three";
}
return debug << "Attribute::Components::(invalid)";
}
Debug operator<<(Debug debug, SizedAttribute<1, 4>::Components value) {
switch(value) {
case SizedAttribute<1, 4>::Components::One:
return debug << "Attribute::Components::One";
case SizedAttribute<1, 4>::Components::Two:
return debug << "Attribute::Components::Two";
case SizedAttribute<1, 4>::Components::Three:
return debug << "Attribute::Components::Three";
case SizedAttribute<1, 4>::Components::Four:
return debug << "Attribute::Components::Four";
}
return debug << "Attribute::Components::(invalid)";
}
Debug operator<<(Debug debug, SizedMatrixAttribute<2>::Components value) {
switch(value) {
case SizedMatrixAttribute<2>::Components::Two:
return debug << "Attribute::Components::Two";
}
return debug << "Attribute::Components::(invalid)";
}
Debug operator<<(Debug debug, SizedMatrixAttribute<3>::Components value) {
switch(value) {
case SizedMatrixAttribute<3>::Components::Three:
return debug << "Attribute::Components::Three";
}
return debug << "Attribute::Components::(invalid)";
}
Debug operator<<(Debug debug, SizedMatrixAttribute<4>::Components value) {
switch(value) {
case SizedMatrixAttribute<4>::Components::Four:
return debug << "Attribute::Components::Four";
}
return debug << "Attribute::Components::(invalid)";
}
Debug operator<<(Debug debug, Attribute<Math::Vector<4, Float>>::Components value) {
switch(value) {
case Attribute<Math::Vector<4, Float>>::Components::One:
return debug << "Attribute::Components::One";
case Attribute<Math::Vector<4, Float>>::Components::Two:
return debug << "Attribute::Components::Two";
case Attribute<Math::Vector<4, Float>>::Components::Three:
return debug << "Attribute::Components::Three";
case Attribute<Math::Vector<4, Float>>::Components::Four:
return debug << "Attribute::Components::Four";
#ifndef MAGNUM_TARGET_GLES
case Attribute<Math::Vector<4, Float>>::Components::BGRA:
return debug << "Attribute::Components::BGRA";
#endif
}
return debug << "Attribute::Components::(invalid)";
}
Debug operator<<(Debug debug, FloatAttribute::DataType value) {
switch(value) {
#define _c(value) case FloatAttribute::DataType::value: return debug << "Attribute::DataType::" #value;
_c(UnsignedByte)
_c(Byte)
_c(UnsignedShort)
_c(Short)
_c(UnsignedInt)
_c(Int)
_c(HalfFloat)
_c(Float)
#ifndef MAGNUM_TARGET_GLES
_c(Double)
#endif
#undef _c
}
return debug << "Attribute::DataType::(invalid)";
}
#ifndef MAGNUM_TARGET_GLES2
Debug operator<<(Debug debug, IntAttribute::DataType value) {
switch(value) {
#define _c(value) case IntAttribute::DataType::value: return debug << "Attribute::DataType::" #value;
_c(UnsignedByte)
_c(Byte)
_c(UnsignedShort)
_c(Short)
_c(UnsignedInt)
_c(Int)
#undef _c
}
return debug << "Attribute::DataType::(invalid)";
}
#endif
#ifndef MAGNUM_TARGET_GLES
Debug operator<<(Debug debug, DoubleAttribute::DataType value) {
switch(value) {
#define _c(value) case DoubleAttribute::DataType::value: return debug << "Attribute::DataType::" #value;
_c(Double)
#undef _c
}
return debug << "Attribute::DataType::(invalid)";
}
#endif
Debug operator<<(Debug debug, Attribute<Math::Vector<3, Float>>::DataType value) {
switch(value) {
#define _c(value) case Attribute<Math::Vector<3, Float>>::DataType::value: return debug << "Attribute::DataType::" #value;
_c(UnsignedByte)
_c(Byte)
_c(UnsignedShort)
_c(Short)
_c(UnsignedInt)
_c(Int)
_c(HalfFloat)
_c(Float)
#ifndef MAGNUM_TARGET_GLES
_c(Double)
_c(UnsignedInt10f11f11fRev)
#endif
#undef _c
}
return debug << "Attribute::DataType::(invalid)";
}
Debug operator<<(Debug debug, Attribute<Math::Vector<4, Float>>::DataType value) {
switch(value) {
#define _c(value) case Attribute<Math::Vector<4, Float>>::DataType::value: return debug << "Attribute::DataType::" #value;
_c(UnsignedByte)
_c(Byte)
_c(UnsignedShort)
_c(Short)
_c(UnsignedInt)
_c(Int)
_c(HalfFloat)
_c(Float)
#ifndef MAGNUM_TARGET_GLES
_c(Double)
#endif
#ifndef MAGNUM_TARGET_GLES2
_c(UnsignedInt2101010Rev)
_c(Int2101010Rev)
#endif
#undef _c
}
return debug << "Attribute::DataType::(invalid)";
}
}}

582
src/Magnum/Attribute.h

@ -0,0 +1,582 @@
#ifndef Magnum_Attribute_h
#define Magnum_Attribute_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
/** @file
* @brief Class @ref Magnum::Attribute
*/
#include <Corrade/Containers/EnumSet.h>
#include "Magnum/Magnum.h"
#include "Magnum/OpenGL.h"
#include "Magnum/visibility.h"
namespace Magnum {
namespace Implementation { template<class> struct Attribute; }
/**
@brief Base class for attribute location and type
For use in @ref AbstractShaderProgram subclasses. Template parameter @p location
is vertex attribute location, number between `0` and @ref maxVertexAttributes().
To ensure compatibility, you should always have vertex attribute with location
`0`.
Template parameter @p T is the type which is used for shader attribute, e.g.
@ref Vector4i for `ivec4`. DataType is type of passed data when adding vertex
buffers to mesh. By default it is the same as type used in shader (e.g.
@ref DataType::Int for @ref Vector4i). It's also possible to pass integer data
to floating-point shader inputs. In this case you may want to normalize the
values (e.g. color components from 0-255 to 0.0f - 1.0f) -- see
@ref DataOption::Normalized.
Only some types are allowed as attribute types, see @ref AbstractShaderProgram-types
for more information.
See @ref AbstractShaderProgram-subclassing for example usage in shaders and
@ref Mesh-configuration for example usage when adding vertex buffers to mesh.
*/
template<UnsignedInt location, class T> class Attribute {
public:
enum: UnsignedInt {
Location = location, /**< Location to which the attribute is bound */
/**
* Count of vectors in this type
*
* @see @ref vectorSize()
*/
VectorCount = Implementation::Attribute<T>::VectorCount
};
/**
* @brief Type
*
* Type used in shader code.
* @see @ref ScalarType, @ref DataType
*/
typedef T Type;
/**
* @brief Scalar type
*
* The underlying scalar type of the attribute.
* @see @ref Type, @ref DataType
*/
typedef typename Implementation::Attribute<T>::ScalarType ScalarType;
/**
* @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`).
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
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 DataOption::Normalized.
* @requires_gl32 %Extension @extension{ARB,vertex_array_bgra}
* @requires_gl Only RGBA component ordering is supported in OpenGL
* ES.
*/
BGRA = GL_BGRA
#endif
};
#else
typedef typename Implementation::Attribute<T>::Components Components;
#endif
/**
* @brief Data type
*
* Type of data passed to shader.
* @see @ref Type, @ref DataOptions, @ref Attribute()
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
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 */
/**
* Half float. Only for float attribute types.
* @requires_gl30 %Extension @extension{ARB,half_float_vertex}
* @requires_gles30 %Extension @es_extension{OES,vertex_half_float}
* in OpenGL ES 2.0
*/
HalfFloat = GL_HALF_FLOAT,
/** 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.
*/
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.
*/
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) @es_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
*/
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
*/
Int2101010Rev = GL_INT_2_10_10_10_REV
#endif
};
#else
typedef typename Implementation::Attribute<T>::DataType DataType;
#endif
/**
* @brief Data option
* @see @ref DataOptions, @ref Attribute()
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
enum class DataOption: UnsignedByte {
/**
* Normalize integer components. Only for float attribute types.
* Default is to not normalize.
*/
Normalized = 1 << 0
};
#else
typedef typename Implementation::Attribute<T>::DataOption DataOption;
#endif
/**
* @brief Data options
* @see @ref Attribute()
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
typedef typename Containers::EnumSet<DataOption> DataOptions;
#else
typedef typename Implementation::Attribute<T>::DataOptions DataOptions;
#endif
/**
* @brief Constructor
* @param components Component count
* @param dataType Type of passed data. Default is the same as
* type used in shader (e.g. @ref DataType::Int for @ref Vector4i).
* @param dataOptions Data options. Default is no options.
*/
constexpr Attribute(Components components, DataType dataType = Implementation::Attribute<T>::DefaultDataType, DataOptions dataOptions = DataOptions()): _components(components), _dataType(dataType), _dataOptions(dataOptions) {}
/**
* @brief Constructor
* @param dataType Type of passed data. Default is the same as
* type used in shader (e.g. @ref DataType::Int for @ref Vector4i).
* @param dataOptions Data options. Default is no options.
*
* Component count is set to the same value as in type used in shader
* (e.g. @ref Components::Three for @ref Vector3).
*/
constexpr Attribute(DataType dataType = Implementation::Attribute<T>::DefaultDataType, DataOptions dataOptions = DataOptions()): _components(Implementation::Attribute<T>::DefaultComponents), _dataType(dataType), _dataOptions(dataOptions) {}
/** @brief Component count of passed data */
constexpr Components components() const { return _components; }
/** @brief Type of passed data */
constexpr DataType dataType() const { return _dataType; }
/**
* @brief Size of each vector in passed data
*
* @see @ref VectorCount
*/
UnsignedInt vectorSize() const {
return Implementation::Attribute<T>::size(GLint(_components), _dataType);
}
/** @brief Data options */
constexpr DataOptions dataOptions() const { return _dataOptions; }
private:
Components _components;
DataType _dataType;
DataOptions _dataOptions;
};
#ifdef DOXYGEN_GENERATING_OUTPUT
/** @debugoperatorclassenum{Magnum::Attribute,Magnum::Attribute::Components} */
template<class T> Debug operator<<(Debug debug, Attribute<T>::Components);
/** @debugoperatorclassenum{Magnum::Attribute,Magnum::Attribute::DataType} */
template<class T> Debug operator<<(Debug debug, Attribute<T>::DataType);
#endif
namespace Implementation {
/* Base for sized attributes */
template<std::size_t cols, std::size_t rows> struct SizedAttribute;
/* Vector attribute sizes */
template<std::size_t cols> struct SizedVectorAttribute {
enum: UnsignedInt { VectorCount = UnsignedInt(cols) };
};
template<> struct SizedAttribute<1, 1>: SizedVectorAttribute<1> {
enum class Components: GLint { One = 1 };
constexpr static Components DefaultComponents = Components::One;
};
template<> struct SizedAttribute<1, 2>: SizedVectorAttribute<1> {
enum class Components: GLint { One = 1, Two = 2 };
constexpr static Components DefaultComponents = Components::Two;
};
template<> struct SizedAttribute<1, 3>: SizedVectorAttribute<1> {
enum class Components: GLint { One = 1, Two = 2, Three = 3 };
constexpr static Components DefaultComponents = Components::Three;
};
template<> struct SizedAttribute<1, 4>: SizedVectorAttribute<1> {
enum class Components: GLint { One = 1, Two = 2, Three = 3, Four = 4 };
constexpr static Components DefaultComponents = Components::Four;
};
Debug MAGNUM_EXPORT operator<<(Debug debug, SizedAttribute<1, 1>::Components value);
Debug MAGNUM_EXPORT operator<<(Debug debug, SizedAttribute<1, 2>::Components value);
Debug MAGNUM_EXPORT operator<<(Debug debug, SizedAttribute<1, 3>::Components value);
Debug MAGNUM_EXPORT operator<<(Debug debug, SizedAttribute<1, 4>::Components value);
/* Matrix attribute sizes */
template<std::size_t rows> struct SizedMatrixAttribute;
template<> struct SizedMatrixAttribute<2> {
enum class Components: GLint { Two = 2 };
constexpr static Components DefaultComponents = Components::Two;
};
template<> struct SizedMatrixAttribute<3> {
enum class Components: GLint { Three = 3 };
constexpr static Components DefaultComponents = Components::Three;
};
template<> struct SizedMatrixAttribute<4> {
enum class Components: GLint { Four = 4 };
constexpr static Components DefaultComponents = Components::Four;
};
Debug MAGNUM_EXPORT operator<<(Debug debug, SizedMatrixAttribute<2>::Components value);
Debug MAGNUM_EXPORT operator<<(Debug debug, SizedMatrixAttribute<3>::Components value);
Debug MAGNUM_EXPORT operator<<(Debug debug, SizedMatrixAttribute<4>::Components value);
template<> struct SizedAttribute<2, 2>: SizedVectorAttribute<2>, SizedMatrixAttribute<2> {};
template<> struct SizedAttribute<3, 3>: SizedVectorAttribute<3>, SizedMatrixAttribute<3> {};
template<> struct SizedAttribute<4, 4>: SizedVectorAttribute<4>, SizedMatrixAttribute<4> {};
#ifndef MAGNUM_TARGET_GLES2
template<> struct SizedAttribute<2, 3>: SizedVectorAttribute<2>, SizedMatrixAttribute<3> {};
template<> struct SizedAttribute<3, 2>: SizedVectorAttribute<3>, SizedMatrixAttribute<2> {};
template<> struct SizedAttribute<2, 4>: SizedVectorAttribute<2>, SizedMatrixAttribute<4> {};
template<> struct SizedAttribute<4, 2>: SizedVectorAttribute<4>, SizedMatrixAttribute<2> {};
template<> struct SizedAttribute<3, 4>: SizedVectorAttribute<3>, SizedMatrixAttribute<4> {};
template<> struct SizedAttribute<4, 3>: SizedVectorAttribute<4>, SizedMatrixAttribute<3> {};
#endif
/* Base for attributes */
template<class> struct Attribute;
/* Base for float attributes */
struct FloatAttribute {
typedef Float ScalarType;
enum class DataType: GLenum {
UnsignedByte = GL_UNSIGNED_BYTE,
Byte = GL_BYTE,
UnsignedShort = GL_UNSIGNED_SHORT,
Short = GL_SHORT,
UnsignedInt = GL_UNSIGNED_INT,
Int = GL_INT,
#ifndef MAGNUM_TARGET_GLES2
HalfFloat = GL_HALF_FLOAT,
#else
HalfFloat = GL_HALF_FLOAT_OES,
#endif
Float = GL_FLOAT
#ifndef MAGNUM_TARGET_GLES
,
Double = GL_DOUBLE
#endif
};
constexpr static DataType DefaultDataType = DataType::Float;
enum class DataOption: UnsignedByte {
Normalized = 1 << 0
};
typedef Containers::EnumSet<DataOption> DataOptions;
static UnsignedInt MAGNUM_EXPORT size(GLint components, DataType dataType);
};
CORRADE_ENUMSET_OPERATORS(FloatAttribute::DataOptions)
Debug MAGNUM_EXPORT operator<<(Debug debug, FloatAttribute::DataType value);
#ifndef MAGNUM_TARGET_GLES2
/* Base for int attributes */
struct IntAttribute {
typedef Int ScalarType;
enum class DataType: GLenum {
UnsignedByte = GL_UNSIGNED_BYTE,
Byte = GL_BYTE,
UnsignedShort = GL_UNSIGNED_SHORT,
Short = GL_SHORT,
UnsignedInt = GL_UNSIGNED_INT,
Int = GL_INT
};
constexpr static DataType DefaultDataType = DataType::Int;
enum class DataOption: UnsignedByte {};
typedef Containers::EnumSet<DataOption> DataOptions;
static UnsignedInt MAGNUM_EXPORT size(GLint components, DataType dataType);
};
CORRADE_ENUMSET_OPERATORS(IntAttribute::DataOptions)
Debug MAGNUM_EXPORT operator<<(Debug debug, IntAttribute::DataType value);
/* Base for unsigned int attributes */
struct UnsignedIntAttribute {
typedef UnsignedInt ScalarType;
typedef IntAttribute::DataType DataType;
constexpr static DataType DefaultDataType = DataType::UnsignedInt;
typedef IntAttribute::DataOption DataOption;
typedef IntAttribute::DataOptions DataOptions;
static UnsignedInt size(GLint components, DataType dataType) {
return IntAttribute::size(components, dataType);
}
};
#endif
#ifndef MAGNUM_TARGET_GLES
/* Base for double attributes */
struct DoubleAttribute {
typedef Double ScalarType;
enum class DataType: GLenum {
Double = GL_DOUBLE
};
constexpr static DataType DefaultDataType = DataType::Double;
typedef IntAttribute::DataOption DataOption;
typedef IntAttribute::DataOptions DataOptions;
static UnsignedInt MAGNUM_EXPORT size(GLint components, DataType dataType);
};
Debug MAGNUM_EXPORT operator<<(Debug debug, DoubleAttribute::DataType value);
#endif
/* Floating-point three-component vector has additional data type compared to
classic floats */
template<> struct Attribute<Math::Vector<3, Float>>: SizedAttribute<1, 3> {
typedef Float ScalarType;
enum class DataType: GLenum {
UnsignedByte = GL_UNSIGNED_BYTE,
Byte = GL_BYTE,
UnsignedShort = GL_UNSIGNED_SHORT,
Short = GL_SHORT,
UnsignedInt = GL_UNSIGNED_INT,
Int = GL_INT,
#ifndef MAGNUM_TARGET_GLES2
HalfFloat = GL_HALF_FLOAT,
#else
HalfFloat = GL_HALF_FLOAT_OES,
#endif
Float = GL_FLOAT
#ifndef MAGNUM_TARGET_GLES
,
Double = GL_DOUBLE,
UnsignedInt10f11f11fRev = GL_UNSIGNED_INT_10F_11F_11F_REV
#endif
};
constexpr static DataType DefaultDataType = DataType::Float;
typedef FloatAttribute::DataOption DataOption;
typedef FloatAttribute::DataOptions DataOptions;
static UnsignedInt MAGNUM_EXPORT size(GLint components, DataType dataType);
};
Debug MAGNUM_EXPORT operator<<(Debug debug, Attribute<Math::Vector<3, Float>>::DataType value);
/* Floating-point four-component vector is absolutely special case */
template<> struct Attribute<Math::Vector<4, Float>> {
typedef Float ScalarType;
enum class Components: GLint {
One = 1,
Two = 2,
Three = 3,
Four = 4
#ifndef MAGNUM_TARGET_GLES
,
BGRA = GL_BGRA
#endif
};
constexpr static Components DefaultComponents = Components::Four;
enum class DataType: GLenum {
UnsignedByte = GL_UNSIGNED_BYTE,
Byte = GL_BYTE,
UnsignedShort = GL_UNSIGNED_SHORT,
Short = GL_SHORT,
UnsignedInt = GL_UNSIGNED_INT,
Int = GL_INT,
#ifndef MAGNUM_TARGET_GLES2
HalfFloat = GL_HALF_FLOAT,
#else
HalfFloat = GL_HALF_FLOAT_OES,
#endif
Float = GL_FLOAT
#ifndef MAGNUM_TARGET_GLES
,
Double = GL_DOUBLE
#endif
#ifndef MAGNUM_TARGET_GLES2
,
UnsignedInt2101010Rev = GL_UNSIGNED_INT_2_10_10_10_REV,
Int2101010Rev = GL_INT_2_10_10_10_REV
#endif
};
constexpr static DataType DefaultDataType = DataType::Float;
typedef FloatAttribute::DataOption DataOption;
typedef FloatAttribute::DataOptions DataOptions;
enum: UnsignedInt { VectorCount = 1 };
static UnsignedInt MAGNUM_EXPORT size(GLint components, DataType dataType);
};
Debug MAGNUM_EXPORT operator<<(Debug debug, Attribute<Math::Vector<4, Float>>::Components value);
Debug MAGNUM_EXPORT operator<<(Debug debug, Attribute<Math::Vector<4, Float>>::DataType value);
/* Common float, int, unsigned int and double scalar attributes */
template<> struct Attribute<Float>: FloatAttribute, SizedAttribute<1, 1> {};
#ifndef MAGNUM_TARGET_GLES2
template<> struct Attribute<Int>: IntAttribute, SizedAttribute<1, 1> {};
template<> struct Attribute<UnsignedInt>: UnsignedIntAttribute, SizedAttribute<1, 1> {};
#ifndef MAGNUM_TARGET_GLES
template<> struct Attribute<Double>: DoubleAttribute, SizedAttribute<1, 1> {};
#endif
#endif
/* Common float, int, unsigned int and double vector attributes */
template<std::size_t size_> struct Attribute<Math::Vector<size_, Float>>: FloatAttribute, SizedAttribute<1, size_> {};
#ifndef MAGNUM_TARGET_GLES2
template<std::size_t size_> struct Attribute<Math::Vector<size_, Int>>: IntAttribute, SizedAttribute<1, size_> {};
template<std::size_t size_> struct Attribute<Math::Vector<size_, UnsignedInt>>: UnsignedIntAttribute, SizedAttribute<1, size_> {};
#ifndef MAGNUM_TARGET_GLES
template<std::size_t size_> struct Attribute<Math::Vector<size_, Double>>: DoubleAttribute, SizedAttribute<1, size_> {};
#endif
#endif
template<class T> struct Attribute<Math::Vector2<T>>: Attribute<Math::Vector<2, T>> {};
template<class T> struct Attribute<Math::Vector3<T>>: Attribute<Math::Vector<3, T>> {};
template<class T> struct Attribute<Math::Vector4<T>>: Attribute<Math::Vector<4, T>> {};
template<class T> struct Attribute<BasicColor3<T>>: Attribute<Math::Vector3<T>> {};
template<class T> struct Attribute<BasicColor4<T>>: Attribute<Math::Vector4<T>> {};
/* Common float and double rectangular matrix attributes */
template<std::size_t cols, std::size_t rows> struct Attribute<Math::RectangularMatrix<cols, rows, Float>>: FloatAttribute, SizedAttribute<cols, rows> {};
#ifndef MAGNUM_TARGET_GLES
template<std::size_t cols, std::size_t rows> struct Attribute<Math::RectangularMatrix<cols, rows, Double>>: DoubleAttribute, SizedAttribute<cols, rows> {};
#endif
/* Common float and double square matrix attributes */
template<std::size_t size_> struct Attribute<Math::Matrix<size_, Float>>: Attribute<Math::RectangularMatrix<size_, size_, Float>> {};
#ifndef MAGNUM_TARGET_GLES
template<std::size_t size_> struct Attribute<Math::Matrix<size_, Double>>: Attribute<Math::RectangularMatrix<size_, size_, Double>> {};
#endif
template<class T> struct Attribute<Math::Matrix3<T>>: Attribute<Math::Matrix<3, T>> {};
template<class T> struct Attribute<Math::Matrix4<T>>: Attribute<Math::Matrix<4, T>> {};
}
}
#endif

2
src/Magnum/CMakeLists.txt

@ -34,6 +34,7 @@ set(Magnum_SRCS
AbstractQuery.cpp AbstractQuery.cpp
AbstractTexture.cpp AbstractTexture.cpp
AbstractShaderProgram.cpp AbstractShaderProgram.cpp
Attribute.cpp
Buffer.cpp Buffer.cpp
ColorFormat.cpp ColorFormat.cpp
CubeMapTexture.cpp CubeMapTexture.cpp
@ -89,6 +90,7 @@ set(Magnum_HEADERS
AbstractShaderProgram.h AbstractShaderProgram.h
AbstractTexture.h AbstractTexture.h
Array.h Array.h
Attribute.h
Buffer.h Buffer.h
Color.h Color.h
ColorFormat.h ColorFormat.h

1
src/Magnum/DebugTools/ResourceManager.cpp

@ -27,6 +27,7 @@
#include "ResourceManager.h" #include "ResourceManager.h"
#include "Magnum/AbstractShaderProgram.h"
#include "Magnum/Buffer.h" #include "Magnum/Buffer.h"
#include "Magnum/Mesh.h" #include "Magnum/Mesh.h"
#include "Magnum/MeshView.h" #include "Magnum/MeshView.h"

2
src/Magnum/Implementation/MeshState.h

@ -39,7 +39,7 @@ struct MeshState {
void(Mesh::*createImplementation)(); void(Mesh::*createImplementation)();
void(Mesh::*destroyImplementation)(); void(Mesh::*destroyImplementation)();
void(Mesh::*attributePointerImplementation)(const Mesh::Attribute&); void(Mesh::*attributePointerImplementation)(const Mesh::GenericAttribute&);
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void(Mesh::*attributeIPointerImplementation)(const Mesh::IntegerAttribute&); void(Mesh::*attributeIPointerImplementation)(const Mesh::IntegerAttribute&);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES

2
src/Magnum/Magnum.h

@ -454,6 +454,8 @@ template<class T> class Array1D;
template<class T> class Array2D; template<class T> class Array2D;
template<class T> class Array3D; template<class T> class Array3D;
template<UnsignedInt, class> class Attribute;
enum class BufferUsage: GLenum; enum class BufferUsage: GLenum;
class Buffer; class Buffer;

27
src/Magnum/Mesh.cpp

@ -27,6 +27,7 @@
#include <Corrade/Utility/Debug.h> #include <Corrade/Utility/Debug.h>
#include "Magnum/AbstractShaderProgram.h"
#include "Magnum/Buffer.h" #include "Magnum/Buffer.h"
#include "Magnum/Context.h" #include "Magnum/Context.h"
#include "Magnum/Extensions.h" #include "Magnum/Extensions.h"
@ -207,6 +208,18 @@ Mesh& Mesh::setIndexBuffer(Buffer& buffer, GLintptr offset, IndexType type, Unsi
return *this; return *this;
} }
void Mesh::draw(AbstractShaderProgram& shader) {
shader.use();
#ifndef MAGNUM_TARGET_GLES
drawInternal(_count, _baseVertex, _instanceCount, _baseInstance, _indexOffset, _indexStart, _indexEnd);
#elif !defined(MAGNUM_TARGET_GLES2)
drawInternal(_count, _baseVertex, _instanceCount, _indexOffset, _indexStart, _indexEnd);
#else
drawInternal(_count, _baseVertex, _instanceCount, _indexOffset);
#endif
}
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void Mesh::drawInternal(Int count, Int baseVertex, Int instanceCount, UnsignedInt baseInstance, GLintptr indexOffset, Int indexStart, Int indexEnd) void Mesh::drawInternal(Int count, Int baseVertex, Int instanceCount, UnsignedInt baseInstance, GLintptr indexOffset, Int indexStart, Int indexEnd)
#elif !defined(MAGNUM_TARGET_GLES2) #elif !defined(MAGNUM_TARGET_GLES2)
@ -365,11 +378,11 @@ void Mesh::destroyImplementationVAO() {
#endif #endif
} }
void Mesh::attributePointerInternal(const Attribute& attribute) { void Mesh::attributePointerInternal(const GenericAttribute& attribute) {
(this->*Context::current()->state().mesh->attributePointerImplementation)(attribute); (this->*Context::current()->state().mesh->attributePointerImplementation)(attribute);
} }
void Mesh::attributePointerImplementationDefault(const Attribute& attribute) { void Mesh::attributePointerImplementationDefault(const GenericAttribute& attribute) {
#if defined(CORRADE_TARGET_NACL) || defined(MAGNUM_TARGET_WEBGL) #if defined(CORRADE_TARGET_NACL) || defined(MAGNUM_TARGET_WEBGL)
CORRADE_ASSERT(attribute.buffer->targetHint() == Buffer::TargetHint::Array, CORRADE_ASSERT(attribute.buffer->targetHint() == Buffer::TargetHint::Array,
"Mesh::addVertexBuffer(): the buffer has unexpected target hint, expected" << Buffer::TargetHint::Array << "but got" << attribute.buffer->targetHint(), ); "Mesh::addVertexBuffer(): the buffer has unexpected target hint, expected" << Buffer::TargetHint::Array << "but got" << attribute.buffer->targetHint(), );
@ -378,7 +391,7 @@ void Mesh::attributePointerImplementationDefault(const Attribute& attribute) {
_attributes.push_back(attribute); _attributes.push_back(attribute);
} }
void Mesh::attributePointerImplementationVAO(const Attribute& attribute) { void Mesh::attributePointerImplementationVAO(const GenericAttribute& attribute) {
#if defined(CORRADE_TARGET_NACL) || defined(MAGNUM_TARGET_WEBGL) #if defined(CORRADE_TARGET_NACL) || defined(MAGNUM_TARGET_WEBGL)
CORRADE_ASSERT(attribute.buffer->targetHint() == Buffer::TargetHint::Array, CORRADE_ASSERT(attribute.buffer->targetHint() == Buffer::TargetHint::Array,
"Mesh::addVertexBuffer(): the buffer has unexpected target hint, expected" << Buffer::TargetHint::Array << "but got" << attribute.buffer->targetHint(), ); "Mesh::addVertexBuffer(): the buffer has unexpected target hint, expected" << Buffer::TargetHint::Array << "but got" << attribute.buffer->targetHint(), );
@ -389,7 +402,7 @@ void Mesh::attributePointerImplementationVAO(const Attribute& attribute) {
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void Mesh::attributePointerImplementationDSAEXT(const Attribute& attribute) { void Mesh::attributePointerImplementationDSAEXT(const GenericAttribute& attribute) {
_created = true; _created = true;
glEnableVertexArrayAttribEXT(_id, attribute.location); glEnableVertexArrayAttribEXT(_id, attribute.location);
glVertexArrayVertexAttribOffsetEXT(_id, attribute.buffer->id(), attribute.location, attribute.size, attribute.type, attribute.normalized, attribute.stride, attribute.offset); glVertexArrayVertexAttribOffsetEXT(_id, attribute.buffer->id(), attribute.location, attribute.size, attribute.type, attribute.normalized, attribute.stride, attribute.offset);
@ -397,7 +410,7 @@ void Mesh::attributePointerImplementationDSAEXT(const Attribute& attribute) {
} }
#endif #endif
void Mesh::vertexAttribPointer(const Attribute& attribute) { void Mesh::vertexAttribPointer(const GenericAttribute& attribute) {
glEnableVertexAttribArray(attribute.location); glEnableVertexAttribArray(attribute.location);
attribute.buffer->bindInternal(Buffer::TargetHint::Array); attribute.buffer->bindInternal(Buffer::TargetHint::Array);
glVertexAttribPointer(attribute.location, attribute.size, attribute.type, attribute.normalized, attribute.stride, reinterpret_cast<const GLvoid*>(attribute.offset)); glVertexAttribPointer(attribute.location, attribute.size, attribute.type, attribute.normalized, attribute.stride, reinterpret_cast<const GLvoid*>(attribute.offset));
@ -516,7 +529,7 @@ void Mesh::bindIndexBufferImplementationVAO(Buffer& buffer) {
void Mesh::bindImplementationDefault() { void Mesh::bindImplementationDefault() {
/* Specify vertex attributes */ /* Specify vertex attributes */
for(const Attribute& attribute: _attributes) for(const GenericAttribute& attribute: _attributes)
vertexAttribPointer(attribute); vertexAttribPointer(attribute);
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
@ -538,7 +551,7 @@ void Mesh::bindImplementationVAO() {
} }
void Mesh::unbindImplementationDefault() { void Mesh::unbindImplementationDefault() {
for(const Attribute& attribute: _attributes) for(const GenericAttribute& attribute: _attributes)
glDisableVertexAttribArray(attribute.location); glDisableVertexAttribArray(attribute.location);
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2

59
src/Magnum/Mesh.h

@ -30,9 +30,11 @@
*/ */
#include <vector> #include <vector>
#include <Corrade/Containers/Array.h>
#include <Corrade/Utility/ConfigurationValue.h> #include <Corrade/Utility/ConfigurationValue.h>
#include "Magnum/AbstractShaderProgram.h" #include "Magnum/AbstractObject.h"
#include "Magnum/Attribute.h"
namespace Magnum { namespace Magnum {
@ -125,9 +127,8 @@ namespace Implementation { struct MeshState; }
You have to specify at least primitive and vertex/index count using You have to specify at least primitive and vertex/index count using
@ref setPrimitive() and @ref setCount(). Then fill your vertex buffers with @ref setPrimitive() and @ref setCount(). Then fill your vertex buffers with
data, add them to the mesh and specify data, add them to the mesh and specify @ref Attribute "shader attribute" layout
@ref AbstractShaderProgram::Attribute "shader attribute" layout inside the inside the buffers using @ref addVertexBuffer(). You can also use
buffers using @ref addVertexBuffer(). You can also use
@ref MeshTools::interleave() to conveniently interleave vertex data. @ref MeshTools::interleave() to conveniently interleave vertex data.
If you want indexed mesh, fill your index buffer with data and specify its If you want indexed mesh, fill your index buffer with data and specify its
@ -640,7 +641,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* Parameter @p offset is offset of the array from the beginning, * Parameter @p offset is offset of the array from the beginning,
* attribute list is combination of @ref AbstractShaderProgram::Attribute "attribute definitions" * attribute list is combination of @ref Attribute "attribute definitions"
* (specified in implementation of given shader) and offsets between * (specified in implementation of given shader) and offsets between
* interleaved attributes. * interleaved attributes.
* *
@ -807,17 +808,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* @fn_gl{DrawElementsInstancedBaseVertex}/ * @fn_gl{DrawElementsInstancedBaseVertex}/
* @fn_gl{DrawElementsInstancedBaseVertexBaseInstance} * @fn_gl{DrawElementsInstancedBaseVertexBaseInstance}
*/ */
void draw(AbstractShaderProgram& shader) { void draw(AbstractShaderProgram& shader);
shader.use();
#ifndef MAGNUM_TARGET_GLES
drawInternal(_count, _baseVertex, _instanceCount, _baseInstance, _indexOffset, _indexStart, _indexEnd);
#elif !defined(MAGNUM_TARGET_GLES2)
drawInternal(_count, _baseVertex, _instanceCount, _indexOffset, _indexStart, _indexEnd);
#else
drawInternal(_count, _baseVertex, _instanceCount, _indexOffset);
#endif
}
void draw(AbstractShaderProgram&& shader) { draw(shader); } /**< @overload */ void draw(AbstractShaderProgram&& shader) { draw(shader); } /**< @overload */
@ -840,7 +831,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
private: private:
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
struct MAGNUM_LOCAL Attribute { struct MAGNUM_LOCAL GenericAttribute {
Buffer* buffer; Buffer* buffer;
GLuint location; GLuint location;
GLint size; GLint size;
@ -881,8 +872,8 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
Mesh& setLabelInternal(Containers::ArrayReference<const char> label); Mesh& setLabelInternal(Containers::ArrayReference<const char> label);
/* Computing stride of interleaved vertex attributes */ /* Computing stride of interleaved vertex attributes */
template<UnsignedInt location, class T, class ...U> static GLsizei strideOfInterleaved(const AbstractShaderProgram::Attribute<location, T>& attribute, const U&... attributes) { template<UnsignedInt location, class T, class ...U> static GLsizei strideOfInterleaved(const Attribute<location, T>& attribute, const U&... attributes) {
return attribute.vectorSize()*AbstractShaderProgram::Attribute<location, T>::VectorCount + strideOfInterleaved(attributes...); return attribute.vectorSize()*Attribute<location, T>::VectorCount + strideOfInterleaved(attributes...);
} }
template<class ...T> static GLsizei strideOfInterleaved(GLintptr gap, const T&... attributes) { template<class ...T> static GLsizei strideOfInterleaved(GLintptr gap, const T&... attributes) {
return gap + strideOfInterleaved(attributes...); return gap + strideOfInterleaved(attributes...);
@ -890,11 +881,11 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
static GLsizei strideOfInterleaved() { return 0; } static GLsizei strideOfInterleaved() { return 0; }
/* Adding interleaved vertex attributes */ /* Adding interleaved vertex attributes */
template<UnsignedInt location, class T, class ...U> void addVertexBufferInternal(Buffer& buffer, GLintptr offset, GLsizei stride, GLuint divisor, const AbstractShaderProgram::Attribute<location, T>& attribute, const U&... attributes) { template<UnsignedInt location, class T, class ...U> void addVertexBufferInternal(Buffer& buffer, GLintptr offset, GLsizei stride, GLuint divisor, const Attribute<location, T>& attribute, const U&... attributes) {
addVertexAttribute(buffer, attribute, offset, stride, divisor); addVertexAttribute(buffer, attribute, offset, stride, divisor);
/* Add size of this attribute to offset for next attribute */ /* Add size of this attribute to offset for next attribute */
addVertexBufferInternal(buffer, offset+attribute.vectorSize()*AbstractShaderProgram::Attribute<location, T>::VectorCount, stride, divisor, attributes...); addVertexBufferInternal(buffer, offset+attribute.vectorSize()*Attribute<location, T>::VectorCount, stride, divisor, attributes...);
} }
template<class ...T> void addVertexBufferInternal(Buffer& buffer, GLintptr offset, GLsizei stride, GLuint divisor, GLintptr gap, const T&... attributes) { template<class ...T> void addVertexBufferInternal(Buffer& buffer, GLintptr offset, GLsizei stride, GLuint divisor, GLintptr gap, const T&... attributes) {
/* Add the gap to offset for next attribute */ /* Add the gap to offset for next attribute */
@ -902,14 +893,14 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
} }
void addVertexBufferInternal(Buffer&, GLsizei, GLuint, GLintptr) {} void addVertexBufferInternal(Buffer&, GLsizei, GLuint, GLintptr) {}
template<UnsignedInt location, class T> void addVertexAttribute(typename std::enable_if<std::is_same<typename Implementation::Attribute<T>::ScalarType, Float>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute<location, T>& attribute, GLintptr offset, GLsizei stride, GLuint divisor) { template<UnsignedInt location, class T> void addVertexAttribute(typename std::enable_if<std::is_same<typename Implementation::Attribute<T>::ScalarType, Float>::value, Buffer&>::type buffer, const Attribute<location, T>& attribute, GLintptr offset, GLsizei stride, GLuint divisor) {
for(UnsignedInt i = 0; i != AbstractShaderProgram::Attribute<location, T>::VectorCount; ++i) for(UnsignedInt i = 0; i != Attribute<location, T>::VectorCount; ++i)
attributePointerInternal(Attribute{ attributePointerInternal(GenericAttribute{
&buffer, &buffer,
location+i, location+i,
GLint(attribute.components()), GLint(attribute.components()),
GLenum(attribute.dataType()), GLenum(attribute.dataType()),
bool(attribute.dataOptions() & AbstractShaderProgram::Attribute<location, T>::DataOption::Normalized), bool(attribute.dataOptions() & Attribute<location, T>::DataOption::Normalized),
GLintptr(offset+i*attribute.vectorSize()), GLintptr(offset+i*attribute.vectorSize()),
stride, stride,
divisor divisor
@ -917,7 +908,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
} }
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt location, class T> void addVertexAttribute(typename std::enable_if<std::is_integral<typename Implementation::Attribute<T>::ScalarType>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute<location, T>& attribute, GLintptr offset, GLsizei stride, GLuint divisor) { template<UnsignedInt location, class T> void addVertexAttribute(typename std::enable_if<std::is_integral<typename Implementation::Attribute<T>::ScalarType>::value, Buffer&>::type buffer, const Attribute<location, T>& attribute, GLintptr offset, GLsizei stride, GLuint divisor) {
attributePointerInternal(IntegerAttribute{ attributePointerInternal(IntegerAttribute{
&buffer, &buffer,
location, location,
@ -930,8 +921,8 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
template<UnsignedInt location, class T> void addVertexAttribute(typename std::enable_if<std::is_same<typename Implementation::Attribute<T>::ScalarType, Double>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute<location, T>& attribute, GLintptr offset, GLsizei stride, GLuint divisor) { template<UnsignedInt location, class T> void addVertexAttribute(typename std::enable_if<std::is_same<typename Implementation::Attribute<T>::ScalarType, Double>::value, Buffer&>::type buffer, const Attribute<location, T>& attribute, GLintptr offset, GLsizei stride, GLuint divisor) {
for(UnsignedInt i = 0; i != AbstractShaderProgram::Attribute<location, T>::VectorCount; ++i) for(UnsignedInt i = 0; i != Attribute<location, T>::VectorCount; ++i)
attributePointerInternal(LongAttribute{ attributePointerInternal(LongAttribute{
&buffer, &buffer,
location+i, location+i,
@ -964,13 +955,13 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
void MAGNUM_LOCAL destroyImplementationDefault(); void MAGNUM_LOCAL destroyImplementationDefault();
void MAGNUM_LOCAL destroyImplementationVAO(); void MAGNUM_LOCAL destroyImplementationVAO();
void attributePointerInternal(const Attribute& attribute); void attributePointerInternal(const GenericAttribute& attribute);
void MAGNUM_LOCAL attributePointerImplementationDefault(const Attribute& attribute); void MAGNUM_LOCAL attributePointerImplementationDefault(const GenericAttribute& attribute);
void MAGNUM_LOCAL attributePointerImplementationVAO(const Attribute& attribute); void MAGNUM_LOCAL attributePointerImplementationVAO(const GenericAttribute& attribute);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL attributePointerImplementationDSAEXT(const Attribute& attribute); void MAGNUM_LOCAL attributePointerImplementationDSAEXT(const GenericAttribute& attribute);
#endif #endif
void MAGNUM_LOCAL vertexAttribPointer(const Attribute& attribute); void MAGNUM_LOCAL vertexAttribPointer(const GenericAttribute& attribute);
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void attributePointerInternal(const IntegerAttribute& attribute); void attributePointerInternal(const IntegerAttribute& attribute);
@ -1029,7 +1020,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
IndexType _indexType; IndexType _indexType;
Buffer* _indexBuffer; Buffer* _indexBuffer;
std::vector<Attribute> _attributes; std::vector<GenericAttribute> _attributes;
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
std::vector<IntegerAttribute> _integerAttributes; std::vector<IntegerAttribute> _integerAttributes;
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES

4
src/Magnum/MeshTools/FullScreenTriangle.cpp

@ -25,7 +25,7 @@
#include "FullScreenTriangle.h" #include "FullScreenTriangle.h"
#include "Magnum/AbstractShaderProgram.h" #include "Magnum/Attribute.h"
#include "Magnum/Buffer.h" #include "Magnum/Buffer.h"
#include "Magnum/Context.h" #include "Magnum/Context.h"
#include "Magnum/Mesh.h" #include "Magnum/Mesh.h"
@ -55,7 +55,7 @@ std::pair<std::unique_ptr<Buffer>, Mesh> fullScreenTriangle(Version version) {
buffer->setData(triangle, BufferUsage::StaticDraw); buffer->setData(triangle, BufferUsage::StaticDraw);
/** @todo Is it possible to attach moveable buffer here to avoid heap /** @todo Is it possible to attach moveable buffer here to avoid heap
allocation? OTOH this is more effective in most (modern) cases */ allocation? OTOH this is more effective in most (modern) cases */
mesh.addVertexBuffer(*buffer, 0, AbstractShaderProgram::Attribute<0, Vector2>()); mesh.addVertexBuffer(*buffer, 0, Attribute<0, Vector2>{});
} }
return {std::move(buffer), std::move(mesh)}; return {std::move(buffer), std::move(mesh)};

1
src/Magnum/MeshView.cpp

@ -28,6 +28,7 @@
#include <Corrade/Containers/Array.h> #include <Corrade/Containers/Array.h>
#include <Corrade/Utility/Assert.h> #include <Corrade/Utility/Assert.h>
#include "Magnum/AbstractShaderProgram.h"
#include "Magnum/Context.h" #include "Magnum/Context.h"
#include "Magnum/Mesh.h" #include "Magnum/Mesh.h"

14
src/Magnum/Shaders/Generic.h

@ -68,17 +68,17 @@ template<UnsignedInt dimensions> struct Generic {
* *
* Defined as @ref Vector2 in 2D and @ref Vector3 in 3D. * Defined as @ref Vector2 in 2D and @ref Vector3 in 3D.
*/ */
typedef AbstractShaderProgram::Attribute<0, T> Position; typedef Attribute<0, T> Position;
/** @brief 2D texture coordinates */ /** @brief 2D texture coordinates */
typedef AbstractShaderProgram::Attribute<1, Vector2> TextureCoordinates; typedef Attribute<1, Vector2> TextureCoordinates;
/** /**
* @brief Vertex normal * @brief Vertex normal
* *
* Defined only in 3D. * Defined only in 3D.
*/ */
typedef AbstractShaderProgram::Attribute<2, Vector3> Normal; typedef Attribute<2, Vector3> Normal;
}; };
#endif #endif
@ -90,16 +90,16 @@ typedef Generic<3> Generic3D;
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
struct BaseGeneric { struct BaseGeneric {
typedef AbstractShaderProgram::Attribute<1, Vector2> TextureCoordinates; typedef Attribute<1, Vector2> TextureCoordinates;
}; };
template<> struct Generic<2>: BaseGeneric { template<> struct Generic<2>: BaseGeneric {
typedef AbstractShaderProgram::Attribute<0, Vector2> Position; typedef Attribute<0, Vector2> Position;
}; };
template<> struct Generic<3>: BaseGeneric { template<> struct Generic<3>: BaseGeneric {
typedef AbstractShaderProgram::Attribute<0, Vector3> Position; typedef Attribute<0, Vector3> Position;
typedef AbstractShaderProgram::Attribute<2, Vector3> Normal; typedef Attribute<2, Vector3> Normal;
}; };
#endif #endif

28
src/Magnum/Test/AbstractShaderProgramTest.cpp

@ -75,7 +75,7 @@ AbstractShaderProgramTest::AbstractShaderProgramTest() {
} }
void AbstractShaderProgramTest::attributeScalar() { void AbstractShaderProgramTest::attributeScalar() {
typedef AbstractShaderProgram::Attribute<3, Float> Attribute; typedef Attribute<3, Float> Attribute;
CORRADE_VERIFY((std::is_same<Attribute::ScalarType, Float>{})); CORRADE_VERIFY((std::is_same<Attribute::ScalarType, Float>{}));
CORRADE_COMPARE(Attribute::Location, 3); CORRADE_COMPARE(Attribute::Location, 3);
CORRADE_COMPARE(Attribute::VectorCount, 1); CORRADE_COMPARE(Attribute::VectorCount, 1);
@ -95,7 +95,7 @@ void AbstractShaderProgramTest::attributeScalar() {
void AbstractShaderProgramTest::attributeScalarInt() { void AbstractShaderProgramTest::attributeScalarInt() {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
typedef AbstractShaderProgram::Attribute<3, Int> Attribute; typedef Attribute<3, Int> Attribute;
CORRADE_VERIFY((std::is_same<Attribute::ScalarType, Int>{})); CORRADE_VERIFY((std::is_same<Attribute::ScalarType, Int>{}));
CORRADE_COMPARE(Attribute::VectorCount, 1); CORRADE_COMPARE(Attribute::VectorCount, 1);
@ -113,7 +113,7 @@ void AbstractShaderProgramTest::attributeScalarInt() {
void AbstractShaderProgramTest::attributeScalarUnsignedInt() { void AbstractShaderProgramTest::attributeScalarUnsignedInt() {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
typedef AbstractShaderProgram::Attribute<3, UnsignedInt> Attribute; typedef Attribute<3, UnsignedInt> Attribute;
CORRADE_VERIFY((std::is_same<Attribute::ScalarType, UnsignedInt>{})); CORRADE_VERIFY((std::is_same<Attribute::ScalarType, UnsignedInt>{}));
CORRADE_COMPARE(Attribute::VectorCount, 1); CORRADE_COMPARE(Attribute::VectorCount, 1);
@ -131,7 +131,7 @@ void AbstractShaderProgramTest::attributeScalarUnsignedInt() {
void AbstractShaderProgramTest::attributeScalarDouble() { void AbstractShaderProgramTest::attributeScalarDouble() {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
typedef AbstractShaderProgram::Attribute<3, Double> Attribute; typedef Attribute<3, Double> Attribute;
CORRADE_VERIFY((std::is_same<Attribute::ScalarType, Double>{})); CORRADE_VERIFY((std::is_same<Attribute::ScalarType, Double>{}));
CORRADE_COMPARE(Attribute::VectorCount, 1); CORRADE_COMPARE(Attribute::VectorCount, 1);
@ -144,7 +144,7 @@ void AbstractShaderProgramTest::attributeScalarDouble() {
} }
void AbstractShaderProgramTest::attributeVector() { void AbstractShaderProgramTest::attributeVector() {
typedef AbstractShaderProgram::Attribute<3, Vector3> Attribute; typedef Attribute<3, Vector3> Attribute;
CORRADE_VERIFY((std::is_same<Attribute::ScalarType, Float>{})); CORRADE_VERIFY((std::is_same<Attribute::ScalarType, Float>{}));
CORRADE_COMPARE(Attribute::VectorCount, 1); CORRADE_COMPARE(Attribute::VectorCount, 1);
@ -168,7 +168,7 @@ void AbstractShaderProgramTest::attributeVector() {
void AbstractShaderProgramTest::attributeVectorInt() { void AbstractShaderProgramTest::attributeVectorInt() {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
typedef AbstractShaderProgram::Attribute<3, Vector2i> Attribute; typedef Attribute<3, Vector2i> Attribute;
CORRADE_VERIFY((std::is_same<Attribute::ScalarType, Int>{})); CORRADE_VERIFY((std::is_same<Attribute::ScalarType, Int>{}));
CORRADE_COMPARE(Attribute::VectorCount, 1); CORRADE_COMPARE(Attribute::VectorCount, 1);
@ -188,7 +188,7 @@ void AbstractShaderProgramTest::attributeVectorInt() {
void AbstractShaderProgramTest::attributeVectorUnsignedInt() { void AbstractShaderProgramTest::attributeVectorUnsignedInt() {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
typedef AbstractShaderProgram::Attribute<3, Vector4ui> Attribute; typedef Attribute<3, Vector4ui> Attribute;
CORRADE_VERIFY((std::is_same<Attribute::ScalarType, UnsignedInt>{})); CORRADE_VERIFY((std::is_same<Attribute::ScalarType, UnsignedInt>{}));
CORRADE_COMPARE(Attribute::VectorCount, 1); CORRADE_COMPARE(Attribute::VectorCount, 1);
@ -208,7 +208,7 @@ void AbstractShaderProgramTest::attributeVectorUnsignedInt() {
void AbstractShaderProgramTest::attributeVectorDouble() { void AbstractShaderProgramTest::attributeVectorDouble() {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
typedef AbstractShaderProgram::Attribute<3, Vector2d> Attribute; typedef Attribute<3, Vector2d> Attribute;
CORRADE_VERIFY((std::is_same<Attribute::ScalarType, Double>{})); CORRADE_VERIFY((std::is_same<Attribute::ScalarType, Double>{}));
CORRADE_COMPARE(Attribute::VectorCount, 1); CORRADE_COMPARE(Attribute::VectorCount, 1);
@ -227,7 +227,7 @@ void AbstractShaderProgramTest::attributeVectorDouble() {
} }
void AbstractShaderProgramTest::attributeVector4() { void AbstractShaderProgramTest::attributeVector4() {
typedef AbstractShaderProgram::Attribute<3, Vector4> Attribute; typedef Attribute<3, Vector4> Attribute;
CORRADE_VERIFY((std::is_same<Attribute::ScalarType, Float>{})); CORRADE_VERIFY((std::is_same<Attribute::ScalarType, Float>{}));
CORRADE_COMPARE(Attribute::VectorCount, 1); CORRADE_COMPARE(Attribute::VectorCount, 1);
@ -243,7 +243,7 @@ void AbstractShaderProgramTest::attributeVector4() {
void AbstractShaderProgramTest::attributeVectorBGRA() { void AbstractShaderProgramTest::attributeVectorBGRA() {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
typedef AbstractShaderProgram::Attribute<3, Vector4> Attribute; typedef Attribute<3, Vector4> Attribute;
CORRADE_VERIFY((std::is_same<Attribute::ScalarType, Float>{})); CORRADE_VERIFY((std::is_same<Attribute::ScalarType, Float>{}));
CORRADE_COMPARE(Attribute::VectorCount, 1); CORRADE_COMPARE(Attribute::VectorCount, 1);
@ -256,7 +256,7 @@ void AbstractShaderProgramTest::attributeVectorBGRA() {
} }
void AbstractShaderProgramTest::attributeMatrixNxN() { void AbstractShaderProgramTest::attributeMatrixNxN() {
typedef AbstractShaderProgram::Attribute<3, Matrix3> Attribute; typedef Attribute<3, Matrix3> Attribute;
CORRADE_VERIFY((std::is_same<Attribute::ScalarType, Float>{})); CORRADE_VERIFY((std::is_same<Attribute::ScalarType, Float>{}));
CORRADE_COMPARE(Attribute::VectorCount, 3); CORRADE_COMPARE(Attribute::VectorCount, 3);
@ -269,7 +269,7 @@ void AbstractShaderProgramTest::attributeMatrixNxN() {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void AbstractShaderProgramTest::attributeMatrixMxN() { void AbstractShaderProgramTest::attributeMatrixMxN() {
typedef AbstractShaderProgram::Attribute<3, Matrix3x4> Attribute; typedef Attribute<3, Matrix3x4> Attribute;
CORRADE_VERIFY((std::is_same<Attribute::ScalarType, Float>{})); CORRADE_VERIFY((std::is_same<Attribute::ScalarType, Float>{}));
CORRADE_COMPARE(Attribute::VectorCount, 3); CORRADE_COMPARE(Attribute::VectorCount, 3);
@ -283,7 +283,7 @@ void AbstractShaderProgramTest::attributeMatrixMxN() {
void AbstractShaderProgramTest::attributeMatrixNxNd() { void AbstractShaderProgramTest::attributeMatrixNxNd() {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
typedef AbstractShaderProgram::Attribute<3, Matrix4d> Attribute; typedef Attribute<3, Matrix4d> Attribute;
CORRADE_VERIFY((std::is_same<Attribute::ScalarType, Double>{})); CORRADE_VERIFY((std::is_same<Attribute::ScalarType, Double>{}));
CORRADE_COMPARE(Attribute::VectorCount, 4); CORRADE_COMPARE(Attribute::VectorCount, 4);
@ -299,7 +299,7 @@ void AbstractShaderProgramTest::attributeMatrixNxNd() {
void AbstractShaderProgramTest::attributeMatrixMxNd() { void AbstractShaderProgramTest::attributeMatrixMxNd() {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
typedef AbstractShaderProgram::Attribute<3, Matrix4x2d> Attribute; typedef Attribute<3, Matrix4x2d> Attribute;
CORRADE_VERIFY((std::is_same<Attribute::ScalarType, Double>{})); CORRADE_VERIFY((std::is_same<Attribute::ScalarType, Double>{}));
CORRADE_COMPARE(Attribute::VectorCount, 4); CORRADE_COMPARE(Attribute::VectorCount, 4);

61
src/Magnum/Test/MeshGLTest.cpp

@ -23,6 +23,7 @@
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
*/ */
#include "Magnum/AbstractShaderProgram.h"
#include "Magnum/Buffer.h" #include "Magnum/Buffer.h"
#include "Magnum/Color.h" #include "Magnum/Color.h"
#include "Magnum/ColorFormat.h" #include "Magnum/ColorFormat.h"
@ -468,7 +469,7 @@ void MeshGLTest::addVertexBufferUnsignedInt() {
CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available.")); CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available."));
#endif #endif
typedef AbstractShaderProgram::Attribute<0, UnsignedInt> Attribute; typedef Attribute<0, UnsignedInt> Attribute;
constexpr UnsignedInt data[] = { 0, 157, 35681 }; constexpr UnsignedInt data[] = { 0, 157, 35681 };
Buffer buffer; Buffer buffer;
@ -493,7 +494,7 @@ void MeshGLTest::addVertexBufferInt() {
CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available.")); CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available."));
#endif #endif
typedef AbstractShaderProgram::Attribute<0, Int> Attribute; typedef Attribute<0, Int> Attribute;
constexpr Int data[] = { 0, 457931, 27530 }; constexpr Int data[] = { 0, 457931, 27530 };
Buffer buffer; Buffer buffer;
@ -514,7 +515,7 @@ void MeshGLTest::addVertexBufferInt() {
#endif #endif
void MeshGLTest::addVertexBufferFloat() { void MeshGLTest::addVertexBufferFloat() {
typedef AbstractShaderProgram::Attribute<0, Float> Attribute; typedef Attribute<0, Float> Attribute;
const Float data[] = { 0.0f, -0.7f, Math::normalize<Float, UnsignedByte>(96) }; const Float data[] = { 0.0f, -0.7f, Math::normalize<Float, UnsignedByte>(96) };
Buffer buffer; Buffer buffer;
@ -543,7 +544,7 @@ void MeshGLTest::addVertexBufferDouble() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::vertex_attrib_64bit>()) if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::vertex_attrib_64bit>())
CORRADE_SKIP(Extensions::GL::ARB::vertex_attrib_64bit::string() + std::string(" is not available.")); CORRADE_SKIP(Extensions::GL::ARB::vertex_attrib_64bit::string() + std::string(" is not available."));
typedef AbstractShaderProgram::Attribute<0, Double> Attribute; typedef Attribute<0, Double> Attribute;
const Double data[] = { 0.0, -0.7, Math::normalize<Double, UnsignedShort>(45828) }; const Double data[] = { 0.0, -0.7, Math::normalize<Double, UnsignedShort>(45828) };
Buffer buffer; Buffer buffer;
@ -570,7 +571,7 @@ void MeshGLTest::addVertexBufferVectorNui() {
CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available.")); CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available."));
#endif #endif
typedef AbstractShaderProgram::Attribute<0, Vector3ui> Attribute; typedef Attribute<0, Vector3ui> Attribute;
constexpr Vector3ui data[] = { {}, {37448, 547686, 156}, {27592, 157, 25} }; constexpr Vector3ui data[] = { {}, {37448, 547686, 156}, {27592, 157, 25} };
Buffer buffer; Buffer buffer;
@ -595,7 +596,7 @@ void MeshGLTest::addVertexBufferVectorNi() {
CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available.")); CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available."));
#endif #endif
typedef AbstractShaderProgram::Attribute<0, Vector2i> Attribute; typedef Attribute<0, Vector2i> Attribute;
constexpr Vector2i data[] = { {}, {-37448, 547686}, {27592, -157} }; constexpr Vector2i data[] = { {}, {-37448, 547686}, {27592, -157} };
Buffer buffer; Buffer buffer;
@ -616,7 +617,7 @@ void MeshGLTest::addVertexBufferVectorNi() {
#endif #endif
void MeshGLTest::addVertexBufferVectorN() { void MeshGLTest::addVertexBufferVectorN() {
typedef AbstractShaderProgram::Attribute<0, Vector3> Attribute; typedef Attribute<0, Vector3> Attribute;
const Vector3 data[] = { {}, {0.0f, -0.9f, 1.0f}, Math::normalize<Vector3>(Color3ub(96, 24, 156)) }; const Vector3 data[] = { {}, {0.0f, -0.9f, 1.0f}, Math::normalize<Vector3>(Color3ub(96, 24, 156)) };
Buffer buffer; Buffer buffer;
@ -645,7 +646,7 @@ void MeshGLTest::addVertexBufferVectorNd() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::vertex_attrib_64bit>()) if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::vertex_attrib_64bit>())
CORRADE_SKIP(Extensions::GL::ARB::vertex_attrib_64bit::string() + std::string(" is not available.")); CORRADE_SKIP(Extensions::GL::ARB::vertex_attrib_64bit::string() + std::string(" is not available."));
typedef AbstractShaderProgram::Attribute<0, Vector4d> Attribute; typedef Attribute<0, Vector4d> Attribute;
const Vector4d data[] = { const Vector4d data[] = {
{}, {0.0, -0.9, 1.0, 1.25}, {}, {0.0, -0.9, 1.0, 1.25},
@ -669,7 +670,7 @@ void MeshGLTest::addVertexBufferVectorNd() {
#endif #endif
void MeshGLTest::addVertexBufferMatrixNxN() { void MeshGLTest::addVertexBufferMatrixNxN() {
typedef AbstractShaderProgram::Attribute<0, Matrix3x3> Attribute; typedef Attribute<0, Matrix3x3> Attribute;
const Matrix3x3 data[] = { const Matrix3x3 data[] = {
{}, {},
@ -698,7 +699,7 @@ void MeshGLTest::addVertexBufferMatrixNxNd() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::vertex_attrib_64bit>()) if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::vertex_attrib_64bit>())
CORRADE_SKIP(Extensions::GL::ARB::vertex_attrib_64bit::string() + std::string(" is not available.")); CORRADE_SKIP(Extensions::GL::ARB::vertex_attrib_64bit::string() + std::string(" is not available."));
typedef AbstractShaderProgram::Attribute<0, Matrix3x3d> Attribute; typedef Attribute<0, Matrix3x3d> Attribute;
const Matrix3x3d data[] = { const Matrix3x3d data[] = {
{}, {},
@ -731,7 +732,7 @@ void MeshGLTest::addVertexBufferMatrixNxNd() {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void MeshGLTest::addVertexBufferMatrixMxN() { void MeshGLTest::addVertexBufferMatrixMxN() {
typedef AbstractShaderProgram::Attribute<0, Matrix3x4> Attribute; typedef Attribute<0, Matrix3x4> Attribute;
const Matrix3x4 data[] = { const Matrix3x4 data[] = {
{}, {},
@ -761,7 +762,7 @@ void MeshGLTest::addVertexBufferMatrixMxNd() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::vertex_attrib_64bit>()) if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::vertex_attrib_64bit>())
CORRADE_SKIP(Extensions::GL::ARB::vertex_attrib_64bit::string() + std::string(" is not available.")); CORRADE_SKIP(Extensions::GL::ARB::vertex_attrib_64bit::string() + std::string(" is not available."));
typedef AbstractShaderProgram::Attribute<0, Matrix3x4d> Attribute; typedef Attribute<0, Matrix3x4d> Attribute;
const Matrix3x4d data[] = { const Matrix3x4d data[] = {
{}, {},
@ -799,7 +800,7 @@ void MeshGLTest::addVertexBufferUnsignedIntWithUnsignedShort() {
CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available.")); CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available."));
#endif #endif
typedef AbstractShaderProgram::Attribute<0, UnsignedInt> Attribute; typedef Attribute<0, UnsignedInt> Attribute;
constexpr UnsignedShort data[] = { 0, 49563, 16583 }; constexpr UnsignedShort data[] = { 0, 49563, 16583 };
Buffer buffer; Buffer buffer;
@ -824,7 +825,7 @@ void MeshGLTest::addVertexBufferUnsignedIntWithShort() {
CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available.")); CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available."));
#endif #endif
typedef AbstractShaderProgram::Attribute<0, UnsignedInt> Attribute; typedef Attribute<0, UnsignedInt> Attribute;
constexpr Short data[] = { 0, 24563, 16583 }; constexpr Short data[] = { 0, 24563, 16583 };
Buffer buffer; Buffer buffer;
@ -849,7 +850,7 @@ void MeshGLTest::addVertexBufferIntWithUnsignedShort() {
CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available.")); CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available."));
#endif #endif
typedef AbstractShaderProgram::Attribute<0, Int> Attribute; typedef Attribute<0, Int> Attribute;
constexpr UnsignedShort data[] = { 0, 49563, 16583 }; constexpr UnsignedShort data[] = { 0, 49563, 16583 };
Buffer buffer; Buffer buffer;
@ -874,7 +875,7 @@ void MeshGLTest::addVertexBufferIntWithShort() {
CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available.")); CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available."));
#endif #endif
typedef AbstractShaderProgram::Attribute<0, Int> Attribute; typedef Attribute<0, Int> Attribute;
constexpr Short data[] = { 0, 24563, -16583 }; constexpr Short data[] = { 0, 24563, -16583 };
Buffer buffer; Buffer buffer;
@ -903,7 +904,7 @@ void MeshGLTest::addVertexBufferFloatWithHalfFloat() {
CORRADE_SKIP(Extensions::GL::OES::vertex_half_float::string() + std::string(" is not supported.")); CORRADE_SKIP(Extensions::GL::OES::vertex_half_float::string() + std::string(" is not supported."));
#endif #endif
typedef AbstractShaderProgram::Attribute<0, Float> Attribute; typedef Attribute<0, Float> Attribute;
Buffer buffer; Buffer buffer;
buffer.setData({nullptr, 6}, BufferUsage::StaticDraw); buffer.setData({nullptr, 6}, BufferUsage::StaticDraw);
@ -918,7 +919,7 @@ void MeshGLTest::addVertexBufferFloatWithHalfFloat() {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MeshGLTest::addVertexBufferFloatWithDouble() { void MeshGLTest::addVertexBufferFloatWithDouble() {
typedef AbstractShaderProgram::Attribute<0, Float> Attribute; typedef Attribute<0, Float> Attribute;
const Double data[] = { 0.0, -0.7, Math::normalize<Double, UnsignedByte>(186) }; const Double data[] = { 0.0, -0.7, Math::normalize<Double, UnsignedByte>(186) };
Buffer buffer; Buffer buffer;
@ -943,7 +944,7 @@ void MeshGLTest::addVertexBufferVector3WithUnsignedInt10f11f11fRev() {
CORRADE_SKIP(Extensions::GL::ARB::vertex_type_10f_11f_11f_rev::string() + std::string(" is not available.")); CORRADE_SKIP(Extensions::GL::ARB::vertex_type_10f_11f_11f_rev::string() + std::string(" is not available."));
#endif #endif
typedef AbstractShaderProgram::Attribute<0, Vector3> Attribute; typedef Attribute<0, Vector3> Attribute;
Buffer buffer; Buffer buffer;
buffer.setData({nullptr, 12}, BufferUsage::StaticDraw); buffer.setData({nullptr, 12}, BufferUsage::StaticDraw);
@ -964,7 +965,7 @@ void MeshGLTest::addVertexBufferVector4WithUnsignedInt2101010Rev() {
CORRADE_SKIP(Extensions::GL::ARB::vertex_type_2_10_10_10_rev::string() + std::string(" is not available.")); CORRADE_SKIP(Extensions::GL::ARB::vertex_type_2_10_10_10_rev::string() + std::string(" is not available."));
#endif #endif
typedef AbstractShaderProgram::Attribute<0, Vector4> Attribute; typedef Attribute<0, Vector4> Attribute;
Buffer buffer; Buffer buffer;
buffer.setData({nullptr, 12}, BufferUsage::StaticDraw); buffer.setData({nullptr, 12}, BufferUsage::StaticDraw);
@ -983,7 +984,7 @@ void MeshGLTest::addVertexBufferVector4WithInt2101010Rev() {
CORRADE_SKIP(Extensions::GL::ARB::vertex_type_2_10_10_10_rev::string() + std::string(" is not available.")); CORRADE_SKIP(Extensions::GL::ARB::vertex_type_2_10_10_10_rev::string() + std::string(" is not available."));
#endif #endif
typedef AbstractShaderProgram::Attribute<0, Vector4> Attribute; typedef Attribute<0, Vector4> Attribute;
Buffer buffer; Buffer buffer;
buffer.setData({nullptr, 12}, BufferUsage::StaticDraw); buffer.setData({nullptr, 12}, BufferUsage::StaticDraw);
@ -998,7 +999,7 @@ void MeshGLTest::addVertexBufferVector4WithInt2101010Rev() {
#endif #endif
void MeshGLTest::addVertexBufferLessVectorComponents() { void MeshGLTest::addVertexBufferLessVectorComponents() {
typedef AbstractShaderProgram::Attribute<0, Vector4> Attribute; typedef Attribute<0, Vector4> Attribute;
const Vector3 data[] = { const Vector3 data[] = {
{}, {0.0f, -0.9f, 1.0f}, {}, {0.0f, -0.9f, 1.0f},
@ -1026,7 +1027,7 @@ void MeshGLTest::addVertexBufferLessVectorComponents() {
} }
void MeshGLTest::addVertexBufferNormalized() { void MeshGLTest::addVertexBufferNormalized() {
typedef AbstractShaderProgram::Attribute<0, Vector3> Attribute; typedef Attribute<0, Vector3> Attribute;
constexpr Color3ub data[] = { {}, {0, 128, 64}, {32, 156, 228} }; constexpr Color3ub data[] = { {}, {0, 128, 64}, {32, 156, 228} };
Buffer buffer; Buffer buffer;
@ -1057,7 +1058,7 @@ void MeshGLTest::addVertexBufferBGRA() {
CORRADE_SKIP(Extensions::GL::ARB::vertex_array_bgra::string() + std::string(" is not available.")); CORRADE_SKIP(Extensions::GL::ARB::vertex_array_bgra::string() + std::string(" is not available."));
#endif #endif
typedef AbstractShaderProgram::Attribute<0, Vector4> Attribute; typedef Attribute<0, Vector4> Attribute;
constexpr Color4ub data[] = { {}, {0, 128, 64, 161}, {96, 24, 156, 225} }; constexpr Color4ub data[] = { {}, {0, 128, 64, 161}, {96, 24, 156, 225} };
Buffer buffer; Buffer buffer;
@ -1385,7 +1386,7 @@ void MeshGLTest::setInstanceCount() {
CORRADE_SKIP("Required extension is not available."); CORRADE_SKIP("Required extension is not available.");
#endif #endif
typedef AbstractShaderProgram::Attribute<0, Float> Attribute; typedef Attribute<0, Float> Attribute;
const Float data[] = { 0.0f, -0.7f, Math::normalize<Float, UnsignedByte>(96) }; const Float data[] = { 0.0f, -0.7f, Math::normalize<Float, UnsignedByte>(96) };
Buffer buffer; Buffer buffer;
@ -1463,7 +1464,7 @@ void MeshGLTest::setInstanceCountBaseInstance() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::base_instance>()) if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::base_instance>())
CORRADE_SKIP(Extensions::GL::ARB::base_instance::string() + std::string(" is not available.")); CORRADE_SKIP(Extensions::GL::ARB::base_instance::string() + std::string(" is not available."));
typedef AbstractShaderProgram::Attribute<0, Float> Attribute; typedef Attribute<0, Float> Attribute;
const Float data[] = { 0.0f, -0.7f, Math::normalize<Float, UnsignedByte>(96) }; const Float data[] = { 0.0f, -0.7f, Math::normalize<Float, UnsignedByte>(96) };
Buffer buffer; Buffer buffer;
@ -1604,7 +1605,7 @@ void MeshGLTest::addVertexBufferInstancedFloat() {
CORRADE_SKIP("Required drawing extension is not available."); CORRADE_SKIP("Required drawing extension is not available.");
#endif #endif
typedef AbstractShaderProgram::Attribute<0, Float> Attribute; typedef Attribute<0, Float> Attribute;
const Float data[] = { const Float data[] = {
0.0f, /* Offset */ 0.0f, /* Offset */
@ -1645,7 +1646,7 @@ void MeshGLTest::addVertexBufferInstancedInteger() {
CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available.")); CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available."));
#endif #endif
typedef AbstractShaderProgram::Attribute<0, UnsignedInt> Attribute; typedef Attribute<0, UnsignedInt> Attribute;
constexpr UnsignedInt data[] = { constexpr UnsignedInt data[] = {
0, /* Offset */ 0, /* Offset */
@ -1680,7 +1681,7 @@ void MeshGLTest::addVertexBufferInstancedDouble() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::vertex_attrib_64bit>()) if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::vertex_attrib_64bit>())
CORRADE_SKIP(Extensions::GL::ARB::vertex_attrib_64bit::string() + std::string(" is not available.")); CORRADE_SKIP(Extensions::GL::ARB::vertex_attrib_64bit::string() + std::string(" is not available."));
typedef AbstractShaderProgram::Attribute<0, Double> Attribute; typedef Attribute<0, Double> Attribute;
const Double data[] = { const Double data[] = {
0.0, /* Offset */ 0.0, /* Offset */
@ -1760,7 +1761,7 @@ void MeshGLTest::multiDraw() {
Debug() << Extensions::GL::EXT::multi_draw_arrays::string() << "not supported, using fallback implementation"; Debug() << Extensions::GL::EXT::multi_draw_arrays::string() << "not supported, using fallback implementation";
#endif #endif
typedef AbstractShaderProgram::Attribute<0, Float> Attribute; typedef Attribute<0, Float> Attribute;
const Float data[] = { 0.0f, -0.7f, Math::normalize<Float, UnsignedByte>(96) }; const Float data[] = { 0.0f, -0.7f, Math::normalize<Float, UnsignedByte>(96) };
Buffer buffer; Buffer buffer;

4
src/Magnum/Test/SampleQueryGLTest.cpp

@ -111,7 +111,7 @@ void SampleQueryGLTest::querySamplesPassed() {
Mesh mesh; Mesh mesh;
mesh.setPrimitive(MeshPrimitive::Triangles) mesh.setPrimitive(MeshPrimitive::Triangles)
.setCount(3) .setCount(3)
.addVertexBuffer(buffer, 0, AbstractShaderProgram::Attribute<0, Vector2>()); .addVertexBuffer(buffer, 0, Attribute<0, Vector2>{});
MyShader shader; MyShader shader;
@ -160,7 +160,7 @@ void SampleQueryGLTest::conditionalRender() {
Mesh mesh; Mesh mesh;
mesh.setPrimitive(MeshPrimitive::Triangles) mesh.setPrimitive(MeshPrimitive::Triangles)
.setCount(3) .setCount(3)
.addVertexBuffer(buffer, 0, AbstractShaderProgram::Attribute<0, Vector2>()); .addVertexBuffer(buffer, 0, Attribute<0, Vector2>{});
MyShader shader; MyShader shader;
framebuffer.bind(FramebufferTarget::ReadDraw); framebuffer.bind(FramebufferTarget::ReadDraw);

Loading…
Cancel
Save