簡體   English   中英

渲染到 3D 紋理 webgl2

[英]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 開始):

  1. 將深度緩沖區綁定到幀緩沖區會將事情搞砸,我什至在執行此操作時遇到了瀏覽器故障,無論是單個紋理還是紋理數組。 因此,如果您想使用TEXTURE_3D ,請不要綁定任何深度緩沖區。
  2. 沒有浮動紋理,您沒有使用過,但它讓我感到非常失望,以至於我想指出它。

如果上面的要求是必須的,你還不如堅持gl.TEXTURE_2D_ARRAY

AFAICT 在您的示例中,您只需要調用gl.drawArrays

您的示例雖然試圖渲染到 8 層。 WebGL2 只需要支持 4 層。 您可以通過調用gl.getParameter(gl.MAX_DRAW_BUFFERS)來檢查是否支持 8,這可能是您代碼失敗的另一個原因。

根據規范不是必需的,但無論如何可能需要的是使紋理紋理完整,這意味着使其可渲染(即使我們沒有使用它進行渲染,我們也正在渲染它)。 在這種情況下,因為我沒有做MIPS我設置TEXTURE_MIN_FILTERLINEAR ,因為默認情況下它的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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM