Index: /issm/trunk-jpl/src/m/plot/applyoptions.js
===================================================================
--- /issm/trunk-jpl/src/m/plot/applyoptions.js	(revision 21137)
+++ /issm/trunk-jpl/src/m/plot/applyoptions.js	(revision 21138)
@@ -331,3 +331,60 @@
 		canvas.textcanvas = textcanvas;
 	} //}}}
+	//Atmosphere {{{
+	if (options.exist('atmosphere')) {
+		if (options.getfieldvalue('atmosphere')=='on') {
+			var meshresults = processmesh(md,data,options);
+			var x = meshresults[0]; 
+			var y = meshresults[1]; 
+			var z = meshresults[2]; 
+			var elements = meshresults[3];
+			var is2d = meshresults[4]; 
+			var isplanet = meshresults[5];
+			
+			var modelxlim = [ArrayMin(x),ArrayMax(x)];
+			var modelylim = [ArrayMin(y),ArrayMax(y)];
+			var modelzlim = [ArrayMin(z),ArrayMax(z)];
+			var xlim = options.getfieldvalue('xlim',modelxlim);
+			var ylim = options.getfieldvalue('ylim',modelylim);
+			var zlim = options.getfieldvalue('zlim',modelzlim);
+			xmin = xlim[0];
+			xmax = xlim[1];
+			ymin = ylim[0];
+			ymax = ylim[1];
+			zmin = zlim[0];
+			zmax = zlim[1];
+
+			var scale = 1;
+			var atmosphereScale = 1.25;
+			
+			//Atmosphere
+			var node = Node(gl,options);
+			canvas.nodes[canvas.nodes.length] = node;
+			node["shaderName"] = "SkyFromSpace";
+			node["shader"] = gl["shaders"][node["shaderName"]];
+			node["drawOrder"] = 1;
+			node["enableCullFace"] = true;
+			node["mesh"] = GL.Mesh.icosahedron({size:6371000*atmosphereScale,subdivisions:6});
+			node["useIndexBuffer"] = false;
+			node["rotation"] = [0,0,0];
+			node["translation"] = [(xmin + xmax) / (-2 / scale), (ymin + ymax) / (-2 / scale), (zmin + zmax) / (2 / scale)];
+			node["scale"] = [scale, scale, scale];
+			node["modelMatrix"] = recalculateModelMatrix(node);
+			
+			//Skysphere
+			var node = Node(gl,options);
+			canvas.nodes[canvas.nodes.length] = node;
+			node["shaderName"] = "Textured";
+			node["shader"] = gl["shaders"][node["shaderName"]];
+			node["drawOrder"] = 2;
+			node["enableCullFace"] = true;
+			node["mesh"] = GL.Mesh.sphere({size:6371000*10});
+			node["texture"] = initTexture(gl,'../../../js/textures/TychoSkymapII_t4_2k.jpg');
+			node["useIndexBuffer"] = false;
+			node["rotation"] = [0,0,0];
+			node["translation"] = [(xmin + xmax) / (-2 / scale), (ymin + ymax) / (-2 / scale), (zmin + zmax) / (2 / scale)];
+			node["scale"] = [scale, scale, scale];
+			node["modelMatrix"] = recalculateModelMatrix(node);
+		}
+	} //}}}
 }
Index: /issm/trunk-jpl/src/m/plot/plot_mesh.js
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_mesh.js	(revision 21137)
+++ /issm/trunk-jpl/src/m/plot/plot_mesh.js	(revision 21138)
@@ -61,6 +61,6 @@
 	var node = Node(gl,options);
 	canvas.nodes[canvas.nodes.length] = node;
-	scale = 1 / (xmax - xmin);
-	node["shaderName"] = "colored";
+	scale = 1;
+	node["shaderName"] = "Colored";
 	node["shader"] = gl["shaders"][node["shaderName"]];
 	node["lineWidth"] = options.getfieldvalue('linewidth',1);
Index: /issm/trunk-jpl/src/m/plot/plot_overlay.js
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_overlay.js	(revision 21137)
+++ /issm/trunk-jpl/src/m/plot/plot_overlay.js	(revision 21138)
@@ -61,6 +61,6 @@
 	var node = Node(gl,options);
 	canvas.nodes[canvas.nodes.length] = node;
-	scale = 1 / (xmax - xmin);
-	node["shaderName"] = "unlit_textured";
+	scale = 1;
+	node["shaderName"] = "GroundFromSpace";
 	node["shader"] = gl["shaders"][node["shaderName"]];
 	node["scale"] = [scale, scale, scale * matrixscale];
Index: /issm/trunk-jpl/src/m/plot/plot_quiver.js
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_quiver.js	(revision 21137)
+++ /issm/trunk-jpl/src/m/plot/plot_quiver.js	(revision 21138)
@@ -63,6 +63,6 @@
 	var node = Node(gl,options);
 	canvas.nodes[canvas.nodes.length] = node;
-	scale = 1 / (xmax - xmin);
-	node["shaderName"] = "colored";
+	scale = 1;
+	node["shaderName"] = "Colored";
 	node["shader"] = gl["shaders"][node["shaderName"]];
 	node["lineWidth"] = options.getfieldvalue('linewidth',1);
Index: /issm/trunk-jpl/src/m/plot/plot_unit.js
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_unit.js	(revision 21137)
+++ /issm/trunk-jpl/src/m/plot/plot_unit.js	(revision 21138)
@@ -58,11 +58,11 @@
 	zmax = zlim[1];
 	var caxis;
-	
+
 	//Compute gl variables:
 	var gl = canvas.gl;
 	var node = Node(gl,options);
 	canvas.nodes[canvas.nodes.length] = node;
-	scale = 1 / (xmax - xmin);
-	node["shaderName"] = "unlit_textured";
+	scale = 1;
+	node["shaderName"] = "Textured";
 	node["shader"] = gl["shaders"][node["shaderName"]];
 	node["scale"] = [scale, scale, scale * matrixscale];
Index: /issm/trunk-jpl/src/m/plot/webgl.js
===================================================================
--- /issm/trunk-jpl/src/m/plot/webgl.js	(revision 21137)
+++ /issm/trunk-jpl/src/m/plot/webgl.js	(revision 21138)
@@ -1,7 +1,9 @@
 /*This is where we have all our webgl relevant functionality for the plotting routines: */
+	
 //{{{ Canvas Initialization
 function initCanvas(options) {
 	//Initialize open Gl for each canvas, if needed: 
-	var canvas=document.getElementById(options.getfieldvalue('canvasid'));
+	canvas = document.getElementById(options.getfieldvalue('canvasid'));
+	//var canvas = document.getElementById(options.getfieldvalue('canvasid'));
 	if (!canvas.initialized) {
 		canvas.gl = initWebGL(canvas,options);
@@ -30,5 +32,8 @@
 	// Enable color blending/overlay
 	gl.enable(gl.BLEND);
-
+	// Enable face culling
+	gl.enable(gl.CULL_FACE);
+	gl.cullFace(gl.FRONT);
+	
 	// Load shaders and store them in gl object
 	gl.shaders = loadShaders(gl);
@@ -41,4 +46,5 @@
 	canvas.zoomLast = canvas.zoom;
 	canvas.cameraMatrix = mat4.create();
+	canvas.vInverseMatrix = mat4.create();
 	canvas.translation = options.getfieldvalue('origin',[0,0,0.0]);
 	canvas.viewPanning = options.getfieldvalue('viewpanning','off') == 'on';
@@ -79,5 +85,5 @@
 	//Returns a Node object that contains default display states for webgl object
 	return {buffers:[],
-		shader:gl.shaders["colored"],
+		shader:gl.shaders["Colored"],
 		draw:null,
 		hideOcean:false,
@@ -95,5 +101,5 @@
 		scale:vec3.fromValues(1, 1, 1),
 		modelMatrix:mat4.create(),
-		shaderName:"colored",
+		shaderName:"Colored",
 		drawOrder:0,
 		maskEnabled:false,
@@ -146,88 +152,9 @@
 //{{{ Shader Loading
 function loadShaders(gl) { //{{{
-	var shaderNames = ["colored", "unlit_textured"];
 	shaders = {};
-	shaders["colored"] = {loaded:false, vsh:{}, fsh:{}};
-			//basic phong shader
-	shaders["colored"] = new Shader('\
-		precision highp float;\
-		attribute vec3 a_vertex;\
-		attribute vec4 a_color;\
-		uniform mat4 u_mvp;\
-		uniform float u_alpha;\
-		varying vec4 v_color;\
-		void main() {\
-			gl_PointSize = 3.0;\
-			gl_Position = u_mvp * vec4(a_vertex.xyz, 1.0);\
-			v_color = vec4(a_color.xyz, u_alpha);\
-		}\
-		', '\
-		precision mediump float;\
-		varying vec4 v_color;\
-		void main() {\
-			gl_FragColor = v_color;\
-		}\
-	');
-			
-	shaders["unlit_textured"] = new Shader('\
-		precision highp float;\
-		attribute vec3 a_vertex;\
-		attribute vec2 a_coord;\
-		uniform mat4 u_mvp;\
-		varying vec2 v_coord;\
-		varying float v_z;\
-		void main() {\
-			gl_PointSize = 3.0;\
-			gl_Position = u_mvp * vec4(a_vertex.xyz, 1.0);\
-			v_coord = a_coord;\
-			v_z = a_vertex.z;\
-		}\
-		', '\
-		precision mediump float;\
-		varying vec2 v_coord;\
-		varying float v_z;\
-		uniform sampler2D u_texture;\
-		uniform float u_alpha;\
-		uniform bool u_maskEnabled;\
-		uniform float u_maskHeight;\
-		uniform vec4 u_maskColor;\
-		void main() {\
-			if (u_maskEnabled && (v_z < u_maskHeight)) {\
-				gl_FragColor = vec4(u_maskColor.rgb, u_alpha);\
-			}\
-			else {\
-				gl_FragColor = vec4(texture2D(u_texture, v_coord).rgb, u_alpha);\
-			}\
-		}\
-	');
-	/*
-	shaders["phong"] = new Shader('\
-		precision highp float;\
-		attribute vec3 a_vertex;\
-		attribute vec3 a_normal;\
-		attribute vec2 a_coord;\
-		varying vec3 v_normal;\
-		varying vec2 v_coord;\
-		uniform mat4 u_mvp;\
-		uniform mat4 u_model;\
-		void main() {\
-			v_coord = a_coord;\
-			v_normal = (u_model * vec4(a_normal,0.0)).xyz;\
-			gl_Position = u_mvp * vec4(a_vertex,1.0);\
-		}\
-		', '\
-		precision highp float;\
-		varying vec3 v_normal;\
-		varying vec2 v_coord;\
-		uniform vec3 u_lightvector;\
-		uniform vec4 u_color;\
-		uniform sampler2D u_texture;\
-		void main() {\
-		  vec3 N = normalize(v_normal);\
-		  vec4 color = u_color * texture2D( u_texture, v_coord);\
-		  gl_FragColor = color * max(0.0, dot(u_lightvector,N));\
-		}\
-	');
-	*/
+	shaders["Colored"] = new Shader.fromURL("/js/shaders/Colored.vsh", "/js/shaders/Colored.fsh");
+	shaders["Textured"] = new Shader.fromURL("/js/shaders/Textured.vsh", "/js/shaders/Textured.fsh");
+	shaders["SkyFromSpace"] = new Shader.fromURL("/js/shaders/SkyFromSpace.vert", "/js/shaders/SkyFromSpace.frag");
+	shaders["GroundFromSpace"] = new Shader.fromURL("/js/shaders/GroundFromSpace.vert", "/js/shaders/GroundFromSpace.frag");
 	return shaders;
 } //}}}
@@ -282,5 +209,5 @@
 function onZoom(ev,canvas,displaylog) { //{{{
 	ev.preventDefault();
-	var delta = clamp(clamp(ev.scale || ev.wheelDelta || -ev.detail, -1, 1) * canvas.controlSensitivity * canvas.zoom / 20, -1.0, 1.0);
+	var delta = clamp(ev.scale || ev.wheelDelta || -ev.detail, -1, 1) * canvas.controlSensitivity * canvas.zoom / 20;
 	canvas.zoom = clamp(canvas.zoom + delta, canvas.zoomBounds[0], canvas.zoomBounds[1]);
 	
@@ -300,12 +227,12 @@
 
 	if (canvas.twod) {
-		mat4.ortho(pMatrix, -aspectRatio/canvas.zoom, aspectRatio/canvas.zoom, -1/canvas.zoom, 1/canvas.zoom, -1.0, 10000.0);
+		mat4.ortho(pMatrix, -aspectRatio*6371000.0/canvas.zoom, aspectRatio*6371000.0/canvas.zoom, -6371000.0/canvas.zoom, 6371000.0/canvas.zoom, -1.0, 10000000000.0);
 	}
 	else {
-		mat4.perspective(pMatrix, 60 * Math.PI / 180, aspectRatio, 0.001, 10000.0);
+		mat4.perspective(pMatrix, 60 * Math.PI / 180, aspectRatio, 1000, 10000000000.0);
 	}
 	
 	//Apply worldspace translation
-	mat4.translate(translateMatrix, translateMatrix, [canvas.translation[0], canvas.translation[2], canvas.translation[1]]);
+	mat4.translate(translateMatrix, translateMatrix, [6371000.0 * canvas.translation[0], 6371000.0 * canvas.translation[2], 6371000.0 * canvas.translation[1]]);
 	mat4.multiply(vMatrix, translateMatrix, vMatrix);
 	
@@ -324,9 +251,12 @@
 	//Apply rotation and scaling transform
 	mat4.multiply(vMatrix, rotationMatrix, vMatrix);
-	
+
 	//Apply screenspace translation
 	mat4.identity(translateMatrix);
-	mat4.translate(translateMatrix, translateMatrix, [0.0, 0.0, -1/canvas.zoom]);
+	mat4.translate(translateMatrix, translateMatrix, [0.0, 0.0, -6371000.0/canvas.zoom]);
 	mat4.multiply(vMatrix, translateMatrix, vMatrix);
+	
+	//Calculate inverse matrices for lighting
+	mat4.invert(canvas.vInverseMatrix, vMatrix);
 
 	//Apply projection matrix to get camera matrix
@@ -341,28 +271,89 @@
 	if (node["texture"]) node["texture"].bind(0);
 	if (node["disableDepthTest"]) gl.disable(gl.DEPTH_TEST);
-	
+	if (node["enableCullFace"]) gl.enable(gl.CULL_FACE);
+
+	gl.cullFace(node["cullFace"]);
 	gl.lineWidth(node["lineWidth"]);
 	gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
 
+	//Setup for light that originates from camera
+	var origin = vec3.fromValues(0, 0, 0);
+	var lightOrigin = vec3.fromValues(0, 0, 0);
+	var cameraPosition = vec3.create();
+	vec3.transformMat4(origin, origin, canvas.vInverseMatrix);
+	vec3.normalize(lightOrigin, lightOrigin);
+	vec3.sub(cameraPosition, origin, node["translation"]);
+	cameraHeight = vec3.length(cameraPosition);
+	
+	var atm = { 							//Default Values
+				wavelength_r: 0.65, 		//0.65		Red wavelength (micrometers)
+				wavelength_g: 0.57,			//0.57		Green wavelength (micrometers)
+				wavelength_b: 0.475,		//0.475		Green wavelength (micrometers)
+				eSun: 100.0,				//20.0		Sun intensity	
+				kRayleigh: 0.0025,			//0.0025	Rayleigh scattering amount
+				kMie: 0.000, 				//0.01		Mie scattering amount
+				g: -0.99,					//-0.99		Mie phase asymmetry/direction factor
+				hdr_exposure: 0.8,			//0.8		High Dynamic Range Exposure
+				scale: 1.25, 				//1.025		Scale of atmosphere. WARNING: Change atmosphereScale in applyoptions.js, and scaling constants.
+				scaleDepth: 0.25, 			//0.25		Percentage altitude at which the atmosphere's average density is found
+				a: -0.00287,				//-0.00287	Scaling constant a
+				b: 0.459,					//0.459		Scaling constant b
+				c: 3.83,					//3.83		Scaling constant c
+				d: -6.80,					//-6.80		Scaling constant d
+				e: 3.6,						//5.25		Scaling constant e. Lower when increasing atmosphere scale.
+				attenuation: 0.5			//0.5		Strength of atmospheric scattering on ground shading.
+	};
+			
+	var inv_wavelength4 = [1.0 / Math.pow(atm.wavelength_r, 4), 1.0 / Math.pow(atm.wavelength_g, 4), 1.0 / Math.pow(atm.wavelength_b, 4)];
+	var innerRadius = 6371000.0;
+	var outerRadius = innerRadius*atm.scale;
+	var scale = 1.0 / (outerRadius - innerRadius);
+	var scaleDepth = atm.scaleDepth;
+	
 	node["shader"].uniforms({
-		u_mvp: mvpMatrix,
+		m4MVP: mvpMatrix,
+		m4Model: node["modelMatrix"],
 		u_texture: 0,
 		u_alpha: node["alpha"],
 		u_maskEnabled: node["maskEnabled"],
 		u_maskHeight: node["maskHeight"],
-		u_maskColor: node["maskColor"]
-	})
+		u_maskColor: node["maskColor"],
+		v3CameraPosition: origin,
+		v3Translate: node["translation"],
+		v3LightPos: lightOrigin,
+		v3InvWavelength: inv_wavelength4,
+		fOuterRadius: outerRadius,
+		fOuterRadius2: outerRadius * outerRadius,
+		fInnerRadius: innerRadius,
+		fInnerRadius2: innerRadius * innerRadius,
+		fKrESun: atm.kRayleigh * atm.eSun, 
+		fKmESun: atm.kMie * atm.eSun, 
+		fKr4PI: atm.kRayleigh * 4 * Math.PI, 
+		fKm4PI: atm.kMie * 4 * Math.PI,
+		fScale: scale, 
+		fScaleDepth: scaleDepth,
+		fScaleOverScaleDepth: scale/scaleDepth, 
+		v3LightPosFrag: lightOrigin,
+		fHdrExposure: atm.hdr_exposure,	
+		g: atm.g,			
+		g2: atm.g * atm.g,
+		a: atm.a,
+		b: atm.b,
+		c: atm.c,
+		d: atm.d,		
+		e: atm.e,
+		attenuation: atm.attenuation
+	});
 	if (node["useIndexBuffer"] == true) node["shader"].draw(node["mesh"], node["drawMode"], "indices");
 	else node["shader"].draw(node["mesh"], node["drawMode"]);
 
 	gl.enable(gl.DEPTH_TEST);
+	gl.disable(gl.CULL_FACE);
 } //}}}
 function draw(canvas,options) { //{{{
 	// Ensure canvas and gl viewport sizes are the same
-	var displayWidth  = canvas.clientWidth;
-	var displayHeight = canvas.clientHeight;
-	if (canvas.width  != displayWidth || canvas.height != displayHeight) {
-		canvas.width  = displayWidth;
-		canvas.height = displayHeight;
+	if (canvas.width  != canvas.clientWidth || canvas.height != canvas.clientHeight) {
+		canvas.width  = canvas.clientWidth;
+		canvas.height = canvas.clientHeight;
 		canvas.gl.viewport(0, 0, canvas.width, canvas.height);
 	}
@@ -386,9 +377,7 @@
 	gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
 	
-	
-	
 	updateCameraMatrix(canvas);
 	
-	var drawPassNumber = 2;
+	var drawPassNumber = 3;
 	for (var i = drawPassNumber - 1; i >= 0; i--) {
 		for (var node in nodes) {
