Heightmap

heightmap.png

Heightmapとは

高さを輝度で表現した絵です

高さマップの用途

地形・海のレンダリングに使用します

Three.jsによるデモ

heightmapテクスチャとしてこれを使用します。
大きさは257x257です
heightmap257.png
ソースコード
   var imgPath ='http://miffysora.wdfiles.com/local--files/heightmap/heightmap257.png';
    var width=400;
    var height=400;
     var scene = new THREE.Scene(); 
    var camera = new THREE.PerspectiveCamera(65, width / height, 0.1, 10000);
    camera.position.z = 1000;
    var controls = new THREE.OrbitControls(camera);
 
    var renderer = new THREE.WebGLRenderer({ alpha: true ,antialias:true});
    renderer.setClearColor( new THREE.Color(0xffffff),0.0);//背景色
    renderer.setSize(width, height); 
    document.body.appendChild(renderer.domElement); 
 
//画像から高さデータを取得して返す関数
function getHeightData(img,scale) {
 if (scale == undefined) scale=1;
    var canvas = document.createElement( 'canvas' );
    canvas.width = img.width;
    canvas.height = img.height;
    var context = canvas.getContext( '2d' );
 
    var size = img.width * img.height;
    var data = new Float32Array( size );
 
    context.drawImage(img,0,0);
 
    for ( var i = 0; i < size; i ++ ) {
        data[i] = 0
    }
 
    var imgd = context.getImageData(0, 0, img.width, img.height);
    var pix = imgd.data;
 
    var j=0;
    for (var i = 0; i<pix.length; i +=4) {
        var all = pix[i]+pix[i+1]+pix[i+2];
        data[j++] = all/(12*scale);
    }
 
    return data;
}
 
var img = new Image();
img.onload = function () {
 
    console.log("get height data from img");
    var data = getHeightData(img);//画像から高さデータを取得する
 
    //ライティング
    var directionalLight = new THREE.DirectionalLight( 0xffffff, 3 ); //平行光源(色、強度)
    directionalLight.position.set(0,0,3);
    scene.add( directionalLight );
 
    //面を初期化
    var geometry = new THREE.PlaneGeometry(1000,1000,256,256);//分割数はheightmapの画像サイズの各辺-1
    var texloader = new THREE.TextureLoader();
    var texture =texloader.load(imgPath );
    var material = new THREE.MeshLambertMaterial( { map: texture } );
    plane = new THREE.Mesh( geometry, material );
 
    //頂点のz値に高さの値を入れる
    for ( var i = 0; i<plane.geometry.vertices.length; i++ ) {
         plane.geometry.vertices[i].z = data[i];
    }
   //planeの初期見栄えを調整
   plane.rotation.x=-Math.PI /3.0;
 
    scene.add(plane);
 
};
// URL を指定して、画像の読み込みを開始する
img.src =imgPath  ;
 
animate();
function animate() {
   requestAnimationFrame( animate );
   controls.update();
   renderer.render( scene, camera );
}

ポイント

  • THREE.Geometry.verticesで各頂点データの読み書きができる
  • THREE.Textureのimageプロパティは常にundefinedになっていてアクセスできない。なので、javascriptのHTMLImageElementにして画素のデータを取り出す

サポートサイト Wikidot.com