WebGL片段着色器中的奇怪浮点算术

时间:2010-12-17 22:49:25

标签: shader webgl pixel-shader fragment-shader

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

条件( 1.01 * 2.0 > 1.0 )的计算结果为true,但是 条件( 0.99 * 2.0 > 1.0 )评估为flase

每当我将一个小于1.0的数字乘以其他东西时,我得到的数字小于1.0

为什么会这样?

[编辑]

我正在使用片段着色器使用窗口级别和窗口高度(线性渐变)将16位无符号整数数据更改为8位位图并在屏幕上显示。 由于没有直接的方法在WebGL(AFAIK)中存储16位数据作为内部格式,我决定创建Uint8Array(width*height*3),在R通道中存储第一个字节,在B通道中存储第二个字节并将其放入gl.RGBgl.UNSIGNED_BYTE纹理(可能LUMINESCANCE_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上测试过它。我相信我对浮点算术不了解。

2 个答案:

答案 0 :(得分:2)

也许它没有使用花车。

试试这个:

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

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

答案 1 :(得分: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解析器)。解析具有太多有效数字的常量时,完全有可能存在错误。