Thursday, September 27, 2012

Three.js Text Textures

‹prev | My Chain | next›

I was able to get 3D text added to a Three.js scene yesterday. Today I would like to add 2D text. The 3D text works fairly well, but I may not always need 3D. Also I am not quite sure what the font parameter.

I have seen a couple of examples in which a canvas is used to create a texture, so I am going to attempt to get that to work. The canvas and context:
  var canvas = document.createElement('canvas');
  var context = canvas.getContext('2d');
I can then use fillText() to enter some text:

  context.fillText("Game Over", 10, 10);
Now, I can create a texture and try to add that to a Three.js Mesh:

  var texture = new THREE.Texture(canvas);
  var cover = new THREE.MeshBasicMaterial({map: texture});
  var shape = new THREE.PlaneGeometry(100, 100);
  var banner = new THREE.Mesh(shape, cover);
  banner.rotation.x = Math.PI/2;
  banner.position.y = -100;
  scene.add(banner);
But, I only get a grey box:


I have seen that before. I need to tell Three.js that something needs an update:
  var canvas = document.createElement('canvas');
  var context = canvas.getContext('2d');
  context.fillText("Game Over", 10, 10);
  var texture = new THREE.Texture(canvas);
  texture.needsUpdate = true;
  var cover = new THREE.MeshBasicMaterial({map: texture});
  var shape = new THREE.PlaneGeometry(100, 100);
  var banner = new THREE.Mesh(shape, cover);
  banner.rotation.x = Math.PI/2;
  banner.position.y = -100;
  scene.add(banner);
But then the mesh disappears completely.

After fiddling quite a bit, it turns out that my problem is the lack of dimension on the canvas element:
  var canvas = document.createElement('canvas');
  canvas.width = 100;
  canvas.height = 50;
  var context = canvas.getContext('2d');
  context.fillText("Game Over", 0, 10);
  //context.font = '48px';
  var texture = new THREE.Texture(canvas);
  texture.needsUpdate = true;
  var cover = new THREE.MeshBasicMaterial({map: texture});
  var shape = new THREE.PlaneGeometry(100, 100);
  var banner = new THREE.Mesh(shape, cover);
  banner.rotation.x = Math.PI/2;
  banner.position.y = -100;
  scene.add(banner);
With that, I get the "Game Over" texture:


I need to fiddle with the size a little more to get this working just right, but this is a decent start.

Last up, I switch from a plane to a sprite:
  var canvas = document.createElement('canvas');
  canvas.width = 60;
  canvas.height = 20;
  var context = canvas.getContext('2d');
  context.fillText("Game Over", 0, 10);

  var texture = new THREE.Texture(canvas);
  texture.needsUpdate = true;
  var sprite = new THREE.Sprite({
    map: texture,
    transparent: true,
    useScreenCoordinates: false
  });
  sprite.position.set(0,-150,0);
  scene.add(sprite);  
That actually works well:


I am still not quite sure about the ideal canvas dimensions to get this to show, but I can fiddle with that another day.

Day #522

No comments:

Post a Comment