teaching machines

Project Setup Instructions

January 5, 2021 by . Filed under graphics-3d, specifications, spring-2021.

The first step in building an interactive graphics program is an ugly one: you have to choose a graphical user interface (GUI) framework. This step is ugly because there are many frameworks, they are all different, they tend to obsolesce, and they often draw you into a mire of platform-specific issues. But you have to pick one.

In this course, our GUI will be powered by HTML, CSS, and JavaScript. We could write normal desktop applications with these three technologies, in which case we might use Electron. In an Electron app, you secretly run a Chromium web browser right inside your application’s window—but the user has no idea that it isn’t a regular desktop application written in a language like C++.

I have decided against Electron, however, because of its unrelated complexity and because I want to make it easier for you to share your work on the web. Instead, we will write graphical applications that run right in a normal web browser. Targeting a web browser will help us sidestep a few issues we’d encounter with traditional GUI frameworks, like big executables and platform-specificity. However, we can’t escape issues entirely. One of the more painful issues is that the browser runs in a sandbox, unable to access local files. This means we won’t be able to read local image files or 3D models. We overcome this issue by running a little web server that will serve out our local files as if they lived on the web.

Follow the steps below at the start of each of the programming assignments in this course. They will help you set up a development environment and a test server for running your code locally. We will use the Node.js ecosystem but try to employ as little magic as possible.

Software

Install Node.js and Visual Studio Code. Ensure that Visual Studio Code is not open when you install Node.js; otherwise it may not find the Node.js utilities.

Project

Make an empty project folder through your OS’s file explorer. Open the folder in Visual Studio Code.

public

Using Visual Studio’s file explorer, create an empty folder named public. This folder will hold static assets like images, HTML files, and CSS stylesheets.

Inside public, add a file named index.html with this content:

<!DOCTYPE html>
<html>
<head>
  <title>...</title>
  <link rel="icon" href="data:,">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <canvas id="canvas"></canvas>
  <script src="dist/bundle.js"></script>
</body>
</html>

Also add a file named style.css with this content:

body {
  margin: 0;
}

#canvas {
  position: fixed;
  left: 0;
  right: 0;
  width: 100vw;
  height: 100vh;
}

src

Make a folder named src that is a sibling to public—not a child. This folder will hold JavaScript source files.

Inside src, add a file named index.js with this content:

const canvas = document.getElementById('canvas');
window.gl = canvas.getContext('webgl2');

function render() {
  gl.clearColor(1, 0.5, 0, 1);
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
}

function onSizeChanged() {
  canvas.width = canvas.clientWidth;
  canvas.height = canvas.clientHeight;
  render();
}

async function initialize() {
  window.addEventListener('resize', onSizeChanged);
  onSizeChanged();
}

initialize();

package.json

All Node.js projects contain a configuration file named package.json. In the top level of your project folder, create a file named package.json with this content:

{
  "name": "YOUR-APPLICATION-NAME",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack serve --config=.webpack/webpack.development.js --mode development",
    "build": "webpack --mode production --config=.webpack/webpack.production.js"
  }
}

Replace YOUR-APPLICATION-NAME with your application’s actual name.

.webpack

The server that you will use to develop your application locally is named Webpack. It needs its own configuration files. Create a folder named .webpack at the top level of your project.

Inside this folder, add a file named webpack.development.js with this content:

module.exports = {
  mode: 'development',
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
  },
  devServer: {
    open: true,
    contentBase: './public',
    publicPath: '/dist',
  },
  devtool: 'eval-cheap-module-source-map',
};

Also inside this folder, add a file named webpack.production.js with this content:

module.exports = {
  mode: 'production',
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
  },
};

Install Webpack with this command in the terminal:

npm install webpack webpack-cli webpack-dev-server

Look inside package.json and see how these three dependencies have been added to your project configuration.

Run this command to start up a web server that serves out your application:

npm start

Do you see an orange canvas?

By default, you access your application through the URL http://localhost:8080. The application is not actually on the web. No one but you can do anything with this URL.

.gitignore

When you run npm install, the Node Package Manager creates a directory named node_modules and stores in it all of the libraries that your project depends on. This folder should never go into version control. It’s huge, and it can always be remade when you jump to a new machine by running npm install. Later we’ll see another folder named dist that holds a built version of your application. That shouldn’t go in version control either.

To ensure that these folders stay out of Git, create a file named .gitignore at the top level of your project. Add this content:

node_modules
dist