Преглед изворни кода

Merge branch 'next' of https://github.com/blackberry-gaming/GamePlay into next-sgrenier

Steve Grenier пре 14 година
родитељ
комит
1652582d25

+ 15 - 2
gameplay-encoder/src/DAESceneEncoder.cpp

@@ -656,6 +656,7 @@ bool DAESceneEncoder::loadTarget(const domChannelRef& channelRef, AnimationChann
     }
     animationChannel->setTargetAttribute(targetProperty);
     animationChannel->setTargetId(channelTarget.getTargetId());
+    //animationChannel->removeDuplicates();
     return true;
 }
 
@@ -1685,8 +1686,8 @@ Mesh* DAESceneEncoder::loadMesh(const domMesh* meshElement, const std::string& g
 
         // Go through the polygon indices for each input source retrieve the values
         // and iterate by its offset.
-        Vertex vertex;
 
+        Vertex vertex;
         for (unsigned int k = 0; k < inputSourceCount && poly < polyIntsCount;)
         {
             const domListOfFloats& source = polygonInputs[k]->sourceValues;
@@ -1701,7 +1702,7 @@ Mesh* DAESceneEncoder::loadMesh(const domMesh* meshElement, const std::string& g
             switch (type)
             {
             case POSITION:
-                vertex.reset();
+                vertex = Vertex(); // TODO
                 if (_vertexBlendWeights && _vertexBlendIndices)
                 {
                     vertex.hasWeights = true;
@@ -1769,6 +1770,8 @@ Mesh* DAESceneEncoder::loadMesh(const domMesh* meshElement, const std::string& g
                     vertex.texCoord.y = (float)source.get(polyIndex * 2 + 1);
                 }
                 break;
+            default:
+                break;
             }
 
             // On the last input source attempt to add the vertex or index an existing one.
@@ -1891,6 +1894,16 @@ int DAESceneEncoder::getVertexUsageType(const std::string& semantic)
             {
                 type = TEXCOORD0;
             }
+            else if (equals(semantic, "TEXTANGENT"))
+            {
+                // Treat TEXTANGENT as TANGENT
+                type = TANGENT;
+            }
+            else if (equals(semantic, "TEXBINORMAL"))
+            {
+                // Treat TEXBINORMAL as BINORMAL
+                type = BINORMAL;
+            }
         case 'B':
             if (equals(semantic, "BINORMAL"))
             {

+ 2 - 2
gameplay-encoder/src/Light.cpp

@@ -47,7 +47,7 @@ float Light::computeRange(float constantAttenuation, float linearAttenuation, fl
     const float step = 0.01f;
     float range = 0.01f;
     float att = 1.0f;
-    while (att < 0.1f)
+    while (att > 0.01f)
     {
         att = 1 / (constantAttenuation + (range * linearAttenuation) + (range * range * quadraticAttenuation));
         range += step;
@@ -111,7 +111,7 @@ void Light::writeBinary(FILE* file)
         // Compute an approximate inner angle of the spot light using Collada's outer angle.
         _outerAngle = _falloffAngle / 2.0f;
         
-        if (_range == -1.0f)
+        if (_innerAngle == -1.0f)
         {
             _innerAngle = computeInnerAngle(_outerAngle);
         }

+ 16 - 15
gameplay/res/shaders/bumped-specular.fsh

@@ -36,8 +36,8 @@ void lighting(vec3 normalVector, vec3 cameraDirection, vec3 lightDirection, floa
 
 #if defined(POINT_LIGHT)
 
-varying vec3 v_vertexToPointLightDirection; // Light direction w.r.t current vertex in tangent space.
-varying float v_pointLightAttenuation;      // Attenuation of point light.
+varying vec3 v_vertexToPointLightDirection;   // Light direction w.r.t current vertex in tangent space.
+varying float v_pointLightAttenuation;        // Attenuation of point light.
 
 void applyLight()
 {
@@ -45,19 +45,20 @@ void applyLight()
     // Fetch normals from the normal map.
     vec3 normalVector = normalize(texture2D(u_normalMapTexture, v_texCoord).rgb * 2.0 - 1.0);
     vec3 cameraDirection = normalize(v_cameraDirection);
-    
     vec3 vertexToPointLightDirection = normalize(v_vertexToPointLightDirection);
     
-    // Fetch point light attenuation.
-    lighting(normalVector, cameraDirection, vertexToPointLightDirection, v_pointLightAttenuation);
+    float pointLightAttenuation = clamp(v_pointLightAttenuation, 0.0, 1.0);
+    
+    lighting(normalVector, cameraDirection, vertexToPointLightDirection, pointLightAttenuation);
 }
 
 #elif defined(SPOT_LIGHT)
 
-uniform float u_spotLightInnerAngleCos;     // The bright spot [0.0 - 1.0]
-uniform float u_spotLightOuterAngleCos;     // The soft outer part [0.0 - 1.0]
-varying vec3 v_spotLightDirection;          // Direction of spot light in tangent space.
-varying vec3 v_vertexToSpotLightDirection;  // Direction of the spot light w.r.t current vertex in tangent space.
+uniform float u_spotLightInnerAngleCos;       // The bright spot [0.0 - 1.0]
+uniform float u_spotLightOuterAngleCos;       // The soft outer part [0.0 - 1.0]
+varying vec3 v_spotLightDirection;            // Direction of spot light in tangent space.
+varying vec3 v_vertexToSpotLightDirection;    // Direction of the spot light w.r.t current vertex in tangent space.
+varying float v_spotLightAttenuation;         // Attenuation of spot light.
 
 float lerpstep( float lower, float upper, float s)
 {
@@ -66,7 +67,6 @@ float lerpstep( float lower, float upper, float s)
 
 void applyLight()
 {
-    // Normalize the vectors.
     // Fetch normals from the normal map.
     vec3 normalVector = normalize(texture2D(u_normalMapTexture, v_texCoord).rgb * 2.0 - 1.0);
     vec3 cameraDirection = normalize(v_cameraDirection);
@@ -78,23 +78,24 @@ void applyLight()
     // Calculate spot light effect.
     float spotCurrentAngleCos = max(0.0, dot(spotLightDirection, -vertexToSpotLightDirection));
     
-    // Intensity of spot depends on the part of the cone the light direction points to (inner or outer).
-    float spotLightAttenuation = lerpstep(u_spotLightOuterAngleCos, u_spotLightInnerAngleCos, spotCurrentAngleCos);
+    // Intensity of spot depends on the spot light attenuation and the 
+    // part of the cone vertexToSpotLightDirection points to (inner or outer).
+    float spotLightAttenuation = clamp(v_spotLightAttenuation, 0.0, 1.0);
+    spotLightAttenuation *= lerpstep(u_spotLightOuterAngleCos, u_spotLightInnerAngleCos, spotCurrentAngleCos);
 
     lighting(normalVector, cameraDirection, vertexToSpotLightDirection, spotLightAttenuation);
 }
 
 #else
 
-varying vec3 v_directionalLightDirection;    // Direction of light in tangent space.
+varying vec3 v_lightDirection;                 // Direction of light in tangent space.
 
 void applyLight()
 {
-    // Normalize vectors.
     // Fetch normals from the normal map
     vec3 normalVector = normalize(texture2D(u_normalMapTexture, v_texCoord).rgb * 2.0 - 1.0);
     vec3 cameraDirection = normalize(v_cameraDirection);
-    vec3 lightDirection = normalize(v_directionalLightDirection);
+    vec3 lightDirection = normalize(v_lightDirection);
 
     lighting(normalVector, cameraDirection, -lightDirection, 1.0);
 }

+ 177 - 36
gameplay/res/shaders/bumped-specular.vsh

@@ -1,33 +1,160 @@
 // Uniforms
-uniform mat4 u_worldViewProjectionMatrix;       // Matrix to transform a position to clip space.
-uniform mat4 u_inverseTransposeWorldViewMatrix; // Matrix to transform a normal to view space.
-uniform mat4 u_worldMatrix;                     // Matrix to tranform a position to world space.
-uniform mat4 u_worldViewMatrix;                 // Matrix to tranform a position to view space.
-uniform vec3 u_cameraPosition;                  // Position of the camera.
+uniform mat4 u_worldViewMatrix;                     // Matrix to tranform a position to view space.
+uniform mat4 u_worldViewProjectionMatrix;           // Matrix to transform a position to clip space.
+uniform mat4 u_inverseTransposeWorldViewMatrix;     // Matrix to transform a normal to view space.
+uniform vec3 u_cameraPosition;                      // Position of the camera.
 
 // Inputs
-attribute vec4 a_position;                      // Vertex Position (x, y, z, w)
-attribute vec3 a_normal;                        // Vertex Normal (x, y, z)
-attribute vec2 a_texCoord;                      // Vertex Texture Coordinate (u, v)
-attribute vec3 a_tangent;                       // Vertex Tangent (x, y, z)
-attribute vec3 a_binormal;                      // Vertex Binormal (actually Bi-tangent) (x, y, z)
+attribute vec4 a_position;                          // Vertex Position (x, y, z, w)
+attribute vec3 a_normal;                            // Vertex Normal (x, y, z)
+attribute vec2 a_texCoord;                          // Vertex Texture Coordinate (u, v)
+attribute vec3 a_tangent;                           // Vertex Tangent (x, y, z)
+attribute vec3 a_binormal;                          // Vertex Binormal (actually Bi-tangent) (x, y, z)
 
 // Outputs
-varying vec2 v_texCoord;                        // Texture Coordinate (u,v)
-varying vec3 v_cameraDirection;                 // Direction the camera is looking at in tangent space.
+varying vec2 v_texCoord;                            // Texture Coordinate (u,v)
+varying vec3 v_cameraDirection;                     // Direction the camera is looking at in tangent space.
+
+#if defined(SKINNING)
+
+attribute vec4 a_blendWeights;
+attribute vec4 a_blendIndices;
+
+// 32 4x3 matrices as an array of floats
+uniform vec4 u_matrixPalette[SKINNING_JOINT_COUNT * 3];
+
+// Common vectors.
+vec4 _skinnedPosition;
+vec3 _skinnedNormal;
+
+void skinPosition(float blendWeight, int matrixIndex)
+{
+    vec4 tmp;
+
+    tmp.x = dot(a_position, u_matrixPalette[matrixIndex]);
+    tmp.y = dot(a_position, u_matrixPalette[matrixIndex + 1]);
+    tmp.z = dot(a_position, u_matrixPalette[matrixIndex + 2]);
+    tmp.w = a_position.w;
+
+    _skinnedPosition += blendWeight * tmp;
+}
+
+vec4 getPosition()
+{
+    _skinnedPosition = vec4(0.0);
+
+    // Transform position to view space using 
+    // matrix palette with four matrices used to transform a vertex.
+
+    float blendWeight = a_blendWeights[0];
+    int matrixIndex = int (a_blendIndices[0]) * 3;
+    skinPosition(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[1];
+    matrixIndex = int(a_blendIndices[1]) * 3;
+    skinPosition(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[2];
+    matrixIndex = int(a_blendIndices[2]) * 3;
+    skinPosition(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[3];
+    matrixIndex = int(a_blendIndices[2]) * 3;
+    skinPosition(blendWeight, matrixIndex);
+
+    return _skinnedPosition;    
+}
+
+void skinTangentSpaceVector(vec3 vector, float blendWeight, int matrixIndex)
+{
+    vec3 tmp;
+
+    tmp.x = dot(vector, u_matrixPalette[matrixIndex].xyz);
+    tmp.y = dot(vector, u_matrixPalette[matrixIndex + 1].xyz);
+    tmp.z = dot(vector, u_matrixPalette[matrixIndex + 2].xyz);
+
+    _skinnedNormal += blendWeight * tmp;
+}
+
+vec3 getTangentSpaceVector(vec3 vector)
+{
+    _skinnedNormal = vec3(0.0);
+
+    // Transform normal to view space using 
+    // matrix palette with four matrices used to transform a vertex.
+
+    float blendWeight = a_blendWeights[0];
+    int matrixIndex = int (a_blendIndices[0]) * 3;
+    skinTangentSpaceVector(vector, blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[1];
+    matrixIndex = int(a_blendIndices[1]) * 3;
+    skinTangentSpaceVector(vector, blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[2];
+    matrixIndex = int(a_blendIndices[2]) * 3;
+    skinTangentSpaceVector(vector, blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[3];
+    matrixIndex = int(a_blendIndices[2]) * 3;
+    skinTangentSpaceVector(vector, blendWeight, matrixIndex);
+
+    return _skinnedNormal;
+}
+
+vec3 getNormal()
+{
+    return getTangentSpaceVector(a_normal);
+}
+
+vec3 getTangent()
+{
+    return getTangentSpaceVector(a_tangent);
+}
+
+vec3 getBinormal()
+{
+    return getTangentSpaceVector(a_binormal);
+}
+
+#else
+
+vec4 getPosition()
+{
+    return a_position;    
+}
+
+vec3 getNormal()
+{
+    return a_normal;
+}
+
+vec3 getTangent()
+{
+    return a_tangent;
+}
+
+vec3 getBinormal()
+{
+    return a_binormal;
+}
+
+#endif
 
 #if defined(POINT_LIGHT)
 
-uniform vec3 u_pointLightPosition;              // Position
-uniform float u_pointLightRadius;               // Radius 
-varying vec3 v_vertexToPointLightDirection;     // Direction of point light w.r.t current vertex in tangent space.
-varying float v_pointLightAttenuation;          // Attenuation of point light.
+uniform vec3 u_pointLightPosition;                  // Position
+uniform float u_pointLightRangeInverse;             // Inverse of light range 
+varying vec3 v_vertexToPointLightDirection;         // Direction of point light w.r.t current vertex in tangent space.
+varying float v_pointLightAttenuation;              // Attenuation of point light.
 
 void applyLight(mat3 tangentSpaceTransformMatrix)
 {
-    // World space position.
     vec4 positionWorldViewSpace = u_worldViewMatrix * a_position;
     
+    // Compute camera direction and transform it to tangent space.
+    v_cameraDirection = tangentSpaceTransformMatrix * (u_cameraPosition - positionWorldViewSpace.xyz);
+    
     // Compute the light direction with light position and the vertex position.
     vec3 lightDirection = u_pointLightPosition - positionWorldViewSpace.xyz;
     
@@ -35,7 +162,7 @@ void applyLight(mat3 tangentSpaceTransformMatrix)
     vec3 vertexToPointLightDirection = tangentSpaceTransformMatrix * lightDirection;
 
     // Attenuation
-    v_pointLightAttenuation = 1 - dot (lightDirection * u_pointLightRadius, lightDirection * u_pointLightRadius);
+    v_pointLightAttenuation = 1.0 - dot(lightDirection * u_pointLightRangeInverse, lightDirection * u_pointLightRangeInverse);
 
     // Output light direction.
     v_vertexToPointLightDirection =  vertexToPointLightDirection;
@@ -43,15 +170,19 @@ void applyLight(mat3 tangentSpaceTransformMatrix)
 
 #elif defined(SPOT_LIGHT)
 
-uniform vec3 u_spotLightPosition;               // Position
-uniform vec3 u_spotLightDirection;              // Direction
-varying vec3 v_spotLightDirection;              // Direction of spot light in tangent space.
-varying vec3 v_vertexToSpotLightDirection;      // Direction of the spot light w.r.t current vertex in tangent space.
+uniform vec3 u_spotLightPosition;                   // Position
+uniform float u_spotLightRangeInverse;              // Inverse of light range.
+uniform vec3 u_spotLightDirection;                  // Direction
+varying vec3 v_spotLightDirection;                  // Direction of spot light in tangent space.
+varying vec3 v_vertexToSpotLightDirection;          // Direction of the spot light w.r.t current vertex in tangent space.
+varying float v_spotLightAttenuation;               // Attenuation of spot light.
 
 void applyLight(mat3 tangentSpaceTransformMatrix)
 {
-    // World space position.
     vec4 positionWorldViewSpace = u_worldViewMatrix * a_position;
+    
+    // Compute camera direction and transform it to tangent space.
+    v_cameraDirection = tangentSpaceTransformMatrix * (u_cameraPosition - positionWorldViewSpace.xyz);
 
     // Transform spot light direction to tangent space.
     v_spotLightDirection = tangentSpaceTransformMatrix * u_spotLightDirection;
@@ -61,6 +192,9 @@ void applyLight(mat3 tangentSpaceTransformMatrix)
     
     // Transform current light direction to tangent space.
     lightDirection = tangentSpaceTransformMatrix * lightDirection;
+    
+    // Attenuation
+    v_spotLightAttenuation = 1.0 - dot(lightDirection * u_spotLightRangeInverse, lightDirection * u_spotLightRangeInverse);
 
     // Output light direction.
     v_vertexToSpotLightDirection = lightDirection;
@@ -68,35 +202,42 @@ void applyLight(mat3 tangentSpaceTransformMatrix)
 
 #else
 
-uniform vec3 u_lightDirection;                    // Direction
-varying vec3 v_directionalLightDirection;         // Direction of light in tangent space.
+uniform vec3 u_lightDirection;                      // Direction
+varying vec3 v_lightDirection;                      // Direction of light in tangent space.
 
 void applyLight(mat3 tangentSpaceTransformMatrix)
 {
+    vec4 positionWorldViewSpace = u_worldViewMatrix * a_position;
+    
+    // Compute camera direction and transform it to tangent space.
+    v_cameraDirection = tangentSpaceTransformMatrix * (u_cameraPosition - positionWorldViewSpace.xyz);
+    
     // Transform light direction to tangent space.
-    v_directionalLightDirection = tangentSpaceTransformMatrix * u_lightDirection;
+    v_lightDirection = tangentSpaceTransformMatrix * u_lightDirection;
 }
 
 #endif
 
 void main()
 {
+    vec4 position = getPosition();
+    vec3 normal = getNormal();
+    vec3 tangent = getTangent();
+    vec3 binormal = getBinormal();
+    
     // Transform position to clip space.
-    gl_Position = u_worldViewProjectionMatrix * a_position;
+    gl_Position = u_worldViewProjectionMatrix * position;
 
     // Transform the normal, tangent and binormals to  view space.
     mat3 inverseTransposeWorldViewMatrix = mat3(u_inverseTransposeWorldViewMatrix);
-    vec3 tangentVector  = inverseTransposeWorldViewMatrix * a_tangent;
-    vec3 normalVector = inverseTransposeWorldViewMatrix * a_normal;
-    vec3 binormalVector = inverseTransposeWorldViewMatrix * a_binormal;
+    vec3 tangentVector  = normalize(inverseTransposeWorldViewMatrix * tangent);
+    vec3 normalVector = normalize(inverseTransposeWorldViewMatrix * normal);
+    vec3 binormalVector = normalize(inverseTransposeWorldViewMatrix * binormal);
 
     // Create a transform to convert a vector to tangent space.
-    mat3 tangentSpaceTransformMatrix = mat3(tangentVector, binormalVector, normalVector);
-
-    // Compute camera direction and transform it to tangent space.
-    vec4 positionWorldSpace = u_worldMatrix * a_position;
-    v_cameraDirection = tangentSpaceTransformMatrix * (u_cameraPosition - positionWorldSpace.xyz);
-
+    mat3 tangentSpaceTransformMatrix = mat3(tangentVector.x, binormalVector.x, normalVector.x,
+                                            tangentVector.y, binormalVector.y, normalVector.y,
+                                            tangentVector.z, binormalVector.z, normalVector.z);
     // Apply light.
     applyLight(tangentSpaceTransformMatrix);
 

+ 19 - 17
gameplay/res/shaders/bumped.fsh

@@ -1,18 +1,18 @@
 precision highp float;
 
 // Uniforms
-uniform vec3 u_lightColor;                  // Light color.
-uniform vec3 u_ambientColor;                // Ambient color.
-uniform sampler2D u_diffuseTexture;         // Diffuse texture.
-uniform sampler2D u_normalMapTexture;       // Normal map texture.
+uniform vec3 u_lightColor;                   // Light color.
+uniform vec3 u_ambientColor;                 // Ambient color.
+uniform sampler2D u_diffuseTexture;          // Diffuse texture.
+uniform sampler2D u_normalMapTexture;        // Normal map texture.
 
 // Inputs
-varying vec2 v_texCoord;                    // Texture Coordinate.
+varying vec2 v_texCoord;                     // Texture Coordinate.
 
 // Common colors
-vec4 _baseColor;                            // Base color
-vec3 _ambientColor;                         // Ambient Color
-vec3 _diffuseColor;                         // Diffuse Color
+vec4 _baseColor;                             // Base color
+vec3 _ambientColor;                          // Ambient Color
+vec3 _diffuseColor;                          // Diffuse Color
 
 void lighting(vec3 normalVector, vec3 lightDirection, float attenuation)
 {
@@ -35,11 +35,11 @@ void applyLight()
     // Normalize the vectors.
     // Fetch normals from the normal map.
     vec3 normalVector = normalize(texture2D(u_normalMapTexture, v_texCoord).rgb * 2.0 - 1.0);
-    
     vec3 vertexToPointLightDirection = normalize(v_vertexToPointLightDirection);
+    float pointLightAttenuation = clamp(v_pointLightAttenuation, 0.0, 1.0);
     
     // Fetch point light attenuation.
-    lighting(normalVector, vertexToPointLightDirection, v_pointLightAttenuation);
+    lighting(normalVector, vertexToPointLightDirection, pointLightAttenuation);
 }
 
 #elif defined(SPOT_LIGHT)
@@ -48,6 +48,7 @@ uniform float u_spotLightInnerAngleCos;       // The bright spot [0.0 - 1.0]
 uniform float u_spotLightOuterAngleCos;       // The soft outer part [0.0 - 1.0]
 varying vec3 v_spotLightDirection;            // Direction of spot light in tangent space.
 varying vec3 v_vertexToSpotLightDirection;    // Direction of the spot light w.r.t current vertex in tangent space.
+varying float v_spotLightAttenuation;         // Attenuation of spot light.
 
 float lerpstep( float lower, float upper, float s)
 {
@@ -56,9 +57,8 @@ float lerpstep( float lower, float upper, float s)
 
 void applyLight()
 {
-    // Normalize the vectors.
     // Fetch normals from the normal map.
-    vec3 normalVector = normalize(texture2D(u_normalMapTexture, v_texCoord).rgb * 2.0 - 1.0);
+    vec3 normalVector = normalize(texture2D(u_normalMapTexture, v_texCoord).xyz * 2.0 - 1.0);
     vec3 spotLightDirection =normalize(v_spotLightDirection);
     vec3 vertexToSpotLightDirection = normalize(v_vertexToSpotLightDirection);
     
@@ -67,22 +67,24 @@ void applyLight()
     // Calculate spot light effect.
     float spotCurrentAngleCos = max(0.0, dot(spotLightDirection, -vertexToSpotLightDirection));
     
-    // Intensity of spot depends on the part of the cone the light direction points to (inner or outer).
-    float spotLightAttenuation = lerpstep(u_spotLightOuterAngleCos, u_spotLightInnerAngleCos, spotCurrentAngleCos);
+    // Intensity of spot depends on the spot light attenuation and the 
+    // part of the cone vertexToSpotLightDirection points to (inner or outer).
+    float spotLightAttenuation = clamp(v_spotLightAttenuation, 0.0, 1.0);
+    spotLightAttenuation *= lerpstep(u_spotLightOuterAngleCos, u_spotLightInnerAngleCos, spotCurrentAngleCos);
 
     lighting(normalVector, vertexToSpotLightDirection, spotLightAttenuation);
 }
 
 #else
 
-varying vec3 v_directionalLightDirection;    // Direction of light in tangent space.
+varying vec3 v_lightDirection;                  // Direction of light in tangent space.
 
 void applyLight()
 {
     // Normalize vectors.
     // Fetch normals from the normal map
-    vec3 normalVector = normalize(texture2D(u_normalMapTexture, v_texCoord).rgb * 2.0 - 1.0);
-    vec3 lightDirection = normalize(v_directionalLightDirection);
+    vec3 normalVector = normalize(texture2D(u_normalMapTexture, v_texCoord).xyz * 2.0 - 1.0);
+    vec3 lightDirection = normalize(v_lightDirection);
 
     lighting(normalVector, -lightDirection, 1.0);
 }

+ 154 - 17
gameplay/res/shaders/bumped.vsh

@@ -12,11 +12,137 @@ attribute vec3 a_binormal;                      // Vertex Binormal (actually Bi-
 // Outputs
 varying vec2 v_texCoord;                        // Texture Coordinate (u,v)
 
+#if defined(SKINNING)
+
+attribute vec4 a_blendWeights;
+attribute vec4 a_blendIndices;
+
+// 32 4x3 matrices as an array of floats
+uniform vec4 u_matrixPalette[SKINNING_JOINT_COUNT * 3];
+
+// Common vectors.
+vec4 _skinnedPosition;
+vec3 _skinnedNormal;
+
+void skinPosition(float blendWeight, int matrixIndex)
+{
+    vec4 tmp;
+
+    tmp.x = dot(a_position, u_matrixPalette[matrixIndex]);
+    tmp.y = dot(a_position, u_matrixPalette[matrixIndex + 1]);
+    tmp.z = dot(a_position, u_matrixPalette[matrixIndex + 2]);
+    tmp.w = a_position.w;
+
+    _skinnedPosition += blendWeight * tmp;
+}
+
+vec4 getPosition()
+{
+    _skinnedPosition = vec4(0.0);
+
+    // Transform position to view space using 
+    // matrix palette with four matrices used to transform a vertex.
+
+    float blendWeight = a_blendWeights[0];
+    int matrixIndex = int (a_blendIndices[0]) * 3;
+    skinPosition(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[1];
+    matrixIndex = int(a_blendIndices[1]) * 3;
+    skinPosition(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[2];
+    matrixIndex = int(a_blendIndices[2]) * 3;
+    skinPosition(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[3];
+    matrixIndex = int(a_blendIndices[2]) * 3;
+    skinPosition(blendWeight, matrixIndex);
+
+    return _skinnedPosition;    
+}
+
+void skinTangentSpaceVector(vec3 vector, float blendWeight, int matrixIndex)
+{
+    vec3 tmp;
+
+    tmp.x = dot(vector, u_matrixPalette[matrixIndex].xyz);
+    tmp.y = dot(vector, u_matrixPalette[matrixIndex + 1].xyz);
+    tmp.z = dot(vector, u_matrixPalette[matrixIndex + 2].xyz);
+
+    _skinnedNormal += blendWeight * tmp;
+}
+
+vec3 getTangentSpaceVector(vec3 vector)
+{
+    _skinnedNormal = vec3(0.0);
+
+    // Transform normal to view space using 
+    // matrix palette with four matrices used to transform a vertex.
+
+    float blendWeight = a_blendWeights[0];
+    int matrixIndex = int (a_blendIndices[0]) * 3;
+    skinTangentSpaceVector(vector, blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[1];
+    matrixIndex = int(a_blendIndices[1]) * 3;
+    skinTangentSpaceVector(vector, blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[2];
+    matrixIndex = int(a_blendIndices[2]) * 3;
+    skinTangentSpaceVector(vector, blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[3];
+    matrixIndex = int(a_blendIndices[2]) * 3;
+    skinTangentSpaceVector(vector, blendWeight, matrixIndex);
+
+    return _skinnedNormal;
+}
+
+vec3 getNormal()
+{
+    return getTangentSpaceVector(a_normal);
+}
+
+vec3 getTangent()
+{
+    return getTangentSpaceVector(a_tangent);
+}
+
+vec3 getBinormal()
+{
+    return getTangentSpaceVector(a_binormal);
+}
+
+#else
+
+vec4 getPosition()
+{
+    return a_position;    
+}
+
+vec3 getNormal()
+{
+    return a_normal;
+}
+
+vec3 getTangent()
+{
+    return a_tangent;
+}
+
+vec3 getBinormal()
+{
+    return a_binormal;
+}
+
+#endif
+
 #if defined(POINT_LIGHT)
 
 uniform mat4 u_worldViewMatrix;                 // Matrix to tranform a position to view space.
 uniform vec3 u_pointLightPosition;              // Position
-uniform float u_pointLightRadius;               // Radius 
+uniform float u_pointLightRangeInverse;         // Inverse of light range.
 varying vec3 v_vertexToPointLightDirection;     // Direction of point light w.r.t current vertex in tangent space.
 varying float v_pointLightAttenuation;          // Attenuation of point light.
 
@@ -32,23 +158,24 @@ void applyLight(mat3 tangentSpaceTransformMatrix)
     vec3 vertexToSpotLightDirection = tangentSpaceTransformMatrix * lightDirection;
 
     // Attenuation
-    v_pointLightAttenuation = 1 - dot (lightDirection * u_pointLightRadius, lightDirection * u_pointLightRadius);
+    v_pointLightAttenuation = 1.0 - dot(lightDirection * u_pointLightRangeInverse, lightDirection * u_pointLightRangeInverse);
 
     // Output light direction.
-    v_vertexToSpotLightDirection =  vertexToSpotLightDirection;
+    v_vertexToPointLightDirection =  vertexToSpotLightDirection;
 }
 
 #elif defined(SPOT_LIGHT)
 
-uniform mat4 u_worldViewMatrix;                  // Matrix to tranform a position to view space.
-uniform vec3 u_spotLightPosition;                // Position
-uniform vec3 u_spotLightDirection;               // Direction
-varying vec3 v_spotLightDirection;               // Direction of spot light in tangent space.
-varying vec3 v_vertexToSpotLightDirection;       // Direction of the spot light w.r.t current vertex in tangent space.
+uniform mat4 u_worldViewMatrix;                 // Matrix to tranform a position to view space.
+uniform vec3 u_spotLightPosition;               // Position
+uniform float u_spotLightRangeInverse;          // Inverse of light range.
+uniform vec3 u_spotLightDirection;              // Direction
+varying vec3 v_spotLightDirection;              // Direction of spot light in tangent space.
+varying vec3 v_vertexToSpotLightDirection;      // Direction of the spot light w.r.t current vertex in tangent space.
+varying float v_spotLightAttenuation;           // Attenuation of spot light.
 
 void applyLight(mat3 tangentSpaceTransformMatrix)
 {
-    // World space position.
     vec4 positionWorldViewSpace = u_worldViewMatrix * a_position;
 
     // Transform spot light direction to tangent space.
@@ -59,6 +186,9 @@ void applyLight(mat3 tangentSpaceTransformMatrix)
     
     // Transform current light direction to tangent space.
     lightDirection = tangentSpaceTransformMatrix * lightDirection;
+    
+    // Attenuation
+    v_spotLightAttenuation = 1.0 - dot(lightDirection * u_spotLightRangeInverse, lightDirection * u_spotLightRangeInverse);
 
     // Output light direction.
     v_vertexToSpotLightDirection = lightDirection;
@@ -66,30 +196,37 @@ void applyLight(mat3 tangentSpaceTransformMatrix)
 
 #else
 
-uniform vec3 u_lightDirection;                    // Direction
-varying vec3 v_directionalLightDirection;         // Direction of light in tangent space.
+uniform vec3 u_lightDirection;                  // Direction
+varying vec3 v_lightDirection;                  // Direction of light in tangent space.
 
 void applyLight(mat3 tangentSpaceTransformMatrix)
 {
     // Transform light direction to tangent space.
-    v_directionalLightDirection = tangentSpaceTransformMatrix * u_lightDirection;
+    v_lightDirection = tangentSpaceTransformMatrix * u_lightDirection;
 }
 
 #endif
 
 void main()
 {
+    vec4 position = getPosition();
+    vec3 normal = getNormal();
+    vec3 tangent = getTangent();
+    vec3 binormal = getBinormal();
+    
     // Transform position to clip space.
-    gl_Position = u_worldViewProjectionMatrix * a_position;
+    gl_Position = u_worldViewProjectionMatrix * position;
 
     // Transform the normal, tangent and binormals to  view space.
     mat3 inverseTransposeWorldViewMatrix = mat3(u_inverseTransposeWorldViewMatrix);
-    vec3 tangentVector  = inverseTransposeWorldViewMatrix * a_tangent;
-    vec3 normalVector = inverseTransposeWorldViewMatrix * a_normal;
-    vec3 binormalVector = inverseTransposeWorldViewMatrix * a_binormal;
+    vec3 tangentVector  = normalize(inverseTransposeWorldViewMatrix * tangent);
+    vec3 normalVector = normalize(inverseTransposeWorldViewMatrix * normal);
+    vec3 binormalVector = normalize(inverseTransposeWorldViewMatrix * binormal);
 
     // Create a transform to convert a vector to tangent space.
-    mat3 tangentSpaceTransformMatrix = mat3(tangentVector, binormalVector, normalVector);
+    mat3 tangentSpaceTransformMatrix = mat3(tangentVector.x, binormalVector.x, normalVector.x,
+                                            tangentVector.y, binormalVector.y, normalVector.y,
+                                            tangentVector.z, binormalVector.z, normalVector.z);
 
     // Apply light.
     applyLight(tangentSpaceTransformMatrix);

+ 10 - 7
gameplay/res/shaders/colored-specular.fsh

@@ -52,10 +52,11 @@ void applyLight()
 
 #elif defined(SPOT_LIGHT)
 
-uniform vec3 u_spotLightDirection;          // Direction of the spot light.
-uniform float u_spotLightInnerAngleCos;     // The bright spot [0.0 - 1.0]
-uniform float u_spotLightOuterAngleCos;     // The soft outer part [0.0 - 1.0]
-varying vec3 v_vertexToSpotLightDirection;  // Light direction w.r.t current vertex.
+uniform vec3 u_spotLightDirection;              // Direction of the spot light.
+uniform float u_spotLightInnerAngleCos;         // The bright spot [0.0 - 1.0]
+uniform float u_spotLightOuterAngleCos;         // The soft outer part [0.0 - 1.0]
+varying vec3 v_vertexToSpotLightDirection;      // Light direction w.r.t current vertex.
+varying float v_spotLightAttenuation;           // Attenuation of spot light.
 
 float lerpstep( float lower, float upper, float s)
 {
@@ -75,15 +76,17 @@ void applyLight()
     // Calculate spot light effect.
     float spotCurrentAngleCos = max(0.0, dot(spotLightDirection, -vertexToSpotLightDirection));
 
-    // Intensity of spot depends on the part of the cone the light direction points to (inner or outer).
-    float spotLightAttenuation = lerpstep(u_spotLightOuterAngleCos, u_spotLightInnerAngleCos, spotCurrentAngleCos);
+    // Intensity of spot depends on the spot light attenuation and the 
+    // part of the cone vertexToSpotLightDirection points to (inner or outer).
+    float spotLightAttenuation = clamp(v_spotLightAttenuation, 0.0, 1.0);
+    spotLightAttenuation *= lerpstep(u_spotLightOuterAngleCos, u_spotLightInnerAngleCos, spotCurrentAngleCos);
 
     lighting(normalVector, cameraDirection, vertexToSpotLightDirection, spotLightAttenuation);
 }
 
 #else
 
-uniform vec3 u_lightDirection;       // Light direction
+uniform vec3 u_lightDirection;                  // Light direction
 
 void applyLight()
 {

+ 11 - 3
gameplay/res/shaders/colored-specular.vsh

@@ -119,7 +119,7 @@ vec3 getNormal()
 
 uniform mat4 u_worldViewMatrix;                     // Matrix to tranform a position to view space.
 uniform vec3 u_pointLightPosition;                  // Position
-uniform float u_pointLightRadius;                   // Radius 
+uniform float u_pointLightRangeInverse;             // Inverse of light range. 
 varying vec4 v_vertexToPointLightDirection;         // Light direction w.r.t current vertex.
 
 void applyLight(vec4 position)
@@ -134,7 +134,7 @@ void applyLight(vec4 position)
     vertexToPointLightDirection.xyz = lightDirection;
     
     // Attenuation
-    vertexToPointLightDirection.w = 1 - dot (lightDirection * u_pointLightRadius, lightDirection * u_pointLightRadius);
+    vertexToPointLightDirection.w = 1.0 - dot(lightDirection * u_pointLightRangeInverse, lightDirection * u_pointLightRangeInverse);
 
     // Output light direction.
     v_vertexToPointLightDirection =  vertexToPointLightDirection;
@@ -144,7 +144,9 @@ void applyLight(vec4 position)
 
 uniform mat4 u_worldViewMatrix;                     // Matrix to tranform a position to view space.
 uniform vec3 u_spotLightPosition;                   // Position
+uniform float u_spotLightRangeInverse;              // Inverse of light range.
 varying vec3 v_vertexToSpotLightDirection;          // Light direction w.r.t current vertex.
+varying float v_spotLightAttenuation;               // Attenuation of spot light.
 
 void applyLight(vec4 position)
 {
@@ -152,7 +154,13 @@ void applyLight(vec4 position)
     vec4 positionWorldViewSpace = u_worldViewMatrix * position;
 
     // Compute the light direction with light position and the vertex position.
-    v_vertexToSpotLightDirection = u_spotLightPosition - positionWorldViewSpace.xyz;
+    vec3 lightDirection = u_spotLightPosition - positionWorldViewSpace.xyz;
+
+    // Attenuation
+    v_spotLightAttenuation = 1.0 - dot(lightDirection * u_spotLightRangeInverse, lightDirection * u_spotLightRangeInverse);
+
+    // Compute the light direction with light position and the vertex position.
+    v_vertexToSpotLightDirection = lightDirection;
 }
 
 #else

+ 18 - 15
gameplay/res/shaders/colored.fsh

@@ -1,17 +1,17 @@
 precision highp float;
 
 // Uniforms
-uniform vec3 u_lightColor;                  // Light color
-uniform vec3 u_ambientColor;                // Ambient color
-uniform vec4 u_diffuseColor;                // Diffuse color
+uniform vec3 u_lightColor;                      // Light color
+uniform vec3 u_ambientColor;                    // Ambient color
+uniform vec4 u_diffuseColor;                    // Diffuse color
 
 // Inputs
-varying vec3 v_normalVector;                // NormalVector in view space.
+varying vec3 v_normalVector;                    // NormalVector in view space.
 
 // Global variables
-vec4 _baseColor;                            // Base color
-vec3 _ambientColor;                         // Ambient Color
-vec3 _diffuseColor;                         // Diffuse Color
+vec4 _baseColor;                                // Base color
+vec3 _ambientColor;                             // Ambient Color
+vec3 _diffuseColor;                             // Diffuse Color
 
 void lighting(vec3 normalVector, vec3 lightDirection, float attenuation)
 {
@@ -26,7 +26,7 @@ void lighting(vec3 normalVector, vec3 lightDirection, float attenuation)
 
 #if defined(POINT_LIGHT)
 
-varying vec4 v_vertexToPointLightDirection;   // Light direction w.r.t current vertex.
+varying vec4 v_vertexToPointLightDirection;     // Light direction w.r.t current vertex.
 
 void applyLight()
 {
@@ -42,10 +42,11 @@ void applyLight()
 
 #elif defined(SPOT_LIGHT)
 
-uniform vec3 u_spotLightDirection;          // Direction of the spot light.
-uniform float u_spotLightInnerAngleCos;     // The bright spot [0.0 - 1.0]
-uniform float u_spotLightOuterAngleCos;     // The soft outer part [0.0 - 1.0]
-varying vec3 v_vertexToSpotLightDirection;  // Light direction w.r.t current vertex.
+uniform vec3 u_spotLightDirection;              // Direction of the spot light.
+uniform float u_spotLightInnerAngleCos;         // The bright spot [0.0 - 1.0]
+uniform float u_spotLightOuterAngleCos;         // The soft outer part [0.0 - 1.0]
+varying vec3 v_vertexToSpotLightDirection;      // Light direction w.r.t current vertex.
+varying float v_spotLightAttenuation;           // Attenuation of spot light.
 
 float lerpstep( float lower, float upper, float s)
 {
@@ -64,15 +65,17 @@ void applyLight()
     // Calculate spot light effect.
     float spotCurrentAngleCos = max(0.0, dot(spotLightDirection, -vertexToSpotLightDirection));
 
-    // Intensity of spot depends on the part of the cone the light direction points to (inner or outer).
-    float spotLightAttenuation = lerpstep(u_spotLightOuterAngleCos, u_spotLightInnerAngleCos, spotCurrentAngleCos);
+    // Intensity of spot depends on the spot light attenuation and the 
+    // part of the cone vertexToSpotLightDirection points to (inner or outer).
+    float spotLightAttenuation = clamp(v_spotLightAttenuation, 0.0, 1.0);
+    spotLightAttenuation *= lerpstep(u_spotLightOuterAngleCos, u_spotLightInnerAngleCos, spotCurrentAngleCos);
 
     lighting(normalVector, vertexToSpotLightDirection, spotLightAttenuation);
 }
 
 #else
 
-uniform vec3 u_lightDirection;       // Light direction
+uniform vec3 u_lightDirection;       	        // Light direction
 
 void applyLight()
 {

+ 7 - 4
gameplay/res/shaders/colored.vsh

@@ -114,12 +114,11 @@ vec3 getNormal()
 
 uniform mat4 u_worldViewMatrix;                     // Matrix to tranform a position to view space.
 uniform vec3 u_pointLightPosition;                  // Position
-uniform float u_pointLightRadius;                   // Radius 
+uniform float u_pointLightRangeInverse;             // Inverse of light range.
 varying vec4 v_vertexToPointLightDirection;         // Light direction w.r.t current vertex.
 
 void applyLight(vec4 position)
 {
-    // World space position.
     vec4 positionWorldViewSpace = u_worldViewMatrix * position;
     
     // Compute the light direction.
@@ -129,7 +128,7 @@ void applyLight(vec4 position)
     vertexToPointLightDirection.xyz = lightDirection;
     
     // Attenuation.
-    vertexToPointLightDirection.w = 1 - dot (lightDirection * u_pointLightRadius, lightDirection * u_pointLightRadius);
+    vertexToPointLightDirection.w = 1.0 - dot(lightDirection * u_pointLightRangeInverse, lightDirection * u_pointLightRangeInverse);
 
     // Output light direction.
     v_vertexToPointLightDirection =  vertexToPointLightDirection;
@@ -139,16 +138,20 @@ void applyLight(vec4 position)
 
 uniform mat4 u_worldViewMatrix;                     // Matrix to tranform a position to view space.
 uniform vec3 u_spotLightPosition;                   // Position
+uniform float u_spotLightRangeInverse;              // Inverse of light range.
 varying vec3 v_vertexToSpotLightDirection;          // Light direction w.r.t current vertex.
+varying float v_spotLightAttenuation;               // Attenuation of spot light.
 
 void applyLight(vec4 position)
 {
-    // World space position.
     vec4 positionWorldViewSpace = u_worldViewMatrix * position;
 
     // Compute the light direction.
     vec3 lightDirection = u_spotLightPosition - positionWorldViewSpace.xyz;
 
+    // Attenuation
+    v_spotLightAttenuation = 1.0 - dot(lightDirection * u_spotLightRangeInverse, lightDirection * u_spotLightRangeInverse);
+
     // Output light direction.
     v_vertexToSpotLightDirection = lightDirection;
 }

+ 10 - 7
gameplay/res/shaders/diffuse-specular.fsh

@@ -53,10 +53,11 @@ void applyLight()
 
 #elif defined(SPOT_LIGHT)
 
-uniform vec3 u_spotLightDirection;          // Direction of the spot light.
-uniform float u_spotLightInnerAngleCos;     // The bright spot [0.0 - 1.0]
-uniform float u_spotLightOuterAngleCos;     // The soft outer part [0.0 - 1.0]
-varying vec3 v_vertexToSpotLightDirection;  // Light direction w.r.t current vertex.
+uniform vec3 u_spotLightDirection;              // Direction of the spot light.
+uniform float u_spotLightInnerAngleCos;         // The bright spot [0.0 - 1.0]
+uniform float u_spotLightOuterAngleCos;         // The soft outer part [0.0 - 1.0]
+varying vec3 v_vertexToSpotLightDirection;      // Light direction w.r.t current vertex.
+varying float v_spotLightAttenuation;           // Attenuation of spot light.
 
 float lerpstep( float lower, float upper, float s)
 {
@@ -76,15 +77,17 @@ void applyLight()
     // Calculate spot light effect.
     float spotCurrentAngleCos = max(0.0, dot(spotLightDirection, -vertexToSpotLightDirection));
     
-    // Intensity of spot depends on the part of the cone the light direction points to (inner or outer).
-    float spotLightAttenuation = lerpstep(u_spotLightOuterAngleCos, u_spotLightInnerAngleCos, spotCurrentAngleCos);
+    // Intensity of spot depends on the spot light attenuation and the 
+    // part of the cone vertexToSpotLightDirection points to (inner or outer).
+    float spotLightAttenuation = clamp(v_spotLightAttenuation, 0.0, 1.0);
+    spotLightAttenuation *= lerpstep(u_spotLightOuterAngleCos, u_spotLightInnerAngleCos, spotCurrentAngleCos);
 
     lighting(normalVector, cameraDirection, vertexToSpotLightDirection, spotLightAttenuation);
 }
 
 #else
 
-uniform vec3 u_lightDirection;       // Light direction
+uniform vec3 u_lightDirection;                  // Light direction
 
 void applyLight()
 {

+ 18 - 11
gameplay/res/shaders/diffuse-specular.vsh

@@ -117,14 +117,13 @@ vec3 getNormal()
 
 #if defined(POINT_LIGHT)
 
-uniform mat4 u_worldViewMatrix;                     // Matrix to tranform a position to view space.
-uniform vec3 u_pointLightPosition;                  // Position
-uniform float u_pointLightRadius;                   // Radius 
-varying vec4 v_vertexToPointLightDirection;         // Light direction w.r.t current vertex.
+uniform mat4 u_worldViewMatrix;                         // Matrix to tranform a position to view space.
+uniform vec3 u_pointLightPosition;                      // Position
+uniform float u_pointLightRangeInverse;                 // Inverse of light range.
+varying vec4 v_vertexToPointLightDirection;             // Light direction w.r.t current vertex.
 
 void applyLight(vec4 position)
 {
-    // World space position.
     vec4 positionWorldViewSpace = u_worldViewMatrix * position;
     
     // Compute the light direction with light position and the vertex position.
@@ -134,7 +133,7 @@ void applyLight(vec4 position)
     vertexToPointLightDirection.xyz = lightDirection;
 
     // Attenuation
-    vertexToPointLightDirection.w = 1 - dot (lightDirection * u_pointLightRadius, lightDirection * u_pointLightRadius);
+    vertexToPointLightDirection.w = 1.0 - dot(lightDirection * u_pointLightRangeInverse, lightDirection * u_pointLightRangeInverse);
 
     // Output light direction.
     v_vertexToPointLightDirection =  vertexToPointLightDirection;
@@ -142,9 +141,11 @@ void applyLight(vec4 position)
 
 #elif defined(SPOT_LIGHT)
 
-uniform mat4 u_worldViewMatrix;                     // Matrix to tranform a position to view space.
-uniform vec3 u_spotLightPosition;                   // Position
-varying vec3 v_vertexToSpotLightDirection;          // Light direction w.r.t current vertex.
+uniform mat4 u_worldViewMatrix;                         // Matrix to tranform a position to view space.
+uniform vec3 u_spotLightPosition;                       // Position
+uniform float u_spotLightRangeInverse;                  // Inverse of light range.
+varying vec3 v_vertexToSpotLightDirection;              // Light direction w.r.t current vertex.
+varying float v_spotLightAttenuation;                   // Attenuation of spot light.
 
 void applyLight(vec4 position)
 {
@@ -152,7 +153,13 @@ void applyLight(vec4 position)
     vec4 positionWorldViewSpace = u_worldViewMatrix * position;
 
     // Compute the light direction with light position and the vertex position.
-    v_vertexToSpotLightDirection = u_spotLightPosition - positionWorldViewSpace.xyz;
+    vec3 lightDirection = u_spotLightPosition - positionWorldViewSpace.xyz;
+
+    // Attenuation
+    v_spotLightAttenuation = 1.0 - dot(lightDirection * u_spotLightRangeInverse, lightDirection * u_spotLightRangeInverse);
+
+    // Compute the light direction with light position and the vertex position.
+    v_vertexToSpotLightDirection = lightDirection;
 }
 
 #else
@@ -184,4 +191,4 @@ void main()
 
     // Pass on the texture coordinates to Fragment shader.
     v_texCoord = a_texCoord;
-}
+}

+ 19 - 17
gameplay/res/shaders/diffuse.fsh

@@ -1,18 +1,18 @@
 precision highp float;
 
 // Uniforms
-uniform vec3 u_lightColor;                  // Light color
-uniform vec3 u_ambientColor;                // Ambient color
-uniform sampler2D u_diffuseTexture;         // Diffuse texture.
+uniform vec3 u_lightColor;                      // Light color
+uniform vec3 u_ambientColor;                    // Ambient color
+uniform sampler2D u_diffuseTexture;             // Diffuse texture.
 
 // Inputs
-varying vec3 v_normalVector;                // NormalVector in view space.
-varying vec2 v_texCoord;                    // Texture coordinate (u, v).
+varying vec3 v_normalVector;                    // NormalVector in view space.
+varying vec2 v_texCoord;                        // Texture coordinate (u, v).
 
 // Global variables
-vec4 _baseColor;                            // Base color
-vec3 _ambientColor;                         // Ambient Color
-vec3 _diffuseColor;                         // Diffuse Color
+vec4 _baseColor;                                // Base color
+vec3 _ambientColor;                             // Ambient Color
+vec3 _diffuseColor;                             // Diffuse Color
 
 void lighting(vec3 normalVector, vec3 lightDirection, float attenuation)
 {
@@ -27,7 +27,7 @@ void lighting(vec3 normalVector, vec3 lightDirection, float attenuation)
 
 #if defined(POINT_LIGHT)
 
-varying vec4 v_vertexToPointLightDirection;  // Light direction w.r.t current vertex.
+varying vec4 v_vertexToPointLightDirection;     // Light direction w.r.t current vertex.
 
 void applyLight()
 {
@@ -43,10 +43,11 @@ void applyLight()
 
 #elif defined(SPOT_LIGHT)
 
-uniform vec3 u_spotLightDirection;          // Direction of the spot light.
-uniform float u_spotLightInnerAngleCos;     // The bright spot [0.0 - 1.0]
-uniform float u_spotLightOuterAngleCos;     // The soft outer part [0.0 - 1.0]
-varying vec3 v_vertexToSpotLightDirection;  // Light direction w.r.t current vertex.
+uniform vec3 u_spotLightDirection;              // Direction of the spot light.
+uniform float u_spotLightInnerAngleCos;         // The bright spot [0.0 - 1.0]
+uniform float u_spotLightOuterAngleCos;         // The soft outer part [0.0 - 1.0]
+varying vec3 v_vertexToSpotLightDirection;      // Light direction w.r.t current vertex.
+varying float v_spotLightAttenuation;           // Attenuation of spot light.
 
 float lerpstep( float lower, float upper, float s)
 {
@@ -65,19 +66,20 @@ void applyLight()
     // Calculate spot light effect.
     float spotCurrentAngleCos = max(0.0, dot(spotLightDirection, -vertexToSpotLightDirection));
 
-    // Intensity of spot depends on the part of the cone the light direction points to (inner or outer).
-    float spotLightAttenuation = lerpstep(u_spotLightOuterAngleCos, u_spotLightInnerAngleCos, spotCurrentAngleCos);
+    // Intensity of spot depends on the spot light attenuation and the 
+    // part of the cone vertexToSpotLightDirection points to (inner or outer).
+    float spotLightAttenuation = clamp(v_spotLightAttenuation, 0.0, 1.0);
+    spotLightAttenuation *= lerpstep(u_spotLightOuterAngleCos, u_spotLightInnerAngleCos, spotCurrentAngleCos);
 
     lighting(normalVector, vertexToSpotLightDirection, spotLightAttenuation);
 }
 
 #else
 
-uniform vec3 u_lightDirection;       // Light direction
+uniform vec3 u_lightDirection;                  // Light direction
 
 void applyLight()
 {
-    // Normalize the vectors.
     vec3 normalVector = normalize(v_normalVector);
     vec3 lightDirection = normalize(u_lightDirection);
 

+ 7 - 2
gameplay/res/shaders/diffuse.vsh

@@ -117,7 +117,7 @@ vec3 getNormal()
 
 uniform mat4 u_worldViewMatrix;                     // Matrix to tranform a position to view space.
 uniform vec3 u_pointLightPosition;                  // Position
-uniform float u_pointLightRadius;                   // Radius
+uniform float u_pointLightRange;                    // Inverse of light range.
 varying vec4 v_vertexToPointLightDirection;         // Light direction w.r.t current vertex.
 
 void applyLight(vec4 position)
@@ -132,7 +132,7 @@ void applyLight(vec4 position)
     vertexToPointLightDirection.xyz = lightDirection;
     
     // Attenuation
-    vertexToPointLightDirection.w = 1 - dot (lightDirection * u_pointLightRadius, lightDirection * u_pointLightRadius);
+    vertexToPointLightDirection.w = 1.0 - dot(lightDirection * u_pointLightRangeInverse, lightDirection * u_pointLightRangeInverse);
 
     // Output light direction.
     v_vertexToPointLightDirection =  vertexToPointLightDirection;
@@ -142,7 +142,9 @@ void applyLight(vec4 position)
 
 uniform mat4 u_worldViewMatrix;                     // Matrix to tranform a position to view space.
 uniform vec3 u_spotLightPosition;                   // Position
+uniform float u_spotLightRangeInverse;              // Inverse of light range.
 varying vec3 v_vertexToSpotLightDirection;          // Light direction w.r.t current vertex.
+varying float v_spotLightAttenuation;               // Attenuation of spot light.
 
 void applyLight(vec4 position)
 {
@@ -152,6 +154,9 @@ void applyLight(vec4 position)
     // Compute the light direction with light position and the vertex position.
     vec3 lightDirection = u_spotLightPosition - positionWorldViewSpace.xyz;
 
+    // Attenuation
+    v_spotLightAttenuation = 1.0 - dot(lightDirection * u_spotLightRangeInverse, lightDirection * u_spotLightRangeInverse);
+
     // Output light direction.
     v_vertexToSpotLightDirection = lightDirection;
 }

+ 138 - 28
gameplay/res/shaders/parallax-specular.fsh

@@ -1,28 +1,57 @@
 precision highp float;
 
 // Uniforms
-uniform vec3 u_lightColor;                      // RGB color of the light
-uniform vec3 u_ambientColor;                    // Ambient color
+uniform vec3 u_lightColor;                      // Light color.
+uniform vec3 u_ambientColor;                    // Ambient color.
 uniform float u_specularExponent;               // Specular exponent or shininess property.
-uniform float u_parallaxHeight;                 // Parallax height
-uniform sampler2D u_diffuseTexture;             // Diffuse texture
+uniform sampler2D u_diffuseTexture;             // Diffuse texture.
 uniform sampler2D u_bumpMapTexture;             // Height map texture
-uniform sampler2D u_normalMapTexture;           // Normal map texture    
+uniform sampler2D u_normalMapTexture;           // Normal map texture.
+uniform float u_parallaxHeight;                 // Parallax height
 
 // Inputs
-varying vec2 v_texCoord;                        // Texture coordinates (u,v)
-varying vec3 v_lightDirectionTangentSpace;      // Light direction in tangent space
-varying vec3 v_cameraDirectionTangentSpace;     // Camera direction in tangent space
+varying vec2 v_texCoord;                        // Texture Coordinate.
+varying vec3 v_cameraDirection;                 // Direction the camera is looking at in tangent space.
 
-void main()
+// Global variables
+vec4 _baseColor;                                // Base color
+vec3 _ambientColor;                             // Ambient Color
+vec3 _diffuseColor;                             // Diffuse Color
+vec3 _specularColor;                            // Specular color
+
+void lighting(vec3 normalVector, vec3 cameraDirection, vec3 lightDirection, float attenuation)
 {
-    // Normalize vectors.
-    vec3 lightDirection = normalize(v_lightDirectionTangentSpace);
-    vec3 cameraDirection = normalize(v_cameraDirectionTangentSpace);
+    // Ambient
+    _ambientColor = _baseColor.rgb * u_ambientColor;
+
+    // Diffuse
+    float diffuseIntensity = attenuation * max(0.0, dot(normalVector, lightDirection));
+    diffuseIntensity = max(0.0, diffuseIntensity);
+    _diffuseColor = u_lightColor * _baseColor.rgb * diffuseIntensity;
+
+    // Specular
+    vec3 halfVector = normalize(cameraDirection + lightDirection);
+    float specularIntensity = attenuation * max(0.0, pow(dot(normalVector, halfVector), u_specularExponent));
+    specularIntensity = max(0.0, specularIntensity);
+    _specularColor = u_lightColor * _baseColor.rgb * specularIntensity;
+}
+
+#if defined(POINT_LIGHT)
+
+varying vec3 v_vertexToPointLightDirection;     // Light direction w.r.t current vertex in tangent space.
+varying float v_pointLightAttenuation;          // Attenuation of point light.
+
+void applyLight()
+{
+    // Normalize the vectors.
+    vec3 cameraDirection = normalize(v_cameraDirection);
+    vec3 vertexToPointLightDirection = normalize(v_vertexToPointLightDirection);
     
+    float pointLightAttenuation = clamp(v_pointLightAttenuation, 0.0, 1.0);
+
     // Get the height in the bumpmap texture.
     float height = texture2D(u_bumpMapTexture, v_texCoord).r;
-    
+
     // Compute offset within the range (-parallax height to +parallax height).
     float offset = u_parallaxHeight * (2.0 * height - 1.0);
     vec2 parallaxTexCoord = v_texCoord + (cameraDirection.xy * offset);
@@ -31,26 +60,107 @@ void main()
     // Find out the mean height.
     height += texture2D(u_bumpMapTexture, parallaxTexCoord).r;
     offset = u_parallaxHeight * (height - 1.0);
-    parallaxTexCoord = v_texCoord + (cameraDirection.xy * offset);
-    
+    parallaxTexCoord = v_texCoord + ( cameraDirection.xy * offset);
+
+    // Fetch normals from the normal map with the modified texture coordinates.
+    vec3 normalVector = normalize(texture2D(u_normalMapTexture, parallaxTexCoord).xyz * 2.0 - 1.0);
+
     // Fetch diffuse color from texture.
-    vec4 diffuseColor = texture2D(u_diffuseTexture, parallaxTexCoord);
+    _baseColor = texture2D(u_diffuseTexture, parallaxTexCoord);
     
-    // Ambient
-    vec3 lightColor = u_ambientColor;
+    lighting(normalVector, cameraDirection, vertexToPointLightDirection, pointLightAttenuation);
+}
+
+#elif defined(SPOT_LIGHT)
+
+uniform float u_spotLightInnerAngleCos;         // The bright spot [0.0 - 1.0]
+uniform float u_spotLightOuterAngleCos;         // The soft outer part [0.0 - 1.0]
+varying vec3 v_spotLightDirection;              // Direction of spot light in tangent space.
+varying vec3 v_vertexToSpotLightDirection;      // Direction of the spot light w.r.t current vertex in tangent space.
+varying float v_spotLightAttenuation;           // Attenuation of spot light.
+
+float lerpstep( float lower, float upper, float s)
+{
+    return clamp( ( s - lower ) / ( upper - lower ), 0.0, 1.0 );
+}
+
+void applyLight()
+{
+    vec3 cameraDirection = normalize(v_cameraDirection);
+    vec3 spotLightDirection = normalize(v_spotLightDirection);
+    vec3 vertexToSpotLightDirection = normalize(v_vertexToSpotLightDirection);
+
+    // "-lightDirection" because light direction points in opposite direction to
+    // to spot direction.
+    // Calculate spot light effect.
+    float spotCurrentAngleCos = max(0.0, dot(spotLightDirection, -vertexToSpotLightDirection));
+    
+    // Intensity of spot depends on the spot light attenuation and the 
+    // part of the cone vertexToSpotLightDirection points to (inner or outer).
+    float spotLightAttenuation = clamp(v_spotLightAttenuation, 0.0, 1.0);
+    spotLightAttenuation *= lerpstep(u_spotLightOuterAngleCos, u_spotLightInnerAngleCos, spotCurrentAngleCos);
+
+    // Get the height in the bumpmap texture.
+    float height = texture2D(u_bumpMapTexture, v_texCoord).r;
+
+    // Compute offset within the range (-parallax height to +parallax height).
+    float offset = u_parallaxHeight * (2.0 * height - 1.0);
+    vec2 parallaxTexCoord = v_texCoord + (cameraDirection.xy * offset);
+
+    // Compute offset again with the new texture coordinates to get better precision.
+    // Find out the mean height.
+    height += texture2D(u_bumpMapTexture, parallaxTexCoord).r;
+    offset = u_parallaxHeight * (height - 1.0);
+    parallaxTexCoord = v_texCoord + ( cameraDirection.xy * offset);
 
-    // Diffuse
     // Fetch normals from the normal map with the modified texture coordinates.
     vec3 normalVector = normalize(texture2D(u_normalMapTexture, parallaxTexCoord).xyz * 2.0 - 1.0);
-    float diffuseIntensity = max(0.0, dot(normalVector, lightDirection));
-    lightColor += (u_lightColor * diffuseIntensity);
 
-    // Specular
-    vec3 halfVector = normalize(cameraDirection + lightDirection);
-    float specularIntensity = pow(max(0.0, dot(normalVector, halfVector)), u_specularExponent);
+    // Fetch diffuse color from texture.
+    _baseColor = texture2D(u_diffuseTexture, parallaxTexCoord);
+
+    lighting(normalVector, cameraDirection, vertexToSpotLightDirection, spotLightAttenuation);
+}
+
+#else
+
+varying vec3 v_lightDirection;                  // Direction of light in tangent space.
+
+void applyLight()
+{
+    // Normalize vectors.
+    vec3 cameraDirection = normalize(v_cameraDirection);
+    vec3 lightDirection = normalize(v_lightDirection);
+
+    // Get the height in the bumpmap texture.
+    float height = texture2D(u_bumpMapTexture, v_texCoord).r;
+
+    // Compute offset within the range (-parallax height to +parallax height).
+    float offset = u_parallaxHeight * (2.0 * height - 1.0);
+    vec2 parallaxTexCoord = v_texCoord + (cameraDirection.xy * offset);
+
+    // Compute offset again with the new texture coordinates to get better precision.
+    // Find out the mean height.
+    height += texture2D(u_bumpMapTexture, parallaxTexCoord).r;
+    offset = u_parallaxHeight * (height - 1.0);
+    parallaxTexCoord = v_texCoord + ( cameraDirection.xy * offset);
+
+    // Fetch normals from the normal map with the modified texture coordinates.
+    vec3 normalVector = normalize(texture2D(u_normalMapTexture, parallaxTexCoord).xyz * 2.0 - 1.0);
+
+    // Fetch diffuse color from texture.
+    _baseColor = texture2D(u_diffuseTexture, parallaxTexCoord);
+
+    lighting(normalVector, cameraDirection, -lightDirection, 1.0);
+}
+#endif
+
+void main()
+{
+    // Apply light
+    applyLight();
 
-    // Light the pixel.
-    gl_FragColor = diffuseColor;
-    gl_FragColor.rgb *= lightColor;
-    gl_FragColor.rgb += vec3(diffuseColor.rgb * specularIntensity);
+    // Light the pixel
+    gl_FragColor.a = _baseColor.a;
+    gl_FragColor.rgb = _ambientColor + _diffuseColor + _specularColor;
 }

+ 97 - 24
gameplay/res/shaders/parallax-specular.vsh

@@ -1,21 +1,97 @@
 // Uniforms
-uniform    vec3 u_lightDirection;                    // Direction of the light
-uniform mat4 u_worldViewProjectionMatrix;            // Matrix to transform a position to clip space.
-uniform mat4 u_inverseTransposeWorldViewMatrix;      // Matrix to transform a normal to view space.
-uniform mat4 u_worldMatrix;                          // Matrix to tranform a position to world space.
-uniform vec3 u_cameraPosition;                       // Position of the camera.
+uniform mat4 u_worldViewMatrix;                     // Matrix to transform a position to view space.
+uniform mat4 u_worldViewProjectionMatrix;           // Matrix to transform a position to clip space.
+uniform mat4 u_inverseTransposeWorldViewMatrix;     // Matrix to transform a normal to view space.
+uniform vec3 u_cameraPosition;                      // Position of the camera.
+
 
 // Inputs
-attribute vec4 a_position;                           // Vertex Position (x, y, z, w)
-attribute vec3 a_normal;                             // Vertex Normal (x, y, z)
-attribute vec2 a_texCoord;                           // Vertex Texture Coordinate (u, v)
-attribute vec3 a_tangent;                            // Vertex Tangent (x, y, z)
-attribute vec3 a_binormal;                           // Vertex Binormal (actually Bi-tangent) (x, y, z)
+attribute vec4 a_position;                          // Vertex Position (x, y, z, w)
+attribute vec3 a_normal;                            // Vertex Normal (x, y, z)
+attribute vec2 a_texCoord;                          // Vertex Texture Coordinate (u, v)
+attribute vec3 a_tangent;                           // Vertex Tangent (x, y, z)
+attribute vec3 a_binormal;                          // Vertex Binormal (actually Bi-tangent) (x, y, z)
 
 // Outputs
-varying vec2 v_texCoord;                             // Texture Coordinate (u,v)
-varying vec3 v_lightDirectionTangentSpace;           // Direction of the light in tangent space.
-varying vec3 v_cameraDirectionTangentSpace;          // Direction the camera is looking at in tangent space.
+varying vec2 v_texCoord;                            // Texture Coordinate (u,v)
+varying vec3 v_cameraDirection;                     // Direction the camera is looking at in tangent space.
+
+#if defined(POINT_LIGHT)
+
+uniform vec3 u_pointLightPosition;                  // Position
+uniform float u_pointLightRangeInverse;             // Inverse of light range 
+varying vec3 v_vertexToPointLightDirection;         // Direction of point light w.r.t current vertex in tangent space.
+varying float v_pointLightAttenuation;              // Attenuation of point light.
+
+void applyLight(mat3 tangentSpaceTransformMatrix)
+{
+    vec4 positionWorldViewSpace = u_worldViewMatrix * a_position;
+    
+    // Compute camera direction and transform it to tangent space.
+    v_cameraDirection = tangentSpaceTransformMatrix * (u_cameraPosition - positionWorldViewSpace.xyz);
+    
+    // Compute the light direction with light position and the vertex position.
+    vec3 lightDirection = u_pointLightPosition - positionWorldViewSpace.xyz;
+    
+    // Transform current light direction to tangent space.
+    vec3 vertexToPointLightDirection = tangentSpaceTransformMatrix * lightDirection;
+
+    // Attenuation
+    v_pointLightAttenuation = 1.0 - dot(lightDirection * u_pointLightRangeInverse, lightDirection * u_pointLightRangeInverse);
+
+    // Output light direction.
+    v_vertexToPointLightDirection =  vertexToPointLightDirection;
+}
+
+#elif defined(SPOT_LIGHT)
+
+uniform vec3 u_spotLightPosition;                   // Position
+uniform float u_spotLightRangeInverse;              // Inverse of light range.
+uniform vec3 u_spotLightDirection;                  // Direction
+varying vec3 v_spotLightDirection;                  // Direction of spot light in tangent space.
+varying vec3 v_vertexToSpotLightDirection;          // Direction of the spot light w.r.t current vertex in tangent space.
+varying float v_spotLightAttenuation;               // Attenuation of spot light.
+
+void applyLight(mat3 tangentSpaceTransformMatrix)
+{
+    vec4 positionWorldViewSpace = u_worldViewMatrix * a_position;
+    
+    // Compute camera direction and transform it to tangent space.
+    v_cameraDirection = tangentSpaceTransformMatrix * (u_cameraPosition - positionWorldViewSpace.xyz);
+
+    // Transform spot light direction to tangent space.
+    v_spotLightDirection = tangentSpaceTransformMatrix * u_spotLightDirection;
+
+    // Compute the light direction with light position and the vertex position.
+    vec3 lightDirection = u_spotLightPosition - positionWorldViewSpace.xyz;
+    
+    // Transform current light direction to tangent space.
+    lightDirection = tangentSpaceTransformMatrix * lightDirection;
+    
+    // Attenuation
+    v_spotLightAttenuation = 1.0 - dot(lightDirection * u_spotLightRangeInverse, lightDirection * u_spotLightRangeInverse);
+
+    // Output light direction.
+    v_vertexToSpotLightDirection = lightDirection;
+}
+
+#else
+
+uniform vec3 u_lightDirection;                      // Direction
+varying vec3 v_lightDirection;                      // Direction of light in tangent space.
+
+void applyLight(mat3 tangentSpaceTransformMatrix)
+{
+    vec4 positionWorldViewSpace = u_worldViewMatrix * a_position;
+    
+    // Compute camera direction and transform it to tangent space.
+    v_cameraDirection = tangentSpaceTransformMatrix * (u_cameraPosition - positionWorldViewSpace.xyz);
+    
+    // Transform light direction to tangent space.
+    v_lightDirection = tangentSpaceTransformMatrix * u_lightDirection;
+}
+
+#endif
 
 void main()
 {
@@ -24,19 +100,16 @@ void main()
 
     // Transform the normal, tangent and binormals to  view space.
     mat3 inverseTransposeWorldViewMatrix = mat3(u_inverseTransposeWorldViewMatrix);
-    vec3 tangentVector  = inverseTransposeWorldViewMatrix * a_tangent;
-    vec3 normalVector = inverseTransposeWorldViewMatrix * a_normal;
-    vec3 binormalVector = inverseTransposeWorldViewMatrix * a_binormal;
+    vec3 tangentVector  = normalize(inverseTransposeWorldViewMatrix * a_tangent);
+    vec3 normalVector = normalize(inverseTransposeWorldViewMatrix * a_normal);
+    vec3 binormalVector = normalize(inverseTransposeWorldViewMatrix * a_binormal);
 
     // Create a transform to convert a vector to tangent space.
-    mat3 tangentSpaceTransformMatrix = mat3(tangentVector, binormalVector, normalVector);
-
-    // Transform light direction to tangent space.
-    v_lightDirectionTangentSpace = tangentSpaceTransformMatrix * u_lightDirection;
-
-    // Compute camera direction and transform it to tangent space.
-    vec4 positionWorldSpace = u_worldMatrix * a_position;
-    v_cameraDirectionTangentSpace = tangentSpaceTransformMatrix * (u_cameraPosition - positionWorldSpace.xyz);
+    mat3 tangentSpaceTransformMatrix = mat3(tangentVector.x, binormalVector.x, normalVector.x,
+                                            tangentVector.y, binormalVector.y, normalVector.y,
+                                            tangentVector.z, binormalVector.z, normalVector.z);
+    // Apply light.
+    applyLight(tangentSpaceTransformMatrix);
 
     // Pass on the texture coordinates to Fragment shader.
     v_texCoord = a_texCoord;

+ 130 - 21
gameplay/res/shaders/parallax.fsh

@@ -1,27 +1,49 @@
 precision highp float;
 
 // Uniforms
-uniform vec3 u_lightColor;                      // RGB color of the light
-uniform vec3 u_ambientColor;                    // Ambient color
-uniform sampler2D u_diffuseTexture;             // Diffuse texture
+uniform vec3 u_lightColor;                      // Light color.
+uniform vec3 u_ambientColor;                    // Ambient color.
+uniform sampler2D u_diffuseTexture;             // Diffuse texture.
 uniform sampler2D u_bumpMapTexture;             // Height map texture
-uniform sampler2D u_normalMapTexture;           // Normal map texture    
+uniform sampler2D u_normalMapTexture;           // Normal map texture.
 uniform float u_parallaxHeight;                 // Parallax height
 
 // Inputs
-varying vec2 v_texCoord;                        // Texture coordinates (u,v)
-varying vec3 v_lightDirectionTangentSpace;      // Light direction in tangent space
-varying vec3 v_cameraDirectionTangentSpace;     // Camera direction in tangent space
+varying vec2 v_texCoord;                        // Texture Coordinate.
+varying vec3 v_cameraDirection;                 // Direction the camera is looking at in tangent space.
 
-void main()
+// Global variables
+vec4 _baseColor;                                // Base color
+vec3 _ambientColor;                             // Ambient Color
+vec3 _diffuseColor;                             // Diffuse Color
+
+void lighting(vec3 normalVector, vec3 lightDirection, float attenuation)
 {
-    // Normalize vectors.
-    vec3 lightDirection = normalize(v_lightDirectionTangentSpace);
-    vec3 cameraDirection = normalize(v_cameraDirectionTangentSpace);
+    // Ambient
+    _ambientColor = _baseColor.rgb * u_ambientColor;
+
+    // Diffuse
+    float diffuseIntensity = attenuation * max(0.0, dot(normalVector, lightDirection));
+    diffuseIntensity = max(0.0, diffuseIntensity);
+    _diffuseColor = u_lightColor * _baseColor.rgb * diffuseIntensity;
+}
+
+#if defined(POINT_LIGHT)
+
+varying vec3 v_vertexToPointLightDirection;     // Light direction w.r.t current vertex in tangent space.
+varying float v_pointLightAttenuation;          // Attenuation of point light.
+
+void applyLight()
+{
+    // Normalize the vectors.
+    vec3 cameraDirection = normalize(v_cameraDirection);
+    vec3 vertexToPointLightDirection = normalize(v_vertexToPointLightDirection);
     
+    float pointLightAttenuation = clamp(v_pointLightAttenuation, 0.0, 1.0);
+
     // Get the height in the bumpmap texture.
     float height = texture2D(u_bumpMapTexture, v_texCoord).r;
-    
+
     // Compute offset within the range (-parallax height to +parallax height).
     float offset = u_parallaxHeight * (2.0 * height - 1.0);
     vec2 parallaxTexCoord = v_texCoord + (cameraDirection.xy * offset);
@@ -31,19 +53,106 @@ void main()
     height += texture2D(u_bumpMapTexture, parallaxTexCoord).r;
     offset = u_parallaxHeight * (height - 1.0);
     parallaxTexCoord = v_texCoord + ( cameraDirection.xy * offset);
-    
+
+    // Fetch normals from the normal map with the modified texture coordinates.
+    vec3 normalVector = normalize(texture2D(u_normalMapTexture, parallaxTexCoord).xyz * 2.0 - 1.0);
+
     // Fetch diffuse color from texture.
-    gl_FragColor = texture2D(u_diffuseTexture, parallaxTexCoord);
+    _baseColor = texture2D(u_diffuseTexture, parallaxTexCoord);
     
-    // Ambient
-    vec3 lightColor = u_ambientColor;
+    lighting(normalVector, vertexToPointLightDirection, pointLightAttenuation);
+}
+
+#elif defined(SPOT_LIGHT)
+
+uniform float u_spotLightInnerAngleCos;         // The bright spot [0.0 - 1.0]
+uniform float u_spotLightOuterAngleCos;         // The soft outer part [0.0 - 1.0]
+varying vec3 v_spotLightDirection;              // Direction of spot light in tangent space.
+varying vec3 v_vertexToSpotLightDirection;      // Direction of the spot light w.r.t current vertex in tangent space.
+varying float v_spotLightAttenuation;           // Attenuation of spot light.
+
+float lerpstep( float lower, float upper, float s)
+{
+    return clamp( ( s - lower ) / ( upper - lower ), 0.0, 1.0 );
+}
+
+void applyLight()
+{
+    vec3 cameraDirection = normalize(v_cameraDirection);
+    vec3 spotLightDirection = normalize(v_spotLightDirection);
+    vec3 vertexToSpotLightDirection = normalize(v_vertexToSpotLightDirection);
+
+    // "-lightDirection" because light direction points in opposite direction to
+    // to spot direction.
+    // Calculate spot light effect.
+    float spotCurrentAngleCos = max(0.0, dot(spotLightDirection, -vertexToSpotLightDirection));
+    
+    // Intensity of spot depends on the spot light attenuation and the 
+    // part of the cone vertexToSpotLightDirection points to (inner or outer).
+    float spotLightAttenuation = clamp(v_spotLightAttenuation, 0.0, 1.0);
+    spotLightAttenuation *= lerpstep(u_spotLightOuterAngleCos, u_spotLightInnerAngleCos, spotCurrentAngleCos);
+
+    // Get the height in the bumpmap texture.
+    float height = texture2D(u_bumpMapTexture, v_texCoord).r;
+
+    // Compute offset within the range (-parallax height to +parallax height).
+    float offset = u_parallaxHeight * (2.0 * height - 1.0);
+    vec2 parallaxTexCoord = v_texCoord + (cameraDirection.xy * offset);
+
+    // Compute offset again with the new texture coordinates to get better precision.
+    // Find out the mean height.
+    height += texture2D(u_bumpMapTexture, parallaxTexCoord).r;
+    offset = u_parallaxHeight * (height - 1.0);
+    parallaxTexCoord = v_texCoord + ( cameraDirection.xy * offset);
 
-    // Diffuse
     // Fetch normals from the normal map with the modified texture coordinates.
     vec3 normalVector = normalize(texture2D(u_normalMapTexture, parallaxTexCoord).xyz * 2.0 - 1.0);
-    float diffuseIntensity = max(0.0, dot(normalVector, lightDirection));
-    lightColor += (u_lightColor * diffuseIntensity);
 
-    // Light the pixel.
-    gl_FragColor.rgb *= lightColor;
+    // Fetch diffuse color from texture.
+    _baseColor = texture2D(u_diffuseTexture, parallaxTexCoord);
+
+    lighting(normalVector, vertexToSpotLightDirection, spotLightAttenuation);
 }
+
+#else
+
+varying vec3 v_lightDirection;                      // Direction of light in tangent space.
+
+void applyLight()
+{
+    // Normalize vectors.
+    vec3 cameraDirection = normalize(v_cameraDirection);
+    vec3 lightDirection = normalize(v_lightDirection);
+
+    // Get the height in the bumpmap texture.
+    float height = texture2D(u_bumpMapTexture, v_texCoord).r;
+
+    // Compute offset within the range (-parallax height to +parallax height).
+    float offset = u_parallaxHeight * (2.0 * height - 1.0);
+    vec2 parallaxTexCoord = v_texCoord + (cameraDirection.xy * offset);
+
+    // Compute offset again with the new texture coordinates to get better precision.
+    // Find out the mean height.
+    height += texture2D(u_bumpMapTexture, parallaxTexCoord).r;
+    offset = u_parallaxHeight * (height - 1.0);
+    parallaxTexCoord = v_texCoord + ( cameraDirection.xy * offset);
+
+    // Fetch normals from the normal map with the modified texture coordinates.
+    vec3 normalVector = normalize(texture2D(u_normalMapTexture, parallaxTexCoord).xyz * 2.0 - 1.0);
+
+    // Fetch diffuse color from texture.
+    _baseColor = texture2D(u_diffuseTexture, parallaxTexCoord);
+
+    lighting(normalVector, -lightDirection, 1.0);
+}
+#endif
+
+void main()
+{
+    // Apply light
+    applyLight();
+
+    // Light the pixel
+    gl_FragColor.a = _baseColor.a;
+    gl_FragColor.rgb = _ambientColor + _diffuseColor;
+}

+ 95 - 22
gameplay/res/shaders/parallax.vsh

@@ -1,21 +1,97 @@
 // Uniforms
-uniform    vec3 u_lightDirection;                    // Direction of the light
-uniform mat4 u_worldViewProjectionMatrix;            // Matrix to transform a position to clip space.
-uniform mat4 u_inverseTransposeWorldViewMatrix;      // Matrix to transform a normal to view space.
-uniform mat4 u_worldMatrix;                          // Matrix to tranform a position to world space.
-uniform vec3 u_cameraPosition;                       // Position of the camera.
+uniform mat4 u_worldViewMatrix;                     // Matrix to transform a position to view space.
+uniform mat4 u_worldViewProjectionMatrix;           // Matrix to transform a position to clip space.
+uniform mat4 u_inverseTransposeWorldViewMatrix;     // Matrix to transform a normal to view space.
+uniform vec3 u_cameraPosition;                      // Position of the camera.
+
 
 // Inputs
-attribute vec4 a_position;                           // Vertex Position (x, y, z, w)
-attribute vec3 a_normal;                             // Vertex Normal (x, y, z)
-attribute vec2 a_texCoord;                           // Vertex Texture Coordinate (u, v)
-attribute vec3 a_tangent;                            // Vertex Tangent (x, y, z)
-attribute vec3 a_binormal;                           // Vertex Binormal (actually Bi-tangent) (x, y, z)
+attribute vec4 a_position;                          // Vertex Position (x, y, z, w)
+attribute vec3 a_normal;                            // Vertex Normal (x, y, z)
+attribute vec2 a_texCoord;                          // Vertex Texture Coordinate (u, v)
+attribute vec3 a_tangent;                           // Vertex Tangent (x, y, z)
+attribute vec3 a_binormal;                          // Vertex Binormal (actually Bi-tangent) (x, y, z)
 
 // Outputs
-varying vec2 v_texCoord;                             // Texture Coordinate (u,v)
-varying vec3 v_lightDirectionTangentSpace;           // Direction of the light in tangent space.
-varying vec3 v_cameraDirectionTangentSpace;          // Direction the camera is looking at in tangent space.
+varying vec2 v_texCoord;                            // Texture Coordinate (u,v)
+varying vec3 v_cameraDirection;                     // Direction the camera is looking at in tangent space.
+
+#if defined(POINT_LIGHT)
+
+uniform vec3 u_pointLightPosition;                  // Position
+uniform float u_pointLightRangeInverse;             // Inverse of light range 
+varying vec3 v_vertexToPointLightDirection;         // Direction of point light w.r.t current vertex in tangent space.
+varying float v_pointLightAttenuation;              // Attenuation of point light.
+
+void applyLight(mat3 tangentSpaceTransformMatrix)
+{
+    vec4 positionWorldViewSpace = u_worldViewMatrix * a_position;
+    
+    // Compute camera direction and transform it to tangent space.
+    v_cameraDirection = tangentSpaceTransformMatrix * (u_cameraPosition - positionWorldViewSpace.xyz);
+    
+    // Compute the light direction with light position and the vertex position.
+    vec3 lightDirection = u_pointLightPosition - positionWorldViewSpace.xyz;
+    
+    // Transform current light direction to tangent space.
+    vec3 vertexToPointLightDirection = tangentSpaceTransformMatrix * lightDirection;
+
+    // Attenuation
+    v_pointLightAttenuation = 1.0 - dot(lightDirection * u_pointLightRangeInverse, lightDirection * u_pointLightRangeInverse);
+
+    // Output light direction.
+    v_vertexToPointLightDirection =  vertexToPointLightDirection;
+}
+
+#elif defined(SPOT_LIGHT)
+
+uniform vec3 u_spotLightPosition;                   // Position
+uniform float u_spotLightRangeInverse;              // Inverse of light range.
+uniform vec3 u_spotLightDirection;                  // Direction
+varying vec3 v_spotLightDirection;                  // Direction of spot light in tangent space.
+varying vec3 v_vertexToSpotLightDirection;          // Direction of the spot light w.r.t current vertex in tangent space.
+varying float v_spotLightAttenuation;               // Attenuation of spot light.
+
+void applyLight(mat3 tangentSpaceTransformMatrix)
+{
+    vec4 positionWorldViewSpace = u_worldViewMatrix * a_position;
+    
+    // Compute camera direction and transform it to tangent space.
+    v_cameraDirection = tangentSpaceTransformMatrix * (u_cameraPosition - positionWorldViewSpace.xyz);
+
+    // Transform spot light direction to tangent space.
+    v_spotLightDirection = tangentSpaceTransformMatrix * u_spotLightDirection;
+
+    // Compute the light direction with light position and the vertex position.
+    vec3 lightDirection = u_spotLightPosition - positionWorldViewSpace.xyz;
+    
+    // Transform current light direction to tangent space.
+    lightDirection = tangentSpaceTransformMatrix * lightDirection;
+    
+    // Attenuation
+    v_spotLightAttenuation = 1.0 - dot(lightDirection * u_spotLightRangeInverse, lightDirection * u_spotLightRangeInverse);
+
+    // Output light direction.
+    v_vertexToSpotLightDirection = lightDirection;
+}
+
+#else
+
+uniform vec3 u_lightDirection;                      // Direction
+varying vec3 v_lightDirection;                      // Direction of light in tangent space.
+
+void applyLight(mat3 tangentSpaceTransformMatrix)
+{
+    vec4 positionWorldViewSpace = u_worldViewMatrix * a_position;
+    
+    // Compute camera direction and transform it to tangent space.
+    v_cameraDirection = tangentSpaceTransformMatrix * (u_cameraPosition - positionWorldViewSpace.xyz);
+    
+    // Transform light direction to tangent space.
+    v_lightDirection = tangentSpaceTransformMatrix * u_lightDirection;
+}
+
+#endif
 
 void main()
 {
@@ -24,19 +100,16 @@ void main()
 
     // Transform the normal, tangent and binormals to  view space.
     mat3 inverseTransposeWorldViewMatrix = mat3(u_inverseTransposeWorldViewMatrix);
-    vec3 tangentVector  = inverseTransposeWorldViewMatrix * a_tangent;
+    vec3 tangentVector  = normalize(inverseTransposeWorldViewMatrix * a_tangent);
     vec3 normalVector = inverseTransposeWorldViewMatrix * a_normal;
     vec3 binormalVector = inverseTransposeWorldViewMatrix * a_binormal;
 
     // Create a transform to convert a vector to tangent space.
-    mat3 tangentSpaceTransformMatrix = mat3(tangentVector, binormalVector, normalVector);
-
-    // Transform light direction to tangent space.
-    v_lightDirectionTangentSpace = tangentSpaceTransformMatrix * u_lightDirection;
-
-    // Compute camera direction and transform it to tangent space.
-    vec4 positionWorldSpace = u_worldMatrix * a_position;
-    v_cameraDirectionTangentSpace = tangentSpaceTransformMatrix * (u_cameraPosition - positionWorldSpace.xyz);
+    mat3 tangentSpaceTransformMatrix = mat3(tangentVector.x, binormalVector.x, normalVector.x,
+                                            tangentVector.y, binormalVector.y, normalVector.y,
+                                            tangentVector.z, binormalVector.z, normalVector.z);
+    // Apply light.
+    applyLight(tangentSpaceTransformMatrix);
 
     // Pass on the texture coordinates to Fragment shader.
     v_texCoord = a_texCoord;

+ 20 - 0
gameplay/src/Light.cpp

@@ -142,12 +142,30 @@ void Light::setRange(float range)
     {
     case POINT:
         _point->range = range;
+        _point->rangeInverse = 1.0f / range;
         break;
     case SPOT:
         _spot->range = range;
+        _spot->rangeInverse = 1.0f / range;
         break;
     }
 }
+
+float Light::getRangeInverse() const
+{
+    assert(_type != DIRECTIONAL);
+
+    switch (_type)
+    {
+    case POINT:
+        return _point->rangeInverse;
+    case SPOT:
+        return _spot->rangeInverse;
+    default:
+        assert(0);
+        return 0.0f;
+    }
+}
     
 float Light::getInnerAngle()  const
 {
@@ -201,11 +219,13 @@ Light::Directional::Directional(const Vector3& color)
 Light::Point::Point(const Vector3& color, float range)
     : color(color), range(range)
 {
+    rangeInverse = 1.0f / range;
 }
 
 Light::Spot::Spot(const Vector3& color, float range, float innerAngle, float outerAngle)
     : color(color), range(range), innerAngle(innerAngle), outerAngle(outerAngle)
 {
+    rangeInverse = 1.0f / range;
     innerAngleCos = cos(innerAngle);
     outerAngleCos = cos(outerAngle);
 }

+ 9 - 0
gameplay/src/Light.h

@@ -112,6 +112,13 @@ public:
      */
     void setRange(float range);
 
+    /**
+     * Returns the inverse of the range of point or spot light.
+     *
+     * @return The range of the point or spot light.
+     */
+    float getRangeInverse() const;
+
     /**
      * Returns the inner angle the spot light (in radians).
      *
@@ -176,6 +183,7 @@ private:
     public:
         Vector3 color;
         float range;
+        float rangeInverse;
 
         Point(const Vector3& color, float range);
     };
@@ -188,6 +196,7 @@ private:
     public:
         Vector3 color;
         float range;
+        float rangeInverse;
         float innerAngle;
         float innerAngleCos;
         float outerAngle;

+ 10 - 1
gameplay/src/Texture.cpp

@@ -197,7 +197,16 @@ Texture* Texture::create(Format format, unsigned int width, unsigned int height,
     GLuint textureId;
     GL_ASSERT( glGenTextures(1, &textureId) );
     GL_ASSERT( glBindTexture(GL_TEXTURE_2D, textureId) );
-    GL_ASSERT( glTexImage2D(GL_TEXTURE_2D, 0, (GLenum)format, width, height, 0, (GLenum)format, GL_UNSIGNED_BYTE, data) );
+
+    if (format == DEPTH)
+    {
+        // <type> must be UNSIGNED_SHORT or UNSIGNED_INT for a format of DEPTH_COMPONENT.
+        GL_ASSERT( glTexImage2D(GL_TEXTURE_2D, 0, (GLenum)format, width, height, 0, (GLenum)format, GL_UNSIGNED_INT, data) );
+    }
+    else
+    {
+        GL_ASSERT( glTexImage2D(GL_TEXTURE_2D, 0, (GLenum)format, width, height, 0, (GLenum)format, GL_UNSIGNED_BYTE, data) );
+    }
 
     // Set initial minification filter based on whether or not mipmaping was enabled
     GL_ASSERT( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, generateMipmaps ? GL_NEAREST_MIPMAP_LINEAR : GL_LINEAR) );