attribute vec2 position; //the position of the point
		varying vec2 vPosition;
		void main(void) { //pre-built function
			vPosition = position;
			gl_Position = vec4(position, 0., 1.); //0. is the z, and 1 is w				
		}
	
		precision mediump float;

		varying vec2 vPosition;
		uniform sampler2D sampler2d;
		uniform float idx; 
		uniform float timestamp; 
		
		uniform float width;
		uniform float height;
		// Input: It uses texture coords as the random number seed.
		// Output: Random number: [0,1), that is between 0.0 and 0.999999... inclusive.
		// Author: Michael Pohoreski
		// Copyright: Copyleft 2012 :-)

		float rand( vec2 p )
		{
			float seed = 42.0;
		  // We need irrationals for pseudo randomness.
		  // Most (all?) known transcendental numbers will (generally) work.
		  vec2 r = vec2(
			23.1406926327792690,  // e^pi (Gelfond's constant)
			 2.6651441426902251) * cos(timestamp); // 2^sqrt(2) (Gelfond–Schneider constant)
		  return fract( cos( mod( 123456789., 1e-7 + 256. * dot(p*cos(idx+seed),r) ) ) );  
		}	
		
		
		void main(void) {
			float grid_size_x = width / 2.0 ;
			float grid_size_y = height / 2.0 ; 
			
			float x = vPosition.x - mod(vPosition.x, 1.0 / grid_size_x) + 1.0 / grid_size_x / 2.0;
			float y = vPosition.y - mod(vPosition.y, 1.0 / grid_size_y) + 1.0 / grid_size_y / 2.0;
			
			float tx = (x + 1.0) / 2.0;
			float ty = (y + 1.0) / 2.0; 
				
			float dx = 1.0 / grid_size_x / 2.0; 
			float dy = 1.0 / grid_size_y / 2.0; 
			vec2 seed = vec2(tx, ty); 
			
			if(idx < 1.0 ) {		
				float prob = 0.5; 
				gl_FragColor = vec4(step(rand(seed), prob), 
									step(rand(seed), prob), 
									step(rand(seed), prob), 1.0); 
				return;
			}
		
			int neigh = 0;
			for(int i = -1;i < 2;i++) {			
				for(int j = -1;j < 2;j++) {
					if(j != 0 || i != 0) {
						vec4 cells = 1.0 - texture2D(sampler2d, vec2(tx + float(i) * dx, ty + float(j) * dy));					
						if(cells[0] < 0.5) {
							neigh = neigh + 1;
						}					
					}
				}
			}
			vec4 my_cell = 1.0 - texture2D(sampler2d, vec2(tx,ty));
			
			vec3 dead  = vec3(1.0, 1.0, 1.0); 	
			vec3 alive = vec3(0.0, 0.0, 0.0); 
			vec3 rtn = dead;
					
			if(neigh == 3) {
				rtn = alive; 
			} else if(my_cell[0] < 0.5 && neigh >= 2 && neigh <= 3) {
				rtn = alive; 
			} else {
				if(my_cell.x < 0.5) {
					rtn = vec3(1.0, 0.0, 0.0);
				} else {
					rtn = vec3(1.0, my_cell.y + 0.01, my_cell.z + 0.1); 
					if(rtn.z >= 1.0){
						discard; 						
					}
				}
			}	
			
			gl_FragColor = vec4(1.0 - rtn, 1.0); 
		}