Alternative 3D Solutions Tutorial


Creating a Web Application from glTF


20 minutes

Posted on: April 30, 2020

Learn Sumerian
Creating a Web Application from glTF

Your progress

Tags

glTF
babylon
babylon.js
three
js
three.js

In this tutorial you will learn about:

Learn how to create a single-page web application using Three.js or Babylon.js.

In this tutorial, you will learn how to create a single-page web application using either Three.js or Babylon.js to display a glTF model.

Prerequisites

  • Install Node.js.
  • Download the Fox glTF model from https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/Fox/glTF. All three files (Fox.gltf, Fox.bin, and Texture.png) are required. Alternatively, you may use your own glTF content, for example by Exporting an Amazon Sumerian scene.

Step 1: Create a NodeJS Project

In this step, you’ll create a basic project in NodeJS. NodeJS makes it easy to organize your project and import third-party libraries as dependencies via its built-in package manager, Node Package Manager (NPM). We’ll use NPM to bring in our build tools as well as runtime dependencies like Three.js or Babylon.js.

  1. First, open a terminal or command prompt and create the root directory for your project:

     mkdir gltf_tutorial
     cd gltf_tutorial
    
  2. Next, you’ll need to create a package.json file for the project. This file serves as a sort of table of contents that NPM will use to find the scripts and packages your application needs to run properly. We’ll use NPM’s init command to create the file. Run the following command in the same terminal window:

     npm init
    

    Next, fill out the prompts as follows:

     package name: gltf_tutorial 
     version: 1.0.0 
     description: gltf viewer tutorial project
     entry point: index.js 
     test command: 
     git repository: 
     keywords: 
     author: 
     license: ISC 
    

After completing these steps, verify that a file named package.json exists in your project’s root directory with the following contents:

{
  "name": "gltf_tutorial",
  "version": "1.0.0",
  "description": "gltf viewer tutorial project",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

We now have the basic framework of a package, but it has nothing in it. In the next step, we will add some tools to our package that will allow our application to host content on a server.

Step 2: Install and Configure Webpack

webpack is a tool primarily used for bundling JavaScript modules into static content suitable for hosting on a web server. We’ll use it to package up all our code, its dependencies, and any assets (.glTF files, binaries).

webpack also comes with a robust library of plugins; we’ll use several of them in conjunction with its base functionality to simplify the build process.

  1. First, install webpack and its command-line interface. This is the base webpack functionality.

     npm install --save-dev webpack webpack-cli
    
  2. Install webpack-dev-server, a development web server that supports hot reloading. We’ll use this to test our application locally. This way, we can make sure our application behaves correctly before we publish it to the web, where anyone can see it.

     npm install --save-dev webpack-dev-server
    
  3. Install html-webpack-plugin. This plugin automates creation of the root index.html file that will load our scripts.

     npm install --save-dev html-webpack-plugin
    
  4. Install gltf-webpack-loader and file-loader. These plugins resolve file imports, copying their contents to the output directory and modifying filenames as configured. We use them to modify file names to support hot-swapping.

     npm install --save-dev gltf-webpack-loader file-loader
    
  5. Next, you’ll configure webpack. In your project’s root directory, create a file named webpack.config.js and paste in the following:

     const webpack = require('webpack');
     const path = require('path');
    
     const HtmlWebpackPlugin = require('html-webpack-plugin');
    
     const dist = path.resolve(__dirname, 'dist');
     const src = path.resolve(__dirname, 'src');
    
     module.exports = {
       entry: path.resolve(src, 'index.js'),
       output: {
         filename: '[name].[hash].js',
         path: dist
       },
       module: {
         rules: [
           {
             test: /\.js$/,
             exclude: /node_modules/
           },
           {
             test: /\.(gltf)$/,
             use: [
               {
                 loader: "gltf-webpack-loader"
               }
             ]
           },
           {
             test: [/\.(bin)$/, /\.(jpg)$/, /\.(png)$/],
             use: [
               {
                 loader: 'file-loader',
                 options: {
                   name: '[name]-[hash].[ext]'
                 }
               }
             ]
           }
         ]
       },
       devServer: {
         contentBase: dist,
         watchContentBase: true,
         overlay: true,
         hot: true,
       },
       plugins: [
         new HtmlWebpackPlugin({
           template: path.resolve(src, 'index.html')
         }),
         new webpack.HotModuleReplacementPlugin(),
       ]
     };
    

    This script is responsible for setting webpack’s input and output directories (i.e. look for code in src, output everything to dst), and for determining which plugins to run based on the input file’s type (i.e. when encountering a glTF file, run the webpack-gltf-loader plugin). For more information on how to configure webpack, see the documentation.

  6. Finally, modify the scripts property in the package.json file so that webpack and wepback-dev-server are run when we build or debug the project:

     {
     ...
       "scripts": {
         "start": "webpack-dev-server --mode development --devtool eval-source-map",
         "build": "webpack --mode production"
       }
     ...
     }
    

Now our application can interface with the web, but it still lacks content. In the next step, we’ll use HTML to create a web page that will contain our glTF viewer and add it to the application.

Step 3: Create the Web Application

Next, you’ll create the source files for your web application. To start, you’ll need an index.html to define the page’s layout and an index.js that contains your application’s code.

  1. Create a directory for your application’s source code within the project’s root directory:

     mkdir src
     cd src
    
  2. Create a file named index.html in the src directory and paste in the following:

     <!DOCTYPE html>
     <html lang="en">
    
     <head>
       <meta charset="utf-8">
       <title>glTF Tutorial</title>
       <meta name="viewport" content="width=device-width, initial-scale=1">
       <style>
         html,
         body {
           height: 100%;
           width: 100%;
           margin: 0;
           padding: 0;
         }
    
         body {
           display: flex;
           flex-direction: column;
           font-family: 'Roboto', Helvetica, sans-serif;
         }
    
         #container {
           flex: 1 1 auto;
           min-height: 0;
         }
    
         #canvas {
           width: 100%;
           height: 100%;
           touch-action: none;
         }
    
         #controls {
           background: #262f40;
           color: #eaecec;
           height: 40px;
           flex: 0 0 auto;
           display: flex;
           align-items: center;
         }
    
         #controls>* {
           flex: 0 0 auto;
           margin-left: 10px;
         }
    
         #title {
           font-size: x-large;
         }
       </style>
     </head>
    
     <body>
       <div id='container'>
         <canvas id='canvas'></canvas>
       </div>
       <div id='controls'>
         <div id='title'>My Scene</div>
       </div>
     </body>
    
     </html>
    

    This HTML file defines a simple page with only two elements: a container to hold our canvas (into which the 3D scene will be rendered) and an additional element to show the scene’s title.

  3. Create a file named index.js in the src directory with the following contents:

     console.log("gltf tutorial scene loaded!");
    

    index.js will eventually contain code to load the glTF model, but we’ll keep it simple to begin with and log a line of text to the console.

  4. Test it out. In the terminal:

     npm run start
    

Next, point a web browser to http://localhost:8080, open the developer console and verify that gltf tutorial scene loaded! is printed.

You now have a successfully loaded web page in your application. In the final step, you’ll create a glTF viewer to display your 3D content on this page.

Step 4: Add the glTF Viewer

At this point you’ve created a simple single-page web application and verified that it runs in a web browser. In this step, you’ll learn how to use either the Three.js or Babylon.js engine to display a WebGL scene in the canvas element on the page.

First, you’ll need to select either the Babylon.js or Three.js 3D engine. The tutorial contains instructions for both engines, but the choice is mutually exclusive; follow all steps for Three.js or all steps for Babylon.js.

  • Note: the same content may render slightly differently when imported to another engine, and not all features are supported by all engines. For example, the fox model glTF file suggested for this tutorial has animations which will be enabled by default if the file is imported to Babylon.js, but not in Three.js. See the documentation pages for Three.js and Babylon.js for more information about working with your glTF files using these engines.
  1. Create a directory for the glTF content. From the project’s root directory:

     mkdir scene
    

    Then copy the three files comprising the model (Fox.gltf, Fox.bin, and Texture.png) into that directory. If you’re using your own content, copy all relevant files into the scene directory.

  2. Follow the steps below for the 3D engine you have chosen:

Three.js:

  1. Install the engine:

     npm install three
    
  2. Open index.js in the src directory and replace its contents with:

     import { Scene, WebGLRenderer, AmbientLight, PerspectiveCamera } from 'three';
     import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
    
     // Import our glTF model.
     import gltfUrl from '../scene/Fox.gltf'
    
     // Create the renderer and scene, which will consist of one light and the main camera.
     const canvas = document.getElementById('canvas');
     const renderer = new WebGLRenderer({ canvas });
     renderer.setSize(canvas.clientWidth, canvas.clientHeight, false);
     const scene = new Scene();
    
     const camera = new PerspectiveCamera(45, canvas.clientWidth / canvas.clientHeight, 1, 1000);
     camera.position.set(200, 40, 0);
     camera.lookAt(0, 40, 0);
     scene.add(camera);
    
     const light = new AmbientLight();
     scene.add(light);
    
     // Load the glTF model and add it to the scene.
     const loader = new GLTFLoader();
     loader.load(gltfUrl, (gltf) => {
       scene.add(...gltf.scene.children);
     });
    
     // Instruct the engine to resize when the window does.
     window.addEventListener('resize', () => {
       camera.aspect = canvas.clientWidth / canvas.clientHeight;
       camera.updateProjectionMatrix();
    
       renderer.setSize(canvas.clientWidth, canvas.clientHeight, false);
     });
    
     // Start the engine's main render loop.
     const animate = () => {
       renderer.render(scene, camera);
       requestAnimationFrame(animate);
     }
    
     animate();
    
  3. Test the finished application:

     npm run start
    

Babylon.js:

  1. Install the engine:

     npm install babylonjs babylonjs-loaders
    
  2. Open index.js in the src directory and replace its contents with:
     import {Engine, SceneLoader, HemisphericLight, Vector3, ArcRotateCamera, Scene} from 'babylonjs';
     import 'babylonjs-loaders';
    
     // Import our glTF model.
     import gltf from '../scene/Fox.gltf';
    
     // Create the engine and scene, which will consist of one light and the main camera.
     const canvas = document.getElementById('canvas');
     const engine = new Engine(canvas, true);
     const scene = new Scene(engine);
     const light = new HemisphericLight("HemiLight", new Vector3(0, 1, 0), scene);
     const camera = new ArcRotateCamera("camera1", 0, 1, 220, new Vector3(0, 20, 0), scene);
     camera.attachControl(canvas, false);
    
     // Load the glTF model and add it to the scene.
     SceneLoader.Append("/", gltf, scene);
    
     // Instruct the engine to resize when the window does.
     window.addEventListener('resize', () => engine.resize());
    
     // Start the engine's main render loop.
     engine.runRenderLoop(() => scene.render());
    
  3. Test the finished application:

     npm run start
    

If you’ve chosen to use your own glTF content, you may have to adjust the camera’s position and the scene’s lighting to properly display the model.

You have now successfully built a standalone application to view glTF content. If you want to learn how to publish your application to the web using AWS Amplify, continue to the Publishing a Web Application Using AWS Amplify tutorial

Back to Tutorials

© 2019 Amazon Web Services, Inc or its affiliates. All rights reserved.