Saturday, July 21, 2012

Can't Make a Three.js Skybox

‹prev | My Chain | next›

I have a pretty decent Three.js avatar and even have decent animation of the arms and legs as it walks about:

I would still like to add a bit more before switching back to Gladius. First, I would like to switch the controls so that they move the avatar around instead of moving the camera. To see that, I think I need to add some terrain on which the avatar can walk. I would also like to give the avatar a nice sunny day to walk about in. I think the way to accomplish the terrain on which to walk is a simple plane.

The sky seems a little trickier so I start with that first. In CubicVR.js, there is the concept of a SkyBox (though it does not seem to be exposed by Gladius' CubicVR.js plugin yet). There does not appear to be a similar concept in Three.js.

After rooting through some of the Three.js examples, the most common thing seems to be to make a really, really big cube. That seems... less than ideal, but lacking the imagination to devise a better idea, let's see how that works.

Again, there seems to be no documentation for the CubeGemotry class proper, but the code uses expressive variable names. I think something like this ought to suffice:
  var M = 1000 * 1000;
  var skyGeometry = new THREE.CubeGeometry(M, M, M, 1, 1, 1, null, true);
I set the x, y, and z dimension to 1 million units each. The number of segments needed to represent each is one because, really, how many segments does it take to represent a plane? The null option is the materials, which I will set separately in the mesh. The last argument says to use sides.

I then add a plain-old material (the same one that I am using for the avatar) to the sky and use this to build and add the skybox to the scene:
  var skyMaterial = new THREE.MeshNormalMaterial();
  var skyboxMesh  = new THREE.Mesh(skyGeometry, skyMaterial);
Only, I don't see a skybox, just the same white background. I fiddle with various materials, to no end. Frustrated, I call it a night. Hopefully tomorrow I will be able to get this working.

Update: I should be in bed, but couldn't let this go. In the end I did get this working, though the changes seem to beg more questions. The first change seems reasonable: I need to tell the skybox that it is flip-sided. That is, the sides of the box do not face outward, but inward. I can live with that as I have seen similar things in Gladius. The second change that needs to be made is that... I need more segments to render the skybox cube. After making fun of it earlier, I find through trial and error that 4 segments seem to do the trick:
  var M = 1000 * 10;
  var skyGeometry = new THREE.CubeGeometry(M, M, M, 4, 4, 4, null, true);
  var skyMaterial = new THREE.MeshBasicMaterial({color: 0x3030ff});
  var skyboxMesh  = new THREE.Mesh(skyGeometry, skyMaterial);
  skyboxMesh.flipSided = true;
I am also unable to get this to work with really large cubes. A skybox with dimensions in the neighborhood of ten thousands seems to be the maximum. This works:

But seems a little clunky. I think tomorrow I will experiment with images instead of plain filled materials.

Day #454


  1. I tried adding that code to my scene, but nothing appeared. What version of three.js were you using? I'm on build 51.

    1. I was on 49 at the time.

      For what it's worth, I realized a little while later that the sky box was not a good approach. The more proper way to accomplish a background color is with renderer.setClearColorHex(). Hopefully that still works in r51.

  2. The reason this will not work for big cubes, is that its vertices would be beyond the cameras far plane. Geometry beyond the far plane is not drawn.

    1. You are correct. It took me an embarrassingly long time to realize that. At times, the far side of the skybox would go white and I could not figure out why. Camera far plane -- silly me.

      In the end, all I really wanted was a background color, which is better done with setClearColorHex or a simple CSS style. I think the skybox was just one of those concepts I latched onto as a beginner. I'm still a beginner, but I know better about a few things now :)

      Thanks for the pointer. Hopefully it'll prevent someone else from doing silly things like me.