【问题标题】:Drawing an image on a canvas and returning as a texture在画布上绘制图像并作为纹理返回
【发布时间】:2016-12-27 19:34:06
【问题描述】:

首先,我想明确一点,当谈到 canvas & three.js 时,我是一个绝对的初学者

我采用了一个现有项目,并正在尝试进行一些小的修改,即在纹理上绘制图像而不是仅仅编写文本。我希望纹理具有设置的背景颜色,并将尝试在其上绘制透明的 png 图像。

我正在尝试修改的方法返回一个纹理以用于另一个函数,该函数当前正在执行更多我可能无法在此解释的内容。

我尝试了几种方法,但似乎无法获得我想要的行为。

方法#1

在这种方法中,我得到了背景颜色,但没有显示图像

                var ts = calc_texture_size(size + size * 2 * margin) * 2;
                canvas.width = canvas.height = ts;
                context.fillStyle = back_color;
                context.fillRect(0, 0, canvas.width, canvas.height);
                var img = new Image();
                function drawIcon() {
                    context.drawImage(img,0,0);
                }
                img.onload = drawIcon();
                img.src = "img/test.png";

                var texture = new THREE.Texture(canvas);
                texture.needsUpdate = true;
                return texture;

方法 #2

在做了一些研究之后,似乎我应该使用 TextureLoader,但我不知道如何在画布上绘制颜色/形状。在这种情况下,图像会自行显示,没有任何背景颜色。

 var imgTex = new new THREE.TextureLoader().load( "img/test.png",function(t){
                    texture.map = imgTex;
                });
                texture.needsUpdate = true;
                return texture;

如何在彩色背景上成功绘制图像并将其作为纹理返回以供其他功能使用?

【问题讨论】:

  • HERE 是在画布上组合 2 个图像并将其应用为纹理的示例

标签: three.js html5-canvas


【解决方案1】:

您的问题与 JavaScript 事件处理有很大关系,就像我昨天回答的一个问题:How to make a Json model auto-rotates in the scene?。您永远不能有一个“onload”,然后期望它为您返回变量 - 在执行回调之前不会定义变量。相反,您需要将工作推迟到回调,或者在其他地方继续轮询变量,直到它被定义。

更具体到您的问题:

使用方法 #1,您将回填纹理发送到 GPU,然后向其渲染其他内容,但不会更新加载图像后发送到 GPU 的纹理。将texture.needsUpdate = true; 移动到您的drawIcon() 可能会在这里解决它。未经测试的示例:

var ts = calc_texture_size(size + size * 2 * margin) * 2;
var img = new Image();
var texture = new THREE.Texture(canvas);

canvas.width = canvas.height = ts;
context.fillStyle = back_color;
context.fillRect(0, 0, canvas.width, canvas.height);
img.onload = function() {
    context.drawImage(img,0,0);
    texture.needsUpdate = true;
};
img.src = "img/test.png";
return texture;

注意:您应该始终在 JavaScript 的作用域开头定义您的 var 变量,以使事情更清晰...... drawIcon() 可以访问该 texture 变量,尽管它从您的示例代码中看起来并不像它,因为它似乎在它之后定义,但这不是 JavaScript 的工作方式:var 变量对于它们定义的范围始终是全局的。

使用方法 #2,您需要做一些额外的工作来绘制纹理,将纹理转回画布并将生成的画布发送到 GPU。 ImageLoaderTexture 文档组合提示您需要如何绘制从 TextureLoader 获得的图像。

结合这两种方法,它应该是这样的(也完全未经测试):

var ts = calc_texture_size(size + size * 2 * margin) * 2;
canvas.width = canvas.height = ts;
context.fillStyle = back_color;
context.fillRect(0, 0, canvas.width, canvas.height);

var textureLoader = new THREE.TextureLoader().load(
    "img/test.png",
    function( texture ) {
        var image = texture.image;
        context.drawImage( texture.image, 0, 0 0 );
        var texture = new THREE.Texture(canvas);
        texture.needsUpdate = true;
        // Now do something with texture, like assigning it
        // to your material
    }
);

注意:不要忘记使用数据 URL,如果您需要绘制的图像很小,那么可以将其作为“数据:” URL 包含在您的代码中,这样就无需访问服务器和等待它加载到事件处理程序中。 MDN 的示例。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-10-19
    • 1970-01-01
    • 2013-11-07
    • 2018-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-11
    相关资源
    最近更新 更多