1 /***************************************
  2  * Copyright 2011, 2012 GlobWeb contributors.
  3  *
  4  * This file is part of GlobWeb.
  5  *
  6  * GlobWeb is free software: you can redistribute it and/or modify
  7  * it under the terms of the GNU Lesser General Public License as published by
  8  * the Free Software Foundation, version 3 of the License, or
  9  * (at your option) any later version.
 10  *
 11  * GlobWeb is distributed in the hope that it will be useful,
 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 14  * GNU Lesser General Public License for more details.
 15  *
 16  * You should have received a copy of the GNU General Public License
 17  * along with GlobWeb. If not, see <http://www.gnu.org/licenses/>.
 18  ***************************************/
 19  
 20 define(['./Program','./Tile'], function(Program,Tile) {
 21 
 22 //*************************************************************************
 23 
 24 /** 
 25 	@constructor
 26  */
 27 var GroundOverlayRenderer = function(tileManager)
 28 {
 29 	this.renderContext = tileManager.renderContext;
 30 	this.tileIndexBuffer = tileManager.tileIndexBuffer;
 31 	
 32 	var vertexShader = "\
 33 	attribute vec3 vertex;\n\
 34 	attribute vec2 tcoord;\n\
 35 	uniform mat4 modelViewMatrix;\n\
 36 	uniform mat4 projectionMatrix;\n\
 37 	uniform vec4 extent; \n\
 38 	\
 39 	varying vec2 texCoord;\n\
 40 	\
 41 	void main(void) \n\
 42 	{\n\
 43 		gl_Position = projectionMatrix * modelViewMatrix * vec4(vertex, 1.0);\n\
 44 		texCoord.x = tcoord.x * (extent[1] - extent[0]) + extent[0];\n\
 45 		texCoord.y = tcoord.y * (extent[3] - extent[2]) + extent[2];\n\
 46 	}\n\
 47 	";
 48 
 49 	var fragmentShader = "\
 50 	#ifdef GL_ES\n\
 51 	precision highp float;\n\
 52 	#endif\n\
 53 	\n\
 54 	varying vec2 texCoord;\n\
 55 	uniform sampler2D overlayTexture;\n\
 56 	uniform mat3 transform;\n\
 57 	uniform float opacity; \n\
 58 	\n\
 59 	void main(void)\n\
 60 	{\n\
 61 		vec3 tc = transform * vec3(texCoord,1.0); \n\
 62 		tc.xy /= tc.z; \n\
 63 		gl_FragColor.rgba = texture2D(overlayTexture, tc.xy); \n\
 64 		gl_FragColor.a = (tc.x >= 0.0 && tc.x <= 1.0 && tc.y >= 0.0 && tc.y <= 1.0) ? opacity * gl_FragColor.a  : 0.0; \n\
 65 	}\n\
 66 	";
 67 	
 68     this.program = new Program(this.renderContext);
 69 	this.program.createFromSource( vertexShader, fragmentShader );
 70 	
 71 	this.groundOverlays = [];
 72 	
 73 	this.needsOffset = true;
 74 }
 75 
 76 //*************************************************************************
 77 
 78 /*
 79 	Render the ground overlays above the tiles in parameter
 80  */
 81 GroundOverlayRenderer.prototype.render = function( tiles )
 82 {
 83  	var gl = this.renderContext.gl;
 84 
 85 	// Setup program
 86     this.program.apply();
 87 	
 88 	var attributes = this.program.attributes;
 89 		
 90 	gl.uniformMatrix4fv(this.program.uniforms["projectionMatrix"], false, this.renderContext.projectionMatrix);
 91 	gl.uniform1i(this.program.uniforms["overlayTexture"], 0);
 92 	gl.enable(gl.BLEND);
 93 	gl.blendFunc( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA );
 94 	gl.depthFunc( gl.LEQUAL );
 95 	
 96 	var modelViewMatrix = mat4.create();
 97 	
 98 	var currentIB = null;
 99 
100 	for ( var j=0; j < this.groundOverlays.length; j++ )
101 	{
102 		var go = this.groundOverlays[j];
103 		
104 		// Image is not loaded, nothing to be done
105 		if ( !go.image.complete )
106 		{
107 			continue;
108 		}
109 		
110 		if ( !go.texture )
111 		{
112 			if ( go.flipY )
113 				gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true );
114 			go.texture = this.renderContext.createNonPowerOfTwoTextureFromImage(go.image);
115 			if ( go.flipY )
116 				gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false );
117 		}
118 		
119 		var initialized = false;
120 		
121 		for ( var i = 0; i < tiles.length; i++ )
122 		{
123 			var tile = tiles[i];
124 			if ( go.geoBound.intersects( tile.geoBound ) )
125 			{
126 				if (!initialized)
127 				{					
128 					gl.uniformMatrix3fv(this.program.uniforms["transform"], false, go.inverseTransform );
129 					gl.uniform1f(this.program.uniforms["opacity"], go.opacity );
130 
131 					gl.activeTexture(gl.TEXTURE0);
132 					gl.bindTexture(gl.TEXTURE_2D, go.texture);
133 					
134 					initialized = true;
135 				}
136 
137 				var extent = (tile.state == Tile.State.LOADED) ? tile.geoBound : tile.parent.geoBound;
138 				
139 				gl.uniform4f(this.program.uniforms["extent"], extent.west, extent.east, extent.north, extent.south );
140 				mat4.multiply( this.renderContext.viewMatrix, tile.matrix, modelViewMatrix );
141 				gl.uniformMatrix4fv(this.program.uniforms["modelViewMatrix"], false, modelViewMatrix);
142 
143 				// Bind the vertex buffer
144 				gl.bindBuffer(gl.ARRAY_BUFFER, tile.vertexBuffer);
145 				gl.vertexAttribPointer(attributes['vertex'], 3, gl.FLOAT, false, 0, 0);
146 				
147 				// Bind the index buffer only if different (index buffer is shared between tiles)
148 				var indexBuffer = ( tile.state == Tile.State.LOADED ) ? this.tileIndexBuffer.getSolid() : this.tileIndexBuffer.getSubSolid(tile.parentIndex);
149 				if ( currentIB != indexBuffer )
150 				{
151 					gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
152 					currentIB = indexBuffer;
153 				}
154 				
155 				// Finally draw the tiles
156 				gl.drawElements(gl.TRIANGLES, indexBuffer.numIndices, gl.UNSIGNED_SHORT, 0);
157 			}
158 		}
159 	}
160 
161 	gl.disable(gl.BLEND);
162 }
163 
164 //*************************************************************************
165 
166 return GroundOverlayRenderer;
167 
168 });