简体   繁体   English

在ThreeJS中更新纹理贴图

[英]Update texture map in ThreeJS

For future viewers , I was able to solve it by using mesh.material.map.image.src = texture; 对于未来的观众 ,我能够通过使用mesh.material.map.image.src = texture;来解决它mesh.material.map.image.src = texture;

Original question: 原始问题:

As part of my ThreeJS project, I need to change the texture on a mesh. 作为我的ThreeJS项目的一部分,我需要更改网格上的纹理。 Unfortunately, I can't get Three to update to the new texture. 不幸的是,我无法让Three更新到新纹理。

I've tried all the things mentioned in the following SO questions, but nothing has worked so far: 我已经尝试了以下SO问题中提到的所有内容,但到目前为止还没有任何工作:

The texture that I am trying to change is scene.children[0].children[1].material.map.sourceFile and the structure looks like this: 我想要改变的纹理是scene.children[0].children[1].material.map.sourceFile ,结构如下所示:

  • SCENE scene 场景现场
    • 3DOBJECT banner 3DOBJECT横幅
      • MESH flag MESH标志
        • MESHBASICMATERIAL flag_M MESHBASICMATERIAL flag_M
          • TEXTURE flag_MT TEXTURE flag_MT

flag_MT texture is the one I want to update and these are the following methods I've tried: flag_MT纹理是我想要更新的纹理,这些是我尝试过的以下方法:

  • flag_M.needsUpdate = true;
  • flag_MT.needsUpdate = true;
  • flag_MT = THREE.ImageUtils.loadTexture(texture); with texture being a base64 data string 纹理是base64数据字符串
  • practically remaking the entire object and replacing that into the scene 实际上重塑整个对象并将其替换为场景

Thanks. 谢谢。

Edit: The important parts of code: 编辑:代码的重要部分:

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;

I had a similar issue in my project and your first try should have worked flag_M.needsUpdate = true; 我在我的项目中遇到了类似的问题,你的第一次尝试应该工作了flag_M.needsUpdate = true;

You can recreate a texture with ImageUtils, flag_MT = THREE.ImageUtils.loadTexture(texture); 您可以使用ImageUtils重新创建纹理, flag_MT = THREE.ImageUtils.loadTexture(texture); and then do flag_M.needsUpdate = true; 然后执行flag_M.needsUpdate = true; and this should work. 这应该工作。

But this solution is really not the best if you change your texture too often and you should think about updating by yourself the image source in the Texture Object and then put to true the needsUpdate flag. 但是如果你经常更改纹理,这个解决方案真的不是最好的,你应该考虑自己更新纹理对象中的图像源,然后将needsUpdate标志置为true。

For example in my code I did this : 例如,在我的代码中,我这样做了:

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

mesh was a cube with a FaceMaterial. mesh是一个带有FaceMaterial的立方体。 array is an Uint8Array buffer containing all the data in RGB format and did the work. array是一个Uint8Array缓冲区,包含RGB格式的所有数据并完成了工作。 If you can, for performance purpose, avoid deleting and creating things just to change it. 如果出于性能目的,可以避免删除和创建只是为了更改它。 It's more expensive for your GPU and your bus to do that, than just update the texture buffer. 你的GPU和你的总线要比更新纹理缓冲区更昂贵。

And please, post the code you have to see what is wrong in it, since your firt try should have done what you want. 并且,请发布你需要的代码,看看它有什么问题,因为你的第一次尝试应该做你想要的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM