1

我正在编写一个简单的 WebGL 程序。我在着色器程序中遇到了一个奇怪的行为:

条件( 1.01 * 2.0 > 1.0 )评估为真,但条件( 0.99 * 2.0 > 1.0 )评估为flase

每次我将小于的数字乘以其他数字时1.0,我得到的数字小于1.0

为什么会这样?

[编辑]

我正在使用片段着色器使用窗口级别和窗口高度(线性斜坡)将 16 位无符号整数数据更改为 8 位位图并显示在屏幕上。由于没有直接的方法将 16 位数据存储为 WebGL(AFAIK)中的内部格式,我决定创建,将第一个字节存储在 R 通道中,第二个字节存储在 B 通道中Uint8Array(width*height*3)并将其放入纹理(也许会更好)。gl.RGBgl.UNSIGNED_BYTELUMINESCANCE_ALPHA

在着色器中,我重建字形字节并进行调平。着色器程序:

#ifdef GL_ES
precision highp float;
#endif

uniform highp sampler2D   s_texture;
uniform highp float       u_ww;
uniform highp float       u_wc;
varying highp vec2        v_texcoord;

void main(void)
{
     highp vec3 color = texture2D(s_texture, v_texcoord).rgb;
 highp float S = 255.;
 highp float d = 65280.;
 highp float m = 0.9;
 highp float c = color.g*d + color.r*S;

 float dp = 0.;

 float min = u_wc - u_ww/2.;
 float max = u_wc + u_ww/2.;

 if( 1.0*2.0 > 1.1 ) gl_FragData[0] = vec4(1,0,0,1);
 else{
    if( c<min ) c=0.;
    else if( c>max ) c=255.;
    else c=(255.*(max-c))/u_ww; 

    c = c/S;
    gl_FragData[0] = vec4(c,c,c,1);
 }
}

如您所见,有一条愚蠢的线if( 1.0*2.0 > 1.1 ) gl_FragData[0] = vec4(1,0,0,1); 是我测试浮点运算的地方。在这个例子中,整个图像是红色的,但是当条件是答案时0.999999999*2.0 > 1.1,答案是错误的。当我重新采样的 16 位图像中出现奇怪的伪影时,我开始怀疑某些事情。

我在 Chrome 8 和 Firefox 4 上对其进行了测试。我相信我对浮点运算一无所知。

4

2 回答 2

2

也许它没有使用浮点数。

尝试这个:

float xa = 1.01; //then change to 0.99
float xb = 1.0;
float xc = 2.0;
if (xa * xb > xc)
    ...

这有帮助吗?如果是这样,则编译器(或硬件)可能出于某种原因将它们转换为 int 。

于 2010-12-23T07:23:48.267 回答
1

您应该将着色器剥离到尽可能小的情况。

if( 1.0*2.0 > 1.1 ) gl_FragData[0] = vec4(1,0,0,1);
else gl_FragData[0] = vec4(1,0,1,1);

if( 0.999999*2.0 > 1.1 ) gl_FragData[0] = vec4(1,0,0,1);
else gl_FragData[0] = vec4(1,0,1,1);

您需要添加多少个 9 才能触发错误?仅 0.9 仍然会发生这种情况吗?

完成此操作后,使用该代码报告 Chrome 或 Firefox 的错误(它们使用相同的 GLSL 解析器)。解析具有太多有效数字的常量完全有可能存在错误。

于 2013-06-16T11:36:34.603 回答