【问题标题】:Save & load a texture with alpha component in three.js在 three.js 中保存和加载带有 alpha 分量的纹理
【发布时间】:2021-05-18 03:50:52
【问题描述】:

以下代码非常适用于不包含 alpha 通道的图像:

toJSON() {
    let output = super.toJSON();
    output["geometry"] = this.geometry;
    output['imageURL'] = this.mesh.toJSON().images[0]["url"];
    return output;
}

fromJSON(data) {
    super.fromJSON(data);
    this.geometry = data["geometry"];
    this.image_path = data["imageURL"];
    this.refreshImage();
}

refreshImage() {
    const this_obj = this;
    const image_texture = new THREE.TextureLoader().load(
        //image to load
        this.image_path,
        //onLoad callback to create the material only once the texture is loaded and its dimensions are available,
        //this will ensure aspect ratio is based on the actual texture loaded.
        (texture) => {
            this_obj.changeGeometry(texture.image.width / texture.image.height)
        },
        //not required
        undefined,
        //onError callback
        (err) => {
            alert("An error occurred while attempting to load image");
        }
    );
    this.mesh.material.map.dispose();
    this.mesh.material.dispose();
    this.mesh.material = new THREE.MeshPhongMaterial({map: image_texture, side: THREE.DoubleSide,
        transparent: true})
    this.mesh.material.color.set(this.color);

    this.mesh.material.needsUpdate = true;
}

很遗憾,它不适用于具有 Alpha 通道的图像,因为透明区域会以黑色不透明颜色呈现。

有谁知道为什么会发生这种情况以及如何最好地达到预期的结果?

编辑:

当我意识到问题来自 Mesh.toJSON 调用时,我得到了问题的答案。该方法是一种递归方法,它是一个真正的兔子洞。但是在兔子洞的底部,您会发现纹理图像通过将图像绘制到临时内部画布上而转换为 base64。这发生在 getDataURL() 函数内的 ImageUtils.js 模块中

问题是宽度或高度大于 2048 的纹理图像被转换为​​压缩的“jpeg”格式,而不是保留 alpha 分量的“png”格式。

这说明了一切。

您可以加载任何图像,使用 TextureLoader 将其应用到材质,但一旦您调用 toJSON 序列化您的网格,如果底层图像的宽度或长度大于 2048,则 alpha 组件会丢失。

在我的情况下,解决方案是编写自己的函数,将图像绘制到画布并将图像转换为 base64,但支持更大的图像尺寸。当然,必须警告用户执行转换可能需要一些时间。

【问题讨论】:

    标签: json three.js textures


    【解决方案1】:

    这是我想出的纹理到 url 转换器...从 ImageUtils.js 中大量窃取并删除错误处理代码。

    function ImageURLfromTexture( image_texture, retain_alpha = true ) {
        const image = image_texture.image;
        if (image !== undefined) {
                if (/^data:/i.test(image.src)) {
                    return image.src;
                }
                let _canvas = document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas');
                _canvas.width = image.width;
                _canvas.height = image.height;
    
                const context = _canvas.getContext('2d');
                if (image instanceof ImageData) {
                    context.putImageData(image, 0, 0);
                } else {
                    context.drawImage(image, 0, 0, image.width, image.height);
                }
                if ((_canvas.width > 2048 || _canvas.height > 2048) && (!retain_alpha)) {
                    return _canvas.toDataURL('image/jpeg', 0.6);
                } else {
                    return _canvas.toDataURL('image/png');
                }
        } else {
            return null;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2018-10-06
      • 2013-06-28
      • 2018-04-02
      • 2015-05-30
      • 1970-01-01
      • 2014-03-10
      • 1970-01-01
      • 1970-01-01
      • 2016-10-11
      相关资源
      最近更新 更多