Browse Source

Shaders: ambient, diffuse and specular texture support in Phong.

pull/277/head
Vladimír Vondruš 13 years ago
parent
commit
41f7784dc5
  1. 26
      src/Shaders/Phong.cpp
  2. 71
      src/Shaders/Phong.frag
  3. 116
      src/Shaders/Phong.h
  4. 14
      src/Shaders/Phong.vert

26
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<Extensions::GL::ARB::shading_language_420pack>())
#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({});

71
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;

116
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<Flag, UnsignedByte> 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

14
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
}

Loading…
Cancel
Save