我已经和他搏斗了好几天。我想我最终将它缩小到每顶点切线的问题,但我不确定解决它的最佳方法。
Context是iPhone app,opengl es2使用我自己的引擎。我的着色器是使用提供的每个顶点切线创建TBN矩阵的凹凸贴图(法线贴图)。顶点着色器将光矢量和眼睛矢量转换为切线空间,将它们传递给片段着色器并计算光源。但是我前两个测试模型中的一些几何体在照明中显示出奇怪的瑕疵。在镜面反射分量中最容易看到。
在尝试调试时,我用普通平面png替换了法线贴图..所有像素都是128,128,255。我也对颜色进行了硬编码。
我的第一个模特是按钮形状。它将人工制品显示为外圈上的扇形镜面撞击。需要注意的重要一点是,这里的UV映射方法是“平坦的”,以使垂直于映射的边基本上划过纹理。我认为这会使切线很难计算出几何形状,因为其中两个点的纹理坐标完全相同。
我尝试调试渲染器将gl_FragColor设置为不同的变量。当将它设置为每个顶点法线时,我们看到扇形消失,表明法线是正确的。但是当将它设置为每个顶点切线时,您可以看到扇贝。
下一个形状是一个简单的球体。有了它,模型的顶部和底部就是工件显示的位置。在线框中,您将看到这是几个三角形在一个顶点相交的地方。我无法绕过切线的意义,因为每个三角形都有完全不同的UV贴图。
如果我不显示着色器代码,我想我会得到很多瑕疵......
顶点着色器:
v_fragmentTexCoord0 = a_vertexTexCoord0;
gl_Position = u_modelViewProjectionMatrix * vec4(a_vertexPosition,1.0);
vec3 normal = normalize(u_normalMatrix * a_vertexNormal);
vec3 tangent = normalize(u_normalMatrix * a_vertexTangent);
vec3 bitangent = cross(normal, tangent);
mat3 TBNMatrix = mat3(tangent, bitangent, normal);
v_eyeVec = -a_vertexPosition.xyz;
v_eyeVec *= TBNMatrix;
v_lightVec = u_lightPosition - a_vertexPosition.xyz;
v_lightVec *= TBNMatrix;
v_normal = a_vertexTangent;
Fragment Shader:
vec3 norm = texture2D(u_normalSampler, v_fragmentTexCoord0).rgb * 2.0 - 1.0;
vec4 baseColor = vec4(0.6015625,0.0,0.0,1.0); // is normally texture2D(u_textureSampler,v_fragmentTexCoord0);
float dist = length(v_lightVec);
vec3 lightVector = normalize(v_lightVec);
float nxDir = max(0.0, dot(norm, lightVector));
vec4 diffuse = u_lightColorDiffuse * nxDir;
float specularPower = 0.0;
if(nxDir != 0.0)
{
vec3 cameraVector = v_eyeVec;
vec3 halfVector = normalize(v_lightVec + cameraVector);
float nxHalf = max(0.0,dot(norm, halfVector));
specularPower = pow(nxHalf, u_shininess);
}
vec4 specular = u_lightColorSpecular * specularPower;
gl_FragColor = (diffuse * vec4(baseColor.rgb,1.0)) + specular;
在试图找出着色器并在线查看所有样本和教程时,我发现......我很惊讶为什么凹凸贴图着色器不会干扰3d模型提供的法线贴图。我想如果没有某种参考点你怎么知道如何修改模型的正常?按什么方向?我猜这就是TBN矩阵的用途。但在上面的测试中,法线贴图中的法线向量是0,0,1 - 直线向上。所以似乎根本不应该修改它。任何时候1仍然是1.但是在数学或TBN矩阵中必须有一些搞砸的东西,它不会出现与3d模型中的法线相同的法线。然后这个想法与我发生了一些关系......在我的顶点着色器中,我也首先将顶点法线乘以normalMatrix,以使其进入模型空间。但话说回来,这些调试渲染在转换之前是顶点法线。
是否有其他方法可以在不使用TBN矩阵的情况下扰乱模型的法线?使用没有法线贴图的phong着色器进行渲染不会显示伪影。
更新:我几乎肯定问题是导入应用创建的预先切线。在尝试使用不同UV贴图的不同模型后,我发现了类似的外观问题,有时它是黑暗而不是高光。因此,除非我可以应用没有TBM矩阵或转换为切线空间的法线贴图,否则我需要找到另一个导入器。
更新#2:我刚刚发现了另一个问题,听起来这可能是真正问题的线索。 3d graphics, unit vectors and orthogonal matrices
重要的是要注意,这些奇怪的灯不会发生在顶点上,而只会发生在它们之间。即使在球体上,我们也会看到一个位于顶部顶点和正顶部之间的环。我开始相信这是一个插值问题。在那里只取一个三角形:
为了第二个原因而忽略了糟糕的比特,我正在重新计算。但是切线具有相反的极性。因此,当在这两种状态之间进行插值时,您将获得指向所有位置的向量。
新问题是我该如何解决?修剪切线?修复着色器处理它?</ p>
答案 0 :(得分:1)
有时最简单的答案是正确答案。切线很糟糕。它们与正常情况不正交。
我使用此处描述的方法手动重新计算所有切线和bitangents:
http://www.terathon.com/code/tangent.html
这个问题消失了。