为什么在 webgl2 中从 16 字节缓冲区创建 2x8 R8 纹理失败?
Why does creating a 2x8 R8 texture from a 16 byte buffer fail in webgl2?
当我尝试在 webgl2 中创建 2x8 R8 纹理时,出现错误。这不会发生在 4x8 纹理上。如果我将输入缓冲区的大小比我预期的大一倍,则 2x8 成功。
当 creating/reading 纹理时,webgl2 是否具有 'column alignment' 4?
下面是一些重现该问题的代码。我在 Chrome 和 Firefox 的 Windows 上测试了它:
function test_read(w) {
let gl = document.createElement('canvas').getContext('webgl2');
let h = 8;
let data = new Uint8Array(w*h);
data[5] = 5;
let texture = gl.createTexture();
let frameBuffer = gl.createFramebuffer();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.R8, w, h, 0, gl.RED, gl.UNSIGNED_BYTE, data);
if (gl.getError() !== gl.NO_ERROR) {
return 'bad w=' + w;
}
return 'good w=' + w;
}
console.log(test_read(4)); // good w=4
console.log(test_read(2)); // bad w=2
出来的错误代码是0x502(INVALID_OPERATION)。读取通过扩展缓冲区创建的纹理时会发生类似的问题:似乎期望 'column alignment' 为 4.
您需要设置gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1)
默认的UNPACK_ALIGNMENT
是4,这意味着WebGL期望每一行像素都是4字节的倍数。由于您使用的是 R8(1 字节像素)并且宽度为 2,因此您的行只有 2 个字节长。当您将宽度更改为 4 时,它开始工作。
function test_read(w) {
let gl = document.createElement('canvas').getContext('webgl2');
let h = 8;
let data = new Uint8Array(w*h);
data[5] = 5;
// ---=== ADDED ===---
gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
let texture = gl.createTexture();
let frameBuffer = gl.createFramebuffer();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.R8, w, h, 0, gl.RED, gl.UNSIGNED_BYTE, data);
if (gl.getError() !== gl.NO_ERROR) {
return 'bad w=' + w;
}
return 'good w=' + w;
}
console.log(test_read(4)); // good w=4
console.log(test_read(2)); // bad w=2
当我尝试在 webgl2 中创建 2x8 R8 纹理时,出现错误。这不会发生在 4x8 纹理上。如果我将输入缓冲区的大小比我预期的大一倍,则 2x8 成功。
当 creating/reading 纹理时,webgl2 是否具有 'column alignment' 4?
下面是一些重现该问题的代码。我在 Chrome 和 Firefox 的 Windows 上测试了它:
function test_read(w) {
let gl = document.createElement('canvas').getContext('webgl2');
let h = 8;
let data = new Uint8Array(w*h);
data[5] = 5;
let texture = gl.createTexture();
let frameBuffer = gl.createFramebuffer();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.R8, w, h, 0, gl.RED, gl.UNSIGNED_BYTE, data);
if (gl.getError() !== gl.NO_ERROR) {
return 'bad w=' + w;
}
return 'good w=' + w;
}
console.log(test_read(4)); // good w=4
console.log(test_read(2)); // bad w=2
出来的错误代码是0x502(INVALID_OPERATION)。读取通过扩展缓冲区创建的纹理时会发生类似的问题:似乎期望 'column alignment' 为 4.
您需要设置gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1)
默认的UNPACK_ALIGNMENT
是4,这意味着WebGL期望每一行像素都是4字节的倍数。由于您使用的是 R8(1 字节像素)并且宽度为 2,因此您的行只有 2 个字节长。当您将宽度更改为 4 时,它开始工作。
function test_read(w) {
let gl = document.createElement('canvas').getContext('webgl2');
let h = 8;
let data = new Uint8Array(w*h);
data[5] = 5;
// ---=== ADDED ===---
gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
let texture = gl.createTexture();
let frameBuffer = gl.createFramebuffer();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.R8, w, h, 0, gl.RED, gl.UNSIGNED_BYTE, data);
if (gl.getError() !== gl.NO_ERROR) {
return 'bad w=' + w;
}
return 'good w=' + w;
}
console.log(test_read(4)); // good w=4
console.log(test_read(2)); // bad w=2