1

簡単なWebGLプログラムを書いています。シェーダープログラムで奇妙な動作に悩まされています:

条件( 1.01 * 2.0 > 1.0 )はtrueと評価されますが、条件( 0.99 * 2.0 > 1.0 )はflaseと評価されます

1.0他の何かよりも小さい数を掛けるたびに、私はより少ない数を得る1.0

なんでそうなの?

[編集]

フラグメントシェーダーを使用して、ウィンドウレベルとウィンドウの高さ(線形ランプ)を使用して16ビットの符号なし整数データを8ビットのビットマップに変更し、画面に表示しています。16ビットデータを内部形式としてWebGL(AFAIK)に直接保存する方法がないためUint8Array(width*height*3)、最初のバイトをRチャネルに保存し、2番目を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ビット画像に奇妙なアーティファクトが含まれていると、何かを疑うようになりました。

Chrome8とFirefox4でテストしました。浮動小数点演算について何も理解していないと思います。

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 に答える