Browse Source

Phong

Signed-off-by: Squareys <squareys@googlemail.com>
pull/444/head
Squareys 6 years ago
parent
commit
68834eb9a8
  1. 4
      src/Magnum/Shaders/Generic.h
  2. 44
      src/Magnum/Shaders/Phong.cpp
  3. 81
      src/Magnum/Shaders/Phong.h
  4. 45
      src/Magnum/Shaders/Phong.vert
  5. 5
      src/Magnum/Shaders/generic.glsl

4
src/Magnum/Shaders/Generic.h

@ -470,10 +470,10 @@ struct BaseGeneric {
typedef GL::Attribute<4, UnsignedInt> ObjectId; typedef GL::Attribute<4, UnsignedInt> ObjectId;
#endif #endif
typedef GL::Attribute<6, Vector4> Weights; typedef GL::Attribute<6, Vector4> Weights;
typedef GL::Attribute<7, Vector4> JointIds; typedef GL::Attribute<7, Vector4ui> JointIds;
typedef GL::Attribute<10, Vector4> SecondaryWeights; typedef GL::Attribute<10, Vector4> SecondaryWeights;
typedef GL::Attribute<11, Vector4> SecondaryJointIds; typedef GL::Attribute<11, Vector4ui> SecondaryJointIds;
typedef GL::Attribute<15, Vector2> TextureOffset; typedef GL::Attribute<15, Vector2> TextureOffset;

44
src/Magnum/Shaders/Phong.cpp

@ -54,9 +54,13 @@ namespace {
}; };
} }
Phong::Phong(const Flags flags, const UnsignedInt lightCount): _flags{flags}, _lightCount{lightCount}, _lightColorsUniform{_lightPositionsUniform + Int(lightCount)} { Phong::Phong(const Flags flags, const UnsignedInt lightCount, const UnsignedInt jointCount, const UnsignedInt jointsPerVertex): _flags{flags}, _lightCount{lightCount}, _jointCount{jointCount}, _jointsPerVertex{jointsPerVertex}, _lightColorsUniform{_lightPositionsUniform + Int(lightCount)}, _jointMatricesUniform{_lightPositionsUniform + 2*Int(lightCount)} {
CORRADE_ASSERT(!(flags & Flag::TextureTransformation) || (flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture|Flag::NormalTexture)), CORRADE_ASSERT(!(flags & Flag::TextureTransformation) || (flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture|Flag::NormalTexture)),
"Shaders::Phong: texture transformation enabled but the shader is not textured", ); "Shaders::Phong: texture transformation enabled but the shader is not textured", );
CORRADE_ASSERT(!(flags & Flag::Skinning) || (jointCount != 0),
"Shaders::Phong: skinning enabled, but jointCount is zero", );
CORRADE_ASSERT(!(flags & Flag::Skinning) || (jointsPerVertex > 0 && jointsPerVertex <= 8),
"Shaders::Phong: skinning enabled, but jointsPerVertex is not in [1;8]", );
#ifdef MAGNUM_BUILD_STATIC #ifdef MAGNUM_BUILD_STATIC
/* Import resources on static build, if not already */ /* Import resources on static build, if not already */
@ -120,7 +124,12 @@ Phong::Phong(const Flags flags, const UnsignedInt lightCount): _flags{flags}, _l
#endif #endif
.addSource(Utility::formatString( .addSource(Utility::formatString(
"#define LIGHT_COUNT {}\n" "#define LIGHT_COUNT {}\n"
"#define LIGHT_COLORS_LOCATION {}\n", lightCount, _lightPositionsUniform + lightCount)); "#define LIGHT_COLORS_LOCATION {}\n", lightCount, _lightColorsUniform))
.addSource(flags & Flag::Skinning ? "#define SKINNING\n" : "")
.addSource(Utility::formatString(
"#define JOINT_COUNT {}\n"
"#define JOINTS_PER_VERTEX {}\n"
"#define JOINT_MATRICES_LOCATION {}\n", jointCount, jointsPerVertex, _jointMatricesUniform));
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(lightCount) frag.addSource(std::move(lightInitializer)); if(lightCount) frag.addSource(std::move(lightInitializer));
#endif #endif
@ -159,6 +168,15 @@ Phong::Phong(const Flags flags, const UnsignedInt lightCount): _flags{flags}, _l
if(flags >= Flag::InstancedTextureOffset) if(flags >= Flag::InstancedTextureOffset)
bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset"); bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset");
#endif #endif
if(flags & Flag::Skinning) {
bindAttributeLocation(Weights::Location, "weights");
bindAttributeLocation(JointIds::Location, "jointIds");
if(jointCount > 4) {
bindAttributeLocation(SecondaryWeights::Location, "secondaryWeights");
bindAttributeLocation(SecondaryJointIds::Location, "secondaryJointIds");
}
}
} }
#endif #endif
@ -185,6 +203,8 @@ Phong::Phong(const Flags flags, const UnsignedInt lightCount): _flags{flags}, _l
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags & Flag::ObjectId) _objectIdUniform = uniformLocation("objectId"); if(flags & Flag::ObjectId) _objectIdUniform = uniformLocation("objectId");
#endif #endif
if(flags & Flag::Skinning)
_jointMatricesUniform = uniformLocation("jointMatrices");
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -353,6 +373,26 @@ Phong& Phong::setLightColor(UnsignedInt id, const Magnum::Color4& color) {
return *this; return *this;
} }
Phong& Phong::setJointMatrices(const Containers::ArrayView<const Matrix4> matrices) {
CORRADE_ASSERT(_jointCount == matrices.size(),
"Shaders::Phong::setJointMatrices(): expected" << _jointCount << "items but got" << matrices.size(), *this);
if(_jointCount) setUniform(_jointMatricesUniform, matrices);
return *this;
}
Phong& Phong::setJointMatrix(UnsignedInt id, const Matrix4& matrix) {
CORRADE_ASSERT(id < _jointCount,
"Shaders::Phong::setJointMatrix(): joint ID" << id << "is out of bounds for" << _jointCount << "joints", *this);
setUniform(_jointMatricesUniform + id, matrix);
return *this;
}
/* It's light, but can't be in the header because MSVC needs to know the size
of Matrix4 for the initializer list use */
Phong& Phong::setJointMatrices(std::initializer_list<Matrix4> matrices) {
return setJointMatrices({matrices.begin(), matrices.size()});
}
Debug& operator<<(Debug& debug, const Phong::Flag value) { Debug& operator<<(Debug& debug, const Phong::Flag value) {
debug << "Shaders::Phong::Flag" << Debug::nospace; debug << "Shaders::Phong::Flag" << Debug::nospace;

81
src/Magnum/Shaders/Phong.h

@ -207,6 +207,42 @@ class MAGNUM_SHADERS_EXPORT Phong: public GL::AbstractShaderProgram {
*/ */
typedef Generic3D::Color4 Color4; typedef Generic3D::Color4 Color4;
/**
* @brief Joint ids
* @m_since_latest
*
* @ref shaders-generic "Generic attribute", @ref Magnum::Vector4ui.
* Used only if @ref Flag::Skinning is set.
*/
typedef Generic3D::JointIds JointIds;
/**
* @brief Weights
* @m_since_latest
*
* @ref shaders-generic "Generic attribute", @ref Magnum::Vector4.
* Used only if @ref Flag::Skinning is set.
*/
typedef Generic3D::Weights Weights;
/**
* @brief Secondary joint ids
* @m_since_latest
*
* @ref shaders-generic "Generic attribute", @ref Magnum::Vector4ui.
* Used only if @ref Flag::Skinning is set and @cpp jointCount > 4 @ce.
*/
typedef Generic3D::SecondaryJointIds SecondaryJointIds;
/**
* @brief Secondary weights
* @m_since_latest
*
* @ref shaders-generic "Generic attribute", @ref Magnum::Vector4.
* Used only if @ref Flag::Skinning is set and @cpp jointCount > 4 @ce.
*/
typedef Generic3D::Weights SecondaryWeights;
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
/** /**
* @brief (Instanced) object ID * @brief (Instanced) object ID
@ -416,7 +452,14 @@ class MAGNUM_SHADERS_EXPORT Phong: public GL::AbstractShaderProgram {
* in WebGL 1.0. * in WebGL 1.0.
* @m_since_latest * @m_since_latest
*/ */
InstancedTextureOffset = (1 << 10)|TextureTransformation InstancedTextureOffset = (1 << 10)|TextureTransformation,
/**
* Skinning.
* @TODO docs
* @m_since_latest
*/
Skinning = 1 << 11
}; };
/** /**
@ -430,8 +473,11 @@ class MAGNUM_SHADERS_EXPORT Phong: public GL::AbstractShaderProgram {
* @brief Constructor * @brief Constructor
* @param flags Flags * @param flags Flags
* @param lightCount Count of light sources * @param lightCount Count of light sources
* @param jointCount Count of joints for skinning (see @ref Flag::Skinning)
* @param jointsPerVertex Max count of joints that may influence a vertex
* default @cpp 4 @ce (see @ref Flag::Skinning)
*/ */
explicit Phong(Flags flags = {}, UnsignedInt lightCount = 1); explicit Phong(Flags flags = {}, UnsignedInt lightCount = 1, UnsignedInt jointCount = 0, UnsignedInt jointsPerVertex = 4);
/** /**
* @brief Construct without creating the underlying OpenGL object * @brief Construct without creating the underlying OpenGL object
@ -465,6 +511,12 @@ class MAGNUM_SHADERS_EXPORT Phong: public GL::AbstractShaderProgram {
/** @brief Light count */ /** @brief Light count */
UnsignedInt lightCount() const { return _lightCount; } UnsignedInt lightCount() const { return _lightCount; }
/** @brief Joint count */
UnsignedInt jointCount() const { return _jointCount; }
/** @brief Joints per vertex */
UnsignedInt jointsPerVertex() const { return _jointsPerVertex; }
/** /**
* @brief Set ambient color * @brief Set ambient color
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
@ -719,6 +771,28 @@ class MAGNUM_SHADERS_EXPORT Phong: public GL::AbstractShaderProgram {
return setLightColors({&color, 1}); return setLightColors({&color, 1});
} }
/**
* @brief Set joint matrices
* @return Reference to self (for method chaining)
*
* Initial values are identity transformations. Expects that the size
* of the @p matrices array is the same as @ref jointCount().
* @see @ref setJointMatrix(UnsignedInt, const Matrix4&)
*/
Phong& setJointMatrices(const Containers::ArrayView<const Matrix4> matrices);
/** @overload */
Phong& setJointMatrices(std::initializer_list<Matrix4> matrices);
/**
* @brief Set joint matrix for given joint
* @return Reference to self (for method chaining)
*
* Unlike @ref setJointMatrices() updates just a single joint matrix.
* Expects that @p id is less than @ref joinCount().
*/
Phong& setJointMatrix(UnsignedInt id, const Matrix4& matrix);
private: private:
/* Prevent accidentally calling irrelevant functions */ /* Prevent accidentally calling irrelevant functions */
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -730,6 +804,8 @@ class MAGNUM_SHADERS_EXPORT Phong: public GL::AbstractShaderProgram {
Flags _flags; Flags _flags;
UnsignedInt _lightCount; UnsignedInt _lightCount;
UnsignedInt _jointCount;
UnsignedInt _jointsPerVertex;
Int _transformationMatrixUniform{0}, Int _transformationMatrixUniform{0},
_projectionMatrixUniform{1}, _projectionMatrixUniform{1},
_normalMatrixUniform{2}, _normalMatrixUniform{2},
@ -744,6 +820,7 @@ class MAGNUM_SHADERS_EXPORT Phong: public GL::AbstractShaderProgram {
#endif #endif
Int _lightPositionsUniform{10}, Int _lightPositionsUniform{10},
_lightColorsUniform; /* 10 + lightCount, set in the constructor */ _lightColorsUniform; /* 10 + lightCount, set in the constructor */
Int _jointMatricesUniform; /* 10 + 2*lightCount, set in the constructor */
}; };
/** @debugoperatorclassenum{Phong,Phong::Flag} */ /** @debugoperatorclassenum{Phong,Phong::Flag} */

45
src/Magnum/Shaders/Phong.vert

@ -80,6 +80,13 @@ layout(location = 10)
uniform highp vec3 lightPositions[LIGHT_COUNT]; /* defaults to zero */ uniform highp vec3 lightPositions[LIGHT_COUNT]; /* defaults to zero */
#endif #endif
#ifdef SKINNING
#ifdef EXPLICIT_UNIFORM_LOCATION
layout(location = JOINT_MATRICES_LOCATION)
#endif
uniform mat4 jointMatrices[JOINT_COUNT];
#endif
#ifdef EXPLICIT_ATTRIB_LOCATION #ifdef EXPLICIT_ATTRIB_LOCATION
layout(location = POSITION_ATTRIBUTE_LOCATION) layout(location = POSITION_ATTRIBUTE_LOCATION)
#endif #endif
@ -117,6 +124,30 @@ in lowp vec4 vertexColor;
out lowp vec4 interpolatedVertexColor; out lowp vec4 interpolatedVertexColor;
#endif #endif
#ifdef SKINNING
#ifdef EXPLICIT_ATTRIB_LOCATION
layout(location = WEIGHTS_ATTRIBUTE_LOCATION)
#endif
in mediump vec4 weights;
#ifdef EXPLICIT_ATTRIB_LOCATION
layout(location = JOINTIDS_ATTRIBUTE_LOCATION)
#endif
in mediump uvec4 jointIds;
#if JOINTS_PER_VERTEX > 4
#ifdef EXPLICIT_ATTRIB_LOCATION
layout(location = SECONDARY_WEIGHTS_ATTRIBUTE_LOCATION)
#endif
in mediump vec4 secondaryWeights;
#ifdef EXPLICIT_ATTRIB_LOCATION
layout(location = SECONDARY_JOINTIDS_ATTRIBUTE_LOCATION)
#endif
in mediump vec4 secondaryJointIds;
#endif
#endif
#ifdef INSTANCED_OBJECT_ID #ifdef INSTANCED_OBJECT_ID
#ifdef EXPLICIT_ATTRIB_LOCATION #ifdef EXPLICIT_ATTRIB_LOCATION
layout(location = OBJECT_ID_ATTRIBUTE_LOCATION) layout(location = OBJECT_ID_ATTRIBUTE_LOCATION)
@ -155,11 +186,25 @@ out highp vec3 cameraDirection;
#endif #endif
void main() { void main() {
#ifdef SKINNING
mat4 skinMatrix;
int i = 0;
for(; i != JOINTS_PER_VERTEX && i != 4; ++i)
skinMatrix += weights[i]*jointMatrices[int(jointIds[i])];
#if JOINTS_PER_VERTEX > 4
for(i = 0; i != JOINTS_PER_VERTEX - 4 && i != 4; ++i)
skinMatrix += secondaryWeights[i]*jointMatrices[int(secondaryJointIds[i])];
#endif
#endif
/* Transformed vertex position */ /* Transformed vertex position */
highp vec4 transformedPosition4 = transformationMatrix* highp vec4 transformedPosition4 = transformationMatrix*
#ifdef INSTANCED_TRANSFORMATION #ifdef INSTANCED_TRANSFORMATION
instancedTransformationMatrix* instancedTransformationMatrix*
#endif #endif
#ifdef SKINNING
skinMatrix*
#endif
position; position;
highp vec3 transformedPosition = transformedPosition4.xyz/transformedPosition4.w; highp vec3 transformedPosition = transformedPosition4.xyz/transformedPosition4.w;

5
src/Magnum/Shaders/generic.glsl

@ -37,6 +37,11 @@
#define NORMAL_MATRIX_ATTRIBUTE_LOCATION 12 #define NORMAL_MATRIX_ATTRIBUTE_LOCATION 12
#define TEXTURE_OFFSET_ATTRIBUTE_LOCATION 15 #define TEXTURE_OFFSET_ATTRIBUTE_LOCATION 15
#define WEIGHTS_ATTRIBUTE_LOCATION 6
#define JOINTIDS_ATTRIBUTE_LOCATION 7
#define SECONDARY_WEIGHTS_ATTRIBUTE_LOCATION 10
#define SECONDARY_JOINTIDS_ATTRIBUTE_LOCATION 11
/* Outputs */ /* Outputs */
#define COLOR_OUTPUT_ATTRIBUTE_LOCATION 0 #define COLOR_OUTPUT_ATTRIBUTE_LOCATION 0
#define OBJECT_ID_OUTPUT_ATTRIBUTE_LOCATION 1 #define OBJECT_ID_OUTPUT_ATTRIBUTE_LOCATION 1

Loading…
Cancel
Save