使用glFrameBufferTextureLayer分层渲染到3D纹理

时间:2018-03-25 08:47:40

标签: javascript webgl rendering

我的目标是使用gl.frameBufferTextureLayer将切片渲染到3D纹理。但是,当我使用gl.readPixels回读数据时,不会呈现任何内容。

当我将gl.TEXTURE_3D更改为gl.TEXTURE_2D_ARRAY时,它可以正常工作,但在测试here中,他们肯定会在FBO上附加一层3D纹理。 WebGL docs并没有说明纹理应该是什么,但是 GLES3 docs允许纹理确定为3D纹理。我已经检查了帧缓冲完整状态和所有这些东西......

是否有任何资源可以将3D纹理图层附加到WebGL2中的FBO,这是否可能?一些代码:

this.fbo= gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, this.fbo);

this.colorTexture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_3D, this.colorTexture);
gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA8, 64, 64, 64, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);

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);

// Use level 1 in 3D texture
// Works when texture is GL_TEXTURE_2D_ARRAY
gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, this.texture, 0, 1);

// ... Render scene

let data = new Uint8Array(64 * 64 * 4);
gl.readPixels(0, 0, 64, 64, gl.RGBA, gl.UNSIGNED_BYTE, data, 0); // data is empty

1 个答案:

答案 0 :(得分:1)

首先让我们尝试一个简单的无渲染



const gl = document.createElement("canvas").getContext("webgl2");
const fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);

const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_3D, tex);
gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA8, 2, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);

gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex, 0, 1);

gl.clearColor(.25, .5, .75, 1);
gl.clear(gl.COLOR_BUFFER_BIT);

const data = new Uint8Array(2 * 2 * 4);
gl.readPixels(0, 0, 2, 2, gl.RGBA, gl.UNSIGNED_BYTE, data);
console.log(data);




有效

现在让我们尝试渲染



const gl = document.createElement("canvas").getContext("webgl2");
const fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);

const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_3D, tex);
gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA8, 2, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);

gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex, 0, 1);

const vs = `
#version 300 es
void main() {
  gl_Position = vec4(0, 0, 0, 1);
  gl_PointSize = 4.0;
}
`;

const fs = `
#version 300 es
precision mediump float;
out vec4 color;
void main() {
  color = vec4(.75, .5, .25, 1);
}
`

const prg = twgl.createProgram(gl, [vs, fs]);
gl.useProgram(prg);
gl.viewport(0, 0, 2, 2);
gl.drawArrays(gl.POINTS, 0, 1);

const data = new Uint8Array(2 * 2 * 4);
gl.readPixels(0, 0, 2, 2, gl.RGBA, gl.UNSIGNED_BYTE, data);
console.log(data);

<script src="https://twgljs.org/dist/4.x/twgl.min.js"></script>
&#13;
&#13;
&#13;

也有效。

让我们试试深度缓冲区

&#13;
&#13;
const gl = document.createElement("canvas").getContext("webgl2");
const fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);

const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_3D, tex);
gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA8, 2, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);

gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex, 0, 1);

const rb = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, 2, 2);    
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, rb);


const vs = `
#version 300 es
uniform float depth;
void main() {
  gl_Position = vec4(0, 0, depth, 1);
  gl_PointSize = 4.0;
}
`;

const fs = `
#version 300 es
precision mediump float;
uniform vec4 color;
out vec4 outColor;
void main() {
  outColor = color;
}
`

const prgInfo = twgl.createProgramInfo(gl, [vs, fs]);
gl.useProgram(prgInfo.program);
gl.viewport(0, 0, 2, 2);
gl.enable(gl.DEPTH_TEST);

// draw in middle
twgl.setUniforms(prgInfo, {
  depth: 0,
  color: [1, 0, 0, 1],
});
gl.drawArrays(gl.POINTS, 0, 1);


// draw in front
twgl.setUniforms(prgInfo, {
  depth: -.5,
  color: [0, 1, 0, 1],
});
gl.drawArrays(gl.POINTS, 0, 1);

// draw in back
twgl.setUniforms(prgInfo, {
  depth: .5,
  color: [0, 0, 1, 1],
});
gl.drawArrays(gl.POINTS, 0, 1);

// should be front color (0, 255, 0, 255)

const data = new Uint8Array(2 * 2 * 4);
gl.readPixels(0, 0, 2, 2, gl.RGBA, gl.UNSIGNED_BYTE, data);
console.log(data);
&#13;
<script src="https://twgljs.org/dist/4.x/twgl.min.js"></script>
&#13;
&#13;
&#13;

似乎工作

也许您忘了设置视口?我经常犯这个错误