GLSL normal mapping issue - c++

Below is listed the shader code for normal mapping. Nevertheless there is something wrong with the code since the resulting image is incorrect. The normals seem to be off. Other features seem to work fine so I believe the problem is with the shaders. Any ideas what could be wrong?
Vertex shader
#version 150
in vec3 position;
in vec2 texcoord;
in vec3 normal;
in vec3 tangent;
in vec3 bitangent;
out vec2 Texcoord;
out vec3 VertexPos_World;
out vec3 LightDir_Tan;
uniform vec3 lightPos0_World;
uniform mat4 model;
uniform mat4 view;
uniform mat4 proj;
void main()
{
gl_Position = proj * view * model * vec4(position, 1.0);
Texcoord = texcoord;
VertexPos_World = (model * vec4(position, 1.0)).xyz;
vec3 normal_Cam = (view * model * vec4(normal, 1.0)).xyz;
vec3 tangent_Cam = (view * model * vec4(tangent, 1.0)).xyz;
vec3 bitangent_Cam = (view * model * vec4(bitangent, 1.0)).xyz;
mat3 TBN = transpose(mat3(tangent_Cam, bitangent_Cam, normal_Cam));
vec3 lightDir_Cam = lightPos_Cam - vertexPos_Cam;
LightDir_Tan = TBN * lightDir_Cam;
}
Fragment Shader
#version 150
in vec2 Texcoord;
in vec3 VertexPos_World;
in vec3 LightDir_Tan;
out vec4 outColor;
uniform vec3 lightPos0_World;
uniform vec3 lightColor0;
uniform float lightPower0;
uniform vec3 ambientColor;
uniform vec3 diffuseColor;
uniform sampler2D tex0;
uniform sampler2D tex0normal;
void main()
{
float lightDistance = length(lightPos0_World - VertexPos_World);
vec3 materialDiffuseColor = texture(tex0, Texcoord).xyz * diffuseColor;
vec3 materialAmbientColor = ambientColor * materialDiffuseColor;
vec3 n = normalize(texture(tex0normal, Texcoord).rgb * 2.0 - 1.0);
vec3 l = normalize(LightDir_Tan);
float diff = clamp(dot(n,l), 0, 1);
outColor.rgb =
materialAmbientColor +
materialDiffuseColor * lightColor0 * lightPower0 * diff / (lightDistance * lightDistance);
}

This might not be the only issue, but in your shader you have:
vec3 normal_Cam = (view * model * vec4(normal, 1.0)).xyz;
vec3 tangent_Cam = (view * model * vec4(tangent, 1.0)).xyz;
vec3 bitangent_Cam = (view * model * vec4(bitangent, 1.0)).xyz;
This should be:
vec3 normal_Cam = (view * model * vec4(normal, 0.0)).xyz;
vec3 tangent_Cam = (view * model * vec4(tangent, 0.0)).xyz;
vec3 bitangent_Cam = (view * model * vec4(bitangent, 0.0)).xyz;
Using 0.0 instead of 1.0 because these are direction vectors, not positions, so you want to ignore the translations in the matrices.
Also, you should multiply those matrices in your application and use a uniform view_model in your shader (otherwise you do this work per-vertex instead of per-model).

Your normals are most likely very off. Make sure that instead of submitting a cube with 8 vertices, you submit a cube with 4 vertices per face so that you can send the correct normals per face. Otherwise, the interpolator will simply use the normals from indexed neighbour triangles and that is what causes that issue.

Related

GLSL having strange black faces with the second mesh

platform: Windows10
context: OpenGL, glew, Win32
So I loaded 2 meshes(using a simple OBJ parser, which only reads the triangulated mesh), with vertexpos,uv and normal data. The first mesh is lighted okay. No black faces.The second one looks like this.
The Strange Effects
my vertex shader:
#version 440
in vec3 pos;
in vec2 tex;
in vec3 nor;
uniform float Scale;
uniform mat4 perspective;
uniform mat4 model;
out vec3 normaldir;
out vec2 texOut;
out vec3 FragPos;
void main()
{
normaldir = normalize(mat3(transpose(inverse(model))) * nor);
gl_Position = perspective * model * vec4(pos.xyz, 1.0);
texOut = tex;
FragPos = vec3(model * vec4(pos, 1.0));
}
my fragment shader:
#version 440
uniform float Scale;
uniform sampler2D diffuse;
uniform sampler2D normal;
uniform vec3 viewPos;
//uniform sampler2D normalMap0;
in vec3 normaldir;
in vec2 texOut;
in vec3 FragPos;
layout(location = 0) out vec4 FragColor0;
void main()
{
vec3 lightPos = {2,6,0};
lightPos.x = sin(Scale)*5;
lightPos.z = cos(Scale)*5;
vec3 lightDir = normalize(lightPos - FragPos);
vec3 lightColor = {1.0,1.0,1.0};
float specularStrength = 1.6;
float diff = max(dot(normaldir, lightDir), 0.0);
vec3 diffuseD = diff * lightColor;
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, normaldir);
vec3 ambient = {0.0,0.2,0.4};
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 25);
vec3 specular = specularStrength * spec * lightColor;
vec3 diffuseCol = texture(diffuse, texOut).xyz;
vec3 result = (ambient + diffuseD+ specular) * diffuseCol;
FragColor0 = vec4(result, 1.0);
}
Sorry I made a very dumb mistake. Thank you for all your support #Rabbid76 (Yes I did inverted the normals yes) #paddy
The problem was Binding the normal buffers. I bind glm::vec2 * size instead of glm::vec3 * size for normals' buffers

WebGL: adding specular light without the help of THREE.JS

I'm making some first steps in webgl programming. Created a simple setup following this tutorial. Managed to add a few things of my own, though stumbled with adding light, particularly - specular light.
As I assume, most of it would be implemented in my fragment shader, and maybe some additions in the vertex shader and the Light module. So that's the code I provide below.
Vertex shader:
attribute vec3 position;
attribute vec3 normal;
attribute vec2 uv;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
varying vec3 vNormal;
varying vec2 vUv;
void main() {
vUv = uv;
vNormal = (model * vec4(normal, 0.)).xyz;
gl_Position = projection * view * model * vec4(position, 1.);
}
Fragment shader:
#ifdef GL_ES
precision highp float;
#endif
uniform vec3 lightDirection;
uniform float ambientLight;
uniform sampler2D diffuse;
varying vec3 vNormal;
varying vec2 vUv;
void main() {
float lightness = -clamp(dot(normalize(vNormal), normalize(lightDirection)), -1., 0.);
lightness = ambientLight + (1. - ambientLight) * lightness;
gl_FragColor = vec4(texture2D(diffuse, vUv).rgb * lightness, 1.);
}
Light.js module:
function Light () {
this.lightDirection = new Vector3(-1, -1, -1)
this.ambientLight = 0.3
}
Light.prototype.use = function (shaderProgram) {
var dir = this.lightDirection
var gl = shaderProgram.gl
gl.uniform3f(shaderProgram.lightDirection, dir.x, dir.y, dir.z)
gl.uniform1f(shaderProgram.ambientLight, this.ambientLight)
}
I would really appreciate your suggestions here. Thanks in advance!
The most common and simplest light models are the Phong reflection model or the Blinn–Phong model model.
The following shader code, is based on your original code and implements the Blinn–Phong model model. In compare to your code, the light calculations are done in view space, because the specular highlight depends on the view position, which is (0, 0, 0) in view space. So the light direction has to be transformed to view space.
Vertex shader:
attribute vec3 position;
attribute vec3 normal;
attribute vec2 uv;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform vec3 lightDirection;
varying vec3 vPos;
varying vec3 vNormal;
varying vec2 vUv;
varying vec3 lightDirectionView;
void main()
{
lightDirectionView = (view * vec4(lightDirection, 0.)).xyz;
mat4 modelView = view * model;
vec4 viewPos = modelView * vec4(position, 1.0)
vPos = viewPos.xyz;
vUv = uv;
vNormal = (modelView * vec4(normal, 0.)).xyz;
gl_Position = projection * viewPos;
}
Fragemnt shader:
#ifdef GL_ES
precision highp float;
#endif
uniform float shininess;
uniform float ambientLight;
uniform sampler2D diffuse;
varying vec3 vPos;
varying vec3 vNormal;
varying vec2 vUv;
varying vec3 lightDirectionView;
void main()
{
vec3 color = texture2D(diffuse, vUv).rgb;
vec3 N = normalize( vNormal );
vec3 L = normalize( -lightDirectionView );
vec3 V = normalize( -vPos );
vec3 H = normalize( V + L );
float NdotL = dot(N, L);
float NdotH = dot(N, H);
float kDiffuse = max(0.0, NdotL);
// float kSpecular = (shininess + 2.0) * pow(max(0.0, NdotH), shininess) / (2.0 * 3.14159265);
float kSpecular = pow(max(0.0, NdotH), shininess);
vec3 light_col = color * (kDiffuse + kSpecular);
gl_FragColor = vec4(light_col, 1.0);
}
The value of the uniform shininess has to be a positive value in range [1, 100].
See also Phong and Gouraud Shading WebGL.

Modern GLSL ( opengl 3+ ) : Implementing phong effect correctly;

I am implementing a basic phong lighting GLSL shader; I have looked up some things on the internet, and found that the phong effect was created by adding an ambient, diffuse, and specular layer on the object (see image below, from tom dalling's site); problem is I have seen a lot of examples, and none of them really suits my GLSL set-up. Can any of you give me a code example of the correct way to implement the phong effect which would fit my GLSL set-up ? :
PS : This question could be put on hold because of the fact that it may be based on user opinion : In my mind, it is not, because I would like to know the most effective, and better way of implementing it.
Here is my vertex shader :
#version 120
uniform mat4 modelView;
uniform mat4 MVP;
uniform float time;
attribute vec3 position;
attribute vec2 texCoord;
attribute vec3 normal;
varying vec3 position0;
varying vec2 texCoord0;
varying vec3 normal0;
varying mat4 modelView0;
void main()
{
//Updating varyings...
position0 = position;
texCoord0 = texCoord;
normal0 = (MVP * vec4(normal, 0.0)).xyz;
modelView0 = modelView;
//set position
gl_Position = MVP * vec4(position, 1.0);
}
and my fragment shader :
#version 120
varying vec3 position0;
varying vec2 texCoord0;
varying vec3 normal0;
varying mat4 modelView0;
uniform sampler2D diffuse;
void main()
{
vec4 surfaceColor = texture2D(diffuse, texCoord0);
gl_FragColor = (texture2D(diffuse, texCoord0))
* clamp(dot(-vec3(0.0, 0.5, 0.5), normal0), 0, 1.0);
}
try this:
void main()
{
vec4 texread = texture2D(diffuse, texCoord0);
vec3 normal = normalize(normal0);
vec3 material_kd = vec3(1.0,1.0,1.0);
vec3 material_ks = vec3(1.0,1.0,1.0);
vec3 material_ka = vec3(0.2,0.2,0.2);
vec3 material_ke = vec3(0.0,0.0,0.0);
float material_shininess = 60;
vec3 lightpos = vec3(0.0,10.0,5.0);
vec3 lightcolor = vec3(1.0,1.0,1.0);
vec3 lightdir = normalize(lightpos - worldPosition);
float shade = clamp(dot(lightdir, normal), 0.0, 1.0);
vec3 toWorldpos = normalize((worldPosition) - u_eyePos);
vec3 reflectDir = reflect( toWorldpos, normal );
vec4 specular = vec4(pow(clamp(dot(lightdir, reflectDir),0.0,1.0), material_shininess) * lightcolor * material_ks, 1.0);
vec4 shaded = texread * vec4(material_kd, 1.0) * vec4(lightcolor , 1.0) * shade;
vec4 ambient = texread * vec4(material_ka, 1.0);
vec4 emission = vec4(material_ke, 1.0);
gl_FragColor = shaded + specular + emission + ambient;
}
it may have some compilation errors though as i didnt run it...
you may need to upload your eye position as a uniform (u_eyePos), and calculate the worldposition (worldPosition) for it to work
I made my own sphong shader : here is the code :
fragment shader :
#version 150
uniform mat4 modelView;
uniform mat3 normalMatrix;
uniform vec3 cameraPosition;
uniform sampler2D materialTex;
uniform float materialShininess;
uniform vec3 materialSpecularColor;
uniform vec3 lightPosition;//light settings
uniform vec3 lightIntensities;
uniform float lightAttenuation;
uniform float lightAmbientCoeff;
in vec3 position0;
in vec2 texCoord0;
in vec3 normal0;
out vec4 fragmentColor;
void main()
{
//calculate normal in world coordinates
vec3 normal = normalize(normalMatrix * normal0);
//calculate the location of this fragment (pixel) in world coordinates
vec3 surfacePos = vec3(modelView * vec4(position0, 1));
//color of the current fragment
vec4 surfaceColor = texture(materialTex, texCoord0);
//calculate the vector from this pixels surface to the light source
vec3 surfaceToLight = normalize(lightPosition - surfacePos);
//cam distance
vec3 surfaceToCamera = normalize(cameraPosition - surfacePos);
///////////////////////////DIFUSE///////////////////////////////////////
//calculate the cosine of the angle of incidence
//float diffuseCoeff = dot(normal, surfaceToLight) / (length(surfaceToLight) * length(normal));
float diffuseCoeff = max(0.0, dot(normal, surfaceToLight));
vec3 diffuse = diffuseCoeff * surfaceColor.rgb * lightIntensities;
/////////////////////////AMBIENT////////////////////////////////////////
vec3 ambient = lightAmbientCoeff * surfaceColor.rgb * lightIntensities;
/////////////////////////SPECULAR//////////////////////////////////////
float specularCoeff = 0.0;
if(diffuseCoeff > 0.0)
specularCoeff = pow(max(0.0, dot(surfaceToCamera, reflect(-surfaceToLight, normal))), materialShininess);
vec3 specular = specularCoeff * materialSpecularColor * lightIntensities;
////////////////////////ATTENUATION///////////////////////////////////
float distanceToLight = length(lightPosition - surfacePos);
float attenuation = 1.0 / (1.0 + lightAttenuation * pow(distanceToLight, 2));
/////////////////////////////////FINAL/////////////////////////////////
vec3 linearColor = ambient + attenuation * (diffuse + specular);
//finalColor with gamma correction
vec3 gamma = vec3(1.0/2.2);
fragmentColor = vec4(pow(linearColor, gamma), surfaceColor.a);
//fragmentColor = vec4(diffuseCoeff * lightIntensities * surfaceColor.rgb, surfaceColor.a);
}

GLSL normal mapping flickering

I was trying to add a normal map effect to a shader tutorial I have found here but with no luck.
UPDATE 1:
I updated the code adding a tangent space matrix
Vertex shader:
#version 330
in vec3 inPosition;
in vec3 vertNormal;
in vec2 vertTexCoord;
in vec4 vertNormalMapping;
out vec3 fragVert;
out vec3 fragNormal;
out vec2 fragTexCoord;
out vec4 fragNormalMapping;
out mat3 TBNMatrix;
uniform mat4 modelViewProjectionMatrix;
uniform mat4 camera;
void main(){
vec3 tangent;
vec3 binormal;
vec3 c1 = cross( vertNormal, vec3(0.0, 0.0, 1.0) );
vec3 c2 = cross( vertNormal, vec3(0.0, 1.0, 0.0) );
if( length(c1)>length(c2) )
{
tangent = c1;
}
else
{
tangent = c2;
}
tangent = normalize(tangent);
binormal = cross(vertNormal, tangent);
binormal = normalize(binormal);
mat3 normalMatrix = transpose(inverse(mat3(camera * modelViewProjectionMatrix )));
vec3 n = normalize(normalMatrix * vertNormal);
vec3 t = normalize(normalMatrix * tangent.xyz);
vec3 b = normalize(normalMatrix * binormal.xyz);
TBNMatrix = mat3(t, b, n);
fragTexCoord = vertTexCoord;
fragNormal = vertNormal;
fragVert = inPosition;
fragNormalMapping = vertNormalMapping;
gl_Position = camera * modelViewProjectionMatrix * vec4(inPosition, 1.0);
}
Fragment shader
#version 330
precision highp float;
uniform vec3 cameraPosition;
uniform mat4 modelViewProjectionMatrix;
uniform mat4 camera;
uniform sampler2D tex;
uniform sampler2D heightMap;
uniform float materialShininess;
uniform vec3 materialSpecularColor;
uniform struct Light {
vec3 position;
vec3 intensities; //a.k.a the color of the light
float attenuation;
float ambientCoefficient;
} light;
in vec3 fragNormal;
in vec3 fragVert;
in vec2 fragTexCoord;
in vec4 fragNormalMapping;
in mat3 TBNMatrix;
out vec4 finalColor;
void main() {
vec3 surfacePos = vec3(modelViewProjectionMatrix * vec4(fragVert, 1));
vec4 surfaceColor = texture(tex, fragTexCoord);
vec3 surfaceToLight = TBNMatrix * (light.position - surfacePos) ;
vec3 surfaceToCamera = TBNMatrix * (cameraPosition - surfacePos);
vec3 normal = normalize(texture(heightMap, fragTexCoord).xyz * 2.0 - 1.0);
//ambient
vec3 ambient = light.ambientCoefficient * surfaceColor.rgb * light.intensities;
//diffuse
float diffuseCoefficient = max(0.0, dot(normal, surfaceToLight));
vec3 diffuse = diffuseCoefficient * surfaceColor.rgb * light.intensities;
//specular
float specularCoefficient = 0.0;
if(diffuseCoefficient > 0.0)
specularCoefficient = pow(max(0.0, dot(surfaceToCamera, reflect(-surfaceToLight, normal))), materialShininess);
vec3 specular = specularCoefficient * materialSpecularColor * light.intensities;
//attenuation
float distanceToLight = length(light.position - surfacePos);
float attenuation = 1.0 / (1.0 + light.attenuation * pow(distanceToLight, 2));
//linear color (color before gamma correction)
vec3 linearColor = ambient + attenuation*(diffuse + specular);
//final color (after gamma correction)
vec3 gamma = vec3(1.0/2.2);
finalColor = vec4(pow(linearColor, gamma), surfaceColor.a);
}
The result is better but now the lighting is calculated wrong O.O
//OLD
I have tried with a blank color texture and a correct normal map texture and the result is this: The normal map is calculated correctly but... these lines are not so cool to see :-(
Any idea of what is the cause? thank you everyone for the help =D
posting here for clarity...
mv = camera * transform;//modelview
mvp = proj * camera * transform;//modelviewprojection
mvi = transpose(inverse(mv))//modelview inverse (=gl_NormalMatrix)
so you should have in place of modelViewProjectionMatrix passed to the shader the modelView and the projection separately, and compute the resulting mvp in the vertex shader.
(or precompute them all on cpu side)

GLSL Shader Producing Unwanted Results

I cannot get the following shader to work.
Vertex Shader
#version 430
in vec4 vPosition;
in vec4 vColor;
in vec2 vTexCoord;
in vec3 vNormal;
in vec3 vTangent;
in vec3 vBitangent;
//out vec4 color;
out vec2 texCoord;
uniform mat4 Model;
uniform mat4 View;
uniform mat4 Projection;
out vec3 LightDirection_cameraspace;
out vec3 Position_worldspace;
uniform vec3 LightPosition;
out vec3 EyeDirection_cameraspace;
out vec3 LightDirection_tangentspace;
out vec3 EyeDirection_tangentspace;
void main()
{
gl_Position = Projection * View * Model * vPosition;
Position_worldspace = (Model * vPosition).xyz;
vec3 vertexPosition_cameraspace = (View * Model * vPosition).xyz;
EyeDirection_cameraspace = vec3(0, 0, 0) - vertexPosition_cameraspace;
vec3 LightPosition_cameraspace = (View * vec4(LightPosition, 1)).xyz;
LightDirection_cameraspace = LightPosition_cameraspace + EyeDirection_cameraspace;
texCoord = vTexCoord;
mat4 ModelView = View * Model;
mat3 MV3x3 = mat3(ModelView);
vec3 vertexTangent_cameraspace = MV3x3 * vTangent;
vec3 vertexBitangent_cameraspace = MV3x3 * vBitangent;
vec3 vertexNormal_cameraspace = MV3x3 * vNormal;
mat3 TBN = transpose(mat3(
vertexTangent_cameraspace,
vertexBitangent_cameraspace,
vertexNormal_cameraspace
));
LightDirection_tangentspace = TBN * LightDirection_cameraspace;
EyeDirection_tangentspace = TBN * EyeDirection_cameraspace;
}
Fragment Shader
#version 430
in vec4 vColor;
in vec2 texCoord;
out vec4 fColor;
uniform sampler2D tex;
in vec3 Position_worldspace;
in vec3 EyeDirection_cameraspace;
uniform vec3 LightPosition;
//uniform sampler2D DiffuseTex; pretty much just tex
uniform sampler2D NormalTex;
uniform sampler2D SpecularTex;
in vec3 LightDirection_tangentspace;
in vec3 EyeDirection_tangentspace;
void main()
{
vec3 LightColor = vec3(1, 1, 1);
float LightPower = 50.0f;
//vec3 MaterialDiffuseColor = texture2D(tex, texCoord).rgb; // EDITABLE VALU 3 LINE
//vec3 MaterialAmbientColor = vec3(0.1, 0.1, 0.1) * MaterialDiffuseColor;
//vec3 MaterialSpecularColor = texture2D(SpecularTex, texCoord).rgb * 0.3;
vec3 MaterialDiffuseColor = vec3(0.5, 0.5, 0.5);
vec3 MaterialAmbientColor = vec3(0.1, 0.1, 0.1);
vec3 MaterialSpecularColor = vec3(1, 1, 1);
vec3 TextureNormal_tangentspace = normalize(texture2D(NormalTex, vec2(texCoord.x, texCoord.y)).rgb * 2.0 - 1.0); // EDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDIT this line if upside down
float distance = length(LightPosition - Position_worldspace);
vec3 n = TextureNormal_tangentspace;
vec3 l = normalize(LightDirection_tangentspace);
float cosTheta = clamp(dot(n, l), 0, 1);
vec3 E = normalize(EyeDirection_tangentspace);
vec3 R = reflect(-l, n);
float cosAlpha = clamp(dot(E, R), 0, 1);
fColor = vec4(MaterialAmbientColor + MaterialDiffuseColor * LightColor * LightPower * cosTheta / (distance*distance) + MaterialSpecularColor * LightColor * LightPower * pow(cosAlpha,5) / (distance*distance), 1.0);
}
Here's an imgur album with photos including the diffuse, specular, and normal maps as well as the image the program produces. http://imgur.com/a/8MMU1
P.S. The shader DOES compile, it just does not produce the desired image.
Firstly, nice code! I've seen shaders far more difficult to read than that.
You can simplify the projection/view/model transformations so there are no duplicates...
vec4 worldPosition = Modle * vPosition;
vec4 cameraPosition = View * worldPosition;
vec4 clipPosition = Projection * cameraPosition;
gl_Position = clipPosition;
To transform the normal, you need a normal matrix (inverse transpose modelview), otherwise scales can mess things up.
It's pretty common to compute LightPosition_cameraspace outside the shader, since it doesn't change. You also don't need Position_worldspace as distance can be computed in camera/eye space. View * Model is pretty expensive, and can be computed once and passed in. Now that View isn't needed, you can simply replace both View and Model with the single ModelView matrix.
The binormal can be computed implicitly from the normal and tangent via a cross product. This saves a fair bit of storage and memory bandwidth. If your normal/tangent are not perpendicular it may be necessary to use two cross products to ensure all three are orthonormal.
The main problem seems to be in your last line...
fColor = vec4(
MaterialAmbientColor
+ (
MaterialDiffuseColor * LightColor * LightPower * cosTheta
/ (distance*distance)
)
+ (
MaterialSpecularColor * LightColor * LightPower * pow(cosAlpha,5)
/ (distance*distance)
)
, 1.0);
LightPower is scaling your diffuse and specular components. Change to the following
float attenuation = 1.0/distance*distance; //just for readability
fColor = vec4(
MaterialAmbientColor
+ (
MaterialDiffuseColor * LightColor * cosTheta * attenuation
)
+ (
MaterialSpecularColor * LightColor * pow(cosAlpha, LightPower) * attenuation
)
, 1.0);
If after this you're still not seeing the right result, you'll have to start doing some debugging of each variable to narrow down the trouble maker. For example, as #user1118321 suggested check the colours aren't just black or something. Check your LightDirection_tangentspace with fColor = vec4(l,1) - you might look for (0,0,1)/blue for the parts that face the light directly. Make sure tangent/normals/light position are non-zero, the normal texture is bound etc (fColor = vec4(n,1)).