2010-12-17 4 views
1

간단한 WebGL 프로그램을 작성하고 있습니다.WebGL 조각 쉐이더에서 이상한 부동 소수점 연산

조건 (1.01 * 2.0 > 1.0)이 true로 평가하지만 조건 (0.99 * 2.0 > 1.0) 다른 내가 적은 숫자를 얻을 수

내가 뭔가에 의해 다수의 적은보다는 1.0를 곱 때마다 flase로 평가 나는 셰이더 프로그램의 이상한 행동에 붙어있어 1.0

왜 그렇습니까?

[EDIT] I 윈도우 레벨 화면 윈도우 높이 (선형 램프) 및 디스플레이를 사용하여 8 비트의 비트 맵으로 16 비트의 부호없는 정수 데이터를 변경하는 프래그먼트 쉐이더를 사용하고

. 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

도움이 될만한 상황이 더 필요합니다. 예를 들어 비교 결과를 어떻게 테스트하고 있습니까? 셰이더의 조건은 정상적인 코드보다 더 악명 높습니다. 테스트하는 정확한 코드를 제공해 주시면 올바르게 지원해 드리겠습니다. –

+0

이 플랫폼을 실행하고 계십니까? 이것은 GL/GL ES 쉐이더 컴파일러의 버그와 관련이있을 수 있습니다. 'if (1.0 * 2.0> 1.)'와 같은 간단한 셰이더를 사용하면 문제가 지속됩니까?1) gl_FragData [0] = vec4 (1.0.0.1); else gl_FragData [0] = vec4 (0,1,0,1); ' ? – rotoglup

답변

2

어쩌면 수레를 사용하지 않고있을 수도 있습니다.

이 시도 :

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

가 도움이됩니까? 그렇다면 컴파일러 (또는 하드웨어)가 어떤 이유로 int로 변환하는 것일 수 있습니다.

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); 

얼마나 많은 9S 당신이 버그를 실행하는 데 추가해야합니까? 단지 0.9로 여전히 발생합니까?

일단 코드를 작성하면 Chrome 또는 Firefox (동일한 GLSL 파서를 사용함)에서 버그를 신고 할 수 있습니다. 유효 숫자가 너무 많은 상수를 파싱 할 때 버그가있을 가능성이 있습니다.