gpt4 book ai didi

javascript - textImage2D 加载 1 个组件纹理而不复制

转载 作者:行者123 更新时间:2023-12-03 03:54:44 25 4
gpt4 key购买 nike

我正在尝试从包含具有 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.LUMINANCEgl.LUMINANCE_ALPHA 正如文档所说

Each color component is a ...

gl.ALPHA 相反,例如它说:

Discards the red, green and blue components and reads the alpha component

由此看来,很明显 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 个组件的临时镜像?

最佳答案

您正在阅读什么类型的文档?您提供的引用均不适用于 ArrayBuffers,并且在 WebGL(1) 规范中都找不到它们。ALPHALUMINANCE 都是单 channel 格式,每个像素只期望一个值,它们之间唯一有效的区别在于您可以在着色器中访问它们的组件。然而,LUMINANCE_ALHPA channel 格式(第一个 channel 映射到 rgb,第二个 channel 映射到 a)。

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

Specifies the alignment requirements for the start of each pixel row in memory. The allowable values are 1 (byte-alignment), 2 (rows aligned to even-numbered bytes), 4 (word-alignment), and 8 (rows start on double-word boundaries).

OpenGL ES 3.0 Manpage

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

ctx.pixelStorei(ctx.UNPACK_ALIGNMENT,1);

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

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>

关于javascript - textImage2D 加载 1 个组件纹理而不复制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45001381/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com