为了账号安全,请及时绑定邮箱和手机立即绑定

片段着色器行为异常(测试网格)

片段着色器行为异常(测试网格)

largeQ 2024-01-25 15:17:10
我正在尝试编写一个简单的片段着色器来在多边形上显示网格(或更确切地说是棋盘格图案)。我希望这个图案“保持在原位”,即当多边形本身移动时,正方形保持在同一位置,因此生成的图案会在图案的表面上滑动。我正在 Java 中使用 LWJGL 针对基于 ARM 的嵌入式系统进行开发,我可以在连接到我的 PC 的 ARM 设备上远程调试,也可以在 PC 本身上进行本地调试。我为此使用intelliJ。在 PC 上,我的程序默认使用 OpenGL 3.2。在 ARM 上,上下文是 OpenGL ES 3.0。ARM上的显卡是Vivante GC 2000。问题是:在本地,在我的电脑上,着色器工作完美,就像我想要的那样。但当我使用 ARM 时,图案会抖动、扭曲,并且构成多边形的两个三角形之间不同步。有趣的事实是,图案会根据相机位置而变化和移动,即使着色器仅使用模型矩阵和平面的顶点位置进行计算,这两者在帧之间保持完全相同(我检查过)。然而相机位置在某种程度上会极大地影响结果,这是不应该发生的。这是我的顶点着色器:#version 300 eslayout (location=0) in vec3 position;uniform mat4 projectionMatrix;uniform mat4 modelViewMatrix;uniform mat4 modelMatrix;out highp vec3 vertexPosition;void main(){       // generate position data for the fragment shader    // does not take view matrix or projection matrix into account    vec4 vp = modelMatrix * vec4(position, 1.0);    vertexPosition = vec3(vp.x, vp.y, vp.z);    // position data for the OpenGL vertex drawing    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);}片段着色器:#version 300 esprecision highp float;in highp vec3 vertexPosition;out mediump vec4 fragColor;void main(){    highp float c = float((int(round(vertexPosition.x/5.0))+int(round(vertexPosition.z/5.0))) % 2);    fragColor = vec4(vec3(c/2.0 + 0.3), 1);}正如你所看到的,我尝试修改浮动操作的精度,可惜没有成功。您还可以注意到,只有多边形的 modelMatrix 和 Vertex 位置会影响 fragColor,我可以保证我将它们连接起来,并且它们在着色器调用之间不会改变,但不知何故,相机移动最终会影响生成的片段颜色/图案。还值得注意的是,场景中物体上的其他纹理似乎没有受到该问题的影响
查看完整描述

3 回答

?
元芳怎么了

TA贡献1798条经验 获得超7个赞

所以最终结果是两个问题的混合体:

1) 运算符 % 在 OGL 3.2 和 OGLES 3.0 中的工作方式不同。在前者中,即使操作数为负数,它也始终返回正整数。即 3 % 2 = -3 % 2 = 1 然而,在 OpenGL ES 中,它实际上保留了符号。

2)这是一个精度问题。我正在高正坐标中工作,因此我的 vertexPosition 坐标最终在 10k 正值范围内。当我计算总和时,它可能会达到20k。似乎即使是 highP float 也不足以在如此高的数字下保持足够的精度,所以它最终会崩溃。这是奇数,因为高精度范围显示为 -2^127~~2^127,这对于我的计算来说应该足够了。但事实并非如此。我的解决方案是标准化坐标,将值减小到 <10。

如果有人可以进一步详细说明我可以做的事情 - 请告诉我!


查看完整回答
反对 回复 2024-01-25
?
白板的微信

TA贡献1883条经验 获得超3个赞

我的着色器的问题仍然存在。多边形的“纹理”在某些视角下会变形。我在这里发现了另一个问题,它与我遇到的问题几乎完全相同,并且它有一些解决方法的答案。


查看完整回答
反对 回复 2024-01-25
?
炎炎设计

TA贡献1808条经验 获得超4个赞

我将发布我对这个问题的最终答案,这是经过大量努力、搜索和反复试验的结果。实际上,屏幕截图中描绘了两个独立的问题,因此我将同时介绍这两个问题。

关于多边形交叉点上奇怪的纹理偏移。已确认这是 Vivante 驱动程序问题。对于片段着色器来说,位于截锥体之外太远的点的坐标计算错误(请注意,它们在顶点着色器中完全正常,因此平面不会出现撕裂 - 只有纹理受到影响)。

目前似乎没有驱动程序修复。

但是,您可以实施一种解决方法。分割网格。不要使用由 2 个三角形组成的大四边形,而是用几个较小的四边形构建它。在我的例子中,我制作了一个 6x6 结构,总共 36 个四边形和 64 个三角形。这样,任何点都不会超出截锥体,并且精度看起来很好。

是的,这远非理想,但它比让片段着色器产生视觉伪影要好。


关于颜色。您可能会注意到,在屏幕截图中,颜色最终变为灰色和黑色,而它们应该是浅灰色和深灰色。

解决方案并不容易达成。这是系统区域设置。

你们中的一些人可能甚至没有意识到,在某些斯拉夫语言环境中,分隔符是逗号,而不是点。所以基本上是这样的:

fragColor = vec4(vec3(c/2.0 + 0.3), 1);

变成

fragColor = vec4(vec3(c/2 , 0 + 0 , 3), 1);

正如你可以猜到的,这是完全错误的。事实上,令我印象深刻的是,GLSL 似乎对此完全没问题,并且不会给出任何运行时错误。可能是因为 vec3 在创建过程中可以采用 3 个坐标,或者其他什么。无论如何,这个bug使得我代码中的所有浮点常量完全错误,并且得到的计算结果也是错误的。

以防万一有人遇到这个问题。


查看完整回答
反对 回复 2024-01-25
  • 3 回答
  • 0 关注
  • 104 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信