我已经按照许多在线教程进行了法线贴图,并且在一定程度上使其能够正常工作...
除非多边形与视图向量垂直,否则我似乎无法使其正常工作。
我创建了一个视频来说明这一点,因为图片不足以显示我的意思。
http://www.youtube.com/watch?v=9D4o_zy-61s
我已经发布了我的着色器:
顶点:
#version 400
layout (location = 0) in vec3 attribPosition;
layout (location = 1) in vec3 attribNormal;
layout (location = 2) in vec2 attribTexCoord;
layout (location = 3) in vec3 attribTangent;
layout (location = 3) in vec3 attribBinormal;
uniform mat4 mvp;
uniform mat4 mvm;
uniform mat3 nm;
uniform vec3 lightPos_World;
out vec2 vUvs;
out vec3 lightPos_Eye;
out vec3 vertexPos_Eye;
out vec3 normalDir_Eye;
out vec3 normalDir_World;
out mat3 tbnMatrix;
void main()
{
vUvs = attribTexCoord;
normalDir_World = attribNormal;
normalDir_Eye = (nm * attribNormal);
vec3 t = nm * attribTangent;
vec3 n = nm * attribNormal;
vec3 b = nm * cross(n,t);
mat3 tbnMatrix = mat3(t.x, b.x, n.x,
t.y, b.y, n.y,
t.z, b.z, n.z);
vertexPos_Eye = (mvm * vec4(attribPosition,1.0)).xyz;
lightPos_Eye = (mvm * vec4(lightPos_World,1.0)).xyz;
gl_Position = mvp * vec4(attribPosition,1.0);
}
分段:
#version 400
layout( location = 0 ) out vec4 frag_main;
struct PointLight{
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
float shininess;
float intensity;
};
uniform PointLight light[2];
uniform sampler2D colorTexture;
uniform sampler2D normalTexture;
uniform mat4 mvm;
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// FLAGS - all flags start false;
// [0][0] = colour map
// [0][1] = normal map
// [0][2] = unused
// [0][3] = show normal map in colour channel
// [1][0] = use tangent space
// [1][1] = unused
// [1][2] = unused
// [1][3] = unused
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
uniform bvec4 flags[2];
in vec3 vertexPos_Eye;
in vec3 normalDir_World;
in vec3 normalDir_Eye;
in vec2 vUvs;
in mat3 tbnMatrix;
void main(){
uint numLights=2;
vec3 colorFragment;
if(flags[0][0]){
colorFragment = texture(colorTexture,vUvs).xyz;
}else{
colorFragment = vec3(0.5);
}
vec3 normalMapNormal = (texture(normalTexture,vUvs).rgb * 2) - 1;
vec3 normalDir;
if(flags[0][1]){
normalDir = normalize(normalDir_Eye);
}else{
normalDir = normalize(normalMapNormal.rgb);
}
vec4 outColor = vec4(1);
outColor.xyz = vec3(0);
float duller = 1/numLights;
for(int i = 0;i< numLights;i++){
vec3 lightPos_Eye = (mvm * vec4(light[i].position,1.0)).xyz;
vec3 lightDir_Eye = normalize(lightPos_Eye - vertexPos_Eye);
vec3 lightDir_Tangent = lightDir_Eye * tbnMatrix;
vec3 vertDir_Eye = normalize(-vertexPos_Eye);
vec3 vertDir_Tangent = vertDir_Eye * tbnMatrix;
vec3 halfDir_Eye = normalize(vertDir_Eye + lightDir_Eye);
vec3 halfDir_Tangent = halfDir_Eye * tbnMatrix;
vec3 Ia = colorFragment.xyz * light[i].ambient;
vec3 Id;
vec3 Is;
// tangent space
Id = (colorFragment.xyz * light[i].diffuse ) * max(dot(lightDir_Tangent, normalDir), 0);
Is = light[i].specular * pow(max(dot(halfDir_Eye, normalDir), 0), light[i].shininess*2);
// eye space
//Id = (colorFragment.xyz * light[i].diffuse ) * max(dot(lightDir_Eye, normalDir), 0);
//Is = light[i].specular * pow(max(dot(halfDir_Eye, normalDir), 0), light[i].shininess*2);
outColor.xyz += (Ia + Id + Is);
}
if(flags[0][3]){
outColor.xyz = normalDir;
}
frag_main = (outColor);
}
最佳答案
我注意到这一行:
vec3 b = nm * cross(n,t);
但应该是:
vec3 b = cross(n,t);
由于
nm
和n
在所需的摄影机空间内,因此无需再次乘以t
。另一件事:
lightPos_Eye = (mvm * vec4(lightPos_World,1.0)).xyz;
由于
lightPos_World
位于世界空间中(顾名思义),因此应将其乘以* world_matrix *之类的内容,而不是乘以模型视图。或者只是在应用程序代码中计算lightPos_Eye
并将其发送到顶点着色器。管理所有这些不同的向量并将它们放在一个适当的空间中是非常困难的。有时,视觉错误非常微妙且难以发现。