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

标签 iphone ios opengl-es 3d glsl

我已经为此纠结了好几天。我想我终于将它缩小到每个顶点切线的问题,但我不确定解决它的最佳方法。

上下文是 iPhone 应用程序,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;

片段着色器:
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:我刚刚发现this other question听起来可能是真正问题的线索。 3d graphics, unit vectors and orthogonal matrices

需要注意的是,这些奇怪的光不会发生在顶点上,而只会发生在它们之间。即使在球体上,我们也能看到顶部顶点和其正下方顶点之间的环。我开始相信这是一个插值问题。仅取其中一个三角形:

enter image description here

第二个原因忽略坏的bitangent,我正在重新计算它。但是切线具有相反的极性。因此,在这两个状态之间进行插值时,您将获得指向所有地方的向量。

新问题是我该如何解决?修复切线?修复着色器来处理它?

最佳答案

有时,最简单的答案就是正确的答案。切线很糟糕。它们与法线不正交。

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

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

那个问题就消失了。

关于iphone - Opengl 着色器问题 - 奇怪的光反射伪影,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15385474/

相关文章:

ios - OpenGLES 无法在 iOS 的顶点着色器中使用输入参数

iphone - 是提供新的艺术作品更好还是缩小大图像来处理 Retina 显示屏更好?

iphone - 我的应用中的HTTPS是否认为 “Encryption”

javascript - 将 'Core Data' 与 Phonegap 一起使用?

ios - 在调试 iOs lldb 时动态创建图像

ios - 如何使用 Firebase 分发 iOS 应用程序?

javascript - Three.js 中的球形冒名顶替者

opengl-es - 在 OpenGLES 着色器中使用 LUT 进行假着色

iphone - 如何在同一层继承两个类?

ios - Xcode UI 测试登录用户重定向到主屏幕