きっかけ
WebXRの仕事でTexture切り替えをすることになった。
大層なものは作っていないが、動くものをメモで残しておきたい。
本番はVue.jsでやるものの、まずはJavaScriptでやる方法から残しておく。
※ Vue.js版も投稿しました
やりたいこと
CubeのTextureを
ソースコード
まずはCubeを表示させて、Textureを張る。
SelectBoxでTextureのイメージを切り替える。
changeTexture.html
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<title>change texture</title>
<select onchange="onChange(this.value)">
<option value="circle.png">Circle</option>
<option value="gori128.png">Gori</option>
</select>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/85/three.min.js"></script>
<script>
// scene
const scene = new THREE.Scene();
// renderer
const renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true }); // force background transparent
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// camera
const camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 0, 10);
// light
const light = new THREE.AmbientLight(0xffffff);
scene.add(light);
// cube
const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);
const cubeMaterial = new THREE.MeshBasicMaterial({
map: new THREE.TextureLoader().load("circle.png")
});
const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube.name = "cube" // need name to find object afterwards
scene.add(cube);
render();
function render() {
cube.rotation.x += 0.1;
cube.rotation.y += 0.1;
requestAnimationFrame(render);
renderer.render(scene, camera);
}
function onChange(val) {
const object = scene.getObjectByName("cube"); // find obj by name
object.material.map = new THREE.TextureLoader().load(val);
object.material.needsUpdate = true; // necessary
}
</script>
</body>
</html>
プロジェクトの起動
http-serverを使う。
Three.jsのテクスチャ関連は、Http起動してあげないと読み込まない。
$npm install --global http-server
$http-server . -p 8000
結果
メモ
Cubeオブジェクトに名前を付けておいて、後からCubeを検索してMaterialを更新する。
needsUpdate = true;
がないと、Materialは更新されない。
テクスチャの貼り方はググると色々やり方がありそうなものの、thee.js公式ホームページによると、THREE.TextureLoaderが一番一般的なやり方のよう。
Cubeの6面に違うイメージを張る場合にはTHREE.CubeTextureLoaderが良い。
SkyBoxみたいなのに役立つ。↓昔作ったSkyBoxのメモ。いつかまたキレイにしたい。
skybox.js
class Skybox {
constructor(urls) {
var texCube = new THREE.CubeTextureLoader().load(urls);
texCube.format = THREE.RGBFormat;
texCube.mapping = THREE.CubeReflectionMapping;
// skybox用のマテリアルを生成
var cubeShader = THREE.ShaderLib["cube"];
var cubeMat = new THREE.ShaderMaterial({
fragmentShader: cubeShader.fragmentShader,
vertexShader: cubeShader.vertexShader,
uniforms: cubeShader.uniforms,
depthWrite: false,
side: THREE.BackSide,
});
cubeMat.uniforms["tCube"].value = texCube;
// Skybox用ジオメトリ生成
var d = 10000;
var cubeGeo = new THREE.BoxGeometry(d, d, d);
this.cubeMesh = new THREE.Mesh(cubeGeo, cubeMat);
return this.cubeMesh
}
}