BEGINNER'S GUIDE

Customizing Object3Ds

Setting object properties

In this guide you'll learn how to render semi-transparent objects, apply textures and how to spice up objects' surfaces utilizing specular and normal maps. This guide is based on the previous guides and will only focus on new code. You can find the complete code at the bottom of this page or download it here. The code of this guide will render two cubes, a transparent one and one that makes use of a normal map. In order to render a transparent object you need to declare it as transparent. This will enable the alpha channel of the respective texture or color and will take care of transparent sorting. Specular and normal maps are automatically loaded and applied after you've added the image paths to the object. It's important to note that transparency and specular / normal mapping will only work if you enable these attributes before calling addToScene().

    var cube = new Ayce.OBJLoader("assets/obj/cube.obj");
    cube = cube[0];
    cube.position.set(1, 0, -2);
    cube.scale.set(0.9, 0.9, 0.9);
    cube.imageSrc = "assets/obj/textures/cube2.png";
    cube.transparent = true;
    cube.twoFaceTransparency = true;

    var axis = new Ayce.Vector3(1, 1, 0);
    cube.onUpdate = function(){
        var r = (Date.now() / 2000) % Math.PI * 2.0;
        cube.rotation.fromAxisAngle(axis, -r);
    };
    scene.addToScene(cube);

Let's start by creating the semi-transparent cube. After setting up the OBJ loader and setting values for position and scale we're setting up the texture source by setting imageSrc to the appropriate file path. That's all you need to do to use a texture. In the next line we're declaring that the object has an alpha channel. This handles transparent object sorting and enables transparency. twoFaceTransparency lets you render the texture on the outside as well as the inside of the cube. If twoFaceTransparency is false only the outside is rendered. Finally, before adding the cube to the scene we're setting some rotational values.

    var cube2 = new Ayce.OBJLoader("assets/obj/cube.obj");
    cube2 = cube2[0];
    cube2.position.set(-1, 0, -2);
    cube2.scale.set(0.9, 0.9, 0.9);
    cube2.useFragmentLighting = true;
    cube2.useSpecularLighting = true;
    cube2.shininess = 4.0;
    cube2.imageSrc = "assets/obj/textures/cube.png";
    cube2.normalMap = "assets/obj/textures/cube_normal.png";

    var axis = new Ayce.Vector3(1, 1, 0);
    cube2.onUpdate = function(){
        var r = (Date.now() / 2000) % Math.PI * 2.0;
        cube2.rotation.fromAxisAngle(axis, -r);
    };
    scene.addToScene(cube2);

Now for the second cube, a normal map is applied to create the illusion of the surface being textured although it's actually flat. This is achieved by altering the surface normals used for light calculation. The "new" normal information is stored in a different texture, the normal map. You should be familiar with most of the code here by now. We're loading the model, setting position and scale of the object, enabling fragment and specular lighting and setting a shininess value that's used for specular lighting. It is important to note that normal maps will only be applied if both fragment and specular lighting are enabled. Next we're setting the respective file paths to the texture and normal map images. That's all you need to enable normal mapping. Again before adding the cube to the scene we're setting some rotation values for animation.

...
    <script>
        var canvas = document.getElementById("ayce_canvas");
        var scene = new Ayce.Scene(canvas);
        scene.setClearColor(0.2, 0.2, 0.35);

        var light = new Ayce.Light();
        light.position.set(0, 1, 2);
        scene.addToScene(light);

        var cube = new Ayce.OBJLoader("assets/obj/cube.obj");
        cube = cube[0];
        cube.position.set(1, 0, -2);
        cube.scale.set(0.9, 0.9, 0.9);
        cube.imageSrc = "assets/obj/textures/cube2.png";
        cube.transparent = true;
        cube.twoFaceTransparency = true;

        var axis = new Ayce.Vector3(1, 1, 0);
        cube.onUpdate = function(){
            var r = (Date.now() / 2000) % Math.PI * 2.0;
            cube.rotation.fromAxisAngle(axis, -r);
        };
        scene.addToScene(cube);

        var cube2 = new Ayce.OBJLoader("assets/obj/cube.obj");
        cube2 = cube2[0];
        cube2.position.set(-1, 0, -2);
        cube2.scale.set(0.9, 0.9, 0.9);
        cube2.useFragmentLighting = true;
        cube2.useSpecularLighting = true;
        cube2.shininess = 4.0;
        cube2.imageSrc = "assets/obj/textures/cube.png";
        cube2.normalMap = "assets/obj/textures/cube_normal.png";

        var axis = new Ayce.Vector3(1, 1, 0);
        cube2.onUpdate = function(){
            var r = (Date.now() / 2000) % Math.PI * 2.0;
            cube2.rotation.fromAxisAngle(axis, -r);
        };
        scene.addToScene(cube2);

        function update() {
            Ayce.requestAnimFrame(update);
            scene.updateScene();
            scene.drawScene();
        }

        update();
    </script>
    ...