javascript - webGL 中的短纹理

标签 javascript opengl-es textures webgl

我有一个 short 纹理,我想在着色器中读取它,webgl 不支持 short 纹理,所以我将短纹理分成两个字节并发送它到着色器:

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

最佳答案

我正在解决同样的问题,它对我来说效果很好。我的实现是在 dart 中,但它是相似的。 我有两种可能的解决方案:

1)使用 float 纹理

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.LINEAR 过滤时,它会在图像的高对比度边缘上绘制错误数据,因为红色字节和绿色字节是分别插值的。

结论:两种解决方案都有效,但都无法与线性纹理插值一起使用。也许可以在片段着色器中执行手动插值。

关于javascript - webGL 中的短纹理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26403137/

相关文章:

c# - 如何在 asp.net web 应用程序 (C#) 中制作倒数计时器?

javascript - 如何模拟鼠标左键长按

android - 如何在android中打印3d字符串

java - 安卓OpenGL ES 2.0 : Text aren't showing up

JavaScript 方法,不带括号的调用方法

linux - 在 Ubuntu 中找不到 X11/Xlib.h

java - LIBGDX - 着色器中不需要的纹理混合

javascript - THREE.js - 无法在本地加载纹理

android - 某些手机​​上的 gl 纹理错误

JavaScript/计时