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

2024-01-31

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

上下文是 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 模型中相同的法线。然后这个想法引起了我的注意……在我的顶点着色器中,我首先将顶点法线乘以法线矩阵,以将其放入模型空间。但话又说回来,这些调试渲染是在转换之前的顶点法线。

是否有另一种方法可以在不使用 TBN 矩阵的情况下扰乱模型的法线?使用不带法线贴图的 phong 着色器进行渲染不会显示伪影。

UPDATE:我几乎可以肯定问题是由导入应用程序创建的预先计算的切线。在尝试使用不同 UV 贴图的不同模型后,我发现了类似的问题,有时是黑暗而不是高光。因此,除非我可以在没有 TBM 矩阵的情况下应用法线贴图或转换为切线空间,否则我需要找到另一个导入器。

更新#2:我刚刚发现另一个问题听起来可能是真正问题的线索。3D 图形、单位向量和正交矩阵 https://stackoverflow.com/questions/4553503/3d-graphics-unit-vectors-and-orthogonal-matrices

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

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

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


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

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

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

这个问题就消失了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Opengl 着色器问题 - 奇怪的光反射伪影 的相关文章

  • 如何开始复杂级别的跨平台移动应用开发? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • .showsPhysics 内存泄漏

    我最近花了 5 个小时尝试调试 Spritekit 应用程序中的内存泄漏 应用程序启动后 我注意到内存使用量略有上升 我花了 5 个小时中的 3 个小时挖掘参考资料 了解强与弱的关系ARC https developer apple com
  • 如何在iOS中处理1到3个手指的滑动手势

    我使用以下代码来处理代码中的 1 根手指滑动 UISwipeGestureRecognizer swipe UISwipeGestureRecognizer alloc initWithTarget self action selector
  • 错误域=kAFAssistantErrorDomain 代码=209“(空)”

    我面临着一个问题SFSpeechRecognizer 启动应用程序几秒钟后 我开始收到错误消息 错误域 kAFAssistantErrorDomain 代码 209 空 和 错误 域 kAFAssistantErrorDomain 代码 2
  • Objective-C UILabel 作为超链接

    我正在尝试做一个UILabel一个链接UIWebView 我怎样才能做一个UILabel作为超链接 您可以使用 UITapGestureRecognizer 它将实现与您想要的类似的功能 UILabel myLabel UILabel al
  • 将图像保存在相机胶卷中并获取资源 URL

    对于我正在开发的应用程序 我使用 UIImagePickerController 拍摄照片并将其存储在相机胶卷中 void imagePickerController UIImagePickerController picker didFi
  • 从一个模态视图无缝翻转到另一个模态视图,而不显示纯色背景

    我的 iPad 应用程序的 UI 如下 当我点击Settings按钮 我希望对话框水平翻转以显示设置对话框 我这个工作正常 但是 当对话翻转时会显示背景颜色 如你看到的 有什么办法可以让对话框翻转时不显示该颜色块吗 我希望它看起来更加无缝
  • ios swift parse:从 3 个类收集数据

    我有这样的结构 User CardSet 带有指向 User objectId 的指针 user 和 col name 带有点 cards 的卡片到 Card Set objectId 和列 name 我想选择所有卡数据 包括当前用户的卡集
  • iOS:生成pdf时绘制文本时如何设置字体?

    我在ios应用程序中使用drawpdf函数生成pdf 同时调用nsobject类中的drawtext函数 它根据我指定的框架和字符串清楚地绘制文本 我的代码是 void drawText NSString textToDraw inFram
  • iPhone - UIImage imageWithData 返回 nil

    我需要从字节数组创建 UIImage 现在我创建了字节数组 image CGImageCreateWithImageInRect aux CGImage imageRect context CGBitmapContextCreate dat
  • 会话重新启动后 AVcapture 会话启动缓慢

    我有一个主视图控制器 它连接到具有 avcapturesession 的第二个视图控制器 我第一次从主视图控制器转向捕获会话控制器 大约需要 50 毫秒 使用 仪器 检查 然后我从捕获会话返回到主视图控制器 然后从主控制器返回到 avcap
  • UITableViewCell显示多种字体

    我想在 uitableviewcell 中以类似于 iPhone 地址簿的不同字体显示两个单词 例如 约翰Buchanan 您应该使用两个 UILable 或者您可以使用OH属性标签 https github com AliSoftware
  • 在 UIWebView 中播放 Facebook 视频

    有谁知道如何在 Facebook 上播放视频UIWebView 我的应用程序将视频上 传到 Facebook 并检索视频的网址 我想将此网址嵌入到UIWebView播放 我已经为 youtube 解决了这个问题 但没有为 Facebook
  • 如何在 UIScrollView 中启用缩放

    如何启用缩放功能UIScrollView 答案是here https developer apple com documentation uikit uiscrollview 滚动视图还可以处理内容的缩放和平移 当用户做出捏合或张开手势时
  • 接收者'ClassName'是一个转发类,对应的@interface可能不存在

    我目前正在寻找一个UIPickerTable在 UIPickerView subviews 内 所以我循环并执行isKindOfClass UIPickerTable class 它有效 但由于 UIPickerTable 的标头未公开 我
  • 如何解决 Xcode 5 中的红色(已移动)文件?

    在 Xcode 4 中 当您要移动文件时 可以通过单击右侧菜单中的按钮并通过 Finder 选择新位置来解析文件的新位置 在 Xcode 5 中 右侧菜单中没有按钮 我还没有找到任何方法通过右键单击文件或顶部菜单栏选项来指定文件的新位置 在
  • 从应用程序启动 iPhone 设置屏幕?

    我正在开发一个应用程序 我希望按下按钮时 iPhone 设置屏幕应该打开 苹果有访问限制吗 到底能不能 如果能的话怎么办 不 你不能那样做 但是 作为替代方案 您可以使用这个框架 http www inappsettingskit com
  • 在 Swift 中从 Parse 加载图像

    我成功地将数据从 Parse 提取到 swift 中 但我的图像似乎没有按照我的方式工作 在我的 cellForRowAtIndexPath 方法中 我执行以下操作 var event AnyObject eventContainerArr
  • CoreBluetooth:检测设备超出范围/连接超时

    我正在设计一个 iOS 框架来处理多个 BLE 设备 均为同一类型 目前一切都运行良好 除了一件事 客户想要一个包含可用设备的列表 但是 我如何检测过去发现的设备何时不再可用 当我尝试连接到不再可用的设备时 会出现另一个问题 文档说 连接尝
  • ios - 如何声明静态变量? [复制]

    这个问题在这里已经有答案了 C 中声明的静态变量如下 private const string Host http 80dfgf7c22634nbbfb82339d46 cloudapp net private const string S

随机推荐