我读到here应该可以通过使用多个渲染目标并将3d纹理的每一层作为图层附加到渲染目标来渲染到WebGL2中的3D纹理。
但是我似乎无法让它工作,没有错误,但纹理的值在读取之间没有变化,只是空的。纹理的内部格式为gl.RGBA8
,格式为gl.RGBA
,大小为64x64x64
我做错了什么?这是我到目前为止所尝试的(伪代码):
this.fbo = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, this.fbo);
gl.TEXTURE_3D, this.my3DTexture, 0);
this.renderBuffer = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, this.renderBuffer);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, 64, 64);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this.renderBuffer);
if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
alert("FBO not complete!");
}
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
this.shader.activate();
// Set uniforms ...
for (let i = 0; i < 64; i += 8) {
gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, this.my3DTexture, 0, 0 + i);
gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT1, this.my3DTexture, 0, 1 + i);
gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT2, this.my3DTexture, 0, 2 + i);
gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT3, this.my3DTexture, 0, 3 + i);
gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT4, this.my3DTexture, 0, 4 + i);
gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT5, this.my3DTexture, 0, 5 + i);
gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT6, this.my3DTexture, 0, 6 + i);
gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT7, this.my3DTexture, 0, 7 + i);
gl.drawBuffers([
gl.COLOR_ATTACHMENT0,
gl.COLOR_ATTACHMENT1,
gl.COLOR_ATTACHMENT2,
gl.COLOR_ATTACHMENT3,
gl.COLOR_ATTACHMENT4,
gl.COLOR_ATTACHMENT5,
gl.COLOR_ATTACHMENT6,
gl.COLOR_ATTACHMENT7,
]);
let data = new Uint8Array(64*64 * 4);
gl.readPixels(0, 0, 64, 64, gl.RGBA, gl.UNSIGNED_BYTE, data);
console.log("before", data);
// Render scene
scene.objects.forEach(object => {
this._renderObject(object, scene, camera);
});
gl.readPixels(0, 0, 64, 64, gl.RGBA, gl.UNSIGNED_BYTE, data);
console.log("after one iteration read", data);
}
片段着色器:
#version 300 es
precision highp float;
layout(location = 0) out vec4 layer0;
layout(location = 1) out vec4 layer1;
layout(location = 2) out vec4 layer2;
layout(location = 3) out vec4 layer3;
layout(location = 4) out vec4 layer4;
layout(location = 5) out vec4 layer5;
layout(location = 6) out vec4 layer6;
layout(location = 7) out vec4 layer7;
void main() {
layer0 = vec4(0.5, 0.5, 0.5, 1.0);
layer1 = vec4(0.5, 0.5, 0.5, 1.0);
layer2 = vec4(0.5, 0.5, 0.5, 1.0);
layer3 = vec4(0.5, 0.5, 0.5, 1.0);
layer4 = vec4(0.5, 0.5, 0.5, 1.0);
layer5 = vec4(0.5, 0.5, 0.5, 1.0);
layer6 = vec4(0.5, 0.5, 0.5, 1.0);
layer7 = vec4(0.5, 0.5, 0.5, 1.0);
}
更新:它适用于gl.TEXTURE_2D_ARRAY
,但失败并带有gl.TEXTURE_3D
为什么?在测试here中,它们肯定会附加一个3d纹理层。
答案 0 :(得分:1)
我正在尝试与您完全相同的尝试,但最终成功了,只是为将来的读者指出了一些警告。
与TEXTURE_3D
不兼容的2件事(从Chrome 84开始):
TEXTURE_3D
,请不要绑定任何深度缓冲区。如果有上述要求,您最好坚持使用gl.TEXTURE_2D_ARRAY
答案 1 :(得分:0)
示例中的AFAICT您只需要致电gl.drawArrays
您的样本正尝试渲染为8层。 WebGL2仅需要支持4层。您可以通过调用gl.getParameter(gl.MAX_DRAW_BUFFERS)
来检查是否支持8,这可能是您的代码失败的另一个原因。
根据规范不是必需的,但无论如何可能都是使纹理纹理完整,这意味着使其可渲染(即使我们不使用它进行渲染,我们也正在对其进行渲染)。在这种情况下,因为我没有进行mips,所以我将TEXTURE_MIN_FILTER
设置为LINEAR
,因为默认情况下,它是NEAREST_MIPMAP_LINEAR
,需要mips,否则纹理不可渲染。 不可渲染 = 不可使用期间至少在某些驱动程序中有效。
function main() {
const gl = document.querySelector('canvas').getContext("webgl2");
if (!gl) {
return alert('need webgl2');
}
const vs = `#version 300 es
void main() {
gl_Position = vec4(0, 0, 0, 1);
gl_PointSize = 10.0;
}
`;
const fs = `#version 300 es
precision mediump float;
out vec4 outColor[4];
void main() {
outColor[0] = vec4(.1, .2, .3, .4);
outColor[1] = vec4(.5, .6, .7, .8);
outColor[2] = vec4(.9, 1., .11, .22);
outColor[3] = vec4(.33, .44, .55, .66);
}
`;
const program = twgl.createProgram(gl, [vs, fs]);
const width = 4;
const height = 4;
const depth = 4;
const tex = gl.createTexture(gl.TEXTURE_3D);
gl.bindTexture(gl.TEXTURE_3D, tex);
gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA8, width, height, depth, 0,
gl.RGBA, gl.UNSIGNED_BYTE, null);
gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
const numAttachments = 4;
const fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
for (let i = 0; i < numAttachments; ++i) {
gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i, tex, 0, i);
}
gl.drawBuffers([
gl.COLOR_ATTACHMENT0,
gl.COLOR_ATTACHMENT1,
gl.COLOR_ATTACHMENT2,
gl.COLOR_ATTACHMENT3,
]);
gl.viewport(0, 0, width, height);
gl.useProgram(program);
gl.drawArrays(gl.POINTS, 0, 1);
for (let i = 0; i < numAttachments; ++i) {
gl.readBuffer(gl.COLOR_ATTACHMENT0 + i);
const pixel = new Uint8Array(4);
gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
console.log('layer:', i, '=', Array.from(pixel).map(v => (v / 255).toFixed(2)).join(', '));
}
}
main();
<script src="https://twgljs.org/dist/4.x/twgl.min.js"></script>
<canvas></canvas>