我正在编写一个简单的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.RGB
, gl.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上测试过它。我相信我对浮点算术不了解。
答案 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解析器)。解析具有太多有效数字的常量时,完全有可能存在错误。