iOS上的WebGL着色器中出现无法解释的行为

时间:2018-04-30 18:57:42

标签: ios glsl webgl regl

我看到一些奇怪的行为,我无法在我编写的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错误,还是我在这里误解了什么?

1 个答案:

答案 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等......