我看到一些奇怪的行为,我无法在我编写的WebGL着色器中解释。这对我来说不是一个专业领域,所以我完全有可能误解了一些非常简单的东西,但我不确定是什么。
我有一个codepen来说明这里的奇怪行为https://codepen.io/bjvanminnen/pen/XqMpvL。
void main () {
vec3 color = vec3(0.);
vec2 loc1 = vec2(0.5, 0.) / u_res;
vec2 loc2 = vec2(1.5, 0.) / u_res;
float val1 = texture2D(u_tex, loc1).r * 255.;
float val2 = texture2D(u_tex, loc1).r * 255.;
color.r = val1 == val2 ? 1. : 0.;
// commenting/uncommenting this line somehow affects the b value
// on iOS, when uncommented we end up with (53, 0, 255, 255)
// when commented we end up with (255, 0, 0, 255)
// I can think of no reason why the below line should affect color.b
color.r = floor(val1) / 255.;
color.b = val1 == 53. ? 1. : 0.;
gl_FragColor = vec4(color, 1.);
}
发生了什么
的摘要在JS中,我创建了一个纹理,其中每个像素都是#350000
在我的片段着色器中,读取前两个像素
如果两个像素相同(应该是),则最初将输出的r值设置为1
取消注释时,根据val1的底限更改color.r的值(我不希望影响color.b的步骤)
如果像素值为53(即0x35),则将输出的b值设置为1.
然后我检查JS中的结果像素值。
我的期望:
当第二个color.r
行被注释掉时,我期望得到(53,0,255,255)的结果。这是我在桌面上看到的,但在我的iOS设备上,我看到(53,0,0,255)。似乎是在iOS上,val1最终略大于53。我假设这只是浮点怪异。
什么超级奇怪,我无法理解的是,当我注释掉第二条color.r
行时,我在桌面上得到(255,0,255,255) - 这使得感觉 - 但我的iOS设备上有(255,0,0,255)。
换句话说,行color.r = floor(val1) / 255.;
的存在/不存在会以某种方式改变color.b
的结果。
我遇到过一些奇怪的iOS错误,还是我在这里误解了什么?
答案 0 :(得分:1)
在GLSL ES 1.0 spec中查看有关不变性的一系列章节,从第4.6节开始
您案件的重要部分可能是4.6.2
4.6.2着色器内的不变性
当值存储在变量中时,通常假设它将保持不变,除非明确说明 改变。但是,在优化过程中,编译器可能会选择 重新计算一个值而不是将它存储在寄存器中。由于操作的精确性不完全 指定的(例如,可以以中等或高精度进行低精度操作),这是可能的 因为重新计算的值与原始值不同。
允许值在着色器中变化。为了防止这种情况,不变限定符或不变量 必须使用pragma。
在着色器中,由不同的非常量表达式生成的值不存在不变性,即使 那些表达是完全相同的。
示例1:
precision mediump; vec4 col; vec2 a = ... ... col = texture2D(tex, a); // a has a value a1 ... col = texture2D(tex, a); // a has a value a2 where possibly a1 ≠ a2
要在此示例中强制使用不变性,请使用:
#pragma STDGL invariant(all)
示例2:
vec2 m = ...; vec2 n = ...; vec2 a = m + n; vec2 b = m + n; // a and b are not guaranteed to be exactly equal
没有机制强制执行a和b之间的不变性。
您将浮动与精确值进行比较,这几乎在任何语言中都很危险。如果我改变这一行
color.b = val1 == 53. ? 1. : 0.;
到
color.b = val1 > 52.9 && val1 < 53.1 ? 1. : 0.;
然后它按预期的方式为我工作。另外,如果我用
写出val1
color.g = val1 / 153.;
我没有看到它发生变化。即使您的测试失败,该行是否被注释掉了88。这表明,在一个案例中,它不是53.0。它是53.000000000001或52.9999999999999等......