【问题标题】:Update texture map in ThreeJS在 ThreeJS 中更新纹理贴图
【发布时间】:2014-09-26 07:55:35
【问题描述】:

对于未来的观众,我可以使用mesh.material.map.image.src = texture;解决它

原问题:

作为 ThreeJS 项目的一部分,我需要更改网格上的纹理。不幸的是,我无法让 Three 更新到新纹理。

我已经尝试了以下 SO 问题中提到的所有方法,但到目前为止没有任何效果:

我要更改的纹理是scene.children[0].children[1].material.map.sourceFile,结构如下所示:

  • SCENE 场景
    • 3DOBJECT 横幅
      • 网格标志
        • MESHBASICMATERIAL 标志_M
          • 纹理标志_MT

flag_MT 纹理是我要更新的,这些是我尝试过的以下方法:

  • flag_M.needsUpdate = true;
  • flag_MT.needsUpdate = true;
  • flag_MT = THREE.ImageUtils.loadTexture(texture); 纹理为 base64 数据字符串
  • 实际上是重新制作整个对象并将其替换到场景中

谢谢。

编辑:代码的重要部分:

init()

flag_MT = THREE.ImageUtils.loadTexture(app.setFlagTexture());
flag_MT.magFilter = THREE.NearestFilter;
flag_MT.minFilter = THREE.NearestFilter;

flag_M = new THREE.MeshBasicMaterial({map: flag_MT});
flag_M.needsUpdate = true;

flag_T = { //easyVectory64 just provides a clean function for making vector maps
    u: easyVector64(2, 62, 20, 1), //up face
    d: easyVector64(22, 62, 20, 1), //down face
    f: easyVector64(1, 23, 20, 40), //front face
    b: easyVector64(22, 23, 20, 40), //back face
    l: easyVector64(0, 23, 1, 40), //left face
    r: easyVector64(41, 23, 1, 40)}; //right face

flag_G.faceVertexUvs[0] = []; //Map texture to mesh
flag_G.faceVertexUvs[0][0] = [flag_T["r"][0], flag_T["r"][1], flag_T["r"][3]];
flag_G.faceVertexUvs[0][1] = [flag_T["r"][1], flag_T["r"][2], flag_T["r"][3]];
flag_G.faceVertexUvs[0][2] = [flag_T["l"][0], flag_T["l"][1], flag_T["l"][3]];
flag_G.faceVertexUvs[0][3] = [flag_T["l"][1], flag_T["l"][2], flag_T["l"][3]];
flag_G.faceVertexUvs[0][4] = [flag_T["u"][0], flag_T["u"][1], flag_T["u"][3]];
flag_G.faceVertexUvs[0][5] = [flag_T["u"][1], flag_T["u"][2], flag_T["u"][3]];
flag_G.faceVertexUvs[0][6] = [flag_T["d"][0], flag_T["d"][1], flag_T["d"][3]];
flag_G.faceVertexUvs[0][7] = [flag_T["d"][1], flag_T["d"][2], flag_T["d"][3]];
flag_G.faceVertexUvs[0][8] = [flag_T["f"][0], flag_T["f"][1], flag_T["f"][3]];
flag_G.faceVertexUvs[0][9] = [flag_T["f"][1], flag_T["f"][2], flag_T["f"][3]];
flag_G.faceVertexUvs[0][10] = [flag_T["b"][0], flag_T["b"][1], flag_T["b"][3]];
flag_G.faceVertexUvs[0][11] = [flag_T["b"][1], flag_T["b"][2], flag_T["b"][3]];

flag_G.applyMatrix(new THREE.Matrix4().makeTranslation(0, -20, 0));

flag = new THREE.Mesh(flag_G, flag_M);

app.setFlagTexture()

//Bunch of code that pre-mixes several textures into a single texture
var texture = "data:image/png;base64,..."; //texture being a base64 png data string
flag_MT = THREE.ImageUtils.loadTexture(texture);
if(flag_M !== undefined){ //because flag_M is undefined on the first call
    flag_M.needsUpdate = true;
}
return texture;

【问题讨论】:

    标签: javascript three.js


    【解决方案1】:

    我在我的项目中遇到了类似的问题,您的第一次尝试应该有效flag_M.needsUpdate = true;

    您可以使用 ImageUtils,flag_MT = THREE.ImageUtils.loadTexture(texture); 重新创建纹理,然后执行 flag_M.needsUpdate = true;,这应该可以。

    但是如果你经常改变你的纹理,这个解决方案确实不是最好的,你应该考虑自己更新纹理对象中的图像源,然后将needsUpdate标志设置为true。

    例如在我的代码中我是这样做的:

    mesh.material.materials[0].map.image = { data: array, width: 20, height: 20 };
    mesh.material.materials[0].map.needsUpdate = true;
    

    mesh 是一个带有 FaceMaterial 的立方体。 array 是一个 Uint8Array 缓冲区,其中包含 RGB 格式的所有数据并完成了工作。 如果可以,出于性能目的,请避免删除和创建只是为了更改它的东西。对你的 GPU 和你的总线来说,这样做比仅仅更新纹理缓冲区更昂贵。

    请发布您必须查看其中有什么问题的代码,因为您的第一次尝试应该已经完成​​了您想要的操作。

    【讨论】:

    • 我已经更新了我上面的问题以包含相关代码。我也试过你的mesh.material.materials[0].map.image = { data: array, width: 20, height: 20 };mesh.material.materials[0].map.needsUpdate = true;,但是如何将图像数据字符串转换为数据数组?
    • 从头开始,使用mesh.maerial.map.image.src = texture;,我能够加载它。感谢您的帮助
    • 我不知道 Three.js 到底是怎么做的,如果他只是保留画布的链接或复制画布的内容。如果它以这种方式工作,那么不要担心!但是,如果您需要更好的性能,请朝这个方向看。
    猜你喜欢
    • 2019-08-12
    • 2022-01-08
    • 2019-03-16
    • 2016-05-03
    • 2019-10-21
    • 2018-12-05
    • 2020-01-18
    • 2015-09-18
    • 2014-03-28
    相关资源
    最近更新 更多