渲染为3D纹理webgl2 [英] Render to 3D texture webgl2
问题描述
我在
I read here that it should be possible to render to a 3D texture in WebGL2 by using multiple render targets and attaching each layer of the 3d texture as a layer to the render target.
但是我似乎无法使其正常工作,没有错误,但是纹理的值在两次读取之间没有变化,只是空的.纹理的内部格式为gl.RGBA8
,格式为gl.RGBA
,大小为64x64x64
However I can't seem to get it to work, no errors but the values of the texture doesn't change between the reads and is just empty. The texture has gl.RGBA8
as internal format, gl.RGBA
as format and a size of 64x64x64
我做错了什么?这是我到目前为止尝试过的(伪代码):
What am I doing wrong? This is what I tried so far (pseudo code):
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
一起使用,为什么?在测试中此处他们肯定会附加一层3d纹理.
UPDATE: It works with gl.TEXTURE_2D_ARRAY
but fails with gl.TEXTURE_3D
Why? In the tests here they are certainly attaching a layer of a 3d texture.
推荐答案
示例中的AFAICT您只需要调用gl.drawArrays
AFAICT in your sample you just needed to call gl.drawArrays
尽管您的示例正在尝试渲染为8层. WebGL2仅需要支持4层.您可以通过调用gl.getParameter(gl.MAX_DRAW_BUFFERS)
检查是否支持8,这可能是您的代码失败的另一个原因.
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.
根据规范不是必需的,但无论如何可能都是使纹理纹理完整,这意味着使其成为可渲染的(即使我们不使用它进行渲染,我们也正在对其进行渲染).在这种情况下,因为我没有进行mips操作,所以将TEXTURE_MIN_FILTER
设置为LINEAR
,因为默认情况下,它是NEAREST_MIPMAP_LINEAR
,它需要mips,否则纹理不可渲染. 不可渲染 = 不可使用期间至少在某些驱动程序中有效.
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.
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>
这篇关于渲染为3D纹理webgl2的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!