【问题标题】:WebGL mipmap generation fails for TEXTURE_CUBE_MAPTEXTURE_CUBE_MAP 的 WebGL mipmap 生成失败
【发布时间】:2021-06-27 12:27:09
【问题描述】:

我正在尝试将环境映射(使用立方体映射)添加到我的 WebGL 程序:

https://roninbar.github.io/mobius/

我试着按照这个例子:

https://webglfundamentals.org/webgl/lessons/webgl-environment-maps.html

但由于某种原因,我不断收到这个讨厌的警告:

[.WebGL-00006F8000214F00] GL_INVALID_OPERATION: Texture format does not support mipmap generation.

立方体映射不起作用。

这六个cube images 都是 512×512 像素,因此 WebGL 应该不会有任何问题为它们生成 mipmap。

完整的源代码是on GitHub。不过,以下是我认为相关的部分:

function loadTextureAsync(
  gl: WebGLRenderingContext,
  which: number,
  url: string,
  { kind, target }: {
    kind: 'TEXTURE_2D' | 'TEXTURE_CUBE_MAP';
    target: 'TEXTURE_2D' | `TEXTURE_CUBE_MAP_${'POSITIVE' | 'NEGATIVE'}_${'X' | 'Y' | 'Z'}`;
  } = { kind: 'TEXTURE_2D', target: 'TEXTURE_2D' }
): Promise<WebGLTexture> {
  return new Promise(function (resolve, reject) {
    const texture = gl.createTexture();

    if (!texture) {
      return reject(new Error('Failed to create texture object.'));
    }

    gl.activeTexture(which);
    gl.bindTexture(gl[kind], texture);
    gl.texImage2D(
      gl[target],
      0, // level
      gl.RGBA, // internalFormat
      1, // width
      1, // height
      0, // border
      gl.RGBA, // format
      gl.UNSIGNED_BYTE, // type
      null,
    );

    const image = new Image();
    image.src = url;
    image.crossOrigin = '';
    image.addEventListener('load', function () {
      gl.activeTexture(which);
      gl.bindTexture(gl[kind], texture);
      gl.texImage2D(gl[target], 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
      gl.texParameteri(gl[kind], gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
      gl.texParameteri(gl[kind], gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
      gl.texParameteri(gl[kind], gl.TEXTURE_MAG_FILTER, gl.LINEAR);

      // WebGL1 has different requirements for power of 2 images
      // vs non power of 2 images so check if the image is a
      // power of 2 in both dimensions.
      if (kind === 'TEXTURE_2D' && isPowerOf2(image.width) && isPowerOf2(image.height)) {
        // Yes, it's a power of 2. Generate mips.
        gl.generateMipmap(gl[kind]);
        gl.texParameteri(gl[kind], gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
      } else {
        // No, it's not a power of 2. Turn off mips and set
        // wrapping to clamp to edge.
        gl.texParameteri(gl[kind], gl.TEXTURE_MIN_FILTER, gl.LINEAR);
      }

      return resolve(texture);
    });

    return texture;
  });
}

const loadAllTexturesAsync = async function () {
  const promises: Promise<WebGLTexture>[] = [];

  for (const which of [gl.TEXTURE20, gl.TEXTURE21, gl.TEXTURE22, gl.TEXTURE23]) {
    promises.push(loadTextureAsync(gl, which, `${process.env.PUBLIC_URL}/texture/hours${which - gl.TEXTURE20}.bmp`));
  }

  promises.push(loadTextureAsync(gl, gl.TEXTURE10, `${process.env.PUBLIC_URL}/texture/mobius.png`));

  for (const axis of ['X', 'Y', 'Z']) {
    for (const sign of ['NEGATIVE', 'POSITIVE']) {
      promises.push(loadTextureAsync(gl, gl.TEXTURE0, `https://webglfundamentals.org/webgl/resources/images/computer-history-museum/${sign.slice(0, 3).toLowerCase()}-${axis.toLowerCase()}.jpg`, {
        kind: 'TEXTURE_CUBE_MAP',
        target: `TEXTURE_CUBE_MAP_${sign as 'POSITIVE' | 'NEGATIVE'}_${axis as 'X' | 'Y' | 'Z'}`,
      }));
    }
  }

  return Promise.all(promises);
};

loadAllTexturesAsync().then(function () {
  gl.activeTexture(gl.TEXTURE0);
  gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
  gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
});

【问题讨论】:

    标签: reactjs typescript webgl mipmaps


    【解决方案1】:

    我想通了。我的错误是我为整个多维数据集创建了六个不同的WebGLTextures 而不是一个。我将其更改为以下内容:

    function loadTextureAsync(
      gl: WebGLRenderingContext,
      url: string,
      target: 'TEXTURE_2D' | `TEXTURE_CUBE_MAP_${'POSITIVE' | 'NEGATIVE'}_${'X' | 'Y' | 'Z'}` = 'TEXTURE_2D'
    ): Promise<void> {
      return new Promise(function (resolve) {
        const unit = gl.getParameter(gl.ACTIVE_TEXTURE);
        const image = new Image();
        image.src = url;
        image.addEventListener('load', function () {
          gl.activeTexture(unit);
          gl.texImage2D(gl[target], 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
          return resolve();
        });
      });
    }
    
    const loadAllTexturesAsync = async function () {
      const promises: Promise<void>[] = [];
    
      // Environment
      gl.activeTexture(gl.TEXTURE0);
      const texEnv = gl.createTexture();
      if (!texEnv) {
        throw new Error('Failed to create texture.');
      }
      for (const axis of ['X', 'Y', 'Z']) {
        for (const sign of ['NEGATIVE', 'POSITIVE']) {
          gl.bindTexture(gl.TEXTURE_CUBE_MAP, texEnv);
          promises.push(
            loadTextureAsync(gl, `${process.env.PUBLIC_URL}/texture/env/${sign.slice(0, 3).toLowerCase()}-${axis.toLowerCase()}.jpg`, `TEXTURE_CUBE_MAP_${sign as 'POSITIVE' | 'NEGATIVE'}_${axis as 'X' | 'Y' | 'Z'}`),
          );
        }
      }
    
      return Promise.all(promises);
    };
    
    loadAllTexturesAsync().then(function () {
      gl.activeTexture(gl.TEXTURE0);
      gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
      gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
      gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
      gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
      gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
    });
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-10-12
      • 1970-01-01
      • 1970-01-01
      • 2021-07-16
      • 1970-01-01
      • 1970-01-01
      • 2011-12-15
      • 2011-01-17
      相关资源
      最近更新 更多