Opengl着色器问题 - 奇怪的光反射伪影

时间:2013-03-13 12:33:10

标签: iphone ios opengl-es 3d glsl

我已经和他搏斗了好几天。我想我最终将它缩小到每顶点切线的问题,但我不确定解决它的最佳方法。

Context是iPhone app,opengl es2使用我自己的引擎。我的着色器是使用提供的每个顶点切线创建TBN矩阵的凹凸贴图(法线贴图)。顶点着色器将光矢量和眼睛矢量转换为切线空间,将它们传递给片段着色器并计算光源。但是我前两个测试模型中的一些几何体在照明中显示出奇怪的瑕疵。在镜面反射分量中最容易看到。

在尝试调试时,我用普通平面png替换了法线贴图..所有像素都是128,128,255。我也对颜色进行了硬编码。

我的第一个模特是按钮形状。它将人工制品显示为外圈上的扇形镜面撞击。需要注意的重要一点是,这里的UV映射方法是“平坦的”,以使垂直于映射的边基本上划过纹理。我认为这会使切线很难计算出几何形状,因为其中两个点的纹理坐标完全相同。

我尝试调试渲染器将gl_FragColor设置为不同的变量。当将它设置为每个顶点法线时,我们看到扇形消失,表明法线是正确的。但是当将它设置为每个顶点切线时,您可以看到扇贝。

enter image description here

下一个形状是一个简单的球体。有了它,模型的顶部和底部就是工件显示的位置。在线框中,您将看到这是几个三角形在一个顶点相交的地方。我无法绕过切线的意义,因为每个三角形都有完全不同的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

重要的是要注意,这些奇怪的灯不会发生在顶点上,而只会发生在它们之间。即使在球体上,我们也会看到一个位于顶部顶点和正顶部之间的环。我开始相信这是一个插值问题。在那里只取一个三角形:

enter image description here

为了第二个原因而忽略了糟糕的比特,我正在重新计算。但是切线具有相反的极性。因此,当在这两种状态之间进行插值时,您将获得指向所有位置的向量。

新问题是我该如何解决?修剪切线?修复着色器处理它?<​​/ p>

1 个答案:

答案 0 :(得分:1)

有时最简单的答案是正确答案。切线很糟糕。它们与正常情况不正交。

我使用此处描述的方法手动重新计算所有切线和bitangents:

http://www.terathon.com/code/tangent.html

这个问题消失了。