Render To 3d Texture Webgl2
Solution 1:
I was trying exactly the same thing as you and finally succeeded, just to note some caveats for future readers.
2 things that don't work with TEXTURE_3D
(as of Chrome 84):
- Binding a depth buffer to the framebuffer will screw things up, I even got browser glitches for doing this, no matter it's a single texture or texture array. So if you'd like to use
TEXTURE_3D
, do NOT bind any depth buffer. - No float texture, which you didn't use, but it failed me so hard that I want to point it out.
If the above requirement is necessary, you might as well stick to gl.TEXTURE_2D_ARRAY
Solution 2:
AFAICT in your sample you just needed to call gl.drawArrays
Your sample though is trying to render to 8 layers. WebGL2 only requires 4 layers to be supported. You can check if 8 are supported by calling gl.getParameter(gl.MAX_DRAW_BUFFERS)
so that could be another reason you code was failing.
Not required according to the spec but possibly required anyway is making the texture texture complete, which means make it renderable (even though we are not rendering with it we are rendering to it). In this case because I didn't make mips I set the TEXTURE_MIN_FILTER
to LINEAR
since by default it's NEAREST_MIPMAP_LINEAR
which requires mips otherwise the texture is not renderable. not renderable = not usable period in at least some drivers in the past.
functionmain() {
const gl = document.querySelector('canvas').getContext("webgl2");
if (!gl) {
returnalert('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 = newUint8Array(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();
<scriptsrc="https://twgljs.org/dist/4.x/twgl.min.js"></script><canvas></canvas>
Post a Comment for "Render To 3d Texture Webgl2"