Skybox

Sample Project using the Orientation API to view a skybox

See the full list of sample projects.

This sample HTML file generates a page with a skybox for a user to look around. This demo calls the three.js library and requires WebGL support to build the scene. MotionStack is then used to build in the motion controls.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
    <title>
      MotionStack Orientation three.js interactive test page
    </title>
    <style type="text/css">
      body {
        margin: 0;
        overflow: hidden;
        background-color: #000000;
      }
    </style>
  </head>
  <body>
    <script src="../lib/motionstack-vlatest.js"></script>
    <script type="text/javascript" src="./three.min.js"></script>

    <script type="text/javascript">
      //----------------------
      // Setup THREE.js world
      //----------------------
      var camera, scene, light, renderer;
      var startClientHeight, startFOVFrustrumHeight;

      // build skybox and load texture
      function generateCubeMap() {
        var sides = [
          './textures/posx.jpg',
          './textures/negx.jpg',
          './textures/posy.jpg',
          './textures/negy.jpg',
          './textures/posz.jpg',
          './textures/negz.jpg'
        ];

        var cubemap = THREE.ImageUtils.loadTextureCube(sides);
        cubemap.format = THREE.RGBFormat;

        var shader = THREE.ShaderLib['cube'];
        shader.uniforms['tCube'].value = cubemap;

        var skyBoxMaterial = new THREE.ShaderMaterial( {
          fragmentShader: shader.fragmentShader,
          vertexShader: shader.vertexShader,
          uniforms: shader.uniforms,
          depthWrite: false,
          side: THREE.BackSide
        });

        var skybox = new THREE.Mesh(
          new THREE.BoxGeometry(1000, 1000, 1000),
          skyBoxMaterial
        );

        return skybox;
      }

      // handle window resize gracefully
      function onWindowResize() {
        var relativeFOVFrustrumHeight = startFOVFrustrumHeight * ( window.innerHeight / startClientHeight );
        var relativeVerticalFOV = THREE.Math.radToDeg( 2 * Math.atan( relativeFOVFrustrumHeight / 2000 ) );

        camera.aspect = window.innerWidth / window.innerHeight;
        camera.fov = relativeVerticalFOV;
        camera.updateProjectionMatrix();

        renderer.setSize( window.innerWidth, window.innerHeight );
      }

      // build scene on next browser tick to ensure THREE.js has loaded
      window.requestAnimationFrame(function setupScene() {
        camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 1000 );
        scene = new THREE.Scene();
        scene.add( generateCubeMap() );

        renderer = new THREE.WebGLRenderer();
        renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(renderer.domElement);

        startClientHeight = window.innerHeight;
        startFOVFrustrumHeight = 2000 * Math.tan( THREE.Math.degToRad( (camera.fov || 75) / 2 ) );
        window.addEventListener( 'resize', onWindowResize, false );
      });



      //----------------------
      // Motion controls
      //----------------------
      var viewQuat = new THREE.Quaternion();
      var worldQuat = new THREE.Quaternion(-Math.sqrt(0.5), 0, 0, Math.sqrt(0.5));

      // Define motion controls on next browser tick to ensure MotionStack is loaded
      window.requestAnimationFrame(function setupMotion() {
        var orientation = new MotionStack.Orientation();
        orientation.start(function(e) {
          viewQuat.set(
            e.quaternion.x,
            e.quaternion.y,
            e.quaternion.z,
            e.quaternion.w
          ).premultiply(worldQuat);
        });
      });



      //----------------------
      // Render loop
      //----------------------
      window.requestAnimationFrame(function renderLoop() {
        if (viewQuat) {
          camera.quaternion.copy(viewQuat);
        }

        renderer.render(scene, camera);
        requestAnimationFrame(renderLoop);
      });
    </script>
  </body>
</html>