I have a problem with my shaders. I implemented a phong lightning. In the shader vertices get transformed by position, rotation and scale.
The problems is that when the scale is not (1, 1, 1) I get wrong results (displaced lighting). It's really noticeable for example with scale (100, 20, 100). I see this bug when I was testing with spotlight, so directional light and point light can also be wrong.
I think it's scale+normals problem, but I can't find it. Normal Matrix has scale in accound? How can I deal with this problem? If someone can help me I will be really apreciated. Any other advice not related to this problem it will be wellcome.
If it will help I can upload some images.
(SpotFallOff its usless, I use SpotInnerCutOff and SpotOuterCutOff)
Sorry for my bad English.
Here is my Shader:
<Shader>
<ShaderPart type="Vertex">
<ShaderCode>
<![CDATA[
#version 420
uniform mat4 ModelViewMatrix;
uniform mat4 MVP;
uniform mat3 NormalMatrix;
in vec3 in_Position;
in vec3 in_Normal;
in vec3 in_Tangent;
in vec3 in_Bitangent;
in vec2 in_TexCoord;
out mat3 TBN;
out vec2 pTexCoord;
out vec3 pViewDir;
out vec3 pPosition;
out vec3 pVertexPos;
void main(void)
{
pTexCoord = in_TexCoord;
vec3 n = normalize(NormalMatrix * in_Normal);
vec3 t = normalize(NormalMatrix * in_Tangent);
vec3 b = -normalize( cross(n, t) );
TBN = mat3(
t.x, b.x, n.x,
t.y, b.y, n.y,
t.z, b.z, n.z );
pPosition = vec3( ModelViewMatrix * vec4(in_Position, 1.0) );
pViewDir = TBN * vec3(-pPosition);
pVertexPos = in_Position;
gl_Position = MVP * vec4(in_Position, 1.0);
}
]]>
</ShaderCode>
</ShaderPart>
<ShaderPart type="Fragment" >
<ShaderCode>
<![CDATA[
#version 420
uniform sampler2D Texture0; // Diffuse
uniform sampler2D Texture1; // Normal
uniform sampler2D Texture2; // Specular
uniform float SpecularPower;
uniform struct
{
vec3 ambient;
vec3 diffuse;
vec3 specular;
float constantAtt;
float linearAtt;
float quadraticAtt;
float spotInnerCutOff;
float spotOuterCutOff;
float spotFallOff;
vec3 position;
vec3 direction; // For Spot and Directional lights
int type; // 0-> Point, 1-> Spot, 2-> Directional
}
Lights[16];
uniform int NumLights;
in mat3 TBN;
in vec2 pTexCoord;
in vec3 pViewDir;
in vec3 pPosition;
in vec3 pVertexPos;
out vec4 fragColor;
vec4 computePhongPointLight(in int index)
{
vec3 color = vec3(0.0);
vec4 difColor = texture2D( Texture0, pTexCoord );
vec3 normColor = normalize(texture2D( Texture1, pTexCoord ).xyz * 2.0 - 1.0);
vec3 specColor = texture2D( Texture2, pTexCoord ).rgb;
vec3 lightDir = TBN * (Lights[index].position.xyz - pPosition);
// Normalized lightDir
vec3 lightDirNorm = normalize( lightDir );
vec3 r = reflect( -lightDirNorm, normColor );
float sDotN = max( dot(lightDirNorm, normColor), 0.0 );
// Compute att for point and spot lights. Directional lights has att = 1.0
float att = 1.0;
float distSqr = dot(lightDir, lightDir);
float invAtt = (Lights[index].constantAtt + (Lights[index].linearAtt*sqrt(distSqr)) + (Lights[index].quadraticAtt*distSqr));
att = 0.0;
if (invAtt != 0.0)
att = 1.0/invAtt;
vec3 diffuse = difColor.rgb * Lights[index].diffuse * sDotN;
vec3 ambient = difColor.rgb * Lights[index].ambient; // Cheat here
// Specular power
vec3 specular = vec3(0.0);
if ( sDotN > 0.0 )
{
specular = Lights[index].specular.rgb * specColor * pow( max( dot(r, normalize(pViewDir)), 0.0), SpecularPower );
}
color = (diffuse + specular + ambient)*att;
return vec4(color, difColor.a);
}
vec4 computePhongSpotLight(in int index)
{
vec3 color = vec3(0.0);
vec4 difColor = texture( Texture0, pTexCoord );
vec3 normColor = normalize(texture( Texture1, pTexCoord ).xyz * 2.0 - 1.0);
vec3 specColor = texture( Texture2, pTexCoord ).rgb;
vec3 lightDir = TBN * (Lights[index].position.xyz - pPosition);
// Normalized lightDir
vec3 lightDirNorm = normalize( lightDir );
vec3 r = reflect( -lightDirNorm, normColor );
float sDotN = max( dot(lightDirNorm, normColor), 0.0 );
// Compute att for point and spot lights. Directional lights has att = 1.0
float att = 1.0;
float distSqr = dot(lightDir, lightDir);
float invAtt = (Lights[index].constantAtt + (Lights[index].linearAtt*sqrt(distSqr)) + (Lights[index].quadraticAtt*distSqr));
att = 0.0;
if (invAtt != 0.0)
att = 1.0/invAtt;
// Compute spot
float cos_cur_angle = dot(-lightDirNorm, normalize(TBN * Lights[index].direction));
float cos_inner_cone_angle = cos(Lights[index].spotInnerCutOff);
float cos_outer_cone_angle = cos(Lights[index].spotOuterCutOff);
float cos_inner_minus_outer_angle = cos_inner_cone_angle - cos_outer_cone_angle;
float spot = clamp((cos_cur_angle - cos_outer_cone_angle) / cos_inner_minus_outer_angle, 0.0, 1.0);
vec3 diffuse = difColor.xyz * Lights[index].diffuse * sDotN;
vec3 ambient = difColor.rgb * Lights[index].ambient; // Cheat here
// Specular power
vec3 specular = vec3(0.0);
if ( sDotN > 0.0 )
{
specular = Lights[index].specular.rgb * specColor * pow( max( dot(r, normalize(pViewDir)), 0.0), SpecularPower );
}
color = (diffuse + specular + ambient)*att*spot;
return vec4(color, difColor.a);
}
vec4 computePhongDirectionalLight(in int index)
{
vec3 color = vec3(0.0);
vec4 difColor = texture( Texture0, pTexCoord );
vec3 normColor = normalize(texture( Texture1, pTexCoord ).xyz * 2.0 - 1.0);
vec3 specColor = texture( Texture2, pTexCoord ).rgb;
vec3 lightDir = TBN * Lights[index].direction;
// Normalized lightDir
vec3 lightDirNorm = normalize( lightDir );
vec3 r = reflect( -lightDirNorm, normColor );
float sDotN = max( dot(lightDirNorm, normColor), 0.0 );
vec3 diffuse = difColor.rgb * Lights[index].diffuse * sDotN;
vec3 ambient = difColor.rgb * Lights[index].ambient; // Cheat here
// Specular power
vec3 specular = vec3(0.0);
if ( sDotN > 0.0 )
{
specular = Lights[index].specular.rgb * specColor * pow( max( dot(r, normalize(pViewDir)), 0.0), SpecularPower );
}
color = diffuse + specular + ambient;
return vec4(color, difColor.a);
}
vec4 computeLight(in int index)
{
if (Lights[index].type == 0)
return computePhongPointLight(index);
if (Lights[index].type == 1)
return computePhongSpotLight(index);
else if (Lights[index].type == 2)
return computePhongDirectionalLight(index);
}
void main(void)
{
fragColor = vec4(0.0, 0.0, 0.0, 1.0);
for (int i = 0; i < NumLights; i++)
fragColor += computeLight(i);
if (fragColor.a < 0.5)
discard;
}
]]>
</ShaderCode>
</ShaderPart>
</Shader>






