Browse Source

Ability to send less than all attribute components to the shader.

Remaining unspecified components are set to 0, 0, 1, according to spec.
Also cleaned up and simplified the internals, added debug output
operators for attribute component count and types and tested the whole
thing.
pull/7/head
Vladimír Vondruš 13 years ago
parent
commit
3379e6c794
  1. 179
      src/AbstractShaderProgram.cpp
  2. 427
      src/AbstractShaderProgram.h
  3. 41
      src/Mesh.h
  4. 219
      src/Test/AbstractShaderProgramTest.cpp
  5. 1
      src/Test/CMakeLists.txt

179
src/AbstractShaderProgram.cpp

@ -586,7 +586,7 @@ void AbstractShaderProgram::uniformImplementationDSA(GLint location, const Math:
#ifndef DOXYGEN_GENERATING_OUTPUT
namespace Implementation {
std::size_t Attribute<GLfloat>::size(GLint components, DataType dataType) {
std::size_t FloatAttribute::size(GLint components, DataType dataType) {
switch(dataType) {
case DataType::UnsignedByte:
case DataType::Byte:
@ -609,7 +609,8 @@ std::size_t Attribute<GLfloat>::size(GLint components, DataType dataType) {
return 0;
}
std::size_t Attribute<GLint>::size(GLint components, DataType dataType) {
#ifndef MAGNUM_TARGET_GLES2
std::size_t IntAttribute::size(GLint components, DataType dataType) {
switch(dataType) {
case DataType::UnsignedByte:
case DataType::Byte:
@ -625,9 +626,10 @@ std::size_t Attribute<GLint>::size(GLint components, DataType dataType) {
CORRADE_INTERNAL_ASSERT(false);
return 0;
}
#endif
#ifndef MAGNUM_TARGET_GLES
std::size_t Attribute<GLdouble>::size(GLint components, DataType dataType) {
std::size_t DoubleAttribute::size(GLint components, DataType dataType) {
switch(dataType) {
case DataType::Double:
return 8*components;
@ -639,6 +641,10 @@ std::size_t Attribute<GLdouble>::size(GLint components, DataType dataType) {
#endif
std::size_t Attribute<Math::Vector<4, GLfloat>>::size(GLint components, DataType dataType) {
#ifndef MAGNUM_TARGET_GLES
if(components == GL_BGRA) components = 4;
#endif
switch(dataType) {
case DataType::UnsignedByte:
case DataType::Byte:
@ -668,6 +674,173 @@ std::size_t Attribute<Math::Vector<4, GLfloat>>::size(GLint components, DataType
return 0;
}
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, GLfloat>>::Components value) {
switch(value) {
case Attribute<Math::Vector<4, GLfloat>>::Components::One:
return debug << "AbstractShaderProgram::Attribute::Components::One";
case Attribute<Math::Vector<4, GLfloat>>::Components::Two:
return debug << "AbstractShaderProgram::Attribute::Components::Two";
case Attribute<Math::Vector<4, GLfloat>>::Components::Three:
return debug << "AbstractShaderProgram::Attribute::Components::Three";
case Attribute<Math::Vector<4, GLfloat>>::Components::Four:
return debug << "AbstractShaderProgram::Attribute::Components::Four";
#ifndef MAGNUM_TARGET_GLES
case Attribute<Math::Vector<4, GLfloat>>::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<4, GLfloat>>::DataType value) {
switch(value) {
#define _c(value) case Attribute<Math::Vector<4, GLfloat>>::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)";
}
}
#endif

427
src/AbstractShaderProgram.h

@ -33,7 +33,6 @@ namespace Magnum {
#ifndef DOXYGEN_GENERATING_OUTPUT
namespace Implementation {
template<class> struct Attribute;
template<class> struct AttributeTraits;
}
#endif
@ -330,7 +329,61 @@ class MAGNUM_EXPORT AbstractShaderProgram {
* Type used in shader code.
* @see DataType
*/
typedef typename Implementation::AttributeTraits<T>::AttributeType Type;
typedef typename Implementation::Attribute<T>::Type Type;
/**
* @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.
* @requires_gl32 %Extension @extension{ARB,vertex_array_bgra}
* @requires_gl Only RGBA component ordering is supported
* in OpenGL ES.
*/
BGRA = 1 << 1
#endif
};
#else
typedef typename Implementation::Attribute<T>::Components Components;
#endif
/**
* @brief Data type
@ -400,16 +453,7 @@ class MAGNUM_EXPORT AbstractShaderProgram {
* Normalize integer components. Only for float attribute
* types. Default is to not normalize.
*/
Normalize = 1 << 0,
/**
* BGRA component ordering. Default is RGBA. Only for
* four-component float vector attribute type.
* @requires_gl32 %Extension @extension{ARB,vertex_array_bgra}
* @requires_gl Only RGBA component ordering is supported
* in OpenGL ES.
*/
BGRA = 1 << 1
Normalize = 1 << 0
};
#else
typedef typename Implementation::Attribute<T>::DataOption DataOption;
@ -427,25 +471,42 @@ class MAGNUM_EXPORT AbstractShaderProgram {
/**
* @brief Constructor
* @param components Component count
* @param dataType Type of passed data. Default is the
* same as type used in shader (e.g. DataType::Integer
* for Vector4i).
* @param dataOptions Data options. Default is no options.
*/
inline constexpr Attribute(DataType dataType = Implementation::Attribute<T>::DefaultDataType, DataOptions dataOptions = DataOptions()): _dataType(dataType), _dataOptions(dataOptions) {}
inline 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. DataType::Integer
* for 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 "Components::Three" for Vector3).
*/
inline 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 */
inline constexpr Components components() const { return _components; }
/** @brief Type of passed data */
inline constexpr DataType dataType() const { return _dataType; }
/** @brief Size of passed data */
inline std::size_t dataSize() const {
return Implementation::Attribute<T>::size(Implementation::Attribute<T>::components(), _dataType);
return Implementation::Attribute<T>::size(GLint(_components)*Implementation::Attribute<T>::vectorCount(), _dataType);
}
/** @brief Data options */
inline constexpr DataOptions dataOptions() const { return _dataOptions; }
private:
const Components _components;
const DataType _dataType;
const DataOptions _dataOptions;
};
@ -1065,63 +1126,81 @@ class MAGNUM_EXPORT AbstractShaderProgram {
State state;
};
#ifndef DOXYGEN_GENERATING_OUTPUT
namespace Implementation {
template<class> struct Attribute {};
template<> struct Attribute<GLfloat> {
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
};
#ifdef DOXYGEN_GENERATING_OUTPUT
/** @debugoperator{Magnum::AbstractShaderProgram::Attribute} */
template<class T> Debug operator<<(Debug debug, AbstractShaderProgram::Attribute<T>::Components);
enum class DataOption: std::uint8_t {
Normalized = 1 << 0
};
/** @debugoperator{Magnum::AbstractShaderProgram::Attribute} */
template<class T> Debug operator<<(Debug debug, AbstractShaderProgram::Attribute<T>::DataType);
#endif
typedef Corrade::Containers::EnumSet<DataOption, std::uint8_t> DataOptions;
#ifndef DOXYGEN_GENERATING_OUTPUT
namespace Implementation {
static const DataType DefaultDataType = DataType::Float;
/* Base for sized attributes */
template<std::size_t cols, std::size_t rows> struct SizedAttribute;
inline constexpr static GLint components(DataOptions = {}) { return 1; }
static std::size_t MAGNUM_EXPORT size(GLint components, DataType dataType);
inline constexpr static std::size_t vectorCount() { return 1; }
/* Vector attribute sizes */
template<std::size_t cols> struct SizedVectorAttribute {
inline constexpr static std::size_t vectorCount() { return cols; }
};
CORRADE_ENUMSET_OPERATORS(Attribute<GLfloat>::DataOptions)
template<std::size_t vectorSize> struct Attribute<Math::Vector<vectorSize, GLfloat>>: public Attribute<GLfloat> {
inline constexpr static GLint components(DataOptions = {}) { return vectorSize; }
inline constexpr static std::size_t vectorCount() { return 1; }
template<> struct SizedAttribute<1, 1>: SizedVectorAttribute<1> {
enum class Components: GLint { One = 1 };
constexpr static Components DefaultComponents = Components::One;
};
template<std::size_t cols, std::size_t rows> struct Attribute<Math::RectangularMatrix<cols, rows, GLfloat>>: public Attribute<GLfloat> {
inline constexpr static GLint components(DataOptions = {}) { return rows; }
inline constexpr static std::size_t vectorCount() { return cols; }
template<> struct SizedAttribute<1, 2>: SizedVectorAttribute<1> {
enum class Components: GLint { One = 1, Two = 2 };
constexpr static Components DefaultComponents = Components::Two;
};
template<std::size_t matrixSize> struct Attribute<Math::Matrix<matrixSize, GLfloat>>: public Attribute<GLfloat> {
inline constexpr static GLint components(DataOptions = {}) { return matrixSize; }
inline constexpr static std::size_t vectorCount() { return matrixSize; }
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 GLfloat Type;
template<> struct Attribute<Math::Vector<4, GLfloat>> {
enum class DataType: GLenum {
UnsignedByte = GL_UNSIGNED_BYTE,
Byte = GL_BYTE,
@ -1135,46 +1214,31 @@ template<> struct Attribute<Math::Vector<4, GLfloat>> {
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;
enum class DataOption: std::uint8_t {
Normalized = 1 << 0
#ifndef MAGNUM_TARGET_GLES
,
BGRA = 2 << 0
#endif
};
typedef Corrade::Containers::EnumSet<DataOption, std::uint8_t> DataOptions;
static const DataType DefaultDataType = DataType::Float;
#ifndef MAGNUM_TARGET_GLES
inline constexpr static GLint components(DataOptions options = {}) {
return options & DataOption::BGRA ? GL_BGRA : 4;
}
#else
inline constexpr static GLint components(DataOptions = {}) { return 4; }
#endif
static std::size_t MAGNUM_EXPORT size(GLint components, DataType dataType);
inline constexpr static std::size_t vectorCount() { return 1; }
};
typedef Math::Vector<4, GLfloat> _Vector4;
CORRADE_ENUMSET_OPERATORS(Attribute<_Vector4>::DataOptions)
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 GLint Type;
template<> struct Attribute<GLint> {
enum class DataType: GLenum {
UnsignedByte = GL_UNSIGNED_BYTE,
Byte = GL_BYTE,
@ -1183,135 +1247,148 @@ template<> struct Attribute<GLint> {
UnsignedInt = GL_UNSIGNED_INT,
Int = GL_INT
};
constexpr static DataType DefaultDataType = DataType::Int;
enum class DataOption: std::uint8_t {};
typedef Corrade::Containers::EnumSet<DataOption, std::uint8_t> DataOptions;
static const DataType DefaultDataType = DataType::Int;
inline constexpr static GLint components() { return 1; }
static std::size_t MAGNUM_EXPORT size(GLint components, DataType dataType);
};
template<> struct Attribute<GLuint> {
typedef Attribute<GLint>::DataType DataType;
typedef Attribute<GLint>::DataOption DataOption;
Debug MAGNUM_EXPORT operator<<(Debug debug, IntAttribute::DataType value);
typedef Corrade::Containers::EnumSet<DataOption, std::uint8_t> DataOptions;
/* Base for unsigned int attributes */
struct UnsignedIntAttribute {
typedef GLuint Type;
typedef IntAttribute::DataType DataType;
constexpr static DataType DefaultDataType = DataType::UnsignedInt;
static const DataType DefaultDataType = DataType::UnsignedInt;
typedef IntAttribute::DataOption DataOption;
typedef Corrade::Containers::EnumSet<DataOption, std::uint8_t> DataOptions;
inline constexpr static GLint components() { return 1; }
inline static std::size_t size(GLint components, DataType dataType) {
return Attribute<GLint>::size(components, dataType);
return IntAttribute::size(components, dataType);
}
};
template<std::size_t size_> struct Attribute<Math::Vector<size_, GLint>>: public Attribute<GLint> {
inline constexpr static GLint components() { return size_; }
};
template<std::size_t size_> struct Attribute<Math::Vector<size_, GLuint>>: public Attribute<GLuint> {
inline constexpr static GLint components() { return size_; }
};
#endif
#ifndef MAGNUM_TARGET_GLES
template<> struct Attribute<GLdouble> {
/* Base for double attributes */
struct DoubleAttribute {
typedef GLdouble Type;
enum class DataType: GLenum {
Double = GL_DOUBLE
};
constexpr static DataType DefaultDataType = DataType::Double;
enum class DataOption: std::uint8_t {};
typedef Corrade::Containers::EnumSet<DataOption, std::uint8_t> DataOptions;
static const DataType DefaultDataType = DataType::Double;
inline constexpr static GLint components() { return 1; }
inline constexpr static std::size_t vectorCount() { return 1; }
static std::size_t MAGNUM_EXPORT size(GLint components, DataType dataType);
};
template<std::size_t cols, std::size_t rows> struct Attribute<Math::RectangularMatrix<cols, rows, GLdouble>>: public Attribute<GLdouble> {
inline constexpr static GLint components() { return rows; }
inline constexpr static std::size_t vectorCount() { return cols; }
};
Debug MAGNUM_EXPORT operator<<(Debug debug, DoubleAttribute::DataType value);
#endif
template<std::size_t size_> struct Attribute<Math::Matrix<size_, GLdouble>>: public Attribute<GLdouble> {
inline constexpr static GLint components() { return size_; }
inline constexpr static std::size_t vectorCount() { return size_; }
};
/* Floating-point four-component vector is absolutely special case */
template<> struct Attribute<Math::Vector<4, GLfloat>> {
typedef GLfloat Type;
template<std::size_t size_> struct Attribute<Math::Vector<size_, GLdouble>>: public Attribute<GLdouble> {
inline constexpr static GLint components() { return size_; }
inline constexpr static std::size_t vectorCount() { return size_; }
};
#endif
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;
template<class T> struct Attribute<Math::Vector2<T>>: public Attribute<Math::Vector<2, T>> {};
template<class T> struct Attribute<Math::Vector3<T>>: public Attribute<Math::Vector<3, T>> {};
template<class T> struct Attribute<Math::Vector4<T>>: public Attribute<Math::Vector<4, T>> {};
enum class DataOption: std::uint8_t {
Normalized = 1 << 0
};
typedef Corrade::Containers::EnumSet<DataOption, std::uint8_t> DataOptions;
template<class T> struct Attribute<Math::Point2D<T>>: public Attribute<Math::Vector3<T>> {};
template<class T> struct Attribute<Math::Point3D<T>>: public Attribute<Math::Vector4<T>> {};
inline constexpr static std::size_t vectorCount() { return 1; }
static std::size_t MAGNUM_EXPORT size(GLint components, DataType dataType);
};
template<class T> struct Attribute<Color3<T>>: public Attribute<Math::Vector3<T>> {};
template<class T> struct Attribute<Color4<T>>: public Attribute<Math::Vector4<T>> {};
typedef Math::Vector<4, GLfloat> _Vector4;
CORRADE_ENUMSET_OPERATORS(Attribute<_Vector4>::DataOptions)
template<class T> struct Attribute<Math::Matrix3<T>>: public Attribute<Math::Matrix<3, T>> {};
template<class T> struct Attribute<Math::Matrix4<T>>: public Attribute<Math::Matrix<4, T>> {};
Debug MAGNUM_EXPORT operator<<(Debug debug, Attribute<Math::Vector<4, GLfloat>>::Components value);
Debug MAGNUM_EXPORT operator<<(Debug debug, Attribute<Math::Vector<4, GLfloat>>::DataType value);
/* Types allowed as GLSL attributes */
template<> struct AttributeTraits<GLuint> { typedef GLuint AttributeType; };
template<> struct AttributeTraits<GLint> { typedef GLint AttributeType; };
template<> struct AttributeTraits<GLfloat> { typedef GLfloat AttributeType; };
/* Common float, int, unsigned int and double scalar attributes */
template<> struct Attribute<GLfloat>: FloatAttribute, SizedAttribute<1, 1> {};
#ifndef MAGNUM_TARGET_GLES2
template<> struct Attribute<GLint>: IntAttribute, SizedAttribute<1, 1> {};
template<> struct Attribute<GLuint>: UnsignedIntAttribute, SizedAttribute<1, 1> {};
#ifndef MAGNUM_TARGET_GLES
template<> struct AttributeTraits<GLdouble> { typedef GLdouble AttributeType; };
template<> struct Attribute<GLdouble>: DoubleAttribute, SizedAttribute<1, 1> {};
#endif
#endif
/* Only some vectors can be used as attributes */
template<class> struct VectorAttributeTraits {};
template<> struct VectorAttributeTraits<GLuint> { typedef GLuint AttributeType; };
template<> struct VectorAttributeTraits<GLint> { typedef GLint AttributeType; };
template<> struct VectorAttributeTraits<GLfloat> { typedef GLfloat AttributeType; };
/* Common float, int, unsigned int and double vector attributes */
template<std::size_t size_> struct Attribute<Math::Vector<size_, GLfloat>>: FloatAttribute, SizedAttribute<1, size_> {};
#ifndef MAGNUM_TARGET_GLES2
template<std::size_t size_> struct Attribute<Math::Vector<size_, GLint>>: IntAttribute, SizedAttribute<1, size_> {};
template<std::size_t size_> struct Attribute<Math::Vector<size_, GLuint>>: UnsignedIntAttribute, SizedAttribute<1, size_> {};
#ifndef MAGNUM_TARGET_GLES
template<> struct VectorAttributeTraits<GLdouble> { typedef GLdouble AttributeType; };
template<std::size_t size_> struct Attribute<Math::Vector<size_, GLdouble>>: DoubleAttribute, SizedAttribute<1, size_> {};
#endif
template<class T> struct AttributeTraits<Math::Vector<2, T>>: VectorAttributeTraits<T> {};
template<class T> struct AttributeTraits<Math::Vector<3, T>>: VectorAttributeTraits<T> {};
template<class T> struct AttributeTraits<Math::Vector<4, T>>: VectorAttributeTraits<T> {};
template<class T> struct AttributeTraits<Math::Vector2<T>>: AttributeTraits<Math::Vector<2, T>> {};
template<class T> struct AttributeTraits<Math::Vector3<T>>: AttributeTraits<Math::Vector<3, T>> {};
template<class T> struct AttributeTraits<Math::Vector4<T>>: AttributeTraits<Math::Vector<4, T>> {};
template<class T> struct AttributeTraits<Math::Point2D<T>>: AttributeTraits<Math::Vector<3, T>> {};
template<class T> struct AttributeTraits<Math::Point3D<T>>: AttributeTraits<Math::Vector<4, T>> {};
template<class T> struct AttributeTraits<Color3<T>>: AttributeTraits<Math::Vector<3, T>> {};
template<class T> struct AttributeTraits<Color4<T>>: AttributeTraits<Math::Vector<4, T>> {};
/* Only some floating-point matrices can be used as attributes */
template<class> struct MatrixAttributeTraits {};
template<> struct MatrixAttributeTraits<GLfloat> { typedef GLfloat AttributeType; };
#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<Math::Point2D<T>>: Attribute<Math::Vector3<T>> {};
template<class T> struct Attribute<Math::Point3D<T>>: Attribute<Math::Vector4<T>> {};
template<class T> struct Attribute<Color3<T>>: Attribute<Math::Vector3<T>> {};
template<class T> struct Attribute<Color4<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, GLfloat>>: FloatAttribute, SizedAttribute<cols, rows> {};
#ifndef MAGNUM_TARGET_GLES
template<> struct MatrixAttributeTraits<GLdouble> { typedef GLdouble AttributeType; };
template<std::size_t cols, std::size_t rows> struct Attribute<Math::RectangularMatrix<cols, rows, GLdouble>>: DoubleAttribute, SizedAttribute<cols, rows> {};
#endif
template<class T> struct AttributeTraits<Math::RectangularMatrix<2, 2, T>>: MatrixAttributeTraits<T> {};
template<class T> struct AttributeTraits<Math::RectangularMatrix<3, 3, T>>: MatrixAttributeTraits<T> {};
template<class T> struct AttributeTraits<Math::RectangularMatrix<4, 4, T>>: MatrixAttributeTraits<T> {};
#ifndef MAGNUM_TARGET_GLES2
template<class T> struct AttributeTraits<Math::RectangularMatrix<2, 3, T>>: MatrixAttributeTraits<T> {};
template<class T> struct AttributeTraits<Math::RectangularMatrix<3, 2, T>>: MatrixAttributeTraits<T> {};
template<class T> struct AttributeTraits<Math::RectangularMatrix<2, 4, T>>: MatrixAttributeTraits<T> {};
template<class T> struct AttributeTraits<Math::RectangularMatrix<4, 2, T>>: MatrixAttributeTraits<T> {};
template<class T> struct AttributeTraits<Math::RectangularMatrix<3, 4, T>>: MatrixAttributeTraits<T> {};
template<class T> struct AttributeTraits<Math::RectangularMatrix<4, 3, T>>: MatrixAttributeTraits<T> {};
/* Common float and double square matrix attributes */
template<std::size_t size_> struct Attribute<Math::Matrix<size_, GLfloat>>: Attribute<Math::RectangularMatrix<size_, size_, GLfloat>> {};
#ifndef MAGNUM_TARGET_GLES
template<std::size_t size_> struct Attribute<Math::Matrix<size_, GLdouble>>: Attribute<Math::RectangularMatrix<size_, size_, GLdouble>> {};
#endif
template<class T> struct AttributeTraits<Math::Matrix3<T>>: MatrixAttributeTraits<T> {};
template<class T> struct AttributeTraits<Math::Matrix4<T>>: MatrixAttributeTraits<T> {};
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

41
src/Mesh.h

@ -163,24 +163,39 @@ mesh->setPrimitive(plane.primitive())
// Custom shader with colors specified as four floating-point values
class MyShader: public AbstractShaderProgram {
public:
typedef Attribute<0, Vector3> Position;
typedef Attribute<1, Color4<>> Color;
// ...
};
Mesh* mesh;
Buffer* colorBuffer;
// Fill vertex buffer with colors specified as four-byte BGRA (e.g. directly
// Fill position buffer with positions specified as two-component XY (i.e.,
// no Z component, which is meant to be always 0)
Buffer* positionBuffer;
Vector2 positions[30] = {
// ...
};
// Specify layout of positions buffer -- only two components, unspecified Z
// component will be automatically set to 0
mesh->addVertexBuffer(positionBuffer, 0,
MyShader::Position(MyShader::Position::Components::Two));
// Fill color buffer with colors specified as four-byte BGRA (e.g. directly
// from TGA file)
Buffer* colorBuffer;
GLubyte colors[4*30] = {
// ...
};
colorBuffer.setData(colors, Buffer::Usage::StaticDraw);
// Specify layout of color buffer -- each component is unsigned byte, we want
// to normalize them from [0, 255] to [0.0f, 1.0f] and reorder from BGRA
mesh->addVertexBuffer(colorBuffer, 0,
MyShader::Color(MyShader::Color::DataType::UsignedByte, MyShader::Color::DataOption::Normalized|MyShader::Color::DataOption::BGRA));
// Specify layout of color buffer -- BGRA, each component unsigned byte and we
// want to normalize them from [0, 255] to [0.0f, 1.0f]
mesh->addVertexBuffer(colorBuffer, 0, MyShader::Color(
MyShader::Color::Components::BGRA,
MyShader::Color::DataType::UnsignedByte,
MyShader::Color::DataOption::Normalized));
@endcode
@section Mesh-drawing Rendering meshes
@ -797,25 +812,25 @@ class MAGNUM_EXPORT Mesh {
}
inline void addInterleavedVertexBufferInternal(Buffer*, GLsizei, GLintptr) {}
template<GLuint location, class T> inline void addVertexAttribute(typename std::enable_if<std::is_same<typename Implementation::AttributeTraits<T>::AttributeType, GLfloat>::value, Buffer*>::type buffer, const AbstractShaderProgram::Attribute<location, T>& attribute, GLintptr offset, GLsizei stride) {
template<GLuint location, class T> inline void addVertexAttribute(typename std::enable_if<std::is_same<typename Implementation::Attribute<T>::Type, GLfloat>::value, Buffer*>::type buffer, const AbstractShaderProgram::Attribute<location, T>& attribute, GLintptr offset, GLsizei stride) {
for(GLuint i = 0; i != Implementation::Attribute<T>::vectorCount(); ++i)
(this->*attributePointerImplementation)(Attribute{
buffer,
location+i,
Implementation::Attribute<T>::components(attribute.dataOptions()),
static_cast<GLint>(attribute.components()),
static_cast<GLenum>(attribute.dataType()),
!!(attribute.dataOptions() & AbstractShaderProgram::Attribute<location, T>::DataOption::Normalized),
bool(attribute.dataOptions() & AbstractShaderProgram::Attribute<location, T>::DataOption::Normalized),
offset,
stride
});
}
#ifndef MAGNUM_TARGET_GLES2
template<GLuint location, class T> inline void addVertexAttribute(typename std::enable_if<std::is_integral<typename Implementation::AttributeTraits<T>::AttributeType>::value, Buffer*>::type buffer, const AbstractShaderProgram::Attribute<location, T>& attribute, GLintptr offset, GLsizei stride) {
template<GLuint location, class T> inline void addVertexAttribute(typename std::enable_if<std::is_integral<typename Implementation::Attribute<T>::Type>::value, Buffer*>::type buffer, const AbstractShaderProgram::Attribute<location, T>& attribute, GLintptr offset, GLsizei stride) {
(this->*attributeIPointerImplementation)(IntegerAttribute{
buffer,
location,
Implementation::Attribute<T>::components(),
static_cast<GLint>(attribute.components()),
static_cast<GLenum>(attribute.dataType()),
offset,
stride
@ -823,12 +838,12 @@ class MAGNUM_EXPORT Mesh {
}
#ifndef MAGNUM_TARGET_GLES
template<GLuint location, class T> inline void addVertexAttribute(typename std::enable_if<std::is_same<typename Implementation::AttributeTraits<T>::AttributeType, GLdouble>::value, Buffer*>::type buffer, const AbstractShaderProgram::Attribute<location, T>& attribute, GLintptr offset, GLsizei stride) {
template<GLuint location, class T> inline void addVertexAttribute(typename std::enable_if<std::is_same<typename Implementation::Attribute<T>::Type, GLdouble>::value, Buffer*>::type buffer, const AbstractShaderProgram::Attribute<location, T>& attribute, GLintptr offset, GLsizei stride) {
for(GLuint i = 0; i != Implementation::Attribute<T>::vectorCount(); ++i)
(this->*attributeLPointerImplementation)(LongAttribute{
buffer,
location+i,
Implementation::Attribute<T>::components(),
static_cast<GLint>(attribute.components()),
static_cast<GLenum>(attribute.dataType()),
offset,
stride

219
src/Test/AbstractShaderProgramTest.cpp

@ -0,0 +1,219 @@
/*
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>
This file is part of Magnum.
Magnum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 3
only, as published by the Free Software Foundation.
Magnum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License version 3 for more details.
*/
#include <TestSuite/Tester.h>
#include "AbstractShaderProgram.h"
namespace Magnum { namespace Test {
class AbstractShaderProgramTest: public Corrade::TestSuite::Tester {
public:
explicit AbstractShaderProgramTest();
void attributeScalar();
void attributeScalarInt();
void attributeScalarUnsignedInt();
void attributeScalarDouble();
void attributeVector();
void attributeVectorInt();
void attributeVectorUnsignedInt();
void attributeVectorDouble();
void attributeVector4();
void attributeVectorBGRA();
void attributeMatrix();
void attributeMatrixDouble();
};
AbstractShaderProgramTest::AbstractShaderProgramTest() {
addTests(&AbstractShaderProgramTest::attributeScalar,
&AbstractShaderProgramTest::attributeScalarInt,
&AbstractShaderProgramTest::attributeScalarUnsignedInt,
&AbstractShaderProgramTest::attributeScalarDouble,
&AbstractShaderProgramTest::attributeVector,
&AbstractShaderProgramTest::attributeVectorInt,
&AbstractShaderProgramTest::attributeVectorUnsignedInt,
&AbstractShaderProgramTest::attributeVectorDouble,
&AbstractShaderProgramTest::attributeVector4,
&AbstractShaderProgramTest::attributeVectorBGRA,
&AbstractShaderProgramTest::attributeMatrix,
&AbstractShaderProgramTest::attributeMatrixDouble);
}
void AbstractShaderProgramTest::attributeScalar() {
typedef AbstractShaderProgram::Attribute<3, GLfloat> Attribute;
CORRADE_COMPARE(Attribute::Location, 3);
/* Default constructor */
Attribute a;
CORRADE_COMPARE(a.components(), Attribute::Components::One);
CORRADE_VERIFY(!a.dataOptions());
CORRADE_COMPARE(a.dataSize(), 4);
CORRADE_COMPARE(a.dataType(), Attribute::DataType::Float);
/* Options */
Attribute b(Attribute::DataType::UnsignedShort, Attribute::DataOption::Normalized);
CORRADE_COMPARE(b.dataSize(), 2);
CORRADE_VERIFY(b.dataOptions() <= Attribute::DataOption::Normalized);
}
void AbstractShaderProgramTest::attributeScalarInt() {
typedef AbstractShaderProgram::Attribute<3, GLint> Attribute;
/* Default constructor */
Attribute a;
CORRADE_COMPARE(a.dataSize(), 4);
/* Options */
Attribute b(Attribute::DataType::Short);
CORRADE_COMPARE(b.dataSize(), 2);
}
void AbstractShaderProgramTest::attributeScalarUnsignedInt() {
typedef AbstractShaderProgram::Attribute<3, GLuint> Attribute;
/* Default constructor */
Attribute a;
CORRADE_COMPARE(a.dataSize(), 4);
/* Options */
Attribute b(Attribute::DataType::UnsignedByte);
CORRADE_COMPARE(b.dataSize(), 1);
}
void AbstractShaderProgramTest::attributeScalarDouble() {
#ifndef MAGNUM_TARGET_GLES
typedef AbstractShaderProgram::Attribute<3, GLdouble> Attribute;
/* Default constructor */
Attribute a;
CORRADE_COMPARE(a.dataSize(), 8);
#else
CORRADE_SKIP("Double attributes are not available in OpenGL ES.");
#endif
}
void AbstractShaderProgramTest::attributeVector() {
typedef AbstractShaderProgram::Attribute<3, Vector3> Attribute;
/* Default constructor */
Attribute a;
CORRADE_COMPARE(a.components(), Attribute::Components::Three);
CORRADE_COMPARE(a.dataSize(), 3*4);
CORRADE_COMPARE(a.dataType(), Attribute::DataType::Float);
/* Options */
Attribute b(Attribute::Components::Two, Attribute::DataType::Double);
CORRADE_COMPARE(b.components(), Attribute::Components::Two);
CORRADE_COMPARE(b.dataSize(), 2*8);
}
void AbstractShaderProgramTest::attributeVectorInt() {
typedef AbstractShaderProgram::Attribute<3, Vector2i> Attribute;
/* Default constructor */
Attribute a;
CORRADE_COMPARE(a.components(), Attribute::Components::Two);
CORRADE_COMPARE(a.dataSize(), 2*4);
CORRADE_COMPARE(a.dataType(), Attribute::DataType::Int);
/* Options */
Attribute b(Attribute::Components::One, Attribute::DataType::Int);
CORRADE_COMPARE(b.dataSize(), 4);
}
void AbstractShaderProgramTest::attributeVectorUnsignedInt() {
typedef AbstractShaderProgram::Attribute<3, Vector4ui> Attribute;
/* Default constructor */
Attribute a;
CORRADE_COMPARE(a.components(), Attribute::Components::Four);
CORRADE_COMPARE(a.dataSize(), 4*4);
CORRADE_COMPARE(a.dataType(), Attribute::DataType::UnsignedInt);
/* Options */
Attribute b(Attribute::Components::Three, Attribute::DataType::UnsignedShort);
CORRADE_COMPARE(b.dataSize(), 3*2);
}
void AbstractShaderProgramTest::attributeVectorDouble() {
#ifndef MAGNUM_TARGET_GLES
typedef AbstractShaderProgram::Attribute<3, Vector2d> Attribute;
/* Default constructor */
Attribute a;
CORRADE_COMPARE(a.components(), Attribute::Components::Two);
CORRADE_COMPARE(a.dataSize(), 2*8);
CORRADE_COMPARE(a.dataType(), Attribute::DataType::Double);
/* Options */
Attribute b(Attribute::Components::One);
CORRADE_COMPARE(b.dataSize(), 8);
#else
CORRADE_SKIP("Double attributes are not available in OpenGL ES.");
#endif
}
void AbstractShaderProgramTest::attributeVector4() {
typedef AbstractShaderProgram::Attribute<3, Vector4> Attribute;
/* Custom type */
Attribute a(Attribute::DataType::UnsignedInt2101010Rev);
CORRADE_COMPARE(a.dataSize(), 4);
}
void AbstractShaderProgramTest::attributeVectorBGRA() {
#ifndef MAGNUM_TARGET_GLES
typedef AbstractShaderProgram::Attribute<3, Vector4> Attribute;
/* BGRA */
Attribute a(Attribute::Components::BGRA);
CORRADE_COMPARE(a.dataSize(), 4*4);
#else
CORRADE_SKIP("BGRA attribute component ordering is not available in OpenGL ES.");
#endif
}
void AbstractShaderProgramTest::attributeMatrix() {
typedef AbstractShaderProgram::Attribute<3, Matrix3> Attribute;
/* Default constructor */
Attribute a;
CORRADE_COMPARE(a.components(), Attribute::Components::Three);
CORRADE_COMPARE(a.dataSize(), 3*3*4);
CORRADE_COMPARE(a.dataType(), Attribute::DataType::Float);
}
void AbstractShaderProgramTest::attributeMatrixDouble() {
#ifndef MAGNUM_TARGET_GLES
typedef AbstractShaderProgram::Attribute<3, Matrix4d> Attribute;
/* Default constructor */
Attribute a;
CORRADE_COMPARE(a.components(), Attribute::Components::Four);
CORRADE_COMPARE(a.dataSize(), 4*4*8);
CORRADE_COMPARE(a.dataType(), Attribute::DataType::Double);
#else
CORRADE_SKIP("Double attributes are not available in OpenGL ES.");
#endif
}
}}
CORRADE_TEST_MAIN(Magnum::Test::AbstractShaderProgramTest)

1
src/Test/CMakeLists.txt

@ -1,4 +1,5 @@
corrade_add_test(AbstractImageTest AbstractImageTest.cpp LIBRARIES Magnum)
corrade_add_test(AbstractShaderProgramTest AbstractShaderProgramTest.cpp LIBRARIES Magnum)
corrade_add_test(ArrayTest ArrayTest.cpp)
corrade_add_test(ColorTest ColorTest.cpp LIBRARIES MagnumMathTestLib)
corrade_add_test(MeshTest MeshTest.cpp LIBRARIES Magnum)

Loading…
Cancel
Save