title: Managing z-buffering with transparent textures in Three.js
body: <p>I am trying to create a simple map with flat, paper-like trees sticking out of it in WebGL with THREE.js. I cannot grasp how the library handles z-buffering. I've tried playing with renderer.sortObjects parameter as well as with material.depthWrite and object.renderDepth, but no combination seems to be working - I either get the library to display the trees in proper order (those further from the camera are obstructed by those closer to the camera), but with weird transparency glitches, OR I manage to get the transparency right, but the trees further from the screen appear on top on those that are closer. 
  After hours of trying to get this right, this is what I ended up with:
  <img src="https://dl.dropboxusercontent.com/u/1142760/static/png/Screenshot%202013-11-30%2021.38.26.png" alt="screenshot"></p>
  
  <p>As you can see, the trees that are more to the right are rendered on top on those to the left.</p>
  
  <p>Please help me before I go completely nuts :)</p>
  
  <p>Here's my code: <a href="http://jsfiddle.net/UgZxc/" rel="nofollow">http://jsfiddle.net/UgZxc/</a></p>
  
  <pre><code>var map_size = 80;
  
  var MapModel = {};
  
  var types_amount = 2;
  var floorMap = [];
  
  for(var i=1; i&lt;=map_size; i++){
      floorMap[i]=[];
      for(var j=1; j&lt;=map_size; j++){
          var ran = Math.ceil(Math.random()*types_amount);
          switch(ran){
              case 1:
                  floorMap[i][j]='grass';
                  break;
              case 2: 
                  floorMap[i][j]='water';
                  break;
          }
      }
  }
  
  MapModel.floorMap = floorMap;
  
  var objectMap = [];
  for(var i = map_size; i&gt;=1; i--){
      objectMap[i] = [];
      for(var j=1; j&lt;=map_size; j++){
          objectMap[i][j] = [];
          var rand = Math.ceil(Math.random()*2);
          switch(rand){
              case 1:
                  objectMap[i][j].push('tree');
                  break;
          }
      }
  }
  
  MapModel.objectMap = objectMap;
  
  
  
  
  block_size=100;
  
  
  // Constructor
  MapApp = function()
  {
      Sim.App.call(this);
  }
  
  
  // Subclass Sim.App
  MapApp.prototype = new Sim.App();
  
  // Our custom initializer
  MapApp.prototype.init = function(param)
  {
      Sim.App.prototype.init.call(this, param);
  
      // Create the Earth and add it to our sim
      for(var i=1; i&lt;=map_size; i++){
          for(var j=map_size; j&gt;=1; j--){
              var square = new Square();
              square.init(i, j);
              this.addObject(square);                    
              var arr = MapModel.objectMap[i][j];
              for(var k in arr){
                  var obj = new MapObject();
                  obj.init(i, j, arr[k]);
                  this.addObject(obj);
              }
          }
      }
  
      // Let there be light!
      var sun = new Sun();
      sun.init();
      this.addObject(sun);
  
      this.camera.position.x = 3*block_size;
      this.camera.position.y = 3*block_size;
      this.camera.position.z=5*block_size;
      this.camera.rotation.x = Math.round(45* 100* Math.PI/180)/100;
  
      this.selfUpdate = function(){
          this.camera.position.x += 0.125 * block_size/10;
          this.camera.position.x += 0.050 * block_size/10;
      }
  
  }
  
  Square = function()
  {
      Sim.Object.call(this);
      this.size = block_size;
  }
  
  Square.prototype = new Sim.Object();
  
  wrote2 = false;
  Square.prototype.init = function(x, y){   
      var type=MapModel.floorMap[x][y];
      var reflectivity = 0;    
      switch(type){
          case "grass":
              var earthmap = "http://dl.dropboxusercontent.com/u/1142760/static/html/webgl/tiles/samatrawa.png";
              break;
          case "water":
              var earthmap = "http://dl.dropboxusercontent.com/u/1142760/static/html/webgl/tiles/samawoda.png";
              reflectivity = 1;
              break;
  
      }
      //console.log(earthmap);
      var geometry = new THREE.CubeGeometry(this.size, this.size, this.size );
      var texture = THREE.ImageUtils.loadTexture(earthmap);
      var material = new THREE.MeshPhongMaterial( { map: texture, color: 0xffffff, reflectivity: reflectivity } );
      material.depthWrite = true;
      var mesh = new THREE.Mesh( geometry, material ); 
  
      mesh.translateX(x*this.size);
      mesh.translateY(y*this.size);
      mesh.renderDepth = y*block_size;
  
      if(!wrote2){
          wrote2=true;
          console.log('square renderDepth:', mesh.renderDepth, 'square mesh.position.y:', mesh.position.y);
          console.log('square material.depthWrite', material.depthWrite);
      }
  
      this.setObject3D(mesh); 
  }
  
  
  Square.prototype.update = function()
  {
      // "I feel the Earth move..."
      //this.object3D.rotation.y += 0.1;
  
      //Sim.Object.prototype.update.call(this);
  }
  
  // Custom Sun class
  Sun = function()
  {
      Sim.Object.call(this);
  }
  
  Sun.prototype = new Sim.Object();
  
  Sun.prototype.init = function()
  {
      // Create a point light to show off the earth - set the light out back and to left a bit
      var light = new THREE.DirectionalLight( 0xC5BC98, 2);
      light.position.set(-10, 0, 20);
  
      // Tell the framework about our object
      this.setObject3D(light);    
  }
  
  
  MapObject = function(){
      Sim.Object.call(this);
  }
  
  MapObject.prototype = new Sim.Object();
  wrote=false
  MapObject.prototype.init = function(x, y, type){
      switch(type){
          case "tree":
              var textureURL = "http://dl.dropboxusercontent.com/u/1142760/static/html/webgl/tiles/samodrzewo.png";
              break;
          case "water":
              var textureURL = "http://dl.dropboxusercontent.com/u/1142760/static/html/webgl/tiles/samawoda.png";
              break;
  
      }
      //console.log(textureURL);
      var geometry = new THREE.PlaneGeometry(1*block_size, 2*block_size);
      var texture = THREE.ImageUtils.loadTexture(textureURL);
      var material = new THREE.MeshPhongMaterial( { map: texture, transparent:true } );
      material.depthWrite = false;
  
      var mesh = new THREE.Mesh( geometry, material ); 
  
      mesh.position.x=x*block_size;
      mesh.position.y=y*block_size;
      mesh.translateZ(2*block_size);
  
      mesh.rotation.x = Math.round(45 * 100 * Math.PI /180)/100;
  
      //mesh.renderDepth = y*block_size;
      mesh.renderDepth = -y*1000 ;
      if(!wrote){
          console.log('object renderDepth:', mesh.renderDepth, 'object mesh.position.y:', mesh.position.y);
          console.log('object material.depthWrite', material.depthWrite);
          wrote = true;
      }
      //console.log(mesh.rotation.x);
  
      this.setObject3D(mesh); 
  }
  
  var renderer = null;
              var scene = null;
              var camera = null;
              var mesh = null;
  
              $(document).ready(
                  function() {
                      var container = document.getElementById("container");
                      var app = new MapApp();
                      app.init({ container: container });
                      app.run();
                  }
              );
  </code></pre>