[英]Render to 3D texture webgl2
我在這里讀到,通過使用多個渲染目標並將 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
一起失敗 為什么? 在這里的測試中,他們肯定會附加一層 3d 紋理。
我正在嘗試與您完全相同的事情並最終成功,只是為了給未來的讀者注意一些警告。
2 件不適用於TEXTURE_3D
(從 Chrome 84 開始):
TEXTURE_3D
,請不要綁定任何深度緩沖區。 如果上面的要求是必須的,你還不如堅持gl.TEXTURE_2D_ARRAY
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>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.