void TreeLayer::drawScene(const cinder::Area& renderArea, cinder::gl::GlslProg& shader)
{
  
  // Set up draw states
  gl::disableDepthWrite();
  gl::disableDepthRead();
  gl::color( cinder::ColorA(1, 1, 1, 1) );
  gl::setMatricesWindowPersp(renderArea.x2, renderArea.y2);
  
  // Draw sun
  gl::clear(mFogColor() * 0.5f);
  
  // Set camera up
  mTreeCam.lookAt(mTreePan, mTreePan + mTreeCam.getViewDirection(), mTreeCam.getWorldUp());
  gl::setMatrices(mTreeCam);
  
  Vec3f tl, tr, bl, br;
  mTreeCam.getFarClipCoordinates(&tl, &tr, &bl, &br);
  
  
  Vec3f bbRight, bbUp;
  mTreeCam.getBillboardVectors(&bbRight, &bbUp);
  
  // Draw sun
  gl::enableAlphaBlending();
  texSun.enableAndBind();
  gl::color(mSunColor);
  gl::drawBillboard(mTreePan + Vec3f(0.0f, 0.0f, -(mTreeCam.getFarClip()-1.0f)), Vec2f( mTreeCam.getFarClip(), mTreeCam.getFarClip()), 0, bbRight, bbUp);
  gl::disableAlphaBlending();
  texSun.unbind();

  shader.bind();
  shader.bind();
  shader.uniform("farClip", mFogDistance);
  shader.uniform("fogColor", ColorA(mFogColor));
  shader.uniform("tex", 0);
  shader.uniform("texBlurred", 1);
 
  gl::enableDepthWrite();
  gl::enableDepthRead();
  
  // Draw ground
  gl::color(mGroundColor);
  texGround.enableAndBind();
  texGround.bind(1); 
  gl::draw(mGroundMesh);
  texGround.unbind();
  
  gl::enableAlphaTest(0.2f);
  gl::enableAlphaBlending(false);
  
  gl::color(Color::white());
  // Enable our tree texture
  if (!mWithLeaves)
  {
    texTree.enableAndBind();
    texTreeBlurred.bind(1);
  } else {
    texTreeWithLeaves.enableAndBind();
    texTreeWithLeavesBlurred.bind(1);
  }
  
  glTranslatef(0, 0, -travelBounds.z);
  gl::draw(mTreeMesh);
  glTranslatef(0, 0, travelBounds.z);
  gl::draw(mTreeMesh);
  
  if (!mWithLeaves)
  {
    texTree.unbind();
    texTreeBlurred.unbind();
  } else {
    texTreeWithLeaves.unbind();
    texTreeWithLeavesBlurred.unbind();
  }
  
  if (mZoomToBlack > 0.0f)
  {
    texBlack.enableAndBind();
    texBlack.bind(1);
    Vec3f bbRight, bbUp;
    mTreeCam.getBillboardVectors(&bbRight, &bbUp);
    Vec2f scale = Vec2f(1070.0f / 2311.0f, 1.0f);
    scale *= 2.0f;
    Vec3f middlePos(mTreePan.x,
                    -scale.y * 0.5f,
                    zoomHackZ - 2.0f);
    gl::drawBillboard(middlePos + Vec3f(mZoomOffset, 0.0f, 0.0f), scale, 0.0f, bbRight, bbUp);
    gl::drawBillboard(middlePos - Vec3f(mZoomOffset, 0.0f, 0.0f), scale, 0.0f, bbRight, bbUp);
    texBlack.unbind();
  }
  
  shader.unbind();
  
  gl::disableAlphaTest();
  gl::enableAlphaBlending();
  // Draw overlay
  gl::disableDepthRead();
  gl::disableDepthWrite();
  gl::setMatricesWindowPersp(renderArea.x2, renderArea.y2);
  gl::draw(texOverlay, renderArea);
  gl::disableAlphaBlending();  
}
void ShaderVar::uniform(cinder::gl::GlslProg &shader, Listener &listener) {
	Value v = listener.get( path );
	
	switch ( type ) {
		case Type::Float: {
			float fVal;
			if ( v.isNumeric() ) {
				fVal = v.asFloat();
			} else {
				fVal = defaultFloat;
			}
			shader.uniform( name, fVal );
			
			//cout << listener.path << path << " " << fVal << endl;
			
		}
		break;
			
		case Type::Vec3: {
			shader.uniform( name, jsonToVec3f( v, defaultVec3f ) );
		}
		break;
			
		case Type::Vec4: {
			Vec4f v4Val = defaultVec4f;
			
			if ( v.isNumeric() ) {
				float fVal = v.asFloat();
				v4Val = Vec4f( fVal, fVal, fVal, fVal );
			} else if ( v.isObject() ) {
				if ( v["x"].isNumeric() ) {
					v4Val.x = v["x"].asFloat();
				} else if ( v["r"].isNumeric() ) {
					v4Val.x = v["r"].asFloat();
				}
				
				if ( v["y"].isNumeric() ) {
					v4Val.y = v["y"].asFloat();
				} else if ( v["g"].isNumeric() ) {
					v4Val.y = v["g"].asFloat();
				}
				
				if ( v["z"].isNumeric() ) {
					v4Val.z = v["z"].asFloat();
				} else if ( v["b"].isNumeric() ) {
					v4Val.z = v["b"].asFloat();
				}
				
				if ( v["w"].isNumeric() ) {
					v4Val.w = v["w"].asFloat();
				} else if ( v["a"].isNumeric() ) {
					v4Val.w = v["a"].asFloat();
				}
			}
			
			//cout << "feedback multColour " << v4Val << endl;
			
			shader.uniform( name, v4Val );
		}
		break;
	}
}