Monday, July 30, 2012

Fallback from WebGL to Canvas in Three.js

‹prev | My Chain | next›

My daughter pointed out that avatar island is not working on her older machine. So tonight, I hope to get a fallback working such that, if the browser does not support WebGL, it will still render just fine with canvas.

Three.js includes a example detector similar to Modernizr. I don't need the full detector, but I will use the canvas and WebGL detectors:
var canvas = !! window.CanvasRenderingContext2D;
var webgl = ( function () { try { return !! window.WebGLRenderingContext ∓& !! document.createElement( 'canvas' ).getContext( 'experimental-webgl' ); } catch( e ) { return false; } } )();
Then, for the renderer, I do a simple conditional check:
  if (webgl) renderer = new THREE.WebGLRenderer();
  else if (canvas) renderer = new THREE.CanvasRenderer();
  if (renderer) {
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.setClearColorHex(0x87CEEB);
    document.body.appendChild(renderer.domElement);
  }
  else {
    alert("Can't make renderer. What kind of browser are you using?!");
  }
And this seems to work. Kind of.

On my modern browser, I can see avatar island as it is meant to be:


On my daughter's machine, however, I see:


The missing planes actually appear and disappear as the avatar moves about its island. After some Googling, I find that this is related to an old, non-fixable bug in Three.js' CanvasRenderer. As suggested in the bug report, I try subdividing the geometries of the island and the sea:
 // Sea
  var seaGeometry = new THREE.PlaneGeometry(2*ISLAND_WIDTH, 2*ISLAND_WIDTH, 4, 2)
    , seaMaterial = new THREE.MeshBasicMaterial({color: 0x483D8B})
    , seaMesh = new THREE.Mesh(seaGeometry, seaMaterial);
  seaMesh.position.y = -1;
  scene.add(seaMesh);

  // Island
  var islandGeometry = new THREE.PlaneGeometry(ISLAND_WIDTH, ISLAND_WIDTH, 64, 8)
    , islandMaterial = new THREE.MeshNormalMaterial({color: 0x7CFC00});
  island = new THREE.Mesh(islandGeometry, islandMaterial);
  scene.add(island);
This helps slightly:


But in reality, it kills my CPU and the results are not nearly satisfactory. So I think this means that Gaming JavaScript is going to require WebGL capable browsers. And I'm going to need to install a newer browser for my daughter.


Day #463

No comments:

Post a Comment