2014-10-16 132 views
0

我有一个short的质感,我想从着色器来阅读,WebGL的不支持short纹理,所以我分裂短到两个字节,并将其发送到着色器:短纹理的WebGL

var ushortValue = reinterval(i16Value, -32768, 32767, 0, 65535); 

textureData[j*4] = ushortValue & 0xFF; // first byte 
ushortValue = ushortValue >> 8; 
textureData[j*4+1] = ushortValue & 0xFF; // second byte 
textureData[j*4+2] = 0; 
textureData[j*4+3] = 0; 

然后我把数据上传至显卡:

gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); 
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); 
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, textureData); 

在片段着色器:

vec4 valueInRGBA = texture2D(ctTexture, xy)*255.0; // range 0-1 to 0-255 
float real_value = valueInRGBA.r + valueInRGBA.g*256; 
real_value = reinterval(real_value , 0.0, 65535.0, 0.0, 1.0); 
gl_FragColor = vec4(real_value, real_value, real_value, 1.0); 

但是,与我在正常的opengl中上传支持短纹理的短数据时相比,我的分辨率已经丢失了。任何人都可以看到我做错了什么?

enter image description here

这里是另外一个陌生的不同的WebGL我和OpenGL之间获取,使用相同的数据。我绘制了上面的值我得到了相同的颜色,但我的分辨率稍差。然后我添加两行:

ct_value = reinterval(ct_value, 0.0, 65535.0, -32768.0, 32767.0); 
ct_value = reintervalClamped(ct_value, -275.0, 475.0, 0.0, 1.0); 
gl_FragColor = vec4(ct_value,ct_value,ct_value,1.0); 

在OpenGL一切看起来不错,但在WebGL的一切都变成白色的确切相同的代码。

的Opengl:enter image description here 的WebGL:enter image description here

+1

不应该在着色器中乘以255.0(2^8-1)而不是254.0? – BDL 2014-10-16 11:29:55

+0

甚至* 256 *,因为'ushortValue = ushortValue >> 8;'除以 – 2014-10-16 11:31:35

+0

我改变了它,谢谢,但仍然是,分辨率仍然不好 – hidayat 2014-10-16 11:41:12

回答

0

我解决同样的问题,它为我工作得很好。我的实现是在dart中,但它是相似的。 我有2个可能的解决方案:

1)使用浮纹

gl.getExtension("OES_texture_float") 
texture format = GL.LUMINANCE 
texture data type = GL.FLOAT 

maxValue = (signed)?32767.0:65535.0; 
textureData = new Float32List(width*height); 
for (int i=0;i<size;i++) { 
    textureData[i] = data[i]/maxValue; 
} 

该解决方案的伟大工程,没有必要执行着色器任何特殊的计算,但您需要OES_float_linear扩展使用线性纹理插值目前的Chrome版本不支持它。

2)使用与存放短期价值的解决方案,以RGB

pixels = new Uint8List(width*height*3); 
for (int i=0;i<width*height;i++) { 
    int val = (signed)?data[i].abs():data[i]; 
    textureData[i*3] = val&0xFF; 
    textureData[i*3+1] = val>>8; 
    textureData[i*3+2] = (signed && data[i]<0)?255:0; 
} 

和价值重建着色器:

float tval = texture2D(imageTex, vUv).r/256.0+texture2D(imageTex, vUv).g; 
if (texture2D(imageTex, vUv).b>0.0) tval = -tval 

但这种方法有一个很大的问题,当你放大和有GL 。由于红色字节和grean字节是分开插值的,因此可以在图像中的高对比度边缘上绘制不良数据。

结论:两种解决方案都能正常工作,但都无法用于线性纹理插值。也许可以在片段着色器中执行手动插值。