我有一个 3D 球体,我想将一组图像映射到该球体上,并且我希望能够控制每个单独的图像,即独立地淡出/淡入每个图像。我将提供一个示例图片来说明我想要实现的目标,因为我觉得这是解释它的最佳方式。
正如您在上面看到的,每列 8 个图像,每行 16(?)。
我已经能够通过简单地将图像映射到 SphereGeometry 来重新创建上面的图像,但是我希望能够动态交换图像,并在不同时间淡入它们。
到目前为止我尝试过的/我的想法:
我尝试将 8 个测试图像推送到一个数组并将其用作 Material 贴图,然后循环遍历 SphereGeometry 的每个面并分配 1 到 8 的 Material 索引,然后使用模数每 8 后重置一次,但这不起作用:
function createGlobe() { var geomGlobe = new THREE.SphereGeometry(40, 32, 16); var l = geomGlobe.faces.length; imageArray.push(new THREE.MeshBasicMaterial({map: texture1})); imageArray.push(new THREE.MeshBasicMaterial({map: texture2})); imageArray.push(new THREE.MeshBasicMaterial({map: texture3})); imageArray.push(new THREE.MeshBasicMaterial({map: texture4})); imageArray.push(new THREE.MeshBasicMaterial({map: texture5})); imageArray.push(new THREE.MeshBasicMaterial({map: texture6})); imageArray.push(new THREE.MeshBasicMaterial({map: texture7})); imageArray.push(new THREE.MeshBasicMaterial({map: texture8})); for (var i = 0; i < l; i++) { geomGlobe.faces[i].materialIndex = i % 8; } Globe = new THREE.Mesh(geomGlobe, imageArray); scene.add(Globe); }
我想我需要每4或8个面数一下,然后设置 Material 这些面孔中的每一张的索引都相同,以便它们都使用 同一张图片,但我不确定面孔是否正确排列 就这样。
基本上我需要的是:
一种以每列 8 个、每行 16 个方式将图像动态添加到球体的方法,并且能够单独操作每个图像。
非常感谢任何帮助,因为我很困难!
最佳答案
我建议制作一个大 Canvas 并将其用作纹理,然后将过渡动画设置到 Canvas 中,然后设置texture.needsUpdate = true以在GPU上更新它。
您可能会发现纹理更新花费太多时间..在这种情况下,您可以尝试制作2个 Canvas +球体..并通过更改最前面的不透明度在它们之间进行交叉淡入淡出。
下面的代码片段展示了一种通过一些随机填充的 Canvas 将一个球体淡入另一个球体的方法。
var renderer = new THREE.WebGLRenderer();
var w = 300;
var h = 200;
renderer.setSize(w, h);
document.body.appendChild(renderer.domElement);
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(
45, // Field of view
w / h, // Aspect ratio
0.1, // Near
10000 // Far
);
camera.position.set(15, 10, 15);
camera.lookAt(scene.position);
controls = new THREE.OrbitControls(camera, renderer.domElement);
var light = new THREE.PointLight(0xFFFF00);
light.position.set(20, 20, 20);
scene.add(light);
var light1 = new THREE.AmbientLight(0x808080);
light1.position.set(20, 20, 20);
scene.add(light1);
var light2 = new THREE.PointLight(0x00FFFF);
light2.position.set(-20, 20, -20);
scene.add(light2);
var light3 = new THREE.PointLight(0xFF00FF);
light3.position.set(-20, -20, -20);
scene.add(light3);
var sphereGeom = new THREE.SphereGeometry(5, 16, 16);
function rnd(rng) {
return (Math.random() * rng)
}
function irnd(rng) {
return rnd(rng) | 0
}
function randomCanvasTexture(sz) {
var canv = document.createElement('canvas');
canv.width = canv.height = sz;
var ctx = canv.getContext('2d')
for (var i = 0; i < 100; i++) {
ctx.fillStyle = `rgb(${irnd(256)},${irnd(256)},${irnd(256)})`
ctx.fillRect(irnd(sz), irnd(sz), 32, 32)
}
var tex = new THREE.Texture(canv);
tex.needsUpdate = true;
return tex;
}
var material = new THREE.MeshLambertMaterial({
color: 0x808080,
map: randomCanvasTexture(256)
});
var mesh = new THREE.Mesh(sphereGeom, material);
var mesh1 = mesh.clone()
mesh1.material = mesh.material.clone()
mesh1.material.transparent = true;
mesh1.material.opacity = 0.5;
mesh1.material.map = randomCanvasTexture(256)
scene.add(mesh);
scene.add(mesh1);
renderer.setClearColor(0xdddddd, 1);
(function animate() {
mesh1.material.opacity = (Math.sin(performance.now() * 0.001) + 1) * 0.5
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
})();
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/controls/OrbitControls.js"></script>
关于javascript - Three.js - 将多个图像映射到一个球体并控制每个图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51631632/