我一直在为此摔跤数日。我想我已经把它缩小到每个顶点切线的问题了,但我不确定解决这个问题的最佳方法。Opengl着色器问题 - 怪异的光线反射文物
上下文是iPhone应用程序,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;
片段着色器:
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
重要的是要注意,这些奇怪的灯光不会发生在顶点,而只发生在它们之间。即使在球体上,我们也看到一个位于顶部顶点和它下面的顶点之间的环。我开始相信这是一个插值问题。就拿只是那些三角形在那里的一个:
忽略了第二个原因,我重新计算,坏二重。但切线具有相反的极性。所以,当在这两个状态之间进行插值时,你会得到指向所有位置的向量。
新的问题是我该如何解决它?修正切线?修复着色器来处理它?
为什么不将正常矢量和切线矢量(LERP'd)传递给片段着色器,并在那里处理TBN变换?如果法线在每个顶点都有所不同,则可以通过每片段计算得到更平滑的结果。 – 2013-03-13 12:59:05
我想我担心它会太慢。当它具有纹理贴图和凹凸贴图时,它看起来非常好,而且你不会注意到它。如果它能解决我的问题。 – badweasel 2013-03-13 13:41:39
对于着色器来说没有多大意义,特别是与'pow'函数类似的配置文件相比。正如你所说,这可能不是问题的根源。 – 2013-03-13 13:55:13