LoginSignup
2
0

More than 3 years have passed since last update.

EmissiveMapを使ってマイクラのエンチャントを再現する

Last updated at Posted at 2019-08-07

EmissiveMapとは

テクスチャマップを部分的に光っているようにみせることができるマッピング画像で、Three.jsでは MeshPhongMaterialや、MeshLambertMaterialなどのoptionで指定することができます。
AlphaMapと同じグレイスケールの画像で、白い部分はemissiveプロパティに指定した色で光って見えるようになり、黒い部分は元のまま表示されます。

EmissiveMapは、テクスチャに部分的に色を乗せるイメージではなく、半透明レイヤーのように独立しているイメージです。
またMeshBasicMaterialのようにライティングの影響を受けないため、暗いライティングでも光って見えます。

指定方法

    // マテリアルの作成
    let material = new THREE.MeshLambertMaterial({
        map: texture,
        emissiveMap: emissiveTexture, /// グレイスケールのTHREE.Textureオブジェクト
        emissive: "#FF0000", /// 光らせたい色
    })

ざんねんながら、複数の色は指定できません。

    // マテリアルの作成
    let material = new THREE.MeshLambertMaterial({
        map: texture,
        emissiveMap: [emissiveTexture1, emissiveTexture2], 
        emissive: ["#FF0000", "#0000FF"]
    })
        //////// 何も起きない ////////

See the Pen Minecraft Enchanted item by Urushibara (@pneuma01) on CodePen.

解説のようなもの

モデルの初期化

ゆらめく様にアニメーションさせたいので、あらかじめアニメーション分のEmissiveMapを作成しておきます。


    // Sceneの初期化
    const scene = new THREE.Scene();

    // Geometryの作成
    let img = document.querySelector("#item");
    let canvas = createCanvas(img.width, img.height);
    canvas.context.drawImage(img, 0, 0);
    let geometry = new THREE.PixelArtGeometry(canvas.canvas, 1);
    canvas.canvas.remove();

    // 基本テクスチャの作成
    let texture = new THREE.TextureLoader().load(img.src);
    texture.magFilter = THREE.NearestFilter;
    texture.minFilter = THREE.NearestFilter;
    texture.type = THREE.FloatType;

    // アニメーション Emissive Map の作成
    let emissiveMaps = [];
    for(let i=0; i<56; i++){
        let canvas = drawAnimated(i);
        let texture = new THREE.CanvasTexture(canvas);
        texture.magFilter = THREE.NearestFilter;
        texture.minFilter = THREE.NearestFilter;
        texture.type = THREE.FloatType;
        emissiveMaps.push(texture);
    }

    // マテリアルの作成
    let material = new THREE.MeshLambertMaterial({
        map: texture,
        emissiveMap: emissiveMaps[0],
        emissive: "#7F007F", /// Emissive Color
        transparent: false,
        side: THREE.DoubleSide,
        alphaTest: 0.99 
    })

    // Mesh の作成
    let box = new THREE.Mesh(
        geometry, 
        material
    );
    box.scale.set(10, 10, 10);
    main_object = box;

    // Sceneへ追加
    scene.add(main_object);

アニメーション

描画tick呼び出し時に、emissiveMapを次々と入れ替えます。
CanvasTextureを使ってリアルタイムでEmissiveMapを描画するのも試してみましたが、かなり重たかったのでやめました。


        //// Tick ////
        function tick() {

            // オブジェクトの位置
            pos_cycle = pos_cycle < 360 ? pos_cycle + 1 : 0;
            var y = Math.sin(deg2rad(pos_cycle * 2)) * 20;
            main_object.position.set(0, -y, 0);
            main_object.rotation.set(0, deg2rad(pos_cycle * 1), 0);

            // Emissive Map の切り替え
            main_object.material.emissiveMap = emissiveMaps[Math.floor(glint_cycle)];
            glint_cycle = glint_cycle < emissiveMaps.length ? glint_cycle + 0.1 : 0;

            // 描画
            renderer.render(scene, camera);
            requestAnimationFrame(tick);
        }
2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0