Three.js 2画面表示
今回は、Three.jsで「2画面表示させる方法」を書きます。
2画面表示とは、こんな感じの事です。
左と右、別々の事を表示させています。
ちなみに、左が立方体を上から見た画面で、右が真横からみたものです。
2画面表示させる方法は、簡単に説明しますと、カメラを2つ作り、シーンオブジェクトに追加するというものです。
やり方を書いていきます。
①
レンダラーオブジェクトを生成した後に、こちらを追加してください。
//rendererはレンダラーオブジェクト renderer.autoClear = false
これを追加しないと、描画されません。
autoClearはWebGLRendererのプロパティの一つです。
②
カメラオブジェクトを2つ作ります。
//カメラオブジェクトを2つ作る。cameraLは左画面,cameraRは右画面です。 //position,lookAtは任意で追加してください。 var cameraL = new THREE.PerspectiveCamera( 45 , width / height , 1 , 10000 ); scene.add(cameraL); cameraL.position.set(100, 300, 500); cameraL.lookAt(scene.position); var cameraR = new THREE.PerspectiveCamera( 45 , width / height , 1 , 10000 ); scene.add(cameraR); cameraR.position.set(0, 0, 569); cameraR.lookAt(scene.position);
③
実際の描画処理の部分です。
これらを無限ループ関数に追加します。
var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight; cameraL.aspect = 0.5 * SCREEN_WIDTH / SCREEN_HEIGHT; cameraR.aspect = 0.5 * SCREEN_WIDTH / SCREEN_HEIGHT; cameraR.updateProjectionMatrix(); cameraL.updateProjectionMatrix(); renderer.setViewport( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT ); renderer.clear(); //左画面 renderer.setViewport( 1, 1, 0.5 * SCREEN_WIDTH - 2, SCREEN_HEIGHT - 2 ); renderer.render( scene, cameraL ); //右画面 renderer.setViewport( 0.5 * SCREEN_WIDTH + 1, 1, 0.5 * SCREEN_WIDTH - 2, SCREEN_HEIGHT - 2 ); renderer.render( scene, cameraR );
「cameraL.aspect」でアスペクト比を調節しています。
updateProjectMatrix()は、カメラの内部状態を更新するものです。
以上で終わりです。
次に、青い立方体を表示するプログラムに「2画面表示」,「Orbitcontrols.js」を追加したコードを全文書きます。
<!DOCTYPE html> <html> <head> <title>introduction</title> <meta charset="utf-8"> <script src="Three.js"></script> <script src="OrbitControls.js"></script> <link rel="stylesheet" type="text/css" href="mobile/screan.css"> </head> <body onload="threeStart();" , style="overflow: hidden;"> <div id="canvas-frame"></div> <script> var width, height; var renderer; function initThree() { width = document.getElementById('canvas-frame').clientWidth; height = document.getElementById('canvas-frame').clientHeight; renderer = new THREE.WebGLRenderer({antialias: true}); renderer.setSize(width, height); document.getElementById('canvas-frame').appendChild(renderer.domElement); renderer.shadowMapEnabled = true; renderer.autoClear = false } var cameraL,cameraR; var controls; function initCamera() { cameraL = new THREE.PerspectiveCamera( 45 , width / height , 1 , 10000 ); scene.add(cameraL); cameraL.position.set(100, 300, 500); cameraL.lookAt(scene.position); cameraR = new THREE.PerspectiveCamera( 45 , width / height , 1 , 10000 ); scene.add(cameraR); cameraR.position.set(0, 0, 569); cameraR.lookAt(scene.position); controls = new THREE.OrbitControls(cameraR); } var scene; function initScene() { scene = new THREE.Scene(); } var light, light2; function initLight() { light = new THREE.DirectionalLight(0xcccccc,1.6); light.position = new THREE.Vector3(-100, 500, 800); light.castShadow = true; light.shadowMapWidth = 2048; light.shadowMapHeight = 2048; scene.add(light); light2 = new THREE.AmbientLight(0x333333); scene.add(light2); } var cube,plane; function initObject(){ cube = new THREE.Mesh( new THREE.CubeGeometry(80,80,80), new THREE.MeshPhongMaterial({ color: 0x0000ff, wireframe:false })); cube.castShadow = true; cube.receiveShadow = true; scene.add(cube); cube.position.set(0,100,100); plane = new THREE.Mesh( new THREE.PlaneGeometry(1000, 1000, 10, 10), new THREE.MeshLambertMaterial({ side: THREE.DoubleSide, color: 0xCD5C5C })); plane.position.set(0,0,1); plane.receiveShadow = true; scene.add(plane); } function loop(){ controls.update(); requestAnimationFrame(loop); var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight; cameraL.aspect = 0.5 * SCREEN_WIDTH / SCREEN_HEIGHT; cameraR.aspect = 0.5 * SCREEN_WIDTH / SCREEN_HEIGHT; cameraR.updateProjectionMatrix(); cameraL.updateProjectionMatrix(); renderer.setViewport( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT ); renderer.clear(); renderer.setViewport( 1, 1, 0.5 * SCREEN_WIDTH - 2, SCREEN_HEIGHT - 2 ); renderer.render( scene, cameraL ); renderer.setViewport( 0.5 * SCREEN_WIDTH + 1, 1, 0.5 * SCREEN_WIDTH - 2, SCREEN_HEIGHT - 2 ); renderer.render( scene, cameraR ); } function threeStart() { initThree(); initScene(); initCamera(); initLight(); initObject(); loop(); } </script> </body> </html>
div#canvas-frame{ width: 100%; height: 100%; position: fixed; top: 0; left: 0; background-color: #EEEEEE; }
2画面表示を少し応用すると、4画面表示なども出来るようです。
これで終わりです。
ご不明な点などがありましたら、遠慮なくご質問ください。
ありがとうございました!