diff --git a/src/Shaders/Phong.cpp b/src/Shaders/Phong.cpp index c96fc0e01..e4a93f068 100644 --- a/src/Shaders/Phong.cpp +++ b/src/Shaders/Phong.cpp @@ -31,7 +31,7 @@ namespace Magnum { namespace Shaders { -Phong::Phong(): transformationMatrixUniform(0), projectionMatrixUniform(1), normalMatrixUniform(2), lightUniform(3), diffuseColorUniform(4), ambientColorUniform(5), specularColorUniform(6), lightColorUniform(7), shininessUniform(8) { +Phong::Phong(const Flags flags): transformationMatrixUniform(0), projectionMatrixUniform(1), normalMatrixUniform(2), lightUniform(3), diffuseColorUniform(4), ambientColorUniform(5), specularColorUniform(6), lightColorUniform(7), shininessUniform(8), _flags(flags) { Utility::Resource rs("MagnumShaders"); #ifndef MAGNUM_TARGET_GLES @@ -41,13 +41,17 @@ Phong::Phong(): transformationMatrixUniform(0), projectionMatrixUniform(1), norm #endif Shader vert(v, Shader::Type::Vertex); - vert.addSource(rs.get("compatibility.glsl")) + vert.addSource(flags ? "#define TEXTURED\n" : "") + .addSource(rs.get("compatibility.glsl")) .addSource(rs.get("Phong.vert")); CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile()); attachShader(vert); Shader frag(v, Shader::Type::Fragment); - frag.addSource(rs.get("compatibility.glsl")) + frag.addSource(flags & Flag::AmbientTexture ? "#define AMBIENT_TEXTURE\n" : "") + .addSource(flags & Flag::DiffuseTexture ? "#define DIFFUSE_TEXTURE\n" : "") + .addSource(flags & Flag::SpecularTexture ? "#define SPECULAR_TEXTURE\n" : "") + .addSource(rs.get("compatibility.glsl")) .addSource(rs.get("Phong.frag")); CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile()); attachShader(frag); @@ -61,6 +65,7 @@ Phong::Phong(): transformationMatrixUniform(0), projectionMatrixUniform(1), norm { bindAttributeLocation(Position::Location, "position"); bindAttributeLocation(Normal::Location, "normal"); + if(flags) bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates"); } CORRADE_INTERNAL_ASSERT_OUTPUT(link()); @@ -73,13 +78,22 @@ Phong::Phong(): transformationMatrixUniform(0), projectionMatrixUniform(1), norm projectionMatrixUniform = uniformLocation("projectionMatrix"); normalMatrixUniform = uniformLocation("normalMatrix"); lightUniform = uniformLocation("light"); - diffuseColorUniform = uniformLocation("diffuseColor"); - ambientColorUniform = uniformLocation("ambientColor"); - specularColorUniform = uniformLocation("specularColor"); + if(!(flags & Flag::AmbientTexture)) ambientColorUniform = uniformLocation("ambientColor"); + if(!(flags & Flag::DiffuseTexture)) diffuseColorUniform = uniformLocation("diffuseColor"); + if(!(flags & Flag::SpecularTexture)) specularColorUniform = uniformLocation("specularColor"); lightColorUniform = uniformLocation("lightColor"); shininessUniform = uniformLocation("shininess"); } + #ifndef MAGNUM_TARGET_GLES + if(flags && !Context::current()->isExtensionSupported()) + #endif + { + if(flags & Flag::AmbientTexture) setUniform(uniformLocation("ambientTexture"), AmbientTextureLayer); + if(flags & Flag::DiffuseTexture) setUniform(uniformLocation("diffuseTexture"), DiffuseTextureLayer); + if(flags & Flag::SpecularTexture) setUniform(uniformLocation("specularTexture"), SpecularTextureLayer); + } + /* Set defaults in OpenGL ES (for desktop they are set in shader code itself) */ #ifdef MAGNUM_TARGET_GLES setAmbientColor({}); diff --git a/src/Shaders/Phong.frag b/src/Shaders/Phong.frag index c3411f0ea..3d98851f6 100644 --- a/src/Shaders/Phong.frag +++ b/src/Shaders/Phong.frag @@ -29,35 +29,88 @@ #ifndef GL_ES #ifdef EXPLICIT_UNIFORM_LOCATION -layout(location = 4) uniform vec3 diffuseColor; -layout(location = 5) uniform vec3 ambientColor = vec3(0.0, 0.0, 0.0); -layout(location = 6) uniform vec3 specularColor = vec3(1.0, 1.0, 1.0); layout(location = 7) uniform vec3 lightColor = vec3(1.0, 1.0, 1.0); layout(location = 8) uniform float shininess = 80.0; #else -uniform vec3 diffuseColor; -uniform vec3 ambientColor = vec3(0.0, 0.0, 0.0); -uniform vec3 specularColor = vec3(1.0, 1.0, 1.0); uniform vec3 lightColor = vec3(1.0, 1.0, 1.0); uniform float shininess = 80.0; #endif #else -uniform lowp vec3 diffuseColor; -uniform lowp vec3 ambientColor; -uniform lowp vec3 specularColor; uniform lowp vec3 lightColor; uniform mediump float shininess; #endif +#ifdef AMBIENT_TEXTURE +#ifdef EXPLICIT_TEXTURE_LAYER +layout(binding = 0) uniform sampler2D ambientTexture; +#else +uniform sampler2D ambientTexture; +#endif +#else +#ifndef GL_ES +#ifdef EXPLICIT_UNIFORM_LOCATION +layout(location = 5) uniform vec3 ambientColor = vec3(0.0, 0.0, 0.0); +#else +uniform vec3 ambientColor = vec3(0.0, 0.0, 0.0); +#endif +#else +uniform lowp vec3 ambientColor; +#endif +#endif + +#ifdef DIFFUSE_TEXTURE +#ifdef EXPLICIT_TEXTURE_LAYER +layout(binding = 1) uniform sampler2D diffuseTexture; +#else +uniform sampler2D diffuseTexture; +#endif +#else +#ifdef EXPLICIT_UNIFORM_LOCATION +layout(location = 4) uniform vec3 diffuseColor; +#else +uniform lowp vec3 diffuseColor; +#endif +#endif + +#ifdef SPECULAR_TEXTURE +#ifdef EXPLICIT_TEXTURE_LAYER +layout(binding = 2) uniform sampler2D specularTexture; +#else +uniform sampler2D specularTexture; +#endif +#else +#ifndef GL_ES +#ifdef EXPLICIT_UNIFORM_LOCATION +layout(location = 6) uniform vec3 specularColor = vec3(1.0, 1.0, 1.0); +#else +uniform vec3 specularColor = vec3(1.0, 1.0, 1.0); +#endif +#else +uniform lowp vec3 specularColor; +#endif +#endif + in mediump vec3 transformedNormal; in highp vec3 lightDirection; in highp vec3 cameraDirection; +#if defined(AMBIENT_TEXTURE) || defined(DIFFUSE_TEXTURE) || defined(SPECULAR_TEXTURE) +in mediump vec2 interpolatedTextureCoords; +#endif + #ifdef NEW_GLSL out lowp vec4 color; #endif void main() { + #ifdef AMBIENT_TEXTURE + const vec3 ambientColor = texture(ambientTexture, interpolatedTextureCoords).xyz; + #elif defined(DIFFUSE_TEXTURE) + const vec3 diffuseColor = texture(diffuseTexture, interpolatedTextureCoords).xyz; + #elif defined(SPECULAR_TEXTURE) + const vec3 specularColor = texture(specularTexture, interpolatedTextureCoords).xyz; + #endif + /* Ambient color */ color.rgb = ambientColor; diff --git a/src/Shaders/Phong.h b/src/Shaders/Phong.h index 417611152..f5d91e8b8 100644 --- a/src/Shaders/Phong.h +++ b/src/Shaders/Phong.h @@ -39,46 +39,109 @@ namespace Magnum { namespace Shaders { /** @brief Phong shader -If supported, uses GLSL 3.20 and @extension{ARB,explicit_attrib_location}, -otherwise falls back to GLSL 1.20. +Uses ambient, diffuse and specular color or texture. You need to provide +@ref Position and @ref Normal attributes in your triangle mesh and call at +least @ref setTransformationMatrix(), @ref setNormalMatrix(), +@ref setProjectionMatrix(), @ref setDiffuseColor() and @ref setLightPosition(). + +If you want to use texture instead of color, you need to provide also +@ref TextureCoordinates attribute. Pass appropriate flags to constructor and +then at render time bind the texture to its respective layer instead of setting +the color. Example: +@code +Shaders::Phong shader(Shaders::Phong::Flag::DiffuseTexture); + +// ... + +myDiffuseTexture.bind(Shaders::Phong::DiffuseTextureLayer); +@endcode */ class MAGNUM_SHADERS_EXPORT Phong: public AbstractShaderProgram { public: typedef Attribute<0, Vector3> Position; /**< @brief Vertex position */ typedef Attribute<1, Vector3> Normal; /**< @brief Normal direction */ - explicit Phong(); + /** + * @brief Texture coordinates + * + * Used only if one of @ref Flag "Flag::AmbientTexture", + * @ref Flag "Flag::DiffuseTexture" or @ref Flag "Flag::SpecularTexture" + * is set. + */ + typedef Attribute<2, Vector2> TextureCoordinates; + + enum: Int { + /** + * Layer for ambient texture. Used only if @ref Flag "Flag::AmbientTexture" + * is set. + */ + AmbientTextureLayer = 0, + + /** + * Layer for diffuse texture. Used only if @ref Flag "Flag::DiffuseTexture" + * is set. + */ + DiffuseTextureLayer = 1, + + /** + * Layer for specular texture. Used only if @ref Flag "Flag::SpecularTexture" + * is set. + */ + SpecularTextureLayer = 2 + }; + + /** + * @brief Shader flag + * + * @see @ref Flags, @ref flags() + */ + enum class Flag: UnsignedByte { + AmbientTexture = 1 << 0, /**< The shader uses ambient texture instead of color */ + DiffuseTexture = 1 << 1, /**< The shader uses diffuse texture instead of color */ + SpecularTexture = 1 << 2 /**< The shader uses specular texture instead of color */ + }; + + /** + * @brief Shader flags + * + * @see @ref flags() + */ + typedef Containers::EnumSet Flags; + + /** + * @brief Constructor + * @param flags Shader flags + */ + explicit Phong(Flags flags = Flags()); + + /** @brief Shader flags */ + Flags flags() const { return _flags; } /** * @brief Set ambient color * @return Pointer to self (for method chaining) * - * If not set, default value is `(0.0f, 0.0f, 0.0f)`. + * If not set, default value is `(0.0f, 0.0f, 0.0f)`. Has no effect if + * @ref Flag "Flag::AmbientTexture" is set. */ - Phong* setAmbientColor(const Color3& color) { - setUniform(ambientColorUniform, color); - return this; - } + Phong* setAmbientColor(const Color3& color); /** * @brief Set diffuse color * @return Pointer to self (for method chaining) + * + * Has no effect if @ref Flag "Flag::AmbientTexture" is used. */ - Phong* setDiffuseColor(const Color3& color) { - setUniform(diffuseColorUniform, color); - return this; - } + Phong* setDiffuseColor(const Color3& color); /** * @brief Set specular color * @return Pointer to self (for method chaining) * - * If not set, default value is `(1.0f, 1.0f, 1.0f)`. + * If not set, default value is `(1.0f, 1.0f, 1.0f)`. Has no effect if + * @ref Flag "Flag::SpecularTexture" is set. */ - Phong* setSpecularColor(const Color3& color) { - setUniform(specularColorUniform, color); - return this; - } + Phong* setSpecularColor(const Color3& color); /** * @brief Set shininess @@ -149,8 +212,27 @@ class MAGNUM_SHADERS_EXPORT Phong: public AbstractShaderProgram { specularColorUniform, lightColorUniform, shininessUniform; + + Flags _flags; }; +CORRADE_ENUMSET_OPERATORS(Phong::Flags) + +inline Phong* Phong::setAmbientColor(const Color3& color) { + if(!(_flags & Flag::AmbientTexture)) setUniform(ambientColorUniform, color); + return this; +} + +inline Phong* Phong::setDiffuseColor(const Color3& color) { + if(!(_flags & Flag::DiffuseTexture)) setUniform(diffuseColorUniform, color); + return this; +} + +inline Phong* Phong::setSpecularColor(const Color3& color) { + if(!(_flags & Flag::SpecularTexture)) setUniform(specularColorUniform, color); + return this; +} + }} #endif diff --git a/src/Shaders/Phong.vert b/src/Shaders/Phong.vert index c52eb30f9..cdd51147d 100644 --- a/src/Shaders/Phong.vert +++ b/src/Shaders/Phong.vert @@ -47,6 +47,15 @@ in highp vec4 position; in mediump vec3 normal; #endif +#ifdef TEXTURED +#ifdef EXPLICIT_ATTRIB_LOCATION +layout(location = 2) in mediump vec2 textureCoords; +#else +in mediump vec2 textureCoords; +#endif +out mediump vec2 interpolatedTextureCoords; +#endif + out mediump vec3 transformedNormal; out highp vec3 lightDirection; out highp vec3 cameraDirection; @@ -67,4 +76,9 @@ void main() { /* Transform the position */ gl_Position = projectionMatrix*transformedPosition4; + + #ifdef TEXTURED + /* Texture coordinates, if needed */ + interpolatedTextureCoords = textureCoords; + #endif }