shonen.hateblo.jp

やったこと,しらべたことを書く.

立方体の各面にテクスチャを貼る - three.js アプリ

HelloWorld(https://threejs.org/docs/index.html#manual/introduction/Creating-a-scene)の次からいきなり詰んだので記事書きました .

環境

  • 0.95.0 from npm

dom操作が苦手なので必要以上にjqueryが登場しますが,その場合はv3とします.

material

次のコードは https://threejs.org/docs/index.html#manual/introduction/Creating-a-scene と殆ど変わらない.

textureの情報を持つmaterialを作って適用することで,textureが貼られた立方体が生成される.

なので,コメントで区切られた部分を書き換える.

const screenWidth = 800;
const screenHeight = 600;
let scene;
let camera;
let renderer;

$(()=>{

    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera( 75, screenWidth/screenHeight, 0.1, 1000 );
    
    renderer = new THREE.WebGLRenderer();
    renderer.setSize( screenWidth, screenHeight );
    $("#wrapper").append($(renderer.domElement));
    
    let geometry = new THREE.BoxGeometry(10, 10, 10);
    
    // ======================================

    let material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );

    // ======================================
    
    let cube = new THREE.Mesh( geometry, material );
    scene.add( cube );
    
    camera.position.set(0,0,15);
    
    let animate = () => {
        requestAnimationFrame( animate );
    
        cube.rotation.x += 0.01;
        cube.rotation.y += 0.015;
    
        renderer.render( scene, camera );
    };
    
    animate();
});

各面に同じテクスチャを貼る

texture を読み込むために TextureLoader を使う.callbackが指定できるので,非同期かな?.

https://threejs.org/docs/index.html#api/loaders/TextureLoader

material の生成は,無地と同様に MeshBasicMaterial が使える.

https://threejs.org/docs/index.html#api/materials/MeshBasicMaterial

次の例では,./a/sai1.png を読み込んで,6面に表示させている.(1面に1枚の画像)

let loader = new THREE.TextureLoader();
let texture = loader.load( 'a/sai1.png' );
let material = new THREE.MeshBasicMaterial( { map: texture } );

6面に異なるテクスチャを貼る

6つmaterialを生成して,配列で纏めれば良い.

let loader = new THREE.TextureLoader();
let material = [
    new THREE.MeshBasicMaterial({map: loader.load( 'a/sai2.png' )}),
    new THREE.MeshBasicMaterial({map: loader.load( 'a/sai5.png' )}),
    new THREE.MeshBasicMaterial({map: loader.load( 'a/sai3.png' )}),
    new THREE.MeshBasicMaterial({map: loader.load( 'a/sai4.png' )}),
    new THREE.MeshBasicMaterial({map: loader.load( 'a/sai1.png' )}),
    new THREE.MeshBasicMaterial({map: loader.load( 'a/sai6.png' )})
];

1枚の画像で出来ないのか?

MeshStandardMaterial とか,UV指定してやれば出来るんじゃないのーと思っていましたが,(画像すら)うまく表示させることが出来ず.

壁紙を指定するサンプルコードも6枚指定しているので,この実装がthree.jsにとってスタンダードかもしれません.

new THREE.CubeTextureLoader()
        .setPath('a/')
        .load(['bg.gif', 'bg.gif', 'bg.gif', 'bg.gif', 'bg.gif', 'bg.gif'], (textureCube) => {
            scene.background = textureCube;
    });