WebGL VGA

For some odd reason, I happened to remember a little demo that came with the first 16 bit computer I ever used--an Amstrad PC 2286. It was meant for showing off the capabilities of the new and shiny Paradise VGA graphics adapter that the 2000 line of computers incorporated. 256 simultaneous colours! 640x350 graphics! So stunning back then! I ran this demo from time to time, admiring all those colours at the same time on the screen. Then I learnt how to make the computer output them with GW-Basic, but that is another story.

I wanted to watch that demo again, but it seems that the Amstrad PC line of computers doesn't get as much love as the CPCs do. So there is hardly any software repository (or dump) for those computers, and thus I couldn't locate that demo. It doesn't help that I didn't remember its filename either...

But I found several images depicting the demo, and somehow I decided that rebuilding the demo was an excellent idea --and a great excuse to learn three.js!

This is how the original looked:

VGA demo

And this is what I ended up with:

VGA demo + webgl 2012

In the process I thought I would spice things up a little. Since rotations are "cheap" with WebGL, I made things move around, mostly by rotating them. I also added some scaling here and there, and liberally used Math.sin and Math.cos (as Javascript is so fast nowadays too). Still, I didn't go too far, for the sake of keeping some resemblance to the original!

SFAQ

Although three.js is designed to be simple and intuitive, I had several how do I do this apparently simple thing with three.js? moments, so I thought it would be interesting to write these down as a sort of "SFAQ" (Silly Frequently Asked Questions). There we go:

How do I make a line?

You first create a geometry, then add vertices to its vertices property. Then create a material to set the line color, and use both the geometry and the material to create a line.

var geometry = new THREE.Geometry();

geometry.vertices.push(new THREE.Vertex( new THREE.Vector3(0, 0, 0) ) );
geometry.vertices.push(new THREE.Vertex( new THREE.Vector3(100, 0, 0) ) );

var material = new THREE.LineBasicMaterial({ color: 0xFF0000 });
var line = new THREE.Line(geometry, material);

Actually, you can create the line skipping the material creation. It will get a randomly assigned colour then.

How do I make a line strip? (i.e. a series of connected segments)

You start with a geometry, like in the line example above, but add as many points as you require. Then when creating the line you specify that the line type is THREE.LineStrip:

var geometry = new THREE.Geometry();

geometry.vertices.push(new THREE.Vertex( new THREE.Vector3(0, 0, 0) ) );
geometry.vertices.push(new THREE.Vertex( new THREE.Vector3(100, 0, 0) ) );
geometry.vertices.push(new THREE.Vertex( new THREE.Vector3(100, 100, 0) ) );
// ... add as many vertices as you need

var material = new THREE.LineBasicMaterial({ color: 0xFF0000 });
var line = new THREE.Line(geometry, material, THREE.LineStrip);

How do I make a line in which each segment has a different colour?

The answer to this is vertex colours, which works in the same way as the homonym concept in OpenGL: you need to specify a colour per vertex, instead of just a colour for the entire line. The way to specify the colours is to add instances of THREE.Color with the desired colour to the colors property, and then tell the line material to use them, as follows:

var geometry = new THREE.Geometry();

geometry.vertices.push(new THREE.Vertex( new THREE.Vector3(0, 0, 0) ) );
geometry.colors.push(new THREE.Color( 0xFF0000 ) );
geometry.vertices.push(new THREE.Vertex( new THREE.Vector3(100, 0, 0) ) );
geometry.colors.push(new THREE.Color( 0x00FF00 ) );

var material = new THREE.LineBasicMaterial({ vertexColors: true });
var line = new THREE.Line(geometry, material);

I'm using this for the odd colourful figure on top left.

How do I build hierarchies of objects?

You can use the generic THREE.Object3D class as container for other objects. When you add children to that object, and move it, the children will move along with the parent:

var container = new THREE.Object3D();
var geometry = new THREE.CubeGeometry(10, 10, 10);
var cube = new THREE.Mesh(geometry);

container.add(cube);


cube.position.x = 0; // Local x = 0
container.position.x = 10; // The cube's 'world' X coordinate at this point is 10

I used this for the "moire blocks" in the middle of the screen.

How do I change the colour of an object after having instantiated it?

Simply access its material.color property and change it as required:

var geometry = new THREE.Geometry();

geometry.vertices.push(new THREE.Vertex( new THREE.Vector3(0, 0, 0) ) );
geometry.vertices.push(new THREE.Vertex( new THREE.Vector3(100, 0, 0) ) );

var material = new THREE.LineBasicMaterial({ color: 0xFF0000 });
var line = new THREE.Line(geometry, material);

// the line is red

// But if we change its green attribute to 1...
line.material.color.g = 1;

// ...the line is yellow now!

This technique is used for animating the colour of the rectangles on top right.

A call for help!

If you know the file name, or have a copy of the original demo, please let me know! I would love to watch it again after so many years! Hopefully it will work with DOSBox. Please! :-)