webgl-threejs

Sphere Mapping

This post on sphere mapping is part of ongoing series on implementing the legacy NeHe lessons (originally done in C++ with OpenGL 1.x) using the three.js library. This post covers Lesson 23.

In computer graphics, sphere mapping (or spherical environment mapping) is a type of reflection mapping that approximates reflective surfaces by considering the environment to be an infinitely far-away spherical wall. This environment is stored as a texture (image) depicting what a mirrored sphere would look like if it were placed in that environment.

So how does this magic happen? Once again, three.js does almost all the heavy lifting. However, there are a couple interesting wrinkles, notably how the texture gets mapped onto the sphere and how the background is rendered.

Please see the article linked above on the Geo-F/X website for all the details.

Mapping on to the Sphere

In earlier lessons (like Lesson 9 and Lesson 17) we covered UV coordinates and how they are used to map a texture onto a shape. But in those cases, the texture was flat and the target shape was flat as well. In this case, we use a texture that has a “fake” curvature to it. See the lesson for details on how this was done. Here is the spherized image:

You can most clearly see the effect of the spherical filter in the “halo” in the sky above El Capitan. The details on the math used to map the spherized image are in the article.

Rendering the Background

We map the texture onto a sphere which appears to be in the foreground and can be spun and moved independently of the background. So how is this done? The answer is that the demo contains two scenes, a foreground scene containing the sphere and a second scene which is the background. Then the background is a second scene that has a single plane geometry covering the entire view of the second scene. Finally, the properties of the scene are set such that it is always rendered behind the first scene. Details of all this are in the lesson itself.

The Lessons and Source

More information and a live demo of this lesson can be found at Geo-F/X here. As always, the sources are on github here. Feel free to contact me at rkwright@geofx.com or comment on this article directly below.

Orthographic Projection

This post is part of ongoing series on implementing the legacy NeHe lessons (originally done in C++ with OpenGL 1.x) using the three.js library. This post covers Lesson 21 – Orthographic Projection. This is a relatively complex topic though three.js does most of the heavy lifting. Still, we’ll only hit the high points here. Please see the article linked above on the Geo-F/X website for all the details.

Projections

Orthographic projection is a means of representing a three-dimensional object in two dimensions. It is a form of parallel projection, where all the projection lines are orthogonal to the projection plane. This results in every plane of the scene appearing in an affine transformation on the viewing surface.

There are many types of projections. Two of the most common are perspective projections and orthographic projections. In addition, there are many more. You are probably familiar with many of the geographic projections. These map the surface of sphere (such as the earth) onto a flat surface. Mercator is the most common, but many others exist. A projections section on the Geo-F/X site covers many of these.

Orthographic Projection and GfxScene

As the lesson outlines, the GfxScene object has been expanded for this lesson to support orthographic projections. The lesson shows how to use the new functionality. It allows one to switch back and forth between orthographic and perspective projections for the same scene, like this:

An orthographic projections

A perspective projection

In a later lesson (Lesson 42) we’ll demonstrate how to use both projections in a single scene. This isn’t very commonly used, but it’s a cool technique.

The Lessons and Source

More information and a live demo of this lesson can be found at Geo-F/X here. As always, the sources are on github here. Feel free to contact me at rkwright@geofx.com or comment on this article directly below.

Both of these are using images with WebGL to create some interesting effects. They’re pretty simple though so we’ll cover them pretty quickly.

Alpha Masks

The key point to alpha masks is to create a textured object using TWO images. One is the full color image where the part you want rendered is non-black and the rest of the images is black (i.e. pixel values of 0). The second image is black and white, with the white portions corresponding to the non-black parts of the first image. Then when the two images are combined to form a masked texture in three.js the black portions of the resulting texture are transparent and only the non-black parts of the first image are shown.

Bump Maps

Bump maps also use images to produce the effect, but in a very different way. Bump mapping was invented by Jim Blinn in 1978 as part of his work for the visualization of the Voyager space-probe project. Bump mapping is a technique in computer graphics for simulating bumps and wrinkles on the surface of an object. This is achieved by perturbing the surface normals of the object and using the perturbed normal during lighting calculations. The result is an apparently bumpy surface rather than a smooth surface although the surface of the underlying object is not changed – only the apparent reflection of the light off the surface is changed.

More information and live demos of both these lessons can be found at Geo-F/X here.

The Lessons and Source

You can find the Lesson 20 at Geo-F/X here and lesson 22 is here As always, the sources are on github here. Feel free to contact me at rkwright@geofx.com or comment on this article directly below.

Introduction to Particle Engines

Two particle engines in action

This post is part of ongoing series on implementing the legacy NeHe lessons (originally done in C++ with OpenGL 1.x) using the three.js library. This post covers Lesson 19, which covers particle engines. Two implementations are discussed:

Using the three.js particle engine

Creating a custom particle engine which uses three.js

Particle engines are pretty cool. They allow you to do very cool effects from snow drops to flames to flocks of birds, Anything that is composed of groups of object that obey some rules. There are many good implementations of particle engines using three.js, including implementations by three.js, Stemkoski and squarefeet.

The three.js Particle Engine

The three.js implementation of a particle engine is fairly simplistic one. For all that, there is a lot one can do with it. The usage in this lesson is very simple, just some softly falling snowflakes. One aspect to note about the three.js implementation is that each “particle” is a sprite. In three.js sprites are rendered as Canvas2D objects. So they are effectively parallel to the surface on which the 3D space is projected. The result is that sprites are always “facing the camera” so you can’t have 3D objects as sprites. The plus side of using sprites in this way is that the three.js implementation can handle VERY large numbers of particles before performance is significantly impacted.

A Custom Particle Engine in JavaScript

The second implementation is one I wrote just for this series. It is not terribly sophisticated, but it does support 3D objects. In this case, little colored spheres being shot out of a cannon. The spheres then bounce and roll to the edge of a checkerboard, where they fall off and fade away.

The physics of the cannon and the bouncing balls is crude, but it looks kind of cool (if I do say so myself). It serves to illustrate the basic principles, which is the goal. It also demonstrates how to manage a system with many objects without having to create and destroy objects all the time (thus wasting memory and performance).

The Lessons and Source

You can find the Lesson 19 at Geo-F/X here, As always, the sources are on github here. Feel free to contact me at rkwright@geofx.com or comment on this article directly below.

Introduction to Fog, Texture Atlases and Quadrics

This post is a continuation of the implementation of the legacy NeHe lessons (originally done in C++ with OpenGL 1.x) using the three.js library. This lesson is a “three-fer” as I will quickly cover three NeHe lessons:

The reason for three at a time is that each of them is pretty simple as three.js does almost all the heavy lifting. And there are more interesting lessons down the pike and I’d rather get to them sooner rather than later.

Foggy Bottom

A foggy checkerboard in space

Lesson 16 is pretty simple as three.js does all the work and there aren’t a lot of parameters to manipulate. You can set the density of the fog and the color and that’s about it. Not to exciting. Note that we will also touch on volumetric fog later in Lesson 41.

Texture Atlases

A texture atlas cube

Texture atlases are rather more interesting because they involve texture coordinate mapping, which can be very useful for mapping complex textures onto various shapes. The example in this case is very simple: 6 different textures, one for each face of the cube. This is pretty simplistic use-case but it serves to illustrate the basic principles.

Quadrics

A textured torus knot quadric

Quadrics are well-handled in three.js so the lesson largely consists of a large switch statement allowing the user to switch between the various types of quadrics and see how different textures get mapped onto them. As you’ll see if you view the demo, sometimes the mapping of the textures onto the quadrics is good and other times it is very primitive, resulting in rather strange results. If you spelunk around in stackoverflow you can find some posts there (notably by westlangley) that explain how to do a better job of mapping textures onto some of the quadrics (and other shapes).

The Lessons and Source

You can find the Lesson 16 at Geo-F/X here, Lesson 17 here and Lesson 18 here. As always, the sources are on github here. Feel free to contact me at rkwright@geofx.com or comment on this article directly below.

Introduction

This post is a “twofer” – it’s about vector fonts, but we cover them in two steps. First, a simple vector font with solid colors (Lesson 14), then using a vector font and mapping a texture onto the font with a custom shader (Lesson15). This is the first foray into shaders, but won’t be the last. So let’s take a look.

A Simple Vector Font

Using vector fonts with three.js is very simple:

Get a JSON-based vector font

Load the font with the three.js font-loader

Construct a FontGeometry, specifying a bunch of parameters

Create a mesh with the geometry and a material

Now let’s take a look at each of them.

Getting JSON-based Fonts

You can convert fonts to the necessary JSON format at facetype.js. Facetype doesn’t provide any fonts – so you need to upload your fonts (in OpenType, TrueType or WOFF format) to the site and they will convert them to JSON so you can download them.

Getting fonts is easy. There are many places to get “free” fonts. You can go to Google fonts (all of which are free of licensing) or Fonts101.com. Do not simply upload the fonts on your system as most of those are protected fonts which, though they might be converted by facetype, are protected fonts in the sense that the font foundries (.g. MonoType, Adobe, etc.) have invested a LOT of time and money in them and they are licensed to your system – not you. So go get some free fonts.

Loading the Font

Loading the font is easy, as three.js provides a “font loader”. See the lesson for more information.

Constructing a Font Geometry

Constructing a font geometry in three.js is pretty trivial. Here is a typical call:

Note that the FontLoader takes the name of the font and calls back to the load() method when the font has been loaded. Finally, three.js uses the outline of the glyph (letter) as a shape and they extrudes it to form the 3D shape.

Note one misleading wackiness – what three.js calls the size of the font is the font height and what it calls the height is the thickness of the extruded font.

Then one creates a mesh with an array (the example above uses an array so the face and sides are different colors but that’s a detail.

Creating a Shader Material for the Font

Finally, the second example, Lesson 15, uses a custom shader to map two different textures onto the font. Nothing spectacular here – about the most basic shader one could create, but it does constitute and introduction to the world of shaders. Lots more details in the lesson itself.

You can find the Lesson 14 at Geo-F/X here. Lesson 15 is here. As always, the sources are on github here. Feel free to contact me at rkwright@geofx.com or comment on this article directly.

Introduction

This post is little more interesting than some of the earlier posts as it took me a couple of tries to get it right. Initially, I patterned the code after the original NeHe implementation. I knew that would suffer from poor performance, which it did. I then realized the solution was to build a single vertex buffer object (VBO) in JavaScript and pass that to the GPU. The VBO was created by three.js using a parametric surface mesh.

Initial Go

The first try simply replicated the original NeHe C++ code directly by building a grid in JavaScript and then updating all of those vertices in JS and passing that mesh to the GPU. This was of course thrashing the memory and choking the memory pathway to the GPU.

Using the Vertex Buffer and a Parametric Surface

Instead the solution was create a parametric surface by allocating a THREE.ParametricMesh. The constructor takes a small callback (in JS) which returns a 3-element vector, which three.js uses to create the surface. Those vectors are not used as-is, but are used to fill out a VBO which is then passed to the GPU. However, the JavaScript Mesh object has member variable (a uniform) that points to the VBO via a shader interface. One can then update the vertices via that member variable. This updates the vertices in the VBO, which is all done on the GPU so it is very efficient.

Shader Implementation?

I looked at a shader-side implementation but, at least in WebGL this doesn’t seem possible. It may be possible to in GL-4 to access adjacent vertex coordinates, but not in WebGL. But the solution as-is works well.

You can find the lesson at Geo-F/X here. As always, the sources are on github here. Feel free to contact me at rkwright@geofx.com or comment on this article directly.

Introduction

This post is a bit of a hybrid as it makes use of Canvas2D to render the text and labels, then composites them into the scene as three.js sprites. The original NeHe lesson 13 was about bitmapped fonts and how to use them, but that’s so last century. Canvas2D provides support for true vector fonts so why would one use bitmap fonts?

On the other hand, being able to place labels where you want in a 3D scene is a handy feature. Moreover, the use of three.js sprites has another useful aspect as three.js sprites are implemented such that they are effectively in 2D space in the plane of the screen, so they are always facing the user, no matter how the scene is oriented.

There are four main parts to the demo:

Setting up the Canvas2D that is the basis for the sprite

Rendering the text and label on the canvas

Loading the contents of the canvas as a texture

Positioning the resulting sprite in the scene

Setting up the Canvas

This is standard HTLM5 – nothing tricky here. Two tips:

Make the canvas big since only the label and the text will actually be rendered as the texture since the rest of the canvas is transparent as far as three.js is concerned

Ensure that the canvas size is a power of two, e.g. 2048×2048. If you don’t three.js will change it for you and send a warning to the console

Rendering the Text Sprites

I won’t go into the details how HOW this is done. Take a look at the lesson on the Geo-F/X website here for all the details (and of course the sources are on github). The key is the call to makeTextSprite:

Yeah, the function’s signature is unwieldy. I have a to-do item to convert it to use some form of class/object but it works as-is. Notice that you can set the vertical and horizontal alignment of the text with respect to the 3D point where the sprite will be rendered. You can set the color of both the text and the label, round-corners or not, opacity, etc. etc.

And that’s pretty much it! Fairly simple but rather handy. At some point I will do the refactoring mentioned above and add it to the GFXScene class.

You can find the lesson at Geo-F/X here. As always, the sources are on github here. Feel free to contact me at rkwright@geofx.com or comment on this article directly.

Introduction

This post is pretty simple. Lesson 9 is about masking textures in three.js. Pretty simple. You have a PNG and you want to use it for masking, add some color and animate them on the screen. All basic functionality that three.js supports out of the box.

Lesson 10 is also very simple. It is about building a structure from some coordinates in a file. Back when this lesson was written, the “worlds” being built were very simple. Today of course the worlds are very complex ranging from relatively simple Unity worlds to productions that rival major motion pictures. But it was one of the NeHe lessons, so I included it.

However instead of the mud-styled picture of the original author, I used an image of our puppy, Sammy who was 4 months old at the time (weighing about 55 pounds). Sadly, Sammy was born under a bad sign and had several birth defects making his shoulders weak. Worse at the age of only 3 years old, he developed abdominal cancer and had to be put to sleep in January 2017. Poor guy, poor us. RIP Sammy.

GFX.Scene

One aspect of this lesson is the introduction of the GFX.Scene object. This is a wrapper for the various basic objects in a three.js Scene. Why bother one would wonder. In a series of demos like the NeHe items, there is a LOT of boiler plate: allocating and initializing the scene itself, setting up the camera, setting up the lights, adding stats, maybe some axes, etc. etc. So I wrote an object that makes it pretty easy in a few lines to initialize all of that. As we go through the lessons will see some more functionality added (multiple cameras, etc.).

You can find the lesson at Geo-F/X here. As always, the sources are on github here. Feel free to contact me at rkwright@geofx.com or comment on this article directly.

NeHe and three.js

This is the first of a series of blogs on the implementation of the old NeHe demos in three.js. I’ll try to cover 2 or 3 of them a week, but there are 48 of them so it will take a while.

I got started with 3D a long time ago. Back in the days when OpenGL was just starting. Support was terrible. The hardware was all over the place, mainly proprietary. The APIs varied from platform to platform. The only part that was consistent was the inconsistency. But when you got something to work it was cool! So we persevered. Jeff Molokee therefore came up with a series of demos called NeHe on gamedev.net. I was buried in writing PostScript interpreters in those days, but it was fun to read what others were doing and dabble a little on the side.

The Evolution of OpenGL

Fast forward to the present day (mostly anyway) and here comes OpenGL 3, then 4 and then WebGL. As it happens, I was doing a bunch of JavaScript in conjunction with Readium and EPUB, so the new WebGL and an open-source effort called three.js by mrdoob (Ricardo Cabello) was very interesting. I dabbled with it a little and ran across an effort by Johannes Raida where he was porting the NeHe demos to three.js. I thought that was kind of cool so I pitched in. As it turned out, Johannes got pulled into other work and ended up stopping after the first 8 demoes. As often happens with me, I got the bit in my teeth and couldn’t stop. I have now done all 48 of the demos. Well, 40 of them. The other 8 are not interesting for various reasons (obsolete, not relevant, etc.).

The first 8 NeHe Demos

Here are the first 8, mainly done by Johannes – These first ones are pretty straightforward ports. A few were trivial since three.js did all the heavy lifting, but some were more interesting. I’ll talk about some of the more interesting parts in subsequent blogs.