Three.js 运行时纹理/图像更新

Posted

技术标签:

【中文标题】Three.js 运行时纹理/图像更新【英文标题】:Three.js texture / image update at runtime 【发布时间】:2013-04-10 14:14:53 【问题描述】:

我正在尝试通过从“选择表单”元素中选择一个选项来在运行时更改立方体图像。运行代码时,选择后图像会发生变化,但之前的立方体和图像会留在场景中。

更改材质/图像/纹理时如何正确清除/刷新/更新场景。

<div id = "container"></div>

<form id = "changesForm">
    Cube Image:
    <br>
    <select id = "cubeImage">
        <option value = "random">Random</option>
        <option value = "image1">First Image</option>
        <option value = "Image2">Second Image</option>
    </select>
    <br>
</form>

<script type = "text/javascript">

window.onload = windowLoaded;

function windowLoaded()
    if (window.addEventListener)
        init();
        animate();
                             //document.getElementById('container').addEventListener('mousemove', containerMouseover, false);
    window.addEventListener( 'resize', onWindowResize, false );
    var cubeImage = document.getElementById('cubeImage');
    cubeImage.addEventListener("change", changeCubeImage, false);
    
    else if (window.attachEvent)
        //init();
        //animate();
                  //document.getElementById('container').attachEvent('onmousemove', containerMouseover);
        //window.attachEvent( 'onresize', onWindowResize);
    

function changeCubeImage(e)
    //e.preventDefault();
    var target = e.target;
    cubeImageCheck = target.value;      
    createCube();               


// rest code ..... 

function createCube()
    //image
    var cubeImg;

    switch (cubeImageCheck)
        case 'random': 
           // should load the 2 images random - to do 
            cubeImg = new THREE.ImageUtils.loadTexture("img1.jpg");
           break;
        
        case 'image1': 
            cubeImg = new THREE.ImageUtils.loadTexture("image1.jpg");
            break;
        
        case 'image2': 
            cubeImg = new THREE.ImageUtils.loadTexture("image2.jpg");
            break;
       


cubeImg.needsUpdate = true;


// geometry
var cubeGeometry = new THREE.CubeGeometry(200,200,200);;
// material
var cubeMaterial = new THREE.MeshPhongMaterial(
    map: cubeImg, 
    side:THREE.DoubleSide, 
    transparent: true, 
    opacity:1, 
    shading: THREE.SmoothShading, 
    shininess: 90, 
    specular: 0xFFFFFF
);

cubeMaterial.map.needsUpdate = true;

//mesh
cubeMesh = new THREE.Mesh(cubeGeometry, cubeMaterial);
cubeMesh.needsUpdate = true;
scene.add(cubeMesh);


// rest ....

【问题讨论】:

【参考方案1】:

选择更改后,您可以更新现有网格纹理,无需删除或创建新网格:

mesh.material.map = THREE.ImageUtils.loadTexture( src );
mesh.material.needsUpdate = true;

【讨论】:

如果您之前已将所有纹理预加载到不可见的img 元素中,则此方法显然会检索浏览器缓存的图像。因此无需担心从服务器重新加载图像。 由于之前的纹理没有被释放,这不会导致内存泄漏吗? Kahless - 可能吗?我不确定如何“处置”(也就是摆脱所有引用)在三个中的材质贴图【参考方案2】:

带加载器的完整示例:

首先,创建您的网格并应用任何材料

//Add SPHERE
this.earthMesh = new THREE.Mesh(
  new THREE.SphereBufferGeometry(3, 35, 35),
  new THREE.MeshPhongMaterial()
);
this.scene.add(this.earthMesh);

现在加载您的纹理图像并将其应用到网格材质上

//LOAD TEXTURE and on completion apply it on SPHERE
new THREE.TextureLoader().load(
  "https://images.pexels.com/photos/1089438/pexels-photo-1089438.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260",
  texture => 
    //Update Texture
    this.earthMesh.material.map = texture;
    this.earthMesh.material.needsUpdate = true;
  ,
  xhr => 
    //Download Progress
    console.log((xhr.loaded / xhr.total) * 100 + "% loaded");
  ,
  error => 
    //Error CallBack
    console.log("An error happened" + error);
  
);

进度和错误回调是可选的

【讨论】:

以上是关于Three.js 运行时纹理/图像更新的主要内容,如果未能解决你的问题,请参考以下文章

在运行时使用 Three.js 将文本/图像添加到 Canvas 中呈现的 3D 立方体/模型

three.js css3d 如何更新数据

如何在three.js中为.fbx模型应用纹理?

three.js 图像纹理渲染为颜色(使用 ColladaLoader 加载)

Three.js 更新纹理图片

将模型从 Blender 导出到 Three.js 时没有纹理