WebGL With Three.js – Lesson 3

WebGL With Three.js – Lesson 3

0 57385
WebGL With Three.js - Lesson 3
WebGL With Three.js - Lesson 3

WebGL With Three.js – Lesson 3

Most programmers who are just starting to comprehend the basics of working with 3D (in webgl), usually have difficulties in understanding three-dimensional space. Because we have one extra dimension (volume) compared with what you are used to. Also you may have difficulty in understanding how the different light works, or even how axis are located in space. Today I will help you to deal with these issues. Three.js has all the necessary means to for this – Helpers. In today’s examples, I have prepared you for working demonstration of all existing helpers: ArrowHelper, AxisHelper, BoundingBoxHelper, CameraHelper, DirectionalLightHelper, GridHelper, HemisphereLightHelper, PointLightHelper, SpotLightHelper. All of them will help you understand the insides of WebGL.

Live Demo
Live Demo 2

HTML

This section has not changed, nothing has been added:

<!DOCTYPE html>
<html lang="en" >
    <head>
        <meta charset="utf-8" />
        <meta name="author" content="Script Tutorials" />
        <title>WebGL With Three.js - Lesson 3 | Script Tutorials</title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
        <link href="css/main.css" rel="stylesheet" type="text/css" />
    </head>
    <body>
        <script src="js/three.min.js"></script>
        <script src="js/THREEx.WindowResize.js"></script>
        <script src="js/OrbitControls.js"></script>
        <script src="js/stats.min.js"></script>
        <script src="js/script.js"></script>
    </body>
</html>

Javascript

For a start, let’s create some simple scene that includes the following elements: camera, direct light, the ground and two spheres.:

var dLight, bboxHelper, dlightHelper;
// load texture
var texture = THREE.ImageUtils.loadTexture('texture.png');
texture.repeat.set(10, 10);
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
texture.anisotropy = 16;
texture.needsUpdate = true;
var textureBump = THREE.ImageUtils.loadTexture('bump.png');
textureBump.repeat.set(10, 10);
textureBump.wrapS = textureBump.wrapT = THREE.RepeatWrapping;
textureBump.anisotropy = 16;
textureBump.needsUpdate = true;
var lesson3 = {
    scene: null,
    camera: null,
    renderer: null,
    container: null,
    controls: null,
    clock: null,
    stats: null,
    init: function() { // Initialization
        // create main scene
        this.scene = new THREE.Scene();
        var SCREEN_WIDTH = window.innerWidth,
            SCREEN_HEIGHT = window.innerHeight;
        // prepare camera
        var VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 1, FAR = 10000;
        this.camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR);
        this.scene.add(this.camera);
        this.camera.position.set(-1600, 600, 1200);
        this.camera.lookAt(new THREE.Vector3(0,0,0));
        // prepare renderer
        this.renderer = new THREE.WebGLRenderer({antialias:true, alpha: false});
        this.renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
        this.renderer.setClearColor(0xffffff);
        this.renderer.shadowMapEnabled = true;
        this.renderer.shadowMapSoft = true;
        // prepare container
        this.container = document.createElement('div');
        document.body.appendChild(this.container);
        this.container.appendChild(this.renderer.domElement);
        // events
        THREEx.WindowResize(this.renderer, this.camera);
        // prepare controls (OrbitControls)
        this.controls = new THREE.OrbitControls(this.camera, this.renderer.domElement);
        this.controls.target = new THREE.Vector3(0, 0, 0);
        // prepare clock
        this.clock = new THREE.Clock();
        // prepare stats
        this.stats = new Stats();
        this.stats.domElement.style.position = 'absolute';
        this.stats.domElement.style.bottom = '0px';
        this.stats.domElement.style.zIndex = 10;
        this.container.appendChild( this.stats.domElement );
        // add directional light
        dLight = new THREE.DirectionalLight(0xffffff);
        dLight.position.set(0, 400, 0);
        dLight.castShadow = true;
        // dLight.shadowCameraVisible = true;
        dLight.shadowMapWidth = dLight.shadowMapHeight = 1000;
        this.scene.add(dLight);
        // add simple ground
        var groundGeometry = new THREE.PlaneGeometry(1200, 1200, 1, 1);
        ground = new THREE.Mesh(groundGeometry, new THREE.MeshLambertMaterial({
            color: 0x9669FE
        }));
        ground.position.y = -20;
        ground.rotation.x = - Math.PI / 2;
        ground.receiveShadow = true;
        this.scene.add(ground);
        // create a new group (Object3D)
        var group = new THREE.Object3D();
        // add two spheres
        var sphere  = this.drawSphere(-100, 150, new THREE.MeshPhongMaterial({ map: texture, bumpMap: textureBump, color: 0x00ff00, specular: 0xff2200, emissive: 0x004000 }));
        var sphere2 = this.drawSphere( 100, 150, new THREE.MeshPhongMaterial({ map: texture, bumpMap: textureBump, color: 0x00ff00, specular: 0xff2200, shininess: 3 }));
        // and add them into the group
        group.add(sphere);
        group.add(sphere2);
        this.scene.add(group);
    },
    drawSphere: function(x, z, material) {
        var sphere = new THREE.Mesh(new THREE.SphereGeometry(70, 70, 20), material);
        sphere.rotation.x = sphere.rotation.z = Math.PI * Math.random();
        sphere.position.x = x;
        sphere.position.y = 100;
        sphere.position.z = z;
        sphere.castShadow = sphere.receiveShadow = true;
        return sphere;
    }
};
// Animate the scene
function animate() {
    requestAnimationFrame(animate);
    render();
    update();
}
// Update controls and stats
function update() {
    bboxHelper.update();
    dlightHelper.update();
    lesson3.controls.update(lesson3.clock.getDelta());
    lesson3.stats.update();
    // smoothly move the dLight
    var timer = Date.now() * 0.000025;
    dLight.position.x = Math.sin(timer * 5) * 300;
    dLight.position.z = Math.cos(timer * 5) * 300;
}
// Render the scene
function render() {
    if (lesson3.renderer) {
        lesson3.renderer.render(lesson3.scene, lesson3.camera);
    }
}
// Initialize lesson on page load
function initializeLesson() {
    lesson3.init();
    animate();
}
if (window.addEventListener)
    window.addEventListener('load', initializeLesson, false);
else if (window.attachEvent)
    window.attachEvent('onload', initializeLesson);
else window.onload = initializeLesson;

Please pay attention that two spheres were added into the group (which is ordinary Object3D object). Now, we can start the overview of the helpers.

ArrowHelper

It draws a 3D arrow (starting in origin in the direction dir for a certain length) in space. This helps to understand the direction of a vector in space. To add this helper, use the following code:

  // 1. ArrowHelper
  var directionV3 = new THREE.Vector3(1, 0, 1);
  var originV3 = new THREE.Vector3(0, 200, 0);
  var arrowHelper = new THREE.ArrowHelper(directionV3, originV3, 100, 0xff0000, 20, 10); // 100 is length, 20 and 10 are head length and width
  this.scene.add(arrowHelper);

AxisHelper

It draws an axis object to visualize the the 3 axis in a simple way. The X axis is red. The Y axis is green. The Z axis is blue. This helps to understand the direction of all three axis in space. To add this helper, use the following code:

  // 2. AxisHelper
  var axisHelper = new THREE.AxisHelper(800); // 500 is size
  this.scene.add(axisHelper);

BoundingBoxHelper

It draws a line object to the boundingbox of any object (Object3D) to show the world-axis-aligned bounding box for this object. Remember what we combined the two spheres in the single group object? To add this helper, use the following code:

  // 3. BoundingBoxHelper
  bboxHelper = new THREE.BoundingBoxHelper(group, 0x999999);
  this.scene.add(bboxHelper);

CameraHelper

It draws a specific Object3D object (it looks like pyramid) with line geometry, that helps visualizing what a specified camera contains in its frustum. To add this helper, use the following code:

  // 4. CameraHelper
  var cameraParObj = new THREE.Object3D();
  cameraParObj.position.y = 200;
  cameraParObj.position.z = 700;
  this.scene.add(cameraParObj);
  perspectiveCamera = new THREE.PerspectiveCamera(90, window.innerWidth / window.innerHeight, 0.01, 1500);
  cameraParObj.add(perspectiveCamera);
  var cameraHelper = new THREE.CameraHelper(perspectiveCamera);
  this.scene.add(cameraHelper);

DirectionalLightHelper

It draws a line object to show the direction of a directional light. We will gradually move our source of light for you to see clearly this helper. To add this helper, use the following code:

  // 5. DirectionalLightHelper
  dlightHelper = new THREE.DirectionalLightHelper(dLight, 50); // 50 is helper size
  this.scene.add(dlightHelper);

GridHelper

To see the rest of the helpers, we created the second demo. The next is GridHelper, this helper draws a two-dimensional grid of lines. To add this helper, use the following code:

  var gridHelper = new THREE.GridHelper(500, 40); // 500 is grid size, 20 is grid step
  gridHelper.position = new THREE.Vector3(0, 0, 0);
  gridHelper.rotation = new THREE.Euler(0, 0, 0);
  this.scene.add(gridHelper);
  var gridHelper2 = gridHelper.clone();
  gridHelper2.rotation = new THREE.Euler(Math.PI / 2, 0, 0);
  this.scene.add(gridHelper2);
  var gridHelper3 = gridHelper.clone();
  gridHelper3.rotation = new THREE.Euler(Math.PI / 2, 0, Math.PI / 2);
  this.scene.add(gridHelper3);

Please note, that we created three two-dimensional grid (for all three axis).

HemisphereLightHelper

The rest three helpers are for lights, the HemisphereLightHelper is for HemisphereLight object. We had to turn off our directional light and enable the hemisphere light. To add this helper, use the following code:

  // add hemisphere light
  var hemiLight = new THREE.HemisphereLight(0x0000ff, 0x00ff00, 0.4);
  hemiLight.color.setHSL(0.6, 1, 0.6);
  hemiLight.groundColor.setHSL(0.095, 1, 0.75);
  hemiLight.position.set(-200, 400, -200);
  this.scene.add(hemiLight);
  var hlightHelper = new THREE.HemisphereLightHelper(hemiLight, 50, 300); // 50 is sphere size, 300 is arrow length
  this.scene.add(hlightHelper);

PointLightHelper

Similar to the previous, the PointLightHelper is for PointLight object. To add this helper, use the following code:

  // add point light
  var pointLight = new THREE.PointLight(0xffff00, 1.0);
  pointLight.position.set(300,300,300);
  this.scene.add(pointLight);
  var pointLightHelper = new THREE.PointLightHelper(pointLight, 50); // 50 is sphere size
  this.scene.add(pointLightHelper);

SpotLightHelper

Lastly, we added the spot light: the SpotLightHelper is for SpotLight object. To add this helper, use the following code:

  // add spot light
  var spotLight = new THREE.SpotLight(0xffffff);
  spotLight.position.set(-300,400,300);
  spotLight.castShadow = true;
  spotLight.shadowCameraFov = 60;
  this.scene.add(spotLight);
  var spotLightHelper = new THREE.SpotLightHelper(spotLight, 50); // 50 is sphere size
  this.scene.add(spotLightHelper);

Live Demo
Live Demo 2

[sociallocker]

download in package

[/sociallocker]


Conclusion

Stay tuned for new lessons and you are sure to find something new and interesting for yourself.

SIMILAR ARTICLES

Understanding Closures

0 24615

NO COMMENTS

Leave a Reply