具有gipmap级别的webgl2上的glFramebufferTexture2D

时间:2019-03-02 12:04:29

标签: webgl webgl2

对于源自ES3.0的webGL2,我认为我们可以将 mipmap级别用作以下项的最后一个参数:

void glFramebufferTexture2D(GLenum target,
GLenum attachment,
GLenum textarget,
GLuint texture,
GLint level);

现在Khronos ES3.0的官方文档中指出,应该可以使用mipmap级别:

  

级:   指定要附加的纹理的mipmap级别。

Khronos ES2.0开始,它说它必须为0

  

级:   指定要附加的纹理图像的mipmap级别,必须为0。

现在,我无法从WebGL2.0上下文中找到有关glFramebufferTexture2D的任何文档,但是mozilla文档指出,与ES2.0中一样,mipmap层必须为0,如下所示: Mozilla WebGL doc

  

级:   GLint指定要附加的纹理图像的mipmap级别。必须为0。

我认为该页面涉及WebGL1上下文,但是其中提到了WebGL2功能,在WebGL2文档中找不到glFramebufferTexture2D。

因此,要总结一下,有没有办法在 WebGL2.0 上的帧缓冲区目标上使用 mipmap级别

(我研究了分层图像,但WebGL2.0不支持AFAIK分层渲染)

1 个答案:

答案 0 :(得分:1)

  

有没有办法在WebGL2.0的帧缓冲区目标上使用mipmap级别

我会在那儿结束答案,但我想我想知道您是否真的尝试了一些东西,但没有用?您必须创建一个WebGL2上下文,以将mipmap级别用作帧缓冲区附件,否则可以。在WebGL1上,它将无法正常工作。

function main() {
  const gl = document.querySelector('canvas').getContext('webgl2');
  if (!gl) {
    return alert('need webgl2');
  }
  
  const vs = `#version 300 es
  void main() {
    // just draw an 8x8 pixel point in the center of the target
    // this shader needs/uses no attributes
    gl_Position = vec4(0, 0, 0, 1);
    gl_PointSize = 8.0;
  }
  `;
  const fsColor = `#version 300 es
  precision mediump float;
  uniform vec4 color;
  out vec4 outColor;
  void main() {
    outColor = color;
  }
  `;
  const fsTexture = `#version 300 es
  precision mediump float;
  uniform sampler2D tex;
  out vec4 outColor;
  void main() {
    // this shader needs no texcoords since we just
    // use gl_PoitnCoord provided by rendering a point with gl.POINTS
    // bias lets select the mip level so no need for 
    // some fancier shader just to show that it's working.        
    float bias = gl_PointCoord.x * gl_PointCoord.y * 4.0;
    outColor = texture(tex, gl_PointCoord.xy, bias);
  }
  `;
  
  // compile shaders, link into programs, look up attrib/uniform locations
  const colorProgramInfo = twgl.createProgramInfo(gl, [vs, fsColor]);
  const textureProgramInfo = twgl.createProgramInfo(gl, [vs, fsTexture]);
  
  const tex = gl.createTexture();
  gl.bindTexture(gl.TEXTURE_2D, tex);
  const levels = 4;
  const width = 8;
  const height = 8;
  gl.texStorage2D(gl.TEXTURE_2D, levels, gl.RGBA8, width, height);
  
  // make a framebuffer for each mip level
  const fbs = [];
  for (let level = 0; level < levels; ++level) {
    const fb = gl.createFramebuffer();
    fbs.push(fb);
    gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
    gl.framebufferTexture2D(
        gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
        gl.TEXTURE_2D, tex, level);
  }
  
  // render a different color to each level
  const colors = [
    [1, 0, 0, 1],  // red
    [0, 1, 0, 1],  // green
    [0, 0, 1, 1],  // blue
    [1, 1, 0, 1],  // yellow
  ];
  gl.useProgram(colorProgramInfo.program);
  for (let level = 0; level < levels; ++level) {
    gl.bindFramebuffer(gl.FRAMEBUFFER, fbs[level]);
    const size = width >> level;
    gl.viewport(0, 0, size, size);
    twgl.setUniforms(colorProgramInfo, { color: colors[level] });
    const offset = 0;
    const count = 1;
    gl.drawArrays(gl.POINTS, offset, count);  // draw 1 point
  }
  
  // draw the texture's mips to the canvas
  gl.bindFramebuffer(gl.FRAMEBUFFER, null);
  gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
  gl.useProgram(textureProgramInfo.program);
  // no need to bind the texture it's already bound
  // no need to set the uniform it defaults to 0
  gl.drawArrays(gl.POINT, 0, 1);  // draw 1 point
}
main();
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
<canvas width="8" height="8" style="width: 128px; height: 128px;"></canvas>

您还可以渲染到TEXTURE_2D_ARRAY纹理的图层。

function main() {
  const gl = document.querySelector('canvas').getContext('webgl2');
  if (!gl) {
    return alert('need webgl2');
  }
  
  const vs = `#version 300 es
  void main() {
    // just draw an 8x8 pixel point in the center of the target
    // this shader needs/uses no attributes
    gl_Position = vec4(0, 0, 0, 1);
    gl_PointSize = 8.0;
  }
  `;
  const fsColor = `#version 300 es
  precision mediump float;
  uniform vec4 color;
  out vec4 outColor;
  void main() {
    outColor = color;
  }
  `;
  const fsTexture = `#version 300 es
  precision mediump float;
  uniform mediump sampler2DArray tex;
  out vec4 outColor;
  void main() {
    // this shader needs no texcoords since we just
    // use gl_PoitnCoord provided by rendering a point with gl.POINTS
    float layer = gl_PointCoord.x * gl_PointCoord.y * 4.0;
    outColor = texture(tex, vec3(gl_PointCoord.xy, layer));
  }
  `;
  
  // compile shaders, link into programs, look up attrib/uniform locations
  const colorProgramInfo = twgl.createProgramInfo(gl, [vs, fsColor]);
  const textureProgramInfo = twgl.createProgramInfo(gl, [vs, fsTexture]);
  
  const tex = gl.createTexture();
  gl.bindTexture(gl.TEXTURE_2D_ARRAY, tex);
  const levels = 1;
  const width = 8;
  const height = 8;
  const layers = 4;
  gl.texStorage3D(gl.TEXTURE_2D_ARRAY, levels, gl.RGBA8, width, height, layers);
  // only use level 0 (of course we could render to levels in layers as well)
  gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
  
  // make a framebuffer for each layer
  const fbs = [];
  for (let layer = 0; layer < layers; ++layer) {
    const fb = gl.createFramebuffer();
    fbs.push(fb);
    gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
    const level = 0;  
    gl.framebufferTextureLayer(
        gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
        tex, level, layer);
  }
  
  // render a different color to each layer
  const colors = [
    [1, 0, 0, 1],  // red
    [0, 1, 0, 1],  // green
    [0, 0, 1, 1],  // blue
    [1, 1, 0, 1],  // yellow
  ];
  gl.useProgram(colorProgramInfo.program);
  for (let layer = 0; layer < layers; ++layer) {
    gl.bindFramebuffer(gl.FRAMEBUFFER, fbs[layer]);
    gl.viewport(0, 0, width, height);
    twgl.setUniforms(colorProgramInfo, { color: colors[layer] });
    const offset = 0;
    const count = 1;
    gl.drawArrays(gl.POINTS, offset, count);  // draw 1 point
  }
  
  // draw the texture's mips to the canvas
  gl.bindFramebuffer(gl.FRAMEBUFFER, null);
  gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
  gl.useProgram(textureProgramInfo.program);
  // no need to bind the texture it's already bound
  // no need to set the uniform it defaults to 0
  gl.drawArrays(gl.POINT, 0, 1);  // draw 1 point
}
main();
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
<canvas width="8" height="8" style="width: 128px; height: 128px; image-rendering: pixelated;"></canvas>