textImage2D加载1个没有副本的组件纹理

时间:2017-07-09 21:52:43

标签: javascript webgl webgl2

我正在尝试从包含带有1个组件的图像的ArrayBuffer创建2D纹理。我想这样做而不将其复制成4个组件的图像。 我想知道是否可以使用webglwebgl2(对webgl2有更多希望)。

webgl 1

我试过这个

gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, width, height, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, pixelData);

我尝试使用gl.LUMINANCE ans gl.LUMINANCE_ALPHA作为文档说

  

每种颜色成分都是......

而不是gl.ALPHA,例如:

  

丢弃红色,绿色和蓝色组件并读取alpha组件

由此可见gl.ALPHA预计4组件图片,而gl.LUMINANCEgl.LUMINANCE_ALPHA只需要1个组件。 但是,当我执行以下操作时,我得到一个错误,告诉我缓冲区太小。如果我传入4倍大小的缓冲区,则没有错误,所以它似乎也期待一个4分量图像。

我也尝试过宽度和高度除以4,以为我可以超越我的着色器上的纹理坐标,但得出结论这可能是插值的一个坏主意,或者我不得不自己做。

webgl 2

所以我对webgl 1的期望并不高,但我很确定这对webgl2来说很容易。但遗憾的是以下情况不起作用:

gl.texImage2D(gl.TEXTURE_2D, 0, gl.R8, this.image.width, this.image.height, 0, gl.RED, gl.UNSIGNED_BYTE, pixelData);

它正在做同样的抱怨,缓冲区变小,并且没有抛出任何错误,缓冲区大4倍。

对于任何(或两个)版本是否可能,或者我注定要创建一个包含4个组件的临时图像?

1 个答案:

答案 0 :(得分:1)

你在读什么样的文件?您提供的引用都不适用于ArrayBuffers,并且在WebGL(1)规范中找不到任何引号。 ALPHALUMINANCE都是单通道格式,只期望每个像素有一个值,它们之间唯一有效的区别在于您可以在着色器中访问它们的组件。 LUMINANCE_ALHPA但是两个频道格式(第一个频道映射到rgb,第二个频道映射到a)。

现在,根据您的实际问题,WebGL 1和2都允许通过texImage2D提交单个组件数据,但两者都默认为UNPACK_ALIGNMENT 4(字节)。

  

指定内存中每个像素行开头的对齐要求。允许值为1(字节对齐),2(行与偶数字节对齐),4(字对齐)和8(行以双字边界开始)。

OpenGL ES 3.0 Manpage

通过UNPACK_ALIGNMENT方法将pixelStorei设置为1(字节)可以解决问题。

ctx.pixelStorei(ctx.UNPACK_ALIGNMENT,1);

注意:这是全局设置(未绑定到活动纹理),并且可能导致纹理数据的性能损失,可以通过更好的对齐解压缩。因此,您应该确定每个纹理情况下的最佳解包对齐(考虑格式和数据类型)并相应地设置对齐。

var ctx=canvas.getContext('webgl');
// Create alpha texture
var tex = ctx.createTexture();
ctx.bindTexture(ctx.TEXTURE_2D, tex);
ctx.pixelStorei(ctx.UNPACK_ALIGNMENT,1);
ctx.texImage2D(ctx.TEXTURE_2D,0,ctx.ALPHA,2,2,0,ctx.ALPHA,ctx.UNSIGNED_BYTE,new Uint8Array([0,128,128,0]));
ctx.texParameteri(ctx.TEXTURE_2D,ctx.TEXTURE_MIN_FILTER,ctx.NEAREST);
ctx.texParameteri(ctx.TEXTURE_2D,ctx.TEXTURE_MAG_FILTER,ctx.NEAREST);

// Create screenspace shader program
var
  vshader=ctx.createShader(ctx.VERTEX_SHADER),
  fshader=ctx.createShader(ctx.FRAGMENT_SHADER),
  program=ctx.createProgram()
;
ctx.shaderSource(vshader,`
  attribute vec2 vPosition;
  void main() {
    gl_Position=vec4(vPosition,0,1);
  }
`);
ctx.compileShader(vshader);
ctx.attachShader(program,vshader);
ctx.shaderSource(fshader,`
  precision mediump float;
  uniform sampler2D tex;
  void main(){
    gl_FragColor=vec4(texture2D(tex,gl_FragCoord.xy*.05));
  }
`);
ctx.compileShader(fshader);
ctx.attachShader(program,fshader);
ctx.linkProgram(program);

// Create and bind screenspace geometry
ctx.bindBuffer(ctx.ARRAY_BUFFER, ctx.createBuffer());
ctx.bufferData(ctx.ARRAY_BUFFER, new Float32Array([
  -1,1, 1,1, 1,-1, -1,-1,
  -1,1, -1,-1, 1,-1, 1,1
]), ctx.STATIC_DRAW);
ctx.enableVertexAttribArray(0);
ctx.vertexAttribPointer(0,2,ctx.FLOAT,false,0,0);

// Render
ctx.useProgram(program);
ctx.drawArrays(ctx.TRIANGLE_FAN,0,4);
canvas {outline:1px solid red;position:absolute;left:50%;transform:translateX(-50%);}
html{background:#aaa;}
<canvas id="canvas"></canvas>

相关问题