├── README ├── checkerboard.png ├── grass_normals.png ├── grass_texture.png ├── rock2_normals.png ├── rock_normals.png ├── rock_texture.png ├── grass_material.png ├── rock2_material.png ├── copy.shader ├── flows.shader ├── blur.shader ├── webgl ├── scheduler.js ├── util.js ├── keys.js ├── quad.js ├── vbo.js ├── projection.js ├── loader.js ├── hexgrid.js ├── event.js ├── box.js ├── texture.js ├── quaternion.js ├── framebuffer.js ├── vector.js ├── grid.js ├── framework.js ├── viewpoint.js ├── sphere.js ├── shader.js └── matrix.js ├── shadow.shader ├── water ├── diffuse.shader ├── normals.shader ├── momentum.shader ├── shadowmap.shader ├── cycle.shader ├── init.shader └── display.shader ├── diskpick.html ├── diffuse_soil.shader ├── normal.shader ├── occlusion.shader ├── errode.shader ├── shadowmap.shader ├── style.css ├── simplex.shader ├── jquery.mousewheel.min.js ├── simplex3d.shader ├── index.html ├── god.shader ├── display.shader ├── liquidtest.html ├── main.js └── LICENSE /README: -------------------------------------------------------------------------------- 1 | Craftscape is a WebGL landscaping and erosion demo. 2 | -------------------------------------------------------------------------------- /checkerboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyalot/craftscape/HEAD/checkerboard.png -------------------------------------------------------------------------------- /grass_normals.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyalot/craftscape/HEAD/grass_normals.png -------------------------------------------------------------------------------- /grass_texture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyalot/craftscape/HEAD/grass_texture.png -------------------------------------------------------------------------------- /rock2_normals.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyalot/craftscape/HEAD/rock2_normals.png -------------------------------------------------------------------------------- /rock_normals.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyalot/craftscape/HEAD/rock_normals.png -------------------------------------------------------------------------------- /rock_texture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyalot/craftscape/HEAD/rock_texture.png -------------------------------------------------------------------------------- /grass_material.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyalot/craftscape/HEAD/grass_material.png -------------------------------------------------------------------------------- /rock2_material.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyalot/craftscape/HEAD/rock2_material.png -------------------------------------------------------------------------------- /copy.shader: -------------------------------------------------------------------------------- 1 | /* 2 | :copyright: 2011 by Florian Boesch . 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | vertex: 7 | attribute vec2 position; 8 | void main(){ 9 | gl_Position = vec4(position, 0.0, 1.0); 10 | } 11 | 12 | fragment: 13 | uniform sampler2D source; 14 | uniform vec2 viewport; 15 | 16 | void main(void){ 17 | vec2 uv = gl_FragCoord.xy/viewport; 18 | gl_FragColor = texture2D(source, uv); 19 | } 20 | -------------------------------------------------------------------------------- /flows.shader: -------------------------------------------------------------------------------- 1 | /* 2 | :copyright: 2011 by Florian Boesch . 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | vertex: 7 | attribute vec2 position; 8 | void main(){ 9 | gl_Position = vec4(position, 0.0, 1.0); 10 | } 11 | 12 | fragment: 13 | uniform sampler2D water, flows; 14 | uniform vec2 viewport; 15 | 16 | void main(void){ 17 | vec2 uv = gl_FragCoord.xy/viewport; 18 | vec2 pos = texture2D(flows, uv).xy; 19 | vec3 w = texture2D(water, uv).xyz; 20 | vec2 vel = (w.yz*0.001)/(w.x*0.1+0.001); 21 | gl_FragColor = vec4(pos+vel, 0.0, 1.0); 22 | } 23 | -------------------------------------------------------------------------------- /blur.shader: -------------------------------------------------------------------------------- 1 | /* 2 | :copyright: 2011 by Florian Boesch . 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | vertex: 7 | attribute vec2 position; 8 | void main(){ 9 | gl_Position = vec4(position, 0.0, 1.0); 10 | } 11 | 12 | fragment: 13 | uniform sampler2D source; 14 | uniform vec2 viewport, axis; 15 | 16 | void main(void){ 17 | vec2 off = axis/viewport; 18 | vec2 uv = gl_FragCoord.xy/viewport; 19 | 20 | vec4 a = texture2D(source, uv)*0.375; 21 | vec4 b = texture2D(source, uv+off)*0.3125; 22 | vec4 c = texture2D(source, uv-off)*0.3125; 23 | gl_FragColor = a+b+c; 24 | } 25 | -------------------------------------------------------------------------------- /webgl/scheduler.js: -------------------------------------------------------------------------------- 1 | /* 2 | :copyright: 2011 by Florian Boesch . 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | Scheduler = function(onrun){ 7 | var request = window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame; 8 | if(!request){ 9 | request = function(callback){ 10 | setTimeout(callback, 1000/30); 11 | }; 12 | } 13 | var last; 14 | 15 | var step = function(){ 16 | request(step); 17 | var current = Date.now(); 18 | var delta = current-last; 19 | delta = Math.max(1, Math.min(delta, 500)); 20 | last = current; 21 | onrun(delta/1000, current/1000); 22 | } 23 | 24 | this.start = function(){ 25 | last = Date.now(); 26 | request(step); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /webgl/util.js: -------------------------------------------------------------------------------- 1 | /* 2 | :copyright: 2011 by Florian Boesch . 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | var extend = function(a, b){ 7 | var result = {}; 8 | for(var name in a){ 9 | result[name] = a[name]; 10 | } 11 | for(var name in b){ 12 | result[name] = b[name]; 13 | } 14 | return result; 15 | }; 16 | 17 | var Class = function(obj){ 18 | var constructor = obj.__init__ || function(){}; 19 | 20 | if(obj.__extends__){ 21 | var base = obj.__extends__.prototype; 22 | } 23 | else{ 24 | var base = {}; 25 | } 26 | 27 | constructor.prototype = extend(base, obj); 28 | return constructor; 29 | }; 30 | 31 | 32 | var clamp = function(value, left, right){ 33 | return value < left ? left : (value > right ? right : value); 34 | }; 35 | -------------------------------------------------------------------------------- /shadow.shader: -------------------------------------------------------------------------------- 1 | /* 2 | :copyright: 2011 by Florian Boesch . 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | vertex: 7 | uniform mat4 proj, view; 8 | uniform sampler2D heights; 9 | 10 | attribute vec2 position, texcoord; 11 | 12 | varying float depth; 13 | 14 | void main(){ 15 | float y = texture2D(heights, texcoord).x; 16 | vec4 pos = vec4(position.x, y, -position.y, 1.0); 17 | vec4 eye_pos = view * pos; 18 | depth = eye_pos.z; 19 | gl_Position = proj * eye_pos; 20 | } 21 | 22 | fragment: 23 | varying float depth; 24 | void main(){ 25 | if(gl_FrontFacing){ 26 | gl_FragColor = vec4(depth, depth, depth, 1.0); 27 | } 28 | else{ 29 | gl_FragColor = vec4(100.0, 100.0, 100.0, 1.0); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /webgl/keys.js: -------------------------------------------------------------------------------- 1 | /* 2 | :copyright: 2011 by Florian Boesch . 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | var Keys = function(){ 7 | var keymap = ({ 8 | 87: 'w', 9 | 65: 'a', 10 | 83: 's', 11 | 68: 'd', 12 | 81: 'q', 13 | 69: 'e', 14 | 37: 'left', 15 | 39: 'right', 16 | 38: 'up', 17 | 40: 'down', 18 | 13: 'enter', 19 | 27: 'esc', 20 | 32: 'space', 21 | 8: 'backspace', 22 | 16: 'shift', 23 | 17: 'ctrl', 24 | 18: 'alt', 25 | 91: 'start', 26 | 0: 'altc', 27 | 20: 'caps', 28 | 9: 'tab', 29 | 49: 'key1', 30 | 50: 'key2', 31 | 51: 'key3', 32 | 52: 'key4' 33 | }); 34 | 35 | var self = this; 36 | 37 | $(document).keydown(function(event){ 38 | self[keymap[event.which]] = true; 39 | }); 40 | 41 | $(document).keyup(function(event){ 42 | self[keymap[event.which]] = false; 43 | }); 44 | }; 45 | -------------------------------------------------------------------------------- /water/diffuse.shader: -------------------------------------------------------------------------------- 1 | /* 2 | :copyright: 2011 by Florian Boesch . 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | vertex: 7 | attribute vec2 position; 8 | void main(){ 9 | gl_Position = vec4(position, 0.0, 1.0); 10 | } 11 | 12 | fragment: 13 | uniform sampler2D heights, source; 14 | uniform vec2 viewport, axis; 15 | 16 | vec3 exchange(float t1, float h1, vec2 off){ 17 | vec2 uv = (gl_FragCoord.xy+off)/viewport; 18 | float t2 = texture2D(heights, uv).x; 19 | float h2 = texture2D(source, uv).x; 20 | float f1 = t1+h1; 21 | float f2 = t2+h2; 22 | float diff = (f2-f1)/2.0; 23 | diff = clamp(diff*0.65, -h1/2.0, h2/2.0); 24 | return vec3(diff, -off*diff); 25 | } 26 | 27 | void main(void){ 28 | vec2 uv = gl_FragCoord.xy/viewport; 29 | float t = texture2D(heights, uv).x; 30 | vec3 h = texture2D(source, uv).xyz; 31 | vec3 r = h + exchange(t, h.x, axis) + exchange(t, h.x, -axis); 32 | gl_FragColor = vec4(r, 1.0); 33 | } 34 | -------------------------------------------------------------------------------- /diskpick.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /diffuse_soil.shader: -------------------------------------------------------------------------------- 1 | vertex: 2 | attribute vec2 position; 3 | void main(){ 4 | gl_Position = vec4(position, 0.0, 1.0); 5 | } 6 | 7 | fragment: 8 | uniform sampler2D ground, water; 9 | uniform vec2 viewport, axis; 10 | 11 | vec2 exchange(vec4 g1, float x, float y){ 12 | vec2 uv = (gl_FragCoord.xy+vec2(x, y))/viewport; 13 | vec4 g2 = texture2D(ground, uv); 14 | float diff = (g2.x-g1.x)/4.0; 15 | float sdiff, gdiff; 16 | sdiff = clamp(diff, -g1.z/2.0, g2.z/2.0)*0.08; 17 | if(abs(diff) > 0.001){ 18 | gdiff = diff*0.1; 19 | } 20 | else{ 21 | gdiff = 0.0; 22 | } 23 | return vec2(gdiff, sdiff); 24 | } 25 | 26 | void main(void){ 27 | vec2 uv = gl_FragCoord.xy/viewport; 28 | vec4 g = texture2D(ground, uv); 29 | vec2 c = ( 30 | exchange(g, 1.0, 0.0) + 31 | exchange(g, -1.0, 0.0) + 32 | exchange(g, 0.0, 1.0) + 33 | exchange(g, 0.0, -1.0) 34 | ); 35 | gl_FragColor = g + vec4(0.0, c, 0.0); 36 | } 37 | -------------------------------------------------------------------------------- /normal.shader: -------------------------------------------------------------------------------- 1 | /* 2 | :copyright: 2011 by Florian Boesch . 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | vertex: 7 | attribute vec2 position; 8 | void main(){ 9 | gl_Position = vec4(position, 0.0, 1.0); 10 | } 11 | 12 | fragment: 13 | uniform vec2 viewport; 14 | uniform sampler2D heights; 15 | 16 | vec3 get(float x, float y){ 17 | vec2 uv = (gl_FragCoord.xy+vec2(x,y))/viewport; 18 | float h = texture2D(heights, uv).x; 19 | return vec3(uv.x, h, uv.y); 20 | } 21 | 22 | vec3 getn(vec3 pos, float x, float y){ 23 | vec3 v = get(x, y) - pos; 24 | vec3 perp = cross(vec3(0.0, 1.0, 0.0), v); 25 | return normalize(cross(v, perp)); 26 | } 27 | 28 | void main(){ 29 | vec3 pos = get(0.0, 0.0); 30 | vec3 normal = normalize(( 31 | getn(pos, -1.0, 1.0) + 32 | getn(pos, 0.0, 1.0) + 33 | getn(pos, 1.0, 1.0) + 34 | getn(pos, -1.0, 0.0) + 35 | getn(pos, 1.0, 0.0) + 36 | getn(pos, -1.0, -1.0) + 37 | getn(pos, 0.0, -1.0) + 38 | getn(pos, 1.0, -1.0) 39 | )/8.0); 40 | gl_FragColor = vec4(normal, 1.0); 41 | } 42 | -------------------------------------------------------------------------------- /water/normals.shader: -------------------------------------------------------------------------------- 1 | /* 2 | :copyright: 2011 by Florian Boesch . 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | vertex: 7 | attribute vec2 position; 8 | void main(){ 9 | gl_Position = vec4(position, 0.0, 1.0); 10 | } 11 | 12 | fragment: 13 | uniform vec2 viewport; 14 | uniform sampler2D ground, water; 15 | 16 | vec3 get(float x, float y){ 17 | vec2 uv = (gl_FragCoord.xy+vec2(x,y))/viewport; 18 | float g = texture2D(ground, uv).x; 19 | float w = texture2D(water, uv).x; 20 | float h = g+w; 21 | return vec3(uv.x, h, uv.y); 22 | } 23 | 24 | vec3 getn(vec3 pos, float x, float y){ 25 | vec3 v = get(x, y) - pos; 26 | vec3 perp = cross(vec3(0.0, 1.0, 0.0), v); 27 | return normalize(cross(v, perp)); 28 | } 29 | 30 | void main(){ 31 | vec3 pos = get(0.0, 0.0); 32 | vec3 normal = normalize(( 33 | getn(pos, -1.0, 1.0) + 34 | getn(pos, 0.0, 1.0) + 35 | getn(pos, 1.0, 1.0) + 36 | getn(pos, -1.0, 0.0) + 37 | getn(pos, 1.0, 0.0) + 38 | getn(pos, -1.0, -1.0) + 39 | getn(pos, 0.0, -1.0) + 40 | getn(pos, 1.0, -1.0) 41 | )/8.0); 42 | gl_FragColor = vec4(normal, 1.0); 43 | } 44 | -------------------------------------------------------------------------------- /webgl/quad.js: -------------------------------------------------------------------------------- 1 | /* 2 | :copyright: 2011 by Florian Boesch . 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | Framework.components.push(function(framework, gl){ 7 | framework.Quad = Class({ 8 | __extends__: framework.Drawable, 9 | __init__: function(params){ 10 | var b=params.y; 11 | var t=b+params.h; 12 | var l=params.x; 13 | var r=params.x+params.h; 14 | 15 | this.vbo = new framework.VBO({ 16 | position_2f: [ 17 | r, t, 18 | l, t, 19 | l, b, 20 | 21 | r, t, 22 | l, b, 23 | r, b, 24 | ], 25 | texcoord_2f: [ 26 | 1, 0, 27 | 0, 0, 28 | 0, 1, 29 | 30 | 1, 0, 31 | 0, 1, 32 | 1, 1, 33 | ] 34 | }); 35 | }, 36 | }); 37 | 38 | var unit_quad; 39 | 40 | framework.unitQuad = function(){ 41 | if(!unit_quad){ 42 | unit_quad = new framework.Quad({ 43 | x: -1, y: -1, 44 | w: 2, h: 2, 45 | }); 46 | } 47 | return unit_quad; 48 | }; 49 | }); 50 | -------------------------------------------------------------------------------- /water/momentum.shader: -------------------------------------------------------------------------------- 1 | /* 2 | :copyright: 2011 by Florian Boesch . 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | vertex: 7 | attribute vec2 position; 8 | void main(){ 9 | gl_Position = vec4(position, 0.0, 1.0); 10 | } 11 | 12 | fragment: 13 | uniform sampler2D current, last, ground; 14 | uniform vec2 viewport; 15 | 16 | vec4 get(sampler2D src, float x, float y){ 17 | return texture2D(src, (gl_FragCoord.xy+vec2(x,y))/viewport); 18 | } 19 | 20 | vec3 exchange(float g1, vec3 l1, vec3 c1, float x, float y){ 21 | float g2 = get(ground, x, y).x; 22 | vec3 c2 = get(current, x, y).xyz; 23 | float change = (g2+c2.x) - (g1+l1.x); 24 | change = clamp(change*1.00, -c1.x*0.25, c2.x*0.25); 25 | return vec3(change, vec2(-x*change, -y*change)); 26 | } 27 | 28 | void main(void){ 29 | float g = get(ground, 0.0, 0.0).x; 30 | vec3 l = get(last, 0.0, 0.0).xyz; 31 | vec3 c = get(current, 0.0, 0.0).xyz; 32 | 33 | vec3 v = ( 34 | exchange(g, l, c, 1.0, 0.0) + 35 | exchange(g, l, c, -1.0, 0.0) + 36 | exchange(g, l, c, 0.0, 1.0) + 37 | exchange(g, l, c, 0.0, -1.0) 38 | )*vec3(0.25, 0.25, 0.25); 39 | 40 | vec3 n = c + v; 41 | gl_FragColor = vec4(n, 1.0); 42 | } 43 | -------------------------------------------------------------------------------- /occlusion.shader: -------------------------------------------------------------------------------- 1 | /* 2 | :copyright: 2011 by Florian Boesch . 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | vertex: 7 | attribute vec2 position; 8 | void main(){ 9 | gl_Position = vec4(position, 0.0, 1.0); 10 | } 11 | 12 | fragment: 13 | float pi = 3.14159265358979323846; 14 | 15 | uniform vec2 viewport; 16 | uniform sampler2D heights, normals; 17 | 18 | vec3 get(float x, float y){ 19 | vec2 uv = (gl_FragCoord.xy+vec2(x,y))/viewport; 20 | float h = texture2D(heights, uv).x; 21 | return vec3(uv.x, h, uv.y); 22 | } 23 | 24 | #define raylength 10.0 25 | 26 | void main(){ 27 | float occlusion = 0.0; 28 | vec3 pos = get(0.0, 0.0); 29 | vec3 normal = texture2D(normals, gl_FragCoord.xy/viewport).xyz; 30 | vec3 tangent = normalize(cross(normal, vec3(0.0, 0.0, 1.0))); 31 | vec3 bitangent = normalize(cross(tangent, normal)); 32 | mat3 orthobasis = mat3(tangent, normal, bitangent); 33 | 34 | for(int i=1; i<33; i++){ 35 | float s = float(i)/32.0; 36 | float a = sqrt(s*512.0); 37 | float b = sqrt(s); 38 | float x = sin(a)*b*raylength; 39 | float y = cos(a)*b*raylength; 40 | vec3 sample_uv = orthobasis * vec3(x, 0.0, y); 41 | vec3 sample_pos = get(sample_uv.x, sample_uv.z); 42 | vec3 sample_dir = normalize(sample_pos - pos); 43 | float lambert = clamp(dot(normal, sample_dir), 0.0, 1.0); 44 | float dist_factor = 0.23/sqrt(length(sample_pos - pos)); 45 | occlusion += dist_factor*lambert; 46 | } 47 | float incident = 1.0 - occlusion/32.0; 48 | gl_FragColor = vec4(incident, incident, incident, 1.0); 49 | } 50 | -------------------------------------------------------------------------------- /errode.shader: -------------------------------------------------------------------------------- 1 | /* 2 | :copyright: 2011 by Florian Boesch . 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | vertex: 7 | attribute vec2 position; 8 | void main(){ 9 | gl_Position = vec4(position, 0.0, 1.0); 10 | } 11 | 12 | fragment: 13 | uniform sampler2D ground, water; 14 | uniform vec2 viewport; 15 | uniform float factor; 16 | 17 | vec4 get(sampler2D source, float x, float y){ 18 | return texture2D(source, (gl_FragCoord.xy+vec2(x,y))/viewport); 19 | } 20 | 21 | float tf = 0.0015; 22 | float tm = 0.5; 23 | 24 | void main(void){ 25 | vec4 g = get(ground, 0.0, 0.0); 26 | vec3 w = get(water, 0.0, 0.0).xyz; 27 | 28 | float erroded = (length(w.yz)*0.000005)/(w.x+0.001)*factor; 29 | erroded /= 1.0 + g.z*300.0; 30 | g.y -= erroded; 31 | g.z += erroded; 32 | 33 | vec3 w_left = get(water, -1.0, 0.0).xyz; 34 | vec3 w_right = get(water, 1.0, 0.0).xyz; 35 | vec3 w_top = get(water, 0.0, 1.0).xyz; 36 | vec3 w_bot = get(water, 0.0, -1.0).xyz; 37 | 38 | vec4 g_left = get(ground, -1.0, 0.0); 39 | vec4 g_right = get(ground, 1.0, 0.0); 40 | vec4 g_top = get(ground, 0.0, 1.0); 41 | vec4 g_bot = get(ground, 0.0, -1.0); 42 | 43 | float soil_transported_off = (min(abs(w.y*tf/(w.x+0.001)), tm) + min(abs(w.z*tf/(w.x+0.001)), tm))*g.z; 44 | float soil_transported_in = ( 45 | clamp(w_left.y*tf/(w_left.x+0.001), 0.0, tm) * g_left.z + 46 | clamp(-w_right.y*tf/(w_right.x+0.001), 0.0, tm) * g_right.z + 47 | clamp(-w_top.z*tf/(w_top.x+0.001), 0.0, tm) * g_top.z + 48 | clamp(w_bot.z*tf/(w_bot.x+0.001), 0.0, tm) * g_bot.z 49 | ); 50 | g.z += (soil_transported_in - soil_transported_off)*factor; 51 | g.z = max(0.0, g.z); 52 | g.x = g.y + g.z; 53 | 54 | gl_FragColor = g; 55 | } 56 | -------------------------------------------------------------------------------- /water/shadowmap.shader: -------------------------------------------------------------------------------- 1 | /* 2 | :copyright: 2011 by Florian Boesch . 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | vertex: 7 | attribute vec2 position; 8 | void main(){ 9 | gl_Position = vec4(position, 0.0, 1.0); 10 | } 11 | 12 | fragment: 13 | uniform vec2 viewport, shadowsize; 14 | uniform sampler2D ground, water, shadows, normals; 15 | uniform mat4 view, proj; 16 | 17 | vec2 off = vec2(1.0)/shadowsize; 18 | 19 | vec3 get(float x, float y){ 20 | vec2 uv = (gl_FragCoord.xy+vec2(x,y))/viewport; 21 | float h = texture2D(ground, uv).x + texture2D(water, uv).x; 22 | return vec3(uv.x-0.5, h, -uv.y+0.5); 23 | } 24 | 25 | float shadowed(float depth1, vec2 center, float x, float y){ 26 | float depth2 = texture2D(shadows, center + off*vec2(x, y)).x; 27 | return smoothstep(1.0, 0.0, (depth2 - depth1-0.0001)*100.0); 28 | } 29 | 30 | void main(){ 31 | vec4 pos = vec4(get(0.0, 0.0), 1.0); 32 | vec4 eye = view * pos; 33 | vec4 device = proj * view * pos; 34 | vec3 device_normal = device.xyz / device.w; 35 | vec2 uv = (device_normal.xy+1.0)*0.5; 36 | float depth1 = eye.z; 37 | 38 | float s = ( 39 | shadowed(depth1, uv, 0.0, 0.0) + 40 | shadowed(depth1, uv, 1.0, 0.0) + 41 | shadowed(depth1, uv, -1.0, 0.0) + 42 | shadowed(depth1, uv, 0.0, 1.0) + 43 | shadowed(depth1, uv, 0.0, -1.0) + 44 | shadowed(depth1, uv, -1.0, -1.0) + 45 | shadowed(depth1, uv, 1.0, -1.0) + 46 | shadowed(depth1, uv, -1.0, 1.0) + 47 | shadowed(depth1, uv, 1.0, 1.0) 48 | )/9.0; 49 | 50 | vec4 normal = texture2D(normals, gl_FragCoord.xy/viewport); 51 | normal.z *= -1.0; 52 | normal.xyz = normalize(normal.xyz); 53 | normal = view * normal; 54 | 55 | float c = dot(normalize(normal.xyz), vec3(0.0, 0.0, 1.0)) > 0.1 ? 1.0 : 0.0; 56 | float f = min(s, c); 57 | 58 | gl_FragColor = vec4(f, f, f, 1.0); 59 | } 60 | -------------------------------------------------------------------------------- /shadowmap.shader: -------------------------------------------------------------------------------- 1 | /* 2 | :copyright: 2011 by Florian Boesch . 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | vertex: 7 | attribute vec2 position; 8 | void main(){ 9 | gl_Position = vec4(position, 0.0, 1.0); 10 | } 11 | 12 | fragment: 13 | uniform vec2 viewport, shadowsize; 14 | uniform sampler2D heights, shadows, normals; 15 | uniform mat4 view, proj; 16 | 17 | vec2 off = vec2(1.0)/shadowsize; 18 | 19 | vec3 get(float x, float y){ 20 | vec2 uv = (gl_FragCoord.xy+vec2(x,y))/viewport; 21 | float h = texture2D(heights, uv).x; 22 | return vec3(uv.x-0.5, h, -uv.y+0.5); 23 | } 24 | 25 | float shadowed(float depth1, vec2 center, float x, float y){ 26 | float depth2 = texture2D(shadows, center + off*vec2(x, y)).x; 27 | return smoothstep(1.0, 0.0, (depth2 - depth1-0.0001)*100.0); 28 | } 29 | 30 | void main(){ 31 | vec4 pos = vec4(get(0.0, 0.0), 1.0); 32 | vec4 eye = view * pos; 33 | vec4 device = proj * view * pos; 34 | vec3 device_normal = device.xyz / device.w; 35 | vec2 uv = (device_normal.xy+1.0)*0.5; 36 | float depth1 = eye.z; 37 | 38 | //float depth2 = texture2D(shadows, uv).x; 39 | float s = ( 40 | shadowed(depth1, uv, 0.0, 0.0) + 41 | shadowed(depth1, uv, 1.0, 0.0) + 42 | shadowed(depth1, uv, -1.0, 0.0) + 43 | shadowed(depth1, uv, 0.0, 1.0) + 44 | shadowed(depth1, uv, 0.0, -1.0) + 45 | shadowed(depth1, uv, -1.0, -1.0) + 46 | shadowed(depth1, uv, 1.0, -1.0) + 47 | shadowed(depth1, uv, -1.0, 1.0) + 48 | shadowed(depth1, uv, 1.0, 1.0) 49 | )/9.0; 50 | 51 | vec4 normal = texture2D(normals, gl_FragCoord.xy/viewport); 52 | normal.z *= -1.0; 53 | normal.xyz = normalize(normal.xyz); 54 | normal = view * normal; 55 | 56 | float c = dot(normalize(normal.xyz), vec3(0.0, 0.0, 1.0)) > 0.1 ? 1.0 : 0.0; 57 | float f = min(s, c); 58 | 59 | gl_FragColor = vec4(f, f, f, 1.0); 60 | } 61 | -------------------------------------------------------------------------------- /water/cycle.shader: -------------------------------------------------------------------------------- 1 | /* 2 | :copyright: 2011 by Florian Boesch . 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | vertex: 7 | attribute vec2 position; 8 | void main(){ 9 | gl_Position = vec4(position, 0.0, 1.0); 10 | } 11 | 12 | fragment: 13 | uniform sampler2D water; 14 | uniform vec2 viewport, screen, mousepos; 15 | uniform float rain, evaporate, create, editsize; 16 | 17 | uniform mat4 inv_view, inv_proj; 18 | uniform mat3 inv_rot; 19 | 20 | vec2 get(float x, float y){ 21 | return texture2D(water, (gl_FragCoord.xy+vec2(x,y))/viewport).yz; 22 | } 23 | 24 | vec3 get_world_normal(vec2 coord){ 25 | vec2 frag_coord = coord/screen; 26 | frag_coord = (frag_coord-0.5)*2.0; 27 | vec4 device_normal = vec4(frag_coord, 0.0, 1.0); 28 | vec3 eye_normal = normalize((inv_proj * device_normal).xyz); 29 | vec3 world_normal = normalize(inv_rot*eye_normal); 30 | return world_normal; 31 | } 32 | 33 | void main(void){ 34 | vec2 uv = gl_FragCoord.xy/viewport; 35 | 36 | vec3 mousevec = get_world_normal(mousepos); 37 | vec4 eyepos = inv_view * vec4(0.0, 0.0, 0.0, 1.0); 38 | float u = dot(vec3(0.0, 1.0, 0.0), -eyepos.xyz)/dot(vec3(0.0, 1.0, 0.0), mousevec); 39 | vec3 intersection = eyepos.xyz + mousevec * u; 40 | vec3 position = vec3(uv.x-0.5, 0.0, -uv.y+0.5); 41 | float dist = distance(position, intersection)*pow(editsize, 3.0); 42 | float s = smoothstep(1.0, 0.0, dist); 43 | 44 | vec3 w = texture2D(water, uv).xyz; 45 | w.x += 0.00000005*rain; 46 | w.x *= mix(1.0, 0.999925, evaporate); 47 | w.x += s * create * 0.0001; 48 | w.x = clamp(w.x, 0.0, 1.0); 49 | w.yz = ( 50 | get(-1.0, -1.0)*1.0 + get(0.0, -1.0)*1.4 + get(1.0, -1.0)*1.0 + 51 | get(-1.0, 0.0)*1.4 + w.yz*300.0 + get(1.0, -1.0)*1.4 + 52 | get(-1.0, -1.0)*1.0 + get(0.0, -1.0)*1.4 + get(1.0, -1.0)*1.0 53 | )*0.98*(1.0/(300.0+1.4*4.0+4.0)); 54 | gl_FragColor = vec4(w, 1.0); 55 | } 56 | -------------------------------------------------------------------------------- /webgl/vbo.js: -------------------------------------------------------------------------------- 1 | /* 2 | :copyright: 2011 by Florian Boesch . 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | Framework.components.push(function(framework, gl){ 7 | var float_size = Float32Array.BYTES_PER_ELEMENT; 8 | 9 | framework.VBO = Class({ 10 | __init__: function(params){ 11 | this.pointers = []; 12 | this.type = gl[params.type] || gl.TRIANGLES; 13 | 14 | var data = []; 15 | for(spec in params){ 16 | if(spec.match(/[a-zA-Z_]+_[1234]/)){ 17 | var values = params[spec]; 18 | var split = spec.split(/_(?=[1234])/); 19 | var name = split[0]; 20 | var size = parseInt(split[1]); 21 | this.count = values.length/size; 22 | 23 | this.pointers.push({ 24 | name: name, 25 | size: size, 26 | offset: data.length, 27 | }); 28 | 29 | data = data.concat(values); 30 | } 31 | } 32 | 33 | this.buffer = gl.createBuffer(); 34 | gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer); 35 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), gl.STATIC_DRAW); 36 | gl.bindBuffer(gl.ARRAY_BUFFER, null); 37 | }, 38 | bind: function(shader){ 39 | gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer); 40 | 41 | var pointers = this.pointers; 42 | var l = pointers.length; 43 | 44 | for(var i=0; i= 0){ 48 | gl.enableVertexAttribArray(location); 49 | gl.vertexAttribPointer(location, pointer.size, gl.FLOAT, false, 0, pointer.offset*float_size); 50 | } 51 | } 52 | }, 53 | draw: function(shader){ 54 | gl.drawArrays(this.type, 0, this.count); 55 | } 56 | }); 57 | }); 58 | -------------------------------------------------------------------------------- /webgl/projection.js: -------------------------------------------------------------------------------- 1 | /* 2 | :copyright: 2011 by Florian Boesch . 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | Framework.components.push(function(framework, gl){ 7 | framework.Perspective = Class({ 8 | type: 'projection', 9 | __init__: function(viewport, params){ 10 | var self = this; 11 | this.params = params; 12 | this.proj = new Mat4(); 13 | this.inv_proj = new Mat4(); 14 | viewport.onResize(function(event, width, height){ 15 | self.resize(width, height); 16 | }); 17 | }, 18 | resize: function(width, height){ 19 | this.params.width = width; 20 | this.params.height = height; 21 | this.proj.perspective(this.params); 22 | this.inv_proj.inverse_perspective(this.params); 23 | }, 24 | set: function(shader){ 25 | shader.set({ 26 | near: this.params.near, 27 | far: this.params.far, 28 | proj: this.proj, 29 | inv_proj: this.inv_proj, 30 | }); 31 | }, 32 | }); 33 | 34 | framework.Ortho = Class({ 35 | type: 'projection', 36 | __init__: function(viewport, params){ 37 | var self = this; 38 | this.params = params; 39 | this.proj = new Mat4(); 40 | this.inv_proj = new Mat4(); 41 | viewport.onResize(function(event, width, height){ 42 | self.resize(width, height); 43 | }); 44 | }, 45 | resize: function(width, height){ 46 | var s = this.params.scale; 47 | var aspect = (width*s)/height; 48 | this.params.top = s/2; 49 | this.params.bottom = -s/2; 50 | this.params.left = -aspect/2; 51 | this.params.right = aspect/2; 52 | 53 | this.proj.ortho(this.params); 54 | this.inv_proj.inverse_ortho(this.params); 55 | }, 56 | set: function(shader){ 57 | shader.set({ 58 | near: this.params.near, 59 | far: this.params.far, 60 | proj: this.proj, 61 | inv_proj: this.inv_proj, 62 | }); 63 | }, 64 | }); 65 | }); 66 | -------------------------------------------------------------------------------- /webgl/loader.js: -------------------------------------------------------------------------------- 1 | /* 2 | :copyright: 2011 by Florian Boesch . 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | Framework.components.push(function(framework, gl){ 7 | var extre = /\.([^\.]+)$/; 8 | 9 | framework.Loader = Class({ 10 | __init__: function(){ 11 | this.events = new EventManager(); 12 | }, 13 | error: function(callback){ 14 | this.events.on('error', function(event, description){ 15 | callback(description); 16 | }); 17 | return this; 18 | }, 19 | load: function(data){ 20 | var self = this; 21 | var count = 0; 22 | $.each(data, function(name, path){ 23 | count += 1; 24 | var extension = path.match(extre)[1]; 25 | 26 | switch(extension){ 27 | case 'jpg': case 'png': 28 | $('') 29 | .attr('src', path) 30 | .load(function(){ 31 | count -= 1; 32 | data[name] = new framework.Texture() 33 | .image(this) 34 | .repeat() 35 | .mipmap(); 36 | if(count == 0){ 37 | self.events.dispatch('ready', data); 38 | } 39 | }); 40 | break; 41 | case 'shader': 42 | $.get(path, function(source){ 43 | try{ 44 | data[name] = new framework.Shader(source, path); 45 | count -= 1; 46 | if(count == 0){ 47 | self.events.dispatch('ready', data); 48 | } 49 | } 50 | catch(error){ 51 | self.events.dispatch('error', error); 52 | } 53 | }); 54 | break; 55 | } 56 | }); 57 | return this; 58 | }, 59 | ready: function(callback){ 60 | this.events.on('ready', callback); 61 | return this; 62 | }, 63 | }); 64 | }); 65 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | html, body{ 2 | padding: 0; 3 | margin: 0; 4 | border: 0; 5 | 6 | font-family: sans-serif; 7 | font-size: 10px; 8 | 9 | width: 100%; 10 | height: 100%; 11 | overflow: hidden; 12 | } 13 | 14 | canvas{ 15 | position:absolute; 16 | top: 35px; 17 | width: 100%; 18 | height: 100%; 19 | } 20 | 21 | #controls{ 22 | position: fixed; 23 | top: 5px; 24 | left: 10px; 25 | background-color: white; 26 | z-index: 2; 27 | } 28 | 29 | #share{ 30 | position: fixed; 31 | top: 7px; 32 | right: 5px; 33 | z-index: 1; 34 | } 35 | 36 | #share a{ 37 | color: #cdff48; 38 | font-weight: bold; 39 | font-size: 14px; 40 | text-decoration: none; 41 | text-shadow: black 0px 2px 7px; 42 | } 43 | 44 | #share a:hover{ 45 | color: #ffca57; 46 | } 47 | 48 | div.set{ 49 | float: left; 50 | padding-right: 10px; 51 | } 52 | 53 | #toolstoggle{ 54 | padding-top: 4px; 55 | } 56 | 57 | #seed{ 58 | float:left; 59 | color: black; 60 | font-size: 12px; 61 | width: 36px; 62 | padding-left: 10px; 63 | padding-right: 5px; 64 | padding-top: 1px; 65 | } 66 | 67 | label[for="seed"]{ 68 | float:left; 69 | font-weight:normal; 70 | font-size: 10px; 71 | padding-top: 2px; 72 | padding-right:5px; 73 | } 74 | 75 | div.slider{ 76 | float:left; 77 | width: 200px; 78 | padding-top: 6px; 79 | padding-left: 2px; 80 | } 81 | 82 | #instructions{ 83 | font-weight: bold; 84 | color: white; 85 | font-size: 13px; 86 | position: fixed; 87 | bottom: 5px; 88 | left: 0px; 89 | text-align: center; 90 | text-shadow: black 0px 2px 5px; 91 | width: 100%; 92 | } 93 | 94 | #error{ 95 | position: fixed; 96 | left: 50%; 97 | top: 50%; 98 | width: 500px; 99 | height: 200px; 100 | margin-left: -250px; 101 | margin-top: -100px; 102 | border: 1px solid black; 103 | background-color: #eee; 104 | } 105 | 106 | h1{ 107 | text-align: center; 108 | margin: 10px; 109 | font-size: 16px; 110 | } 111 | 112 | pre{ 113 | font-size: 12px; 114 | padding: 10px; 115 | overflow: auto; 116 | white-space: pre-wrap; 117 | white-space: -moz-pre-wrap; 118 | white-space: -pre-wrap; 119 | white-space: -o-pre-wrap; 120 | word-wrap: break-word; 121 | } 122 | 123 | #bugs{ 124 | padding: 10px; 125 | font-size: 12px; 126 | } 127 | 128 | -------------------------------------------------------------------------------- /simplex.shader: -------------------------------------------------------------------------------- 1 | /* 2 | :copyright: 2011 by Florian Boesch . 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | // Author : Ian McEwan, Ashima Arts. 7 | // Maintainer : ijm 8 | // License : Copyright (C) 2011 Ashima Arts. All rights reserved. 9 | // Distributed under the MIT License. See LICENSE file. 10 | 11 | vertex: 12 | attribute vec2 position; 13 | void main(){ 14 | gl_Position = vec4(position, 0.0, 1.0); 15 | } 16 | 17 | fragment: 18 | uniform vec2 viewport; 19 | uniform float delta; 20 | 21 | vec3 mod289(vec3 x) { 22 | return x - floor(x * (1.0 / 289.0)) * 289.0; 23 | } 24 | 25 | vec2 mod289(vec2 x) { 26 | return x - floor(x * (1.0 / 289.0)) * 289.0; 27 | } 28 | 29 | vec3 permute(vec3 x) { 30 | return mod289(((x*34.0)+1.0)*x); 31 | } 32 | 33 | float snoise(vec2 v){ 34 | const vec4 C = vec4( 35 | 0.211324865405187, // (3.0-sqrt(3.0))/6.0 36 | 0.366025403784439, // 0.5*(sqrt(3.0)-1.0) 37 | -0.577350269189626, // -1.0 + 2.0 * C.x 38 | 0.024390243902439 // 1.0 / 41.0 39 | ); 40 | vec2 i = floor(v + dot(v, C.yy) ); 41 | vec2 x0 = v - i + dot(i, C.xx); 42 | 43 | vec2 i1; 44 | i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); 45 | vec4 x12 = x0.xyxy + C.xxzz; 46 | x12.xy -= i1; 47 | 48 | i = mod289(i); // Avoid truncation effects in permutation 49 | vec3 p = permute( 50 | permute(i.y + vec3(0.0, i1.y, 1.0)) + 51 | i.x + 52 | vec3(0.0, i1.x, 1.0) 53 | ); 54 | 55 | vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), dot(x12.zw,x12.zw)), 0.0); 56 | m = m*m ; 57 | m = m*m ; 58 | 59 | vec3 x = 2.0 * fract(p * C.www) - 1.0; 60 | vec3 h = abs(x) - 0.5; 61 | vec3 ox = floor(x + 0.5); 62 | vec3 a0 = x - ox; 63 | 64 | m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h ); 65 | 66 | vec3 g; 67 | g.x = a0.x * x0.x + h.x * x0.y; 68 | g.yz = a0.yz * x12.xz + h.yz * x12.yw; 69 | return 130.0 * dot(m, g); 70 | } 71 | 72 | void main(){ 73 | float h = 0.0; 74 | for(int i=0; i<9; i++){ 75 | float factor = pow(2.0, float(i)); 76 | h += snoise((gl_FragCoord.xy+delta)*factor/viewport)/(pow(factor, 0.88)*10.0); 77 | } 78 | h = clamp(h, 0.0, 1.0); 79 | gl_FragColor = vec4(h, h, h, 1.0); 80 | } 81 | 82 | -------------------------------------------------------------------------------- /jquery.mousewheel.min.js: -------------------------------------------------------------------------------- 1 | /*! Copyright (c) 2013 Brandon Aaron (http://brandon.aaron.sh) 2 | * Licensed under the MIT License (LICENSE.txt). 3 | * 4 | * Version: 3.1.11 5 | * 6 | * Requires: jQuery 1.2.2+ 7 | */ 8 | !function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof exports?module.exports=a:a(jQuery)}(function(a){function b(b){var g=b||window.event,h=i.call(arguments,1),j=0,l=0,m=0,n=0,o=0,p=0;if(b=a.event.fix(g),b.type="mousewheel","detail"in g&&(m=-1*g.detail),"wheelDelta"in g&&(m=g.wheelDelta),"wheelDeltaY"in g&&(m=g.wheelDeltaY),"wheelDeltaX"in g&&(l=-1*g.wheelDeltaX),"axis"in g&&g.axis===g.HORIZONTAL_AXIS&&(l=-1*m,m=0),j=0===m?l:m,"deltaY"in g&&(m=-1*g.deltaY,j=m),"deltaX"in g&&(l=g.deltaX,0===m&&(j=-1*l)),0!==m||0!==l){if(1===g.deltaMode){var q=a.data(this,"mousewheel-line-height");j*=q,m*=q,l*=q}else if(2===g.deltaMode){var r=a.data(this,"mousewheel-page-height");j*=r,m*=r,l*=r}if(n=Math.max(Math.abs(m),Math.abs(l)),(!f||f>n)&&(f=n,d(g,n)&&(f/=40)),d(g,n)&&(j/=40,l/=40,m/=40),j=Math[j>=1?"floor":"ceil"](j/f),l=Math[l>=1?"floor":"ceil"](l/f),m=Math[m>=1?"floor":"ceil"](m/f),k.settings.normalizeOffset&&this.getBoundingClientRect){var s=this.getBoundingClientRect();o=b.clientX-s.left,p=b.clientY-s.top}return b.deltaX=l,b.deltaY=m,b.deltaFactor=f,b.offsetX=o,b.offsetY=p,b.deltaMode=0,h.unshift(b,j,l,m),e&&clearTimeout(e),e=setTimeout(c,200),(a.event.dispatch||a.event.handle).apply(this,h)}}function c(){f=null}function d(a,b){return k.settings.adjustOldDeltas&&"mousewheel"===a.type&&b%120===0}var e,f,g=["wheel","mousewheel","DOMMouseScroll","MozMousePixelScroll"],h="onwheel"in document||document.documentMode>=9?["wheel"]:["mousewheel","DomMouseScroll","MozMousePixelScroll"],i=Array.prototype.slice;if(a.event.fixHooks)for(var j=g.length;j;)a.event.fixHooks[g[--j]]=a.event.mouseHooks;var k=a.event.special.mousewheel={version:"3.1.11",setup:function(){if(this.addEventListener)for(var c=h.length;c;)this.addEventListener(h[--c],b,!1);else this.onmousewheel=b;a.data(this,"mousewheel-line-height",k.getLineHeight(this)),a.data(this,"mousewheel-page-height",k.getPageHeight(this))},teardown:function(){if(this.removeEventListener)for(var c=h.length;c;)this.removeEventListener(h[--c],b,!1);else this.onmousewheel=null;a.removeData(this,"mousewheel-line-height"),a.removeData(this,"mousewheel-page-height")},getLineHeight:function(b){var c=a(b)["offsetParent"in a.fn?"offsetParent":"parent"]();return c.length||(c=a("body")),parseInt(c.css("fontSize"),10)},getPageHeight:function(b){return a(b).height()},settings:{adjustOldDeltas:!0,normalizeOffset:!0}};a.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})}); -------------------------------------------------------------------------------- /webgl/hexgrid.js: -------------------------------------------------------------------------------- 1 | /* 2 | :copyright: 2011 by Florian Boesch . 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | Framework.components.push(function(framework, gl){ 7 | framework.HexGrid = Class({ 8 | __extends__: framework.Drawable, 9 | __init__: function(params){ 10 | var args = extend({ 11 | xsize: 10, 12 | ysize: 10, 13 | width: 1, 14 | height: 1, 15 | }, params); 16 | 17 | var position_2f = []; 18 | var texcoord_2f = []; 19 | var barycentric_3f = []; 20 | 21 | var width = args.width; 22 | var height = args.height; 23 | var xsize = args.xsize; 24 | var ysize = args.ysize; 25 | var hw = width/2; 26 | var hh = height/2; 27 | 28 | for(var x=0; x<=xsize; x++){ 29 | var x1 = clamp((x-0.5)/xsize, 0, 1); 30 | var x2 = clamp((x+0.0)/xsize, 0, 1); 31 | var x3 = clamp((x+0.5)/xsize, 0, 1); 32 | var x4 = clamp((x+1.0)/xsize, 0, 1); 33 | for(var y=0; y. 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | var EventManager = Class({ 7 | __init__: function(){ 8 | this.listener_ids = 0; 9 | this.listeners = {}; 10 | }, 11 | dispatch: function(name){ 12 | var args = [null]; 13 | for(var i=1; i 1){ 77 | stack.pop(); 78 | this.top = stack[stack.length-1]; 79 | } 80 | else{ 81 | throw 'EventStack Error: stack has length 1'; 82 | } 83 | return this; 84 | }, 85 | on: function(match, obj, callback){ 86 | var stack = this.stack; 87 | var length = stack.length; 88 | 89 | var manager = stack[length-1]; 90 | manager.on(match, obj, callback); 91 | return this; 92 | }, 93 | dispatch: function(){ 94 | var stack = this.stack; 95 | var length = stack.length; 96 | 97 | for(var i=0; i. 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | Framework.components.push(function(framework, gl){ 7 | framework.Box = Class({ 8 | __extends__: framework.Drawable, 9 | __init__: function(params){ 10 | var params = params || {}; 11 | var w = this.width = params.width || 1; 12 | var h = this.height = params.height || 1; 13 | var d = this.depth = params.depth || 1; 14 | 15 | this.vbo = new framework.VBO({ 16 | position_3: [ 17 | -w, -h, -d, -w, h, -d, w, h, -d, 18 | w, -h, -d, -w, -h, -d, w, h, -d, 19 | 20 | w, h, d, -w, h, d, -w, -h, d, 21 | w, h, d, -w, -h, d, w, -h, d, 22 | 23 | -w, h, -d, -w, h, d, w, h, d, 24 | w, h, -d, -w, h, -d, w, h, d, 25 | 26 | w, -h, d, -w, -h, d, -w, -h, -d, 27 | w, -h, d, -w, -h, -d, w, -h, -d, 28 | 29 | -w, -h, -d, -w, -h, d, -w, h, d, 30 | -w, h, -d, -w, -h, -d, -w, h, d, 31 | 32 | w, h, d, w, -h, d, w, -h, -d, 33 | w, h, d, w, -h, -d, w, h, -d, 34 | ], 35 | normal_3: [ 36 | 0, 0, -1, 0, 0, -1, 0, 0, -1, 37 | 0, 0, -1, 0, 0, -1, 0, 0, -1, 38 | 39 | 0, 0, 1, 0, 0, 1, 0, 0, 1, 40 | 0, 0, 1, 0, 0, 1, 0, 0, 1, 41 | 42 | 0, 1, 0, 0, 1, 0, 0, 1, 0, 43 | 0, 1, 0, 0, 1, 0, 0, 1, 0, 44 | 45 | 0, -1, 0, 0, -1, 0, 0, -1, 0, 46 | 0, -1, 0, 0, -1, 0, 0, -1, 0, 47 | 48 | -1, 0, 0, -1, 0, 0, -1, 0, 0, 49 | -1, 0, 0, -1, 0, 0, -1, 0, 0, 50 | 51 | 1, 0, 0, 1, 0, 0, 1, 0, 0, 52 | 1, 0, 0, 1, 0, 0, 1, 0, 0, 53 | ], 54 | texcoord_2: [ 55 | 0, 1, 0, 0, 1, 0, 56 | 1, 1, 0, 1, 1, 0, 57 | 58 | 1, 0, 0, 0, 0, 1, 59 | 1, 0, 0, 1, 1, 1, 60 | 61 | 0, 1, 0, 0, 1, 0, 62 | 1, 1, 0, 1, 1, 0, 63 | 64 | 1, 0, 0, 0, 0, 1, 65 | 1, 0, 0, 1, 1, 1, 66 | 67 | 0, 1, 0, 0, 1, 0, 68 | 1, 1, 0, 1, 1, 0, 69 | 70 | 1, 0, 0, 0, 0, 1, 71 | 1, 0, 0, 1, 1, 1, 72 | ], 73 | }); 74 | }, 75 | }); 76 | }); 77 | -------------------------------------------------------------------------------- /webgl/texture.js: -------------------------------------------------------------------------------- 1 | /* 2 | :copyright: 2011 by Florian Boesch . 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | Framework.components.push(function(framework, gl){ 7 | var bound = {}; 8 | 9 | framework.Texture = Class({ 10 | type: 'Texture', 11 | __init__: function(){ 12 | this.id = gl.createTexture(); 13 | this.linear().repeat(); 14 | }, 15 | bind: function(unit){ 16 | if(unit === undefined){ 17 | var unit = 0; 18 | } 19 | if(bound[unit] !== this){ 20 | bound[unit] = this; 21 | gl.activeTexture(gl.TEXTURE0+unit); 22 | gl.bindTexture(gl.TEXTURE_2D, this.id); 23 | } 24 | return this; 25 | }, 26 | image: function(image){ 27 | this.bind(); 28 | gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); 29 | return this; 30 | }, 31 | size: function(width, height, type){ 32 | var type = type === undefined ? gl.UNSIGNED_BYTE : gl[type.toUpperCase()]; 33 | this.bind(); 34 | this.width = width; 35 | this.height = height; 36 | gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, type, null); 37 | return this; 38 | }, 39 | nearest: function(){ 40 | this.bind(); 41 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); 42 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); 43 | return this; 44 | }, 45 | linear: function(){ 46 | this.bind(); 47 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); 48 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); 49 | return this; 50 | }, 51 | mipmap: function(){ 52 | this.bind(); 53 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); 54 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR); 55 | gl.generateMipmap(gl.TEXTURE_2D); 56 | return this; 57 | }, 58 | repeat: function(){ 59 | return this.wrap(gl.REPEAT); 60 | }, 61 | repeatMirrored: function(){ 62 | return this.wrap(gl.MIRRORED_REPEAT); 63 | }, 64 | clamp: function(){ 65 | return this.wrap(gl.CLAMP); 66 | }, 67 | borderColor: function(x, y, z, a){ 68 | this.bind(); 69 | gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_BORDER_COLOR, x, y, z, a); 70 | return this; 71 | }, 72 | clampToBorder: function(){ 73 | return this.wrap(gl.CLAMP_TO_BORDER); 74 | }, 75 | clampToEdge: function(){ 76 | return this.wrap(gl.CLAMP_TO_EDGE); 77 | }, 78 | wrap: function(value){ 79 | this.bind(); 80 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, value); 81 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, value); 82 | return this; 83 | } 84 | }); 85 | }); 86 | -------------------------------------------------------------------------------- /water/init.shader: -------------------------------------------------------------------------------- 1 | /* 2 | :copyright: 2011 by Florian Boesch . 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | // Author : Ian McEwan, Ashima Arts. 7 | // Maintainer : ijm 8 | // License : Copyright (C) 2011 Ashima Arts. All rights reserved. 9 | // Distributed under the MIT License. See LICENSE file. 10 | 11 | vertex: 12 | attribute vec2 position; 13 | void main(){ 14 | gl_Position = vec4(position, 0.0, 1.0); 15 | } 16 | 17 | fragment: 18 | uniform vec2 viewport; 19 | 20 | vec3 mod289(vec3 x) { 21 | return x - floor(x * (1.0 / 289.0)) * 289.0; 22 | } 23 | 24 | vec2 mod289(vec2 x) { 25 | return x - floor(x * (1.0 / 289.0)) * 289.0; 26 | } 27 | 28 | vec3 permute(vec3 x) { 29 | return mod289(((x*34.0)+1.0)*x); 30 | } 31 | 32 | float snoise(vec2 v){ 33 | const vec4 C = vec4( 34 | 0.211324865405187, // (3.0-sqrt(3.0))/6.0 35 | 0.366025403784439, // 0.5*(sqrt(3.0)-1.0) 36 | -0.577350269189626, // -1.0 + 2.0 * C.x 37 | 0.024390243902439 // 1.0 / 41.0 38 | ); 39 | // First corner 40 | vec2 i = floor(v + dot(v, C.yy) ); 41 | vec2 x0 = v - i + dot(i, C.xx); 42 | 43 | // Other corners 44 | vec2 i1; 45 | //i1.x = step( x0.y, x0.x ); // x0.x > x0.y ? 1.0 : 0.0 46 | //i1.y = 1.0 - i1.x; 47 | i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); 48 | // x0 = x0 - 0.0 + 0.0 * C.xx ; 49 | // x1 = x0 - i1 + 1.0 * C.xx ; 50 | // x2 = x0 - 1.0 + 2.0 * C.xx ; 51 | vec4 x12 = x0.xyxy + C.xxzz; 52 | x12.xy -= i1; 53 | 54 | // Permutations 55 | i = mod289(i); // Avoid truncation effects in permutation 56 | vec3 p = permute( 57 | permute(i.y + vec3(0.0, i1.y, 1.0)) + 58 | i.x + 59 | vec3(0.0, i1.x, 1.0) 60 | ); 61 | 62 | vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), dot(x12.zw,x12.zw)), 0.0); 63 | m = m*m ; 64 | m = m*m ; 65 | 66 | // Gradients: 41 points uniformly over a line, mapped onto a diamond. 67 | // The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287) 68 | 69 | vec3 x = 2.0 * fract(p * C.www) - 1.0; 70 | vec3 h = abs(x) - 0.5; 71 | vec3 ox = floor(x + 0.5); 72 | vec3 a0 = x - ox; 73 | 74 | // Normalise gradients implicitly by scaling m 75 | // Approximation of: m *= inversesqrt( a0*a0 + h*h ); 76 | m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h ); 77 | 78 | // Compute final noise value at P 79 | vec3 g; 80 | g.x = a0.x * x0.x + h.x * x0.y; 81 | g.yz = a0.yz * x12.xz + h.yz * x12.yw; 82 | return 130.0 * dot(m, g); 83 | } 84 | 85 | void main(){ 86 | float h = 0.0; 87 | for(int i=0; i<5; i++){ 88 | float factor = pow(2.0, float(i)); 89 | h += snoise((gl_FragCoord.xy+100.0)*factor/viewport)/(pow(factor, 0.88)*5.0); 90 | } 91 | h = clamp(h-0.20, 0.0, 1.0); 92 | //gl_FragColor = vec4(h, h, h, 1.0); 93 | gl_FragColor = vec4(0.0000, 0.0000, 0.0000, 1.0); 94 | } 95 | -------------------------------------------------------------------------------- /webgl/quaternion.js: -------------------------------------------------------------------------------- 1 | /* 2 | :copyright: 2011 by Florian Boesch . 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | (function(){ 7 | var sin = Math.sin; 8 | var cos = Math.cos; 9 | var tan = Math.tan2; 10 | var sqrt = Math.sqrt; 11 | var p = Math.pow; 12 | 13 | Quat = Class({ 14 | type: 'quaternion', 15 | __init__: function(){ 16 | this.w = 1; 17 | this.x = 0; 18 | this.y = 0; 19 | this.z = 0; 20 | }, 21 | setRotation: function(angle, x, y, z){ 22 | var l = sqrt(x*x + y*y + z*z); 23 | x/=l; 24 | y/=l; 25 | z/=l; 26 | var angle = (angle/360)*Math.PI*2; 27 | 28 | var s = sin(angle/2); 29 | this.w = cos(angle/2); 30 | 31 | this.x = x*s; 32 | this.y = y*s; 33 | this.z = z*s; 34 | return this; 35 | }, 36 | add: function(other){ 37 | this.x += other.x; 38 | this.y += other.y; 39 | this.z += other.z; 40 | this.w += other.w; 41 | return this; 42 | }, 43 | normalize: function(){ 44 | var l = sqrt(p(this.w, 2)+p(this.x, 2)+p(this.y,2)+p(this.z,2)); 45 | this.w /= l; 46 | this.x /= l; 47 | this.y /= l; 48 | this.z /= l; 49 | return this; 50 | }, 51 | dot: function(other){ 52 | return ( 53 | this.w*other.w + 54 | this.x*other.x + 55 | this.y*other.y + 56 | this.z*other.z 57 | ) 58 | }, 59 | ident: function(){ 60 | this.w = 1; 61 | this.x = 0; 62 | this.y = 0; 63 | this.z = 0; 64 | return this; 65 | }, 66 | invert: function(){ 67 | this.x *= -1; 68 | this.y *= -1; 69 | this.z *= -1; 70 | return this; 71 | }, 72 | mul: function(other){ 73 | return this._mul(other.w, other.x, other.y, other.z); 74 | }, 75 | rotateByAxis: function(x, y, z){ 76 | return this._mul(0, x, y, z); 77 | }, 78 | rotate: function(scale, x, y, z){ 79 | var w1=0, x1=x*scale, y1=y*scale, z1=z*scale; 80 | var w2=this.w, x2=this.x, y2=this.y, z2=this.z; 81 | this.w += (w2*w1 - x2*x1 - y2*y1 - z2*z1)*0.5; 82 | this.x += (y2*z1 - z2*y1 + w2*x1 + w1*x2)*0.5; 83 | this.y += (z2*x1 - x2*z1 + w2*y1 + w1*y2)*0.5; 84 | this.z += (x2*y1 - y2*x1 + w2*z1 + w1*z2)*0.5; 85 | return this; 86 | }, 87 | _mul: function(w1, x1, y1, z1){ 88 | var w2=this.w, x2=this.x, y2=this.y, z2=this.z; 89 | var w = w2*w1 - x2*x1 - y2*y1 - z2*z1; 90 | var x = y2*z1 - z2*y1 + w2*x1 + w1*x2; 91 | var y = z2*x1 - x2*z1 + w2*y1 + w1*y2; 92 | var z = x2*y1 - y2*x1 + w2*z1 + w1*z2; 93 | 94 | this.w = w; 95 | this.x = x; 96 | this.y = y; 97 | this.z = z; 98 | return this; 99 | }, 100 | }); 101 | })(); 102 | -------------------------------------------------------------------------------- /webgl/framebuffer.js: -------------------------------------------------------------------------------- 1 | Framework.components.push(function(framework, gl){ 2 | var current = null; 3 | 4 | var screen = framework.screen = { 5 | events: new EventManager(), 6 | bind: function(){ 7 | if(current !== null){ 8 | framework.gl.viewport(0, 0, this.width, this.height); 9 | gl.bindFramebuffer(gl.FRAMEBUFFER, null); 10 | } 11 | }, 12 | onResize: function(callback){ 13 | this.events.on('resize', callback); 14 | callback('resize', this.width, this.height); 15 | return this; 16 | }, 17 | resize: function(){ 18 | var width = this.width = framework.canvas_node.width(); 19 | var height = this.height = framework.canvas_node.height(); 20 | 21 | framework.canvas.width = width; 22 | framework.canvas.height = height; 23 | this.events.dispatch('resize', width, height); 24 | return this; 25 | }, 26 | }; 27 | 28 | framework.canvas_node.resize(function(){ 29 | screen.resize(); 30 | }); 31 | $(window).resize(function(){ 32 | screen.resize(); 33 | }); 34 | screen.resize(); 35 | 36 | framework.Framebuffer = Class({ 37 | __init__: function(){ 38 | this.id = gl.createFramebuffer(); 39 | }, 40 | color: function(texture){ 41 | gl.bindFramebuffer(gl.FRAMEBUFFER, this.id); 42 | gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture.id, 0); 43 | this.check(); 44 | gl.bindFramebuffer(gl.FRAMEBUFFER, null); 45 | current = null; 46 | this.width = texture.width; 47 | this.height = texture.height; 48 | return this; 49 | }, 50 | depth: function(){ 51 | var id = this.depthstencil = gl.createRenderbuffer(); 52 | gl.bindRenderbuffer(gl.RENDERBUFFER, id); 53 | gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, this.width, this.height); 54 | gl.bindRenderbuffer(gl.RENDERBUFFER, null); 55 | gl.bindFramebuffer(gl.FRAMEBUFFER, this.id); 56 | gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, id); 57 | this.check(); 58 | gl.bindFramebuffer(gl.FRAMEBUFFER, null); 59 | current = null; 60 | return this; 61 | }, 62 | check: function(){ 63 | var result = gl.checkFramebufferStatus(gl.FRAMEBUFFER); 64 | if(result == gl.FRAMEBUFFER_UNSUPPORTED){ 65 | throw 'Framebuffer is unsupported'; 66 | } 67 | else if(result == gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT){ 68 | throw 'Framebuffer incomplete attachment'; 69 | } 70 | else if(result == gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS){ 71 | throw 'Framebuffer incomplete dimensions'; 72 | } 73 | else if(result == gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT){ 74 | throw 'Framebuffer incomplete missing attachment'; 75 | } 76 | }, 77 | bind: function(){ 78 | if(current !== this){ 79 | current = this; 80 | framework.gl.viewport(0, 0, this.width, this.height); 81 | gl.bindFramebuffer(gl.FRAMEBUFFER, this.id); 82 | } 83 | }, 84 | onResize: function(callback){ 85 | callback('resize', this.width, this.height); 86 | }, 87 | }); 88 | }); 89 | -------------------------------------------------------------------------------- /simplex3d.shader: -------------------------------------------------------------------------------- 1 | /* 2 | :copyright: 2011 by Florian Boesch . 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | vertex: 7 | attribute vec2 position; 8 | void main(){ 9 | gl_Position = vec4(position, 0.0, 1.0); 10 | } 11 | 12 | fragment: 13 | uniform vec2 viewport; 14 | uniform float delta; 15 | 16 | // 17 | // Description : Array and textureless GLSL 2D/3D/4D simplex 18 | // noise functions. 19 | // Author : Ian McEwan, Ashima Arts. 20 | // Maintainer : ijm 21 | // Lastmod : 20110822 (ijm) 22 | // License : Copyright (C) 2011 Ashima Arts. All rights reserved. 23 | // Distributed under the MIT License. See LICENSE file. 24 | // https://github.com/ashima/webgl-noise 25 | // 26 | 27 | vec3 mod289(vec3 x) { 28 | return x - floor(x * (1.0 / 289.0)) * 289.0; 29 | } 30 | 31 | vec4 mod289(vec4 x) { 32 | return x - floor(x * (1.0 / 289.0)) * 289.0; 33 | } 34 | 35 | vec4 permute(vec4 x) { 36 | return mod289(((x*34.0)+1.0)*x); 37 | } 38 | 39 | vec4 taylorInvSqrt(vec4 r) 40 | { 41 | return 1.79284291400159 - 0.85373472095314 * r; 42 | } 43 | 44 | float snoise(vec3 v) 45 | { 46 | const vec2 C = vec2(1.0/6.0, 1.0/3.0) ; 47 | const vec4 D = vec4(0.0, 0.5, 1.0, 2.0); 48 | 49 | vec3 i = floor(v + dot(v, C.yyy) ); 50 | vec3 x0 = v - i + dot(i, C.xxx) ; 51 | 52 | vec3 g = step(x0.yzx, x0.xyz); 53 | vec3 l = 1.0 - g; 54 | vec3 i1 = min( g.xyz, l.zxy ); 55 | vec3 i2 = max( g.xyz, l.zxy ); 56 | 57 | vec3 x1 = x0 - i1 + C.xxx; 58 | vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y 59 | vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y 60 | 61 | i = mod289(i); 62 | vec4 p = permute( permute( permute( 63 | i.z + vec4(0.0, i1.z, i2.z, 1.0 )) 64 | + i.y + vec4(0.0, i1.y, i2.y, 1.0 )) 65 | + i.x + vec4(0.0, i1.x, i2.x, 1.0 )); 66 | 67 | float n_ = 0.142857142857; // 1.0/7.0 68 | vec3 ns = n_ * D.wyz - D.xzx; 69 | 70 | vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7) 71 | 72 | vec4 x_ = floor(j * ns.z); 73 | vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N) 74 | 75 | vec4 x = x_ *ns.x + ns.yyyy; 76 | vec4 y = y_ *ns.x + ns.yyyy; 77 | vec4 h = 1.0 - abs(x) - abs(y); 78 | 79 | vec4 b0 = vec4( x.xy, y.xy ); 80 | vec4 b1 = vec4( x.zw, y.zw ); 81 | 82 | vec4 s0 = floor(b0)*2.0 + 1.0; 83 | vec4 s1 = floor(b1)*2.0 + 1.0; 84 | vec4 sh = -step(h, vec4(0.0)); 85 | 86 | vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ; 87 | vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ; 88 | 89 | vec3 p0 = vec3(a0.xy,h.x); 90 | vec3 p1 = vec3(a0.zw,h.y); 91 | vec3 p2 = vec3(a1.xy,h.z); 92 | vec3 p3 = vec3(a1.zw,h.w); 93 | 94 | vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3))); 95 | p0 *= norm.x; 96 | p1 *= norm.y; 97 | p2 *= norm.z; 98 | p3 *= norm.w; 99 | 100 | vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0); 101 | m = m * m; 102 | return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1), 103 | dot(p2,x2), dot(p3,x3) ) ); 104 | } 105 | 106 | void main(){ 107 | float h = 0.0; 108 | vec2 uv = gl_FragCoord.xy/viewport; 109 | 110 | for(int i=0; i<10; i++){ 111 | float factor = pow(2.0, float(i)); 112 | h += snoise(vec3(uv*factor, delta*float(i+1)))/(pow(factor, 0.88)*10.0); 113 | } 114 | gl_FragColor = vec4(0, h, 0.0, 1.0); 115 | } 116 | 117 | 118 | -------------------------------------------------------------------------------- /webgl/vector.js: -------------------------------------------------------------------------------- 1 | /* 2 | :copyright: 2011 by Florian Boesch . 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | (function(){ 6 | var fmt = function(value){ 7 | var str = value.toFixed(4); 8 | while(str.length < 7){ 9 | str = ' ' + str; 10 | } 11 | return str; 12 | } 13 | 14 | Vec2 = Class({ 15 | type: 'Vec2', 16 | __init__: function(x, y){ 17 | this.x = x === undefined ? 0 : x; 18 | this.y = y === undefined ? 0 : y; 19 | }, 20 | }); 21 | 22 | Vec3 = function(x, y, z){ 23 | this.x = x || 0; 24 | this.y = y || 0; 25 | this.z = z || 0; 26 | }; 27 | 28 | Vec3.prototype = { 29 | type: 'Vec3', 30 | normalize: function(){ 31 | var length = Math.sqrt(this.x*this.x + this.y*this.y + this.z*this.z); 32 | if(length != 0){ 33 | this.x /= length; 34 | this.y /= length; 35 | this.z /= length; 36 | } 37 | return this; 38 | }, 39 | length: function(){ 40 | var x=this.x, y=this.y, z=this.y; 41 | return Math.sqrt(x*x + y*y + z*z); 42 | }, 43 | log: function(message){ 44 | if(!message){ 45 | var message = 'Vec3'; 46 | } 47 | console.log('%s: %s %s %s', message, fmt(this.x), fmt(this.y), fmt(this.z)); 48 | return this; 49 | }, 50 | mul: function(value){ 51 | if(value.type == 'Vec3'){ 52 | this.x *= value.x; 53 | this.y *= value.y; 54 | this.z *= value.z; 55 | } 56 | else if(value.type == 'Mat3'){ 57 | this.set( 58 | value.data[0]*this.x + value.data[1]*this.y + value.data[2]*this.z, 59 | value.data[3]*this.x + value.data[4]*this.y + value.data[5]*this.z, 60 | value.data[6]*this.x + value.data[7]*this.y + value.data[8]*this.z 61 | ) 62 | } 63 | else{ 64 | this.x *= value; 65 | this.y *= value; 66 | this.z *= value; 67 | } 68 | return this; 69 | }, 70 | cross: function(other){ 71 | var x1=this.x, y1=this.y, z1=this.z; 72 | var x2=other.x, y2=other.y, z2=other.z; 73 | return this.set( 74 | y1*z2 - y2*z1, 75 | z1*x2 - z2*x1, 76 | x1*y2 - x2*y1 77 | ); 78 | }, 79 | sub: function(value){ 80 | if(value.type == 'Vec3'){ 81 | this.x -= value.x; 82 | this.y -= value.y; 83 | this.z -= value.z; 84 | } 85 | else{ 86 | this.x -= value; 87 | this.y -= value; 88 | this.z -= value; 89 | } 90 | return this; 91 | }, 92 | add: function(value){ 93 | if(value.type == 'Vec3'){ 94 | this.x += value.x; 95 | this.y += value.y; 96 | this.z += value.z; 97 | } 98 | else{ 99 | this.x += value; 100 | this.y += value; 101 | this.z += value; 102 | } 103 | return this; 104 | }, 105 | update: function(other){ 106 | this.x = other.x; 107 | this.y = other.y; 108 | this.z = other.z; 109 | return this; 110 | }, 111 | set: function(x, y, z){ 112 | this.x = x; 113 | this.y = y; 114 | this.z = z; 115 | return this; 116 | } 117 | }; 118 | })(); 119 | -------------------------------------------------------------------------------- /webgl/grid.js: -------------------------------------------------------------------------------- 1 | /* 2 | :copyright: 2011 by Florian Boesch . 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | Framework.components.push(function(framework, gl){ 7 | framework.Grid = Class({ 8 | __extends__: framework.Drawable, 9 | __init__: function(params){ 10 | var args = extend({ 11 | xsize: 10, 12 | ysize: 10, 13 | width: 1, 14 | height: 1, 15 | cell_width: 1, 16 | cell_height: 1, 17 | }, params); 18 | 19 | var position_2f = []; 20 | var texcoord_2f = []; 21 | var barycentric_3f = []; 22 | var cell_uv_4f = []; 23 | 24 | var width = args.width; 25 | var height = args.height; 26 | var xsize = args.xsize; 27 | var ysize = args.ysize; 28 | 29 | var cell_count_x = args.xsize/args.cell_width; 30 | var cell_count_y = args.ysize/args.cell_height; 31 | 32 | for(var x=0; x. 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | var Framework = Class({ 7 | __init__: function(canvas){ 8 | var self = this; 9 | 10 | this.canvas = canvas; 11 | this.canvas_node = $(canvas); 12 | 13 | this.gl = canvas.getContext('experimental-webgl', { 14 | premultipliedAlpha: true, 15 | }); 16 | 17 | if(!this.gl){ 18 | throw 'No WebGL support'; 19 | } 20 | 21 | this.gl.pixelStorei(this.gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true); 22 | 23 | for(var i=0; i 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 |
37 |
38 | 39 | 40 | 41 |
42 |
43 | 44 | 45 |
46 |
47 | 48 | 49 | 50 |
51 |
52 | 53 |
54 |
55 |
56 | 57 | 58 |
59 |
60 |
61 |
62 |
63 |
64 | press&drag mouse to look, SPACE=create/remove, scrollwheel=editsize, W=forward, S=backward, A=left, D=right, Q=down, E=up 65 |
66 |
67 |
68 | Website 69 | Github 70 | Youtube 71 | 72 | 73 |
74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /god.shader: -------------------------------------------------------------------------------- 1 | /* 2 | :copyright: 2011 by Florian Boesch . 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | vertex: 7 | attribute vec2 position; 8 | void main(){ 9 | gl_Position = vec4(position, 0.0, 1.0); 10 | } 11 | 12 | fragment: 13 | uniform sampler2D ground; 14 | uniform vec2 viewport, screen, mousepos; 15 | uniform mat4 inv_view, inv_proj; 16 | uniform mat3 inv_rot; 17 | uniform float delta, rockfactor, soilfactor, editsize; 18 | 19 | // 20 | // Description : Array and textureless GLSL 2D/3D/4D simplex 21 | // noise functions. 22 | // Author : Ian McEwan, Ashima Arts. 23 | // Maintainer : ijm 24 | // Lastmod : 20110822 (ijm) 25 | // License : Copyright (C) 2011 Ashima Arts. All rights reserved. 26 | // Distributed under the MIT License. See LICENSE file. 27 | // https://github.com/ashima/webgl-noise 28 | // 29 | 30 | vec3 mod289(vec3 x) { 31 | return x - floor(x * (1.0 / 289.0)) * 289.0; 32 | } 33 | 34 | vec4 mod289(vec4 x) { 35 | return x - floor(x * (1.0 / 289.0)) * 289.0; 36 | } 37 | 38 | vec4 permute(vec4 x) { 39 | return mod289(((x*34.0)+1.0)*x); 40 | } 41 | 42 | vec4 taylorInvSqrt(vec4 r) 43 | { 44 | return 1.79284291400159 - 0.85373472095314 * r; 45 | } 46 | 47 | float snoise(vec3 v) 48 | { 49 | const vec2 C = vec2(1.0/6.0, 1.0/3.0) ; 50 | const vec4 D = vec4(0.0, 0.5, 1.0, 2.0); 51 | 52 | vec3 i = floor(v + dot(v, C.yyy) ); 53 | vec3 x0 = v - i + dot(i, C.xxx) ; 54 | 55 | vec3 g = step(x0.yzx, x0.xyz); 56 | vec3 l = 1.0 - g; 57 | vec3 i1 = min( g.xyz, l.zxy ); 58 | vec3 i2 = max( g.xyz, l.zxy ); 59 | 60 | vec3 x1 = x0 - i1 + C.xxx; 61 | vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y 62 | vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y 63 | 64 | i = mod289(i); 65 | vec4 p = permute( permute( permute( 66 | i.z + vec4(0.0, i1.z, i2.z, 1.0 )) 67 | + i.y + vec4(0.0, i1.y, i2.y, 1.0 )) 68 | + i.x + vec4(0.0, i1.x, i2.x, 1.0 )); 69 | 70 | float n_ = 0.142857142857; // 1.0/7.0 71 | vec3 ns = n_ * D.wyz - D.xzx; 72 | 73 | vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7) 74 | 75 | vec4 x_ = floor(j * ns.z); 76 | vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N) 77 | 78 | vec4 x = x_ *ns.x + ns.yyyy; 79 | vec4 y = y_ *ns.x + ns.yyyy; 80 | vec4 h = 1.0 - abs(x) - abs(y); 81 | 82 | vec4 b0 = vec4( x.xy, y.xy ); 83 | vec4 b1 = vec4( x.zw, y.zw ); 84 | 85 | vec4 s0 = floor(b0)*2.0 + 1.0; 86 | vec4 s1 = floor(b1)*2.0 + 1.0; 87 | vec4 sh = -step(h, vec4(0.0)); 88 | 89 | vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ; 90 | vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ; 91 | 92 | vec3 p0 = vec3(a0.xy,h.x); 93 | vec3 p1 = vec3(a0.zw,h.y); 94 | vec3 p2 = vec3(a1.xy,h.z); 95 | vec3 p3 = vec3(a1.zw,h.w); 96 | 97 | vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3))); 98 | p0 *= norm.x; 99 | p1 *= norm.y; 100 | p2 *= norm.z; 101 | p3 *= norm.w; 102 | 103 | vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0); 104 | m = m * m; 105 | return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1), 106 | dot(p2,x2), dot(p3,x3) ) ); 107 | } 108 | 109 | vec3 get_world_normal(vec2 coord){ 110 | vec2 frag_coord = coord/screen; 111 | frag_coord = (frag_coord-0.5)*2.0; 112 | vec4 device_normal = vec4(frag_coord, 0.0, 1.0); 113 | vec3 eye_normal = normalize((inv_proj * device_normal).xyz); 114 | vec3 world_normal = normalize(inv_rot*eye_normal); 115 | return world_normal; 116 | } 117 | 118 | void main(void){ 119 | vec2 uv = gl_FragCoord.xy/viewport; 120 | vec4 g = texture2D(ground, uv); 121 | 122 | vec3 mousevec = get_world_normal(mousepos); 123 | vec4 eyepos = inv_view * vec4(0.0, 0.0, 0.0, 1.0); 124 | float u = dot(vec3(0.0, 1.0, 0.0), -eyepos.xyz)/dot(vec3(0.0, 1.0, 0.0), mousevec); 125 | vec3 intersection = eyepos.xyz + mousevec * u; 126 | vec3 position = vec3(uv.x-0.5, 0.0, -uv.y+0.5); 127 | float dist = distance(position, intersection)*pow(editsize, 3.0); 128 | float s = smoothstep(1.0, 0.0, dist); 129 | 130 | float h = 0.1; 131 | for(int i=2; i<8; i++){ 132 | float factor = pow(2.0, float(i)); 133 | h += snoise(vec3(uv*factor, 0.05*delta*float(i+1)))/(pow(factor, 0.8)*6.0); 134 | } 135 | 136 | g.y += h*rockfactor*s*0.01; 137 | g.z += h*soilfactor*s*0.01; 138 | g.z = clamp(g.z, 0.0, 1.0); 139 | g.x = g.y + g.z; 140 | 141 | gl_FragColor = g; 142 | } 143 | -------------------------------------------------------------------------------- /webgl/viewpoint.js: -------------------------------------------------------------------------------- 1 | /* 2 | :copyright: 2011 by Florian Boesch . 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | var Viewpoint = Class({ 7 | type: 'viewpoint', 8 | __init__: function(params){ 9 | this.time = Date.now()/1000; 10 | var selector = params.element || document; 11 | this.offset = params.offset || new Vec3(); 12 | this.damping = params.damping || 0.95; 13 | this.acc_factor = params.acc_factor || 50.0; 14 | 15 | var self = this; 16 | this.orientation = params.orientation || 0; 17 | this.orientation_speed = 0; 18 | this.orientation_acc = 0; 19 | this.pitch = params.pitch || 0; 20 | this.pitch_speed = 0; 21 | this.pitch_acc = 0; 22 | 23 | this.pos = new Vec3(params.x, params.y, params.z); 24 | this.last_pos = new Vec3(params.x, params.y, params.z); 25 | this.vel = new Vec3(); 26 | this.acc = new Vec3(); 27 | this.tmp = new Vec3(); 28 | 29 | var x, y, lastx, lasty, pressed; 30 | 31 | $(selector) 32 | .mousedown(function(event){ 33 | pressed = true; 34 | lastx = event.pageX; 35 | lasty = event.pageY; 36 | }) 37 | .mouseup(function(){ 38 | pressed = false; 39 | }) 40 | .mousemove(function(event){ 41 | if(pressed){ 42 | var x = event.pageX; 43 | var y = event.pageY; 44 | 45 | self.orientation_acc += x-lastx; 46 | self.pitch_acc += y-lasty; 47 | 48 | lastx = x; 49 | lasty = y; 50 | } 51 | }) 52 | .bind('selectstart', function(){ 53 | return false; 54 | }); 55 | 56 | this.view = new Mat4(); 57 | this.inv_view = new Mat4(); 58 | this.rot = new Mat3(); 59 | this.inv_rot = new Mat3(); 60 | }, 61 | set: function(shader){ 62 | shader.set({ 63 | view: this.view, 64 | inv_view: this.inv_view, 65 | rot: this.rot, 66 | inv_rot: this.inv_rot, 67 | }); 68 | }, 69 | update: function(){ 70 | var now = Date.now()/1000; 71 | var time = this.time; 72 | var timestep = 1/120; 73 | 74 | var acc = this.acc; 75 | acc.x = keys.a ? +1 : keys.d ? -1 : 0; 76 | acc.y = keys.q ? +1 : keys.e ? -1 : 0; 77 | acc.z = keys.s ? -1 : keys.w ? +1 : 0; 78 | acc.mul(timestep).mul(this.rot); 79 | 80 | if(now - time > 0.25){ 81 | time = now - 0.25; 82 | } 83 | 84 | while(time < now){ 85 | this.step(timestep); 86 | time += timestep; 87 | } 88 | this.time = time; 89 | 90 | var diff = time - now; 91 | if(diff > 0){ 92 | var u = (timestep - diff)/timestep; 93 | var orientation = this.last_orientation + (this.orientation - this.last_orientation)*u; 94 | var pitch = this.last_pitch + (this.pitch - this.last_pitch)*u; 95 | var x = this.last_pos.x + (this.pos.x - this.last_pos.x)*u; 96 | var y = this.last_pos.y + (this.pos.y - this.last_pos.y)*u; 97 | var z = this.last_pos.z + (this.pos.z - this.last_pos.z)*u; 98 | } 99 | else{ 100 | var orientation = this.orientation; 101 | var pitch = this.pitch; 102 | var x = this.pos.x; 103 | var y = this.pos.y; 104 | var z = this.pos.z; 105 | } 106 | 107 | this.orientation_acc = 0; 108 | this.pitch_acc = 0; 109 | 110 | this.view 111 | .ident() 112 | .translate(this.offset.x, this.offset.y, this.offset.z) 113 | .rotatex(pitch) 114 | .rotatey(orientation) 115 | .translate(x, y, z); 116 | 117 | this.inv_view 118 | .updateFrom(this.view) 119 | .invert(); 120 | 121 | this.rot.updateFrom(this.view); 122 | this.inv_rot.updateFrom(this.inv_view); 123 | }, 124 | step: function(delta){ 125 | this.last_pos.update(this.pos); 126 | this.last_orientation = this.orientation; 127 | this.last_pitch = this.pitch; 128 | 129 | this.orientation_speed += this.orientation_acc * delta * this.acc_factor; 130 | this.pitch_speed += this.pitch_acc * delta * this.acc_factor; 131 | 132 | this.orientation_speed *= this.damping; 133 | this.pitch_speed *= this.damping; 134 | 135 | this.orientation += this.orientation_speed * delta; 136 | this.pitch += this.pitch_speed * delta; 137 | 138 | this.vel.add(this.acc).mul(0.975); 139 | this.tmp.update(this.vel).mul(delta); 140 | this.pos.add(this.tmp); 141 | 142 | if(this.pitch > 85){ 143 | this.pitch = 85; 144 | this.pitch_speed = 0; 145 | } 146 | else if(this.pitch < -85){ 147 | this.pitch = -85; 148 | this.pitch_speed = 0; 149 | } 150 | 151 | }, 152 | }); 153 | -------------------------------------------------------------------------------- /display.shader: -------------------------------------------------------------------------------- 1 | /* 2 | :copyright: 2011 by Florian Boesch . 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | vertex: 7 | uniform mat4 proj, view; 8 | uniform sampler2D heights; 9 | uniform vec2 viewport; 10 | 11 | attribute vec2 position; 12 | attribute vec2 texcoord; 13 | attribute vec3 barycentric; 14 | 15 | varying vec2 uv; 16 | varying vec3 bc, v_position; 17 | 18 | const float pi = 3.1415926535897931; 19 | const float pih = pi*0.5; 20 | 21 | void main(){ 22 | uv = texcoord; 23 | bc = barycentric; 24 | float y = texture2D(heights, texcoord).x; 25 | v_position = (view * vec4(position.x, y, -position.y, 1.0)).xyz; 26 | gl_Position = proj * view * vec4(position.x, y, -position.y, 1.0); 27 | } 28 | 29 | fragment: 30 | uniform sampler2D heights, normals, occlusions, shadowmap, water; 31 | uniform sampler2D rock, rock_normals; 32 | uniform sampler2D grass, grass_normals; 33 | uniform vec2 mousepos, viewport; 34 | uniform mat4 inv_proj, inv_view; 35 | uniform mat3 inv_rot; 36 | uniform float editsize; 37 | 38 | varying vec2 uv; 39 | varying vec3 bc, v_position; 40 | 41 | vec3 get_world_normal(vec2 coord){ 42 | vec2 frag_coord = coord/viewport; 43 | frag_coord = (frag_coord-0.5)*2.0; 44 | vec4 device_normal = vec4(frag_coord, 0.0, 1.0); 45 | vec3 eye_normal = normalize((inv_proj * device_normal).xyz); 46 | vec3 world_normal = normalize(inv_rot*eye_normal); 47 | return world_normal; 48 | } 49 | 50 | struct SHC{ 51 | vec3 L00, L1m1, L10, L11, L2m2, L2m1, L20, L21, L22; 52 | }; 53 | 54 | SHC beach = SHC( 55 | vec3( 0.6841148, 0.6929004, 0.7069543), 56 | vec3( 0.3173355, 0.3694407, 0.4406839), 57 | vec3(-0.1747193, -0.1737154, -0.1657420), 58 | vec3(-0.4496467, -0.4155184, -0.3416573), 59 | vec3(-0.1690202, -0.1703022, -0.1525870), 60 | vec3(-0.0837808, -0.0940454, -0.1027518), 61 | vec3(-0.0319670, -0.0214051, -0.0147691), 62 | vec3( 0.1641816, 0.1377558, 0.1010403), 63 | vec3( 0.3697189, 0.3097930, 0.2029923) 64 | ); 65 | 66 | vec3 shLight(vec3 normal, SHC l){ 67 | float x = normal.x; 68 | float y = normal.y; 69 | float z = normal.z; 70 | 71 | const float C1 = 0.429043; 72 | const float C2 = 0.511664; 73 | const float C3 = 0.743125; 74 | const float C4 = 0.886227; 75 | const float C5 = 0.247708; 76 | 77 | return ( 78 | C1 * l.L22 * (x * x - y * y) + 79 | C3 * l.L20 * z * z + 80 | C4 * l.L00 - 81 | C5 * l.L20 + 82 | 2.0 * C1 * l.L2m2 * x * y + 83 | 2.0 * C1 * l.L21 * x * z + 84 | 2.0 * C1 * l.L2m1 * y * z + 85 | 2.0 * C2 * l.L11 * x + 86 | 2.0 * C2 * l.L1m1 * y + 87 | 2.0 * C2 * l.L10 * z 88 | ); 89 | } 90 | 91 | vec3 Kr = vec3(0.18867780436772762, 0.4978442963618773, 0.6616065586417131); // air 92 | vec3 absorb(float dist, vec3 color, float factor){ 93 | return color-color*pow(Kr, vec3(factor/dist)); 94 | } 95 | 96 | void main(){ 97 | vec3 base_normal = normalize(texture2D(normals, uv).xyz); 98 | vec3 tangent = normalize(cross(base_normal, vec3(0.0, 0.0, 1.0))); 99 | vec3 bitangent = normalize(cross(tangent, base_normal)); 100 | mat3 orthobasis = mat3(tangent, base_normal, bitangent); 101 | 102 | vec3 mousevec = get_world_normal(mousepos); 103 | vec4 eyepos = inv_view * vec4(0.0, 0.0, 0.0, 1.0); 104 | float u = dot(vec3(0.0, 1.0, 0.0), -eyepos.xyz)/dot(vec3(0.0, 1.0, 0.0), mousevec); 105 | vec3 intersection = eyepos.xyz + mousevec * u; 106 | float dist = distance((inv_view * vec4(v_position, 1.0)).xz, intersection.xz)*pow(editsize, 3.0); 107 | vec3 selection; 108 | if(dist > mix(0.99, 0.25, editsize/20.0) && dist < 1.0){ 109 | selection = vec3(0.12, 0.92, 0.0); 110 | } 111 | else{ 112 | selection = vec3(1.0, 1.0, 1.0); 113 | } 114 | 115 | vec3 w = texture2D(water, uv).xyz; 116 | float rock_factor = 20.0; 117 | //vec3 rock_color = pow(texture2D(rock, uv*rock_factor).rgb, vec3(0.5)) * 1.5; 118 | vec3 rock_color = texture2D(rock, uv*rock_factor).rgb * 0.8; 119 | vec3 rock_normal = orthobasis * normalize((texture2D(rock_normals, uv*rock_factor).xyz-0.5)*vec3(2.0, 3.0, 2.0)); 120 | 121 | float grass_factor = 8.0; 122 | vec3 grass_color = texture2D(grass, uv*grass_factor).rgb; 123 | vec3 grass_normal = orthobasis * normalize((texture2D(grass_normals, uv*grass_factor).xyz-0.5)*vec3(2.0, 1.0, 2.0)); 124 | 125 | vec3 dirt = vec3(85.0/255.0, 34.0/255.0, 0.0); 126 | vec3 soil = mix(grass_color, dirt, sqrt(clamp(w.x/0.0003+length(w.yz)/0.015, 0.0, 1.0))); 127 | 128 | vec4 ground = texture2D(heights, uv); 129 | float mix_factor = clamp(ground.z*500.0, 0.0, 1.0); 130 | vec3 color = mix(rock_color, soil, mix_factor).xyz; 131 | vec3 normal = mix(rock_normal, grass_normal, mix_factor).xyz; 132 | 133 | float occlusion = mix(0.0, 1.0, texture2D(occlusions, uv).x); 134 | float shadowed = mix(0.3, 1.0, texture2D(shadowmap, uv).x); 135 | vec3 diffuse = shLight(normal, beach); 136 | vec3 exident = diffuse*occlusion*shadowed*color; 137 | float d = length(v_position); 138 | vec3 incident = absorb(d, exident*selection, 2.5) + pow(Kr*d*0.7, vec3(2.0)); 139 | 140 | gl_FragColor = vec4(pow(incident, vec3(1.0/1.8)), 1.0); 141 | } 142 | -------------------------------------------------------------------------------- /webgl/sphere.js: -------------------------------------------------------------------------------- 1 | /* 2 | :copyright: 2011 by Florian Boesch . 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | Framework.components.push(function(framework, gl){ 7 | var phi = (1+Math.sqrt(5))/2; 8 | 9 | var midp = function(v1, v2){ 10 | var x1 = v1[0]; 11 | var y1 = v1[1]; 12 | var z1 = v1[2]; 13 | 14 | var x2 = v2[0]; 15 | var y2 = v2[1]; 16 | var z2 = v2[2]; 17 | 18 | var x3 = (x1+x2)/2; 19 | var y3 = (y1+y2)/2; 20 | var z3 = (z1+z2)/2; 21 | 22 | return [x3, y3, z3]; 23 | } 24 | 25 | var normalize = function(faces, r){ 26 | if(r === undefined){ 27 | var r = 1.0; 28 | } 29 | var result = []; 30 | for(fi in faces){ 31 | var face = faces[fi]; 32 | var new_face = []; 33 | result.push(new_face); 34 | for(vi in face){ 35 | var vertex = face[vi]; 36 | var x = vertex[0]; 37 | var y = vertex[1]; 38 | var z = vertex[2]; 39 | var l = Math.sqrt(x*x + y*y + z*z); 40 | if (l != 0){ 41 | new_face.push([(r*x)/l, (r*y)/l, (r*z)/l]); 42 | } 43 | else{ 44 | new_face.push([0, 0, 0]); 45 | } 46 | } 47 | } 48 | return result; 49 | } 50 | 51 | var subdivide = function(faces){ 52 | var result = []; 53 | for(var i in faces){ 54 | var face = faces[i]; 55 | var v0 = face[0]; 56 | var v1 = face[1]; 57 | var v2 = face[2]; 58 | 59 | var va = midp(v0, v1); 60 | var vb = midp(v1, v2); 61 | var vc = midp(v2, v0); 62 | 63 | result.push( 64 | [v0, va, vc], 65 | [va, v1, vb], 66 | [vc, vb, v2], 67 | [va, vb, vc] 68 | ) 69 | } 70 | return result; 71 | } 72 | 73 | var vertexlist = function(faces){ 74 | var vertices = []; 75 | for(var fi in faces){ 76 | var face = faces[fi]; 77 | for(var vi in face){ 78 | var vertex = face[vi]; 79 | var x = vertex[0]; 80 | var y = vertex[1]; 81 | var z = vertex[2]; 82 | vertices.push(x, y, z); 83 | } 84 | } 85 | return vertices; 86 | } 87 | 88 | var longitude = function(vertex){ 89 | var x = vertex[0]; 90 | var z = vertex[2]; 91 | return Math.atan2(x, z)/(Math.PI*2)+0.5; 92 | } 93 | var lattitude = function(vertex){ 94 | var y = vertex[1]; 95 | return Math.acos(y)/Math.PI; 96 | } 97 | var diff = function(a, b){ 98 | return Math.abs(a-b); 99 | } 100 | 101 | var polar_coords = function(faces){ 102 | var coords = []; 103 | for(var fi in faces){ 104 | var face = faces[fi]; 105 | var l0 = longitude(face[0]); 106 | var l1 = longitude(face[1]); 107 | var l2 = longitude(face[2]); 108 | 109 | var d0 = diff(l0, l1); 110 | var d1 = diff(l0, l2); 111 | var d3 = diff(l1, l2); 112 | if(d0 > 0.5 || d1 > 0.5 || d3 > 0.5){ 113 | correct = 1.0; 114 | } 115 | else{ 116 | correct = 0.0; 117 | } 118 | 119 | for(var vi in face){ 120 | var vertex = face[vi]; 121 | var s = longitude(vertex); 122 | var t = lattitude(vertex); 123 | if(s > 0.5){ 124 | coords.push(s-correct, t); 125 | } 126 | else{ 127 | coords.push(s, t); 128 | } 129 | } 130 | } 131 | return coords; 132 | } 133 | 134 | var barycentric_coords = function(faces){ 135 | var coords = []; 136 | for(var fi in faces){ 137 | coords.push( 138 | 1, 0, 0, 139 | 0, 1, 0, 140 | 0, 0, 1 141 | ) 142 | } 143 | return coords; 144 | } 145 | 146 | var v1 = [ 1, phi, 0]; 147 | var v2 = [ -1, phi, 0]; 148 | var v3 = [ 0, 1, phi]; 149 | var v4 = [ 0, 1, -phi]; 150 | var v5 = [ phi, 0, 1]; 151 | var v6 = [-phi, 0, 1]; 152 | var v7 = [-phi, 0, -1]; 153 | var v8 = [ phi, 0, -1]; 154 | var v9 = [ 0, -1, phi]; 155 | var v10 = [ 0, -1, -phi]; 156 | var v11 = [ -1, -phi, 0]; 157 | var v12 = [ 1, -phi, 0]; 158 | 159 | var faces = [ 160 | [ v1, v2, v3], 161 | [ v2, v1, v4], 162 | [ v1, v3, v5], 163 | [ v2, v6, v3], 164 | [ v2, v7, v6], 165 | [ v2, v4, v7], 166 | [ v1, v5, v8], 167 | [ v1, v8, v4], 168 | [ v9, v3, v6], 169 | [ v3, v9, v5], 170 | [ v4, v10, v7], 171 | [ v4, v8, v10], 172 | [ v6, v7, v11], 173 | [ v6, v11, v9], 174 | [ v7, v10, v11], 175 | [ v5, v12, v8], 176 | [v12, v5, v9], 177 | [v12, v10, v8], 178 | [v11, v12, v9], 179 | [v12, v11, v10] 180 | ]; 181 | 182 | var icosahedron = normalize(faces); 183 | 184 | framework.Sphere = Class({ 185 | __extends__: framework.Drawable, 186 | __init__: function(radius, subdivisions){ 187 | var subdivisions = subdivisions === undefined ? 3 : subdivisions; 188 | var template = icosahedron; 189 | 190 | for(var i=0; i 2 | 3 | 4 | 24 | 25 | 167 | 168 | 169 |
170 | 171 |
172 | 173 | 174 | -------------------------------------------------------------------------------- /water/display.shader: -------------------------------------------------------------------------------- 1 | /* 2 | :copyright: 2011 by Florian Boesch . 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | vertex: 7 | uniform mat4 proj, view; 8 | uniform sampler2D heights, water_heights; 9 | 10 | attribute vec2 position, texcoord; 11 | attribute vec4 cell_uv; 12 | 13 | varying float h; 14 | varying vec2 uv; 15 | varying vec4 v_position, v_cell_uv; 16 | 17 | void main(){ 18 | float h1 = texture2D(heights, texcoord).x; 19 | float h2 = texture2D(water_heights, texcoord).x; 20 | h = h2; 21 | vec4 pos = view * vec4(position.x, h1+h2-0.00000, -position.y, 1.0); 22 | gl_Position = proj * pos; 23 | uv = texcoord; 24 | v_position = pos; 25 | v_cell_uv = cell_uv; 26 | } 27 | 28 | fragment: 29 | varying float h; 30 | varying vec2 uv; 31 | varying vec4 v_position, v_cell_uv; 32 | 33 | uniform vec2 viewport, mousepos; 34 | uniform mat3 inv_rot; 35 | uniform mat4 inv_proj, lightview, inv_view; 36 | uniform float editsize; 37 | uniform sampler2D water_heights, normals, detail_normals, shadowmap, flows; 38 | 39 | vec3 get_world_normal(vec2 coord){ 40 | vec2 frag_coord = coord/viewport; 41 | frag_coord = (frag_coord-0.5)*2.0; 42 | vec4 device_normal = vec4(frag_coord, 0.0, 1.0); 43 | vec3 eye_normal = normalize((inv_proj * device_normal).xyz); 44 | vec3 world_normal = normalize(inv_rot*eye_normal); 45 | return world_normal; 46 | } 47 | 48 | struct SHC{ 49 | vec3 L00, L1m1, L10, L11, L2m2, L2m1, L20, L21, L22; 50 | }; 51 | 52 | SHC beach = SHC( 53 | vec3( 0.6841148, 0.6929004, 0.7069543), 54 | vec3( 0.3173355, 0.3694407, 0.4406839), 55 | vec3(-0.1747193, -0.1737154, -0.1657420), 56 | vec3(-0.4496467, -0.4155184, -0.3416573), 57 | vec3(-0.1690202, -0.1703022, -0.1525870), 58 | vec3(-0.0837808, -0.0940454, -0.1027518), 59 | vec3(-0.0319670, -0.0214051, -0.0147691), 60 | vec3( 0.1641816, 0.1377558, 0.1010403), 61 | vec3( 0.3697189, 0.3097930, 0.2029923) 62 | ); 63 | 64 | vec3 shLight(vec3 normal, SHC l){ 65 | float x = normal.x; 66 | float y = normal.y; 67 | float z = normal.z; 68 | 69 | const float C1 = 0.429043; 70 | const float C2 = 0.511664; 71 | const float C3 = 0.743125; 72 | const float C4 = 0.886227; 73 | const float C5 = 0.247708; 74 | 75 | return ( 76 | C1 * l.L22 * (x * x - y * y) + 77 | C3 * l.L20 * z * z + 78 | C4 * l.L00 - 79 | C5 * l.L20 + 80 | 2.0 * C1 * l.L2m2 * x * y + 81 | 2.0 * C1 * l.L21 * x * z + 82 | 2.0 * C1 * l.L2m1 * y * z + 83 | 2.0 * C2 * l.L11 * x + 84 | 2.0 * C2 * l.L1m1 * y + 85 | 2.0 * C2 * l.L10 * z 86 | ); 87 | } 88 | 89 | vec3 Kr = vec3(0.18867780436772762, 0.4978442963618773, 0.6616065586417131); // air 90 | vec3 absorb(float dist, vec3 color, float factor){ 91 | return color-color*pow(Kr, vec3(factor/dist)); 92 | } 93 | 94 | vec3 getnormal(){ 95 | float s = 1.0/128.0; 96 | 97 | //vec2 off = mod(uv, s); 98 | vec2 off = v_cell_uv.zw*s; 99 | 100 | //vec2 center_uv = uv-off+1.0/64.0; 101 | vec2 center_uv = v_cell_uv.xy+1.0/2048.0; 102 | vec2 right_uv = center_uv + vec2(s, 0.0); 103 | vec2 top_uv = center_uv + vec2(0.0, s); 104 | vec2 topright_uv = center_uv + vec2(s, s); 105 | 106 | vec2 center_pos = texture2D(flows, center_uv).xy; 107 | vec2 right_pos = texture2D(flows, right_uv).xy; 108 | vec2 top_pos = texture2D(flows, top_uv).xy; 109 | vec2 topright_pos = texture2D(flows, topright_uv).xy; 110 | 111 | vec3 center = normalize(texture2D(detail_normals, uv*32.0-center_pos*2.0).xyz*2.0-1.0); 112 | vec3 right = normalize(texture2D(detail_normals, uv*32.0-right_pos*2.0).xyz*2.0-1.0); 113 | vec3 top = normalize(texture2D(detail_normals, uv*32.0-top_pos*2.0).xyz*2.0-1.0); 114 | vec3 topright = normalize(texture2D(detail_normals, uv*32.0-topright_pos*2.0).xyz*2.0-1.0); 115 | 116 | vec3 normal1 = mix(center, right, off.x/s); 117 | vec3 normal2 = mix(top, topright, off.x/s); 118 | vec3 normal = mix(normal1, normal2, off.y/s); 119 | return normalize(normal*vec3(1.0, 0.2, 1.0)); 120 | } 121 | 122 | void main(){ 123 | vec3 w = texture2D(water_heights, uv).xyz; 124 | vec2 c = w.yz/(w.x+0.001)+0.5; 125 | 126 | vec3 mousevec = get_world_normal(mousepos); 127 | vec4 eyepos = inv_view * vec4(0.0, 0.0, 0.0, 1.0); 128 | float u = dot(vec3(0.0, 1.0, 0.0), -eyepos.xyz)/dot(vec3(0.0, 1.0, 0.0), mousevec); 129 | vec3 intersection = eyepos.xyz + mousevec * u; 130 | float dist = distance((inv_view * v_position).xz, intersection.xz)*pow(editsize, 3.0); 131 | vec3 selection; 132 | if(dist > mix(0.99, 0.25, editsize/20.0) && dist < 1.0){ 133 | selection = vec3(0.12, 0.92, 0.0); 134 | } 135 | else{ 136 | selection = vec3(1.0, 1.0, 1.0); 137 | } 138 | 139 | float speed_factor = clamp(length(w.yz)/0.02, 0.0, 1.0); 140 | float depth_factor = clamp(w.x/0.001, 0.0, 1.0); 141 | 142 | vec3 base_normal = normalize(texture2D(normals, uv).xyz); 143 | vec3 tangent = normalize(cross(base_normal, vec3(0.0, 0.0, 1.0))); 144 | vec3 bitangent = normalize(cross(tangent, base_normal)); 145 | mat3 orthobasis = mat3(tangent, base_normal, bitangent); 146 | vec3 detail_normal = orthobasis * getnormal(); 147 | vec3 normal = normalize(mix(base_normal*0.5+detail_normal*0.5, detail_normal, speed_factor)); 148 | normal = normalize(mix(normal, base_normal, sqrt(clamp(w.x/0.0075, 0.0, 1.0))*0.75)); 149 | 150 | vec3 lightdir = (lightview * vec4(0.0, 0.0, 1.0, 1.0)).xyz; 151 | vec3 eye_normal = get_world_normal(gl_FragCoord.xy); 152 | vec3 specular_normal = reflect(eye_normal, normalize(normal * vec3(1.0, 0.35, 1.0))); 153 | float lambert = pow(max(0.0, dot(specular_normal, lightdir)), 0.5); 154 | float specular = pow(lambert, 20.0)*0.9; 155 | vec3 deep = vec3(0.0, 51.0/255.0, 128.0/255.0)*0.5; 156 | vec3 turbulent = vec3(42.0/255.0, 212.0/255.0, 255.0/255.0)*0.9; 157 | 158 | vec3 color = mix(turbulent, deep, sqrt(clamp(w.x/0.0075, 0.0, 1.0))); 159 | color = mix(color, vec3(1.0, 1.0, 1.0), clamp(pow(speed_factor*2.0, 3.0), 0.0, 1.0)); 160 | 161 | vec3 exident = color * mix(shLight(specular_normal, beach), shLight(normal, beach), 0.75); 162 | 163 | float d = length(v_position.xyz); 164 | float shadow = texture2D(shadowmap, uv).x; 165 | vec3 incident = absorb(d, exident*mix(0.45, 1.0, shadow)*selection+specular*shadow, 2.5) + pow(Kr*d*0.7, vec3(2.0)); 166 | 167 | gl_FragColor = vec4(pow(incident, vec3(1.0/1.8)), depth_factor); 168 | } 169 | -------------------------------------------------------------------------------- /webgl/shader.js: -------------------------------------------------------------------------------- 1 | /* 2 | :copyright: 2011 by Florian Boesch . 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | Framework.components.push(function(framework, gl){ 7 | var current = null; 8 | 9 | framework.Shader = Class({ 10 | __init__: function(source, filename){ 11 | this.filename = filename; 12 | this.source = source; 13 | this.fragment = gl.createShader(gl.FRAGMENT_SHADER); 14 | this.vertex = gl.createShader(gl.VERTEX_SHADER); 15 | this.program = gl.createProgram(); 16 | 17 | this.textures = {}; 18 | this.units = {}; 19 | this.unit_counter = 0; 20 | 21 | gl.attachShader(this.program, this.vertex); 22 | gl.attachShader(this.program, this.fragment); 23 | this.link(source); 24 | }, 25 | uniformLocation: function(name){ 26 | var location = this.uniform_cache[name]; 27 | if(location === undefined){ 28 | var location = this.uniform_cache[name] = gl.getUniformLocation(this.program, name); 29 | } 30 | return location; 31 | }, 32 | attributeLocation: function(name){ 33 | var location = this.attribute_cache[name]; 34 | if(location === undefined){ 35 | var location = this.attribute_cache[name] = gl.getAttribLocation(this.program, name); 36 | } 37 | return location; 38 | }, 39 | link: function(source){ 40 | var shaders = this.preprocess(source); 41 | this.uniform_cache = {}; 42 | this.attribute_cache = {}; 43 | 44 | this.compile(this.vertex, shaders.vertex); 45 | this.compile(this.fragment, shaders.fragment); 46 | gl.linkProgram(this.program); 47 | if(!gl.getProgramParameter(this.program, gl.LINK_STATUS)){ 48 | throw this.filename + ': program link: ' + this.path + ': ' + gl.getProgramInfoLog(this.program); 49 | } 50 | }, 51 | compile: function(shader, source){ 52 | var directives = [ 53 | '#version 100', 54 | 'precision highp int;', 55 | 'precision highp float;', 56 | ].join('\n'); 57 | gl.shaderSource(shader, directives + '\n' + source); 58 | gl.compileShader(shader); 59 | if(!gl.getShaderParameter(shader, gl.COMPILE_STATUS)){ 60 | throw this.filename + ': shader compile: ' + gl.getShaderInfoLog(shader); 61 | } 62 | }, 63 | validate: function(){ 64 | gl.validateProgram(this.program); 65 | if(!gl.getProgramParameter(this.program, gl.VALIDATE_STATUS)){ 66 | throw this.filename + ': program validate: ' + gl.getProgramInfoLog(this.program); 67 | } 68 | }, 69 | preprocess: function(source){ 70 | var lines = source.split('\n'); 71 | var shaders = {}; 72 | var type; 73 | 74 | for(var i=0; i. 3 | :license: GNU AGPL3, see LICENSE for more details. 4 | */ 5 | 6 | var editsize = 3; 7 | var lightview = new Mat4().rotatex(15).rotatey(60); 8 | var inv_lightview = new Mat4().updateFrom(lightview).invert(); 9 | var keys = new Keys(); 10 | var controls = { 11 | rock: 1.0, 12 | soil: 0.0, 13 | water: 0.0, 14 | dir: 1.0, 15 | rain: 1.0, 16 | erode: 1.0, 17 | evaporate: 1.0, 18 | }; 19 | var view, mousepos, projection; 20 | var start = Date.now()/1000; 21 | var terrain; 22 | 23 | var Processor = Class({ 24 | __init__: function(width, height, framework){ 25 | this.result = new framework.Texture() 26 | .size(width, height, 'float') 27 | .linear() 28 | .clampToEdge(); 29 | this.fbo = new framework.Framebuffer() 30 | .color(this.result); 31 | this.quad = framework.unitQuad(); 32 | }, 33 | run: function(program){ 34 | program.draw(this.quad, this.fbo); 35 | } 36 | }); 37 | 38 | var Water = Class({ 39 | __init__: function(width, height, framework, programs, heights, normals){ 40 | this.programs = programs; 41 | this.framework = framework; 42 | 43 | this.tmp = new Processor(width, height, framework); 44 | this.last = new Processor(width, height, framework); 45 | this.current = new Processor(width, height, framework); 46 | this.normals = new Processor(width, height, framework); 47 | this.flows = new Processor(128, 128, framework); 48 | this.flows.result.nearest(); 49 | 50 | programs.water_diffuse.set('heights', heights.result); 51 | programs.water_momentum 52 | .set('last', this.last.result) 53 | .set('current', this.current.result) 54 | .set('ground', heights.result); 55 | programs.water_cycle.set('water', this.tmp.result); 56 | programs.water_normals.set({ 57 | ground: heights.result, 58 | water: this.current.result, 59 | }); 60 | programs.flows.set({ 61 | flows: this.flows.result, 62 | water: this.current.result, 63 | }); 64 | }, 65 | update: function(){ 66 | this.programs.water_diffuse.set('axis', 0, 1).set('source', this.current.result); 67 | this.tmp.run(this.programs.water_diffuse); 68 | this.programs.water_diffuse.set('axis', 1, 0).set('source', this.tmp.result); 69 | this.current.run(this.programs.water_diffuse); 70 | 71 | this.tmp.run(this.programs.water_momentum); 72 | this.programs.copy.set('source', this.current.result); 73 | this.last.run(this.programs.copy); 74 | this.programs.water_cycle 75 | .set('rain', controls.rain) 76 | .set('evaporate', controls.evaporate) 77 | .set(view) 78 | .set(projection) 79 | .set('mousepos', mousepos) 80 | .set('editsize', editsize) 81 | .set('screen', [this.framework.screen.width, this.framework.screen.height]) 82 | .set('create', keys.space && controls.water ? 1.0 * controls.dir : 0.0) 83 | 84 | this.current.run(this.programs.water_cycle); 85 | this.normals.run(this.programs.water_normals); 86 | this.tmp.run(this.programs.flows); 87 | this.flows.run(this.programs.copy.set('source', this.tmp.result)); 88 | }, 89 | }); 90 | 91 | var Shadow = Class({ 92 | __init__: function(width, height, framework, programs, terrain, grid){ 93 | this.programs = programs; 94 | this.grid = grid; 95 | this.gl = framework.gl; 96 | 97 | this.depth = new framework.Texture() 98 | .size(2048, 2048, 'float') 99 | .linear() 100 | .clampToEdge(); 101 | 102 | this.fbo = new framework.Framebuffer() 103 | .color(this.depth) 104 | .depth(); 105 | 106 | this.proj = new framework.Ortho(this.fbo, { 107 | scale: 1.5, 108 | near: -20, 109 | far: 20, 110 | }); 111 | 112 | programs.shadow 113 | .set('heights', terrain.heights.result) 114 | .set(this.proj); 115 | 116 | programs.shadowmap 117 | .set('heights', terrain.heights.result) 118 | .set('normals', terrain.normals.result) 119 | .set('shadows', this.depth) 120 | .set('shadowsize', this.depth.width, this.depth.height) 121 | .set(this.proj); 122 | 123 | programs.water_shadowmap 124 | .set('ground', terrain.heights.result) 125 | .set('water', terrain.water.current.result) 126 | .set('normals', terrain.water.normals.result) 127 | .set('shadows', this.depth) 128 | .set('shadowsize', this.depth.width, this.depth.height) 129 | .set(this.proj); 130 | 131 | this.map = new Processor(width*2, height*2, framework); 132 | this.water_map = new Processor(width*2, height*2, framework); 133 | this.tmp = new Processor(width*2, height*2, framework); 134 | }, 135 | update: function(){ 136 | this.fbo.bind(); 137 | this.gl.clearColor(1, 1, 1, 1); 138 | this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT); 139 | this.programs.shadow.set('view', lightview).draw(this.grid, this.fbo); 140 | 141 | this.programs.shadowmap.set('view', lightview); 142 | this.map.run(this.programs.shadowmap); 143 | this.programs.blur.set('axis', 1.2, 0.0).set('source', this.map.result); 144 | this.tmp.run(this.programs.blur); 145 | this.programs.blur.set('axis', 0.0, 1.2).set('source', this.tmp.result); 146 | this.map.run(this.programs.blur); 147 | 148 | this.programs.water_shadowmap.set('view', lightview); 149 | this.water_map.run(this.programs.water_shadowmap); 150 | this.programs.blur.set('axis', 1.2, 0.0).set('source', this.water_map.result); 151 | this.tmp.run(this.programs.blur); 152 | this.programs.blur.set('axis', 0.0, 1.2).set('source', this.tmp.result); 153 | this.water_map.run(this.programs.blur); 154 | } 155 | }); 156 | 157 | var Terrain = Class({ 158 | __init__: function(width, height, framework, programs, grid){ 159 | this.framework = framework; 160 | this.programs = programs; 161 | this.heights = new Processor(width, height, framework); 162 | this.normals = new Processor(width, height, framework); 163 | this.occlusions = new Processor(width, height, framework); 164 | this.water = new Water(width, height, framework, programs, this.heights, this.normals); 165 | this.shadow = new Shadow(width, height, framework, programs, this, grid); 166 | 167 | this.tmp = new Processor(width, height, framework); 168 | 169 | programs.normal.set('heights', this.heights.result); 170 | programs.occlusion.set({ 171 | 'heights': this.heights.result, 172 | 'normals': this.normals.result, 173 | }); 174 | this.reset($( "#seedslider" ).slider( "value" )); 175 | $( "#seed" ).val( $( "#seedslider" ).slider( "value" ) ); 176 | }, 177 | reset: function(delta) { 178 | this.delta = delta; 179 | // console.log(this.delta); 180 | this.programs.simplex.set('delta', this.delta); 181 | this.heights.run(this.programs.simplex); 182 | this.programs.errode.set({ 183 | ground: this.heights.result, 184 | water: this.water.current.result, 185 | }); 186 | this.programs.diffuse_soil.set({ 187 | ground: this.tmp.result, 188 | water: this.water.current.result, 189 | }); 190 | }, 191 | update: function(){ 192 | this.water.update(); 193 | this.programs.errode.set('factor', controls.erode); 194 | this.tmp.run(this.programs.errode); 195 | 196 | this.heights.run(this.programs.diffuse_soil); 197 | 198 | if(keys.space && (controls.soil || controls.rock)){ 199 | this.programs.god 200 | .set(view) 201 | .set(projection) 202 | .set('mousepos', mousepos) 203 | .set('delta', Date.now()/1000-start) 204 | .set('screen', [this.framework.screen.width, this.framework.screen.height]) 205 | .set('rockfactor', controls.rock * controls.dir) 206 | .set('soilfactor', controls.soil * controls.dir) 207 | .set('editsize', editsize) 208 | this.tmp.run(this.programs.god); 209 | this.heights.run(this.programs.copy.set('source', this.tmp.result)); 210 | } 211 | 212 | this.normals.run(this.programs.normal); 213 | this.occlusions.run(this.programs.occlusion); 214 | this.shadow.update(); 215 | }, 216 | }); 217 | 218 | $(function(){ 219 | var canvas = $('canvas'); 220 | $('#modtype').buttonset(); 221 | $('#modop').buttonset(); 222 | $('#params').buttonset(); 223 | 224 | $('input[name="modtype"]').change(function(){ 225 | controls.rock = 0.0; 226 | controls.soil = 0.0; 227 | controls.water = 0.0; 228 | controls[$(this).attr('id')] = 1.0; 229 | }); 230 | 231 | $('input[name="modop"]').change(function(){ 232 | if($(this).attr('id') == 'add'){ 233 | controls.dir = 1.0; 234 | } 235 | else{ 236 | controls.dir = -1.0; 237 | } 238 | }); 239 | 240 | $('#rain,#erode,#evaporate').change(function(){ 241 | var id = $(this).attr('id'); 242 | if(this.checked){ 243 | controls[id] = 1.0; 244 | } 245 | else{ 246 | controls[id] = 0.0; 247 | } 248 | }); 249 | 250 | $( ".ui-icon-wrench" ).click(function() { 251 | $(".hideable").toggle(); 252 | }); 253 | 254 | $('#seed').change(function(){ 255 | var newseed = parseInt($( "#seed" ).val()); 256 | $( "#seedslider" ).slider( 'value', newseed ); 257 | terrain.reset(newseed); 258 | }); 259 | 260 | $( "#seedslider" ).slider( { 261 | slide: function( event, ui ) { 262 | $( "#seed" ).val( ui.value ); 263 | terrain.reset(ui.value); 264 | }, 265 | value:1, 266 | min: 1, 267 | max: 1000, 268 | step: 1 269 | }); 270 | 271 | $(".hideable").toggle(); 272 | 273 | view = new Viewpoint({ 274 | element: canvas, 275 | offset: new Vec3(0, 0, 0.0), 276 | x: -0.08, 277 | y: -0.08, 278 | z: -0.65, 279 | pitch: 12, 280 | }); 281 | 282 | mousepos = [0, 0]; 283 | canvas.mousemove(function(event){ 284 | mousepos[0] = event.pageX; 285 | mousepos[1] = this.height - event.pageY; 286 | }); 287 | 288 | $(document).mousewheel(function(event, delta){ 289 | editsize = clamp(editsize - delta*0.1, 2, 20); 290 | }); 291 | 292 | var handle_error = function(description){ 293 | $(document).unbind(); 294 | $('body').empty(); 295 | var elem = $('
') 296 | .appendTo('body'); 297 | $('

Whoops, shit happens.

') 298 | .appendTo(elem); 299 | $('
').text(description).appendTo(elem);
300 |         $('').appendTo(elem);
301 |     }
302 | 
303 |     try{
304 |         var framework = new Framework(canvas[0])
305 |             .depthLess()
306 |             .blendAlpha()
307 |             .getExt('texture_float')
308 |             .requireParam('MAX_VERTEX_TEXTURE_IMAGE_UNITS', 4);
309 |     }
310 |     catch(error){
311 |         handle_error(error);
312 |         return;
313 |     }
314 |     
315 |     try {   // some browsers need this extension
316 |         framework.getExt('texture_float_linear')
317 |     } catch (error){
318 |         // ignore error in browsers that do not have this extension
319 |     }
320 |     
321 |     projection = new framework.Perspective(framework.screen, {
322 |         near: 0.01,
323 |         far: 20,
324 |         fov: 60,
325 |     });
326 | 
327 |     var gl = framework.gl;
328 | 
329 |     var gridsize = 512;
330 |     var grid, hexgrid;
331 |     var createGrids = function(gridsize) {
332 |         grid = new framework.Grid({
333 |             xsize: gridsize,
334 |             ysize: gridsize,
335 |             cell_width: 4,
336 |             cell_height: 4,
337 |             width: 1,
338 |             height: 1,
339 |         });
340 |     
341 |         hexgrid = new framework.HexGrid({
342 |             xsize: gridsize,
343 |             ysize: gridsize,
344 |             width: 1,
345 |             height: 1,
346 |         });
347 |     };
348 |     createGrids(gridsize);
349 |     
350 |     var scheduler = new Scheduler(function(delta, now){ 
351 |         terrain.update();
352 |         framework.screen.bind();
353 | 
354 |         gl.clearColor(0.7, 0.7, 0.7, 1);
355 |         gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
356 |         view.update(delta);
357 | 
358 |         programs.display
359 |             .set(projection)
360 |             .set(view)
361 |             .set('mousepos', mousepos)
362 |             .set('editsize', editsize)
363 |             .draw(hexgrid, framework.screen);
364 | 
365 |         programs.water_display
366 |             .set(projection)
367 |             .set(view)
368 |             .set('mousepos', mousepos)
369 |             .set('editsize', editsize)
370 |             .draw(grid, framework.screen);
371 |             
372 |         var error = gl.getError();
373 |         if (error == 1285) {    // out of memory
374 |             gridsize /= 4;      // reduce grid size
375 |             console.log("Reducing gridsize to " + gridsize);
376 |             createGrids(gridsize);
377 |         }
378 |     });
379 | 
380 |     var programs = {
381 |         display: 'display.shader',
382 |         simplex: 'simplex3d.shader',
383 |         normal: 'normal.shader',
384 |         occlusion: 'occlusion.shader',
385 |         shadow: 'shadow.shader',
386 |         shadowmap: 'shadowmap.shader',
387 |         blur: 'blur.shader',
388 |         rock: 'rock_texture.png',
389 |         rock_normals: 'rock2_normals.png',
390 |         grass: 'grass_material.png',
391 |         grass_normals: 'grass_normals.png',
392 | 
393 |         water_diffuse: 'water/diffuse.shader',
394 |         water_display: 'water/display.shader',
395 |         water_momentum: 'water/momentum.shader',
396 |         water_cycle: 'water/cycle.shader',
397 |         water_normals: 'water/normals.shader',
398 |         water_shadowmap: 'water/shadowmap.shader',
399 |         flows: 'flows.shader',
400 |         god: 'god.shader',
401 | 
402 |         errode: 'errode.shader',
403 |         diffuse_soil: 'diffuse_soil.shader',
404 | 
405 |         copy: 'copy.shader',
406 |     };
407 |    
408 |     var loader = new framework.Loader()
409 |         .error(function(description){
410 |             handle_error(description);
411 |         })
412 |         .load(programs)
413 |         .ready(function(){
414 |             terrain = new Terrain(512, 512, framework, programs, hexgrid);
415 |             terrain.update();
416 |             programs.display.set({
417 |                 'heights': terrain.heights.result,
418 |                 'normals': terrain.normals.result,
419 |                 'occlusions': terrain.occlusions.result,
420 |                 'rock': programs.rock.mipmap(),
421 |                 'rock_normals': programs.rock_normals.mipmap(),
422 |                 'grass': programs.grass.mipmap(),
423 |                 'grass_normals': programs.grass_normals.mipmap(),
424 |                 'shadowmap': terrain.shadow.map.result,
425 |                 water: terrain.water.current.result,
426 |             });
427 |             programs.water_display.set({
428 |                 lightview: inv_lightview,
429 |                 normals: terrain.water.normals.result,
430 |                 heights: terrain.heights.result,
431 |                 water_heights: terrain.water.current.result,
432 |                 detail_normals: programs.grass_normals,
433 |                 shadowmap: terrain.shadow.water_map.result,
434 |                 flows: terrain.water.flows.result,
435 |             });
436 |             scheduler.start();
437 |         });
438 | });
439 | 


--------------------------------------------------------------------------------
/webgl/matrix.js:
--------------------------------------------------------------------------------
  1 | /*
  2 |     :copyright: 2011 by Florian Boesch .
  3 |     :license: GNU AGPL3, see LICENSE for more details.
  4 | */
  5 | 
  6 | (function(){
  7 |     var fmt = function(value){
  8 |         var str = value.toFixed(2);
  9 |         while(str.length < 7){
 10 |             str = ' ' + str;
 11 |         }
 12 |         return str;
 13 |     }
 14 | 
 15 |     var pi = Math.PI;
 16 |     var tau = 2*pi;
 17 |     var deg = 360/tau
 18 |     var arc = tau/360
 19 | 
 20 |     Mat2 = function(){
 21 |         this.data = [
 22 |             1, 0,
 23 |             0, 1,
 24 |         ];
 25 |     }
 26 | 
 27 |     Mat2.prototype = {
 28 |         type: 'Mat2',
 29 |         set: function(
 30 |             a0, b0,
 31 |             a1, b1
 32 |         ){
 33 |             this.data.splice(0, 16,
 34 |                 a0, b0, 
 35 |                 a1, b1 
 36 |             );
 37 |             return this;
 38 |         },
 39 |     };
 40 |         
 41 |     Mat3 = function(other){
 42 |         this.data = [
 43 |             1, 0, 0, 
 44 |             0, 1, 0, 
 45 |             0, 0, 1
 46 |         ];
 47 |     };
 48 | 
 49 |     Mat3.prototype = {
 50 |         type: 'Mat3',
 51 |         set: function(
 52 |             a0, b0, c0, 
 53 |             a1, b1, c1, 
 54 |             a2, b2, c2
 55 |         ){
 56 |             this.data.splice(0, 16,
 57 |                 a0, b0, c0, 
 58 |                 a1, b1, c1, 
 59 |                 a2, b2, c2
 60 |             );
 61 |             return this;
 62 |         },
 63 |         ident: function(){
 64 |             return this.set(
 65 |                 1, 0, 0, 
 66 |                 0, 1, 0, 
 67 |                 0, 0, 1
 68 |             );
 69 |         },
 70 |         log: function(message){
 71 |             var d = this.data;
 72 |             if(!message){
 73 |                 message = 'Mat3';
 74 |             }
 75 |             console.group(message);
 76 |             console.log(fmt(d[0]), fmt(d[1]), fmt(d[2]));
 77 |             console.log(fmt(d[3]), fmt(d[4]), fmt(d[5]));
 78 |             console.log(fmt(d[6]), fmt(d[7]), fmt(d[8]));
 79 |             console.groupEnd();
 80 |             return this;
 81 |         },
 82 |         rotatex: function(angle){
 83 |             var s = Math.sin(angle*arc);
 84 |             var c = Math.cos(angle*arc);
 85 |             return this.amul(
 86 |                  1,  0,  0,  
 87 |                  0,  c,  s,  
 88 |                  0, -s,  c
 89 |             );
 90 |         },
 91 |         rotatey: function(angle){
 92 |             var s = Math.sin(angle*arc);
 93 |             var c = Math.cos(angle*arc);
 94 |             return this.amul(
 95 |                  c,  0, -s,  
 96 |                  0,  1,  0,  
 97 |                  s,  0,  c
 98 |             );
 99 |         },
100 |         rotatez: function(angle){
101 |             var s = Math.sin(angle*arc);
102 |             var c = Math.cos(angle*arc);
103 |             return this.amul(
104 |                  c,  s,  0,  
105 |                 -s,  c,  0,  
106 |                  0,  0,  1
107 |             );
108 |         },
109 |         updateFrom: function(other){
110 |             if(other.type == 'Mat4'){
111 |                 tmp4.updateFrom(other);
112 |                 tmp4.invert().transpose();
113 |                 var d = tmp4.data;
114 | 
115 |                 var a0 = d[0],  b0 = d[1],  c0 = d[2];
116 |                 var a1 = d[4],  b1 = d[5],  c1 = d[6]; 
117 |                 var a2 = d[8],  b2 = d[9],  c2 = d[10];
118 |             }
119 |             else{
120 |                 var d = other.data;
121 | 
122 |                 var a0 = d[0],  b0 = d[1],  c0 = d[2];
123 |                 var a1 = d[3],  b1 = d[4],  c1 = d[5]; 
124 |                 var a2 = d[6],  b2 = d[7],  c2 = d[8];
125 |             }
126 | 
127 |             return this.set(
128 |                 a0, b0, c0, 
129 |                 a1, b1, c1, 
130 |                 a2, b2, c2
131 |             );
132 |             return this;
133 |         },
134 |         amul: function(
135 |             b00, b10, b20, 
136 |             b01, b11, b21, 
137 |             b02, b12, b22, 
138 |             b03, b13, b23
139 |         ){
140 |             var a = this.data;
141 | 
142 |             var a00 = a[0];
143 |             var a10 = a[1];
144 |             var a20 = a[2];
145 |             
146 |             var a01 = a[3];
147 |             var a11 = a[4];
148 |             var a21 = a[5];
149 |             
150 |             var a02 = a[6];
151 |             var a12 = a[7];
152 |             var a22 = a[8];
153 |             
154 |             a[0]  = a00*b00 + a01*b10 + a02*b20;
155 |             a[1]  = a10*b00 + a11*b10 + a12*b20;
156 |             a[2]  = a20*b00 + a21*b10 + a22*b20;
157 |             
158 |             a[3]  = a00*b01 + a01*b11 + a02*b21;
159 |             a[4]  = a10*b01 + a11*b11 + a12*b21;
160 |             a[5]  = a20*b01 + a21*b11 + a22*b21;
161 |             
162 |             a[6]  = a00*b02 + a01*b12 + a02*b22;
163 |             a[7]  = a10*b02 + a11*b12 + a12*b22;
164 |             a[8] =  a20*b02 + a21*b12 + a22*b22;
165 | 
166 |             return this;
167 |         },
168 |         transpose: function(){
169 |             var d = this.data;
170 |             return this.set(
171 |                 d[0], d[3], d[6], 
172 |                 d[1], d[4], d[7], 
173 |                 d[2], d[5], d[8]
174 |             );
175 |         }
176 |     }
177 | 
178 |     Mat4 = function(other){
179 |         this.data = [
180 |             1, 0, 0, 0,
181 |             0, 1, 0, 0,
182 |             0, 0, 1, 0,
183 |             0, 0, 0, 1
184 |         ];
185 |     };
186 | 
187 |     Mat4.prototype = {
188 |         type: 'Mat4',
189 |         set: function(
190 |             a0, b0, c0, d0,
191 |             a1, b1, c1, d1,
192 |             a2, b2, c2, d2,
193 |             a3, b3, c3, d3
194 |         ){
195 |             this.data.splice(0, 16,
196 |                 a0, b0, c0, d0,
197 |                 a1, b1, c1, d1,
198 |                 a2, b2, c2, d2,
199 |                 a3, b3, c3, d3
200 |             );
201 |             return this;
202 |         },
203 |         setRotation: function(q){
204 |             var d = this.data;
205 |             var w=q.w, x=q.x, y=q.y, z=q.z;
206 | 
207 |             return this.set(
208 |                 1-(2*y*y + 2*z*z),  2*x*y - 2*z*w,      2*x*z + 2*y*w,      d[3],
209 |                 2*x*y + 2*z*w,      1-(2*x*x + 2*z*z),  2*y*z - 2*x*w,      d[7],
210 |                 2*x*z - 2*y*w,      2*y*z + 2*x*w,      1-(2*x*x + 2*y*y),  d[11],
211 |                 d[12],              d[13],              d[14],              d[15]
212 |             );
213 |         },
214 |         rotateQuat: function(q){
215 |             var d = this.data;
216 |             var w=q.w, x=q.x, y=q.y, z=q.z;
217 | 
218 |             return this.amul(
219 |                 1-(2*y*y + 2*z*z),  2*x*y - 2*z*w,      2*x*z + 2*y*w,      0,
220 |                 2*x*y + 2*z*w,      1-(2*x*x + 2*z*z),  2*y*z - 2*x*w,      0,
221 |                 2*x*z - 2*y*w,      2*y*z + 2*x*w,      1-(2*x*x + 2*y*y),  0,
222 |                 0,                  0,                  0,                  1 
223 |             );
224 |         },
225 |         updateFrom: function(other){
226 |             var d = other.data;
227 |             if(other.type == 'Mat4'){
228 |                 var a0 = d[0],  b0 = d[1],  c0 = d[2],  d0 = d[3];
229 |                 var a1 = d[4],  b1 = d[5],  c1 = d[6],  d1 = d[7];
230 |                 var a2 = d[8],  b2 = d[9],  c2 = d[10], d2 = d[11];
231 |                 var a3 = d[12], b3 = d[13], c3 = d[14], d3 = d[15];
232 | 
233 |             }
234 |             else{
235 |                 var a0 = d[0],  b0 = d[1],  c0 = d[2],  d0 = 0;
236 |                 var a1 = d[3],  b1 = d[4],  c1 = d[5],  d1 = 0;
237 |                 var a2 = d[6],  b2 = d[7],  c2 = d[8],  d2 = 0;
238 |                 var a3 = 0,     b3 = 0,     c3 = 0,     d3 = 1;
239 |             }
240 |                 
241 |             return this.set(
242 |                 a0, b0, c0, d0,
243 |                 a1, b1, c1, d1,
244 |                 a2, b2, c2, d2,
245 |                 a3, b3, c3, d3
246 |             );
247 |         },
248 |         det: function(){
249 |             var d = this.data;
250 | 
251 | 
252 |             var a11 = d[0],  a12 = d[1],  a13 = d[2],  a14 = d[3];
253 |             var a21 = d[4],  a22 = d[5],  a23 = d[6],  a24 = d[7];
254 |             var a31 = d[8],  a32 = d[9],  a33 = d[10], a34 = d[11];
255 |             var a41 = d[12], a42 = d[13], a43 = d[14], a44 = d[15];
256 | 
257 |             return (
258 |                 + a11*a22*a33*a44 + a11*a23*a34*a42 + a11*a24*a32*a43
259 |                 + a12*a21*a34*a33 + a12*a23*a31*a44 + a12*a24*a33*a41
260 |                 + a13*a21*a32*a44 + a13*a22*a34*a41 + a13*a24*a31*a42
261 |                 + a14*a21*a33*a42 + a14*a22*a31*a43 + a14*a23*a31*a41
262 |                 - a11*a22*a34*a43 - a11*a23*a32*a44 - a11*a24*a33*a42
263 |                 - a12*a21*a33*a44 - a12*a23*a34*a41 - a12*a24*a31*a43
264 |                 - a13*a21*a34*a42 - a13*a22*a31*a44 - a13*a24*a32*a41
265 |                 - a14*a21*a32*a43 - a14*a22*a33*a41 - a14*a23*a31*a42
266 |             )
267 |         },
268 |         invert: function(){
269 |             var det = this.det();
270 |             if(det == 0){
271 |                 return this.ident();
272 |             }
273 |             else{
274 |                 var d = this.data;
275 |                 var a11 = d[0],  a12 = d[1],  a13 = d[2],  a14 = d[3];
276 |                 var a21 = d[4],  a22 = d[5],  a23 = d[6],  a24 = d[7];
277 |                 var a31 = d[8],  a32 = d[9],  a33 = d[10], a34 = d[11];
278 |                 var a41 = d[12], a42 = d[13], a43 = d[14], a44 = d[15];
279 | 
280 |                 return this.set(
281 |                     (a22*a33*a44 + a23*a34*a42 + a24*a32*a43 - a22*a34*a43 - a23*a32*a44 - a24*a33*a42)/det,
282 |                     (a12*a34*a43 + a13*a32*a44 + a14*a33*a42 - a12*a33*a44 - a13*a34*a42 - a14*a32*a43)/det,
283 |                     (a12*a23*a44 + a13*a24*a42 + a14*a22*a43 - a12*a24*a43 - a13*a22*a44 - a14*a23*a42)/det,
284 |                     (a12*a24*a33 + a13*a22*a34 + a14*a23*a32 - a12*a23*a34 - a13*a24*a32 - a14*a22*a33)/det,
285 |                     
286 |                     (a21*a34*a43 + a23*a31*a44 + a24*a33*a41 - a21*a33*a44 - a23*a34*a41 - a24*a31*a43)/det,
287 |                     (a11*a33*a44 + a13*a34*a41 + a14*a31*a43 - a11*a34*a43 - a13*a31*a44 - a14*a33*a41)/det,
288 |                     (a11*a24*a43 + a13*a21*a44 + a14*a23*a41 - a11*a23*a44 - a13*a24*a41 - a14*a21*a43)/det,
289 |                     (a11*a23*a34 + a13*a24*a31 + a14*a21*a33 - a11*a24*a33 - a13*a21*a34 - a14*a23*a31)/det,
290 |                     
291 |                     (a21*a32*a44 + a22*a34*a41 + a24*a31*a42 - a21*a34*a42 - a22*a31*a44 - a24*a32*a41)/det,
292 |                     (a11*a34*a42 + a12*a31*a44 + a14*a32*a41 - a11*a32*a44 - a12*a34*a41 - a14*a31*a42)/det,
293 |                     (a11*a22*a44 + a12*a24*a41 + a14*a21*a42 - a11*a24*a42 - a12*a21*a44 - a14*a22*a41)/det,
294 |                     (a11*a24*a32 + a12*a21*a34 + a14*a22*a31 - a11*a22*a34 - a12*a24*a31 - a14*a21*a32)/det,
295 |                     
296 |                     (a21*a33*a42 + a22*a31*a43 + a23*a32*a41 - a21*a32*a43 - a22*a33*a41 - a23*a31*a42)/det,
297 |                     (a11*a32*a43 + a12*a33*a41 + a13*a31*a42 - a11*a33*a42 - a12*a31*a43 - a13*a32*a41)/det,
298 |                     (a11*a23*a42 + a12*a21*a43 + a13*a22*a41 - a11*a22*a43 - a12*a23*a41 - a13*a21*a42)/det,
299 |                     (a11*a22*a33 + a12*a23*a31 + a13*a21*a32 - a11*a23*a32 - a12*a21*a33 - a13*a22*a31)/det
300 |                 )
301 |             }
302 |         },
303 |         ident: function(){
304 |             return this.set(
305 |                 1, 0, 0, 0,
306 |                 0, 1, 0, 0,
307 |                 0, 0, 1, 0,
308 |                 0, 0, 0, 1
309 |             );
310 |         },
311 |         perspective: function(params){
312 |             var args = params;
313 |             //var args = $.extend(params, {fov:60, near:1, far:100});
314 |             var near = args.near;
315 |             var far = args.far;
316 | 
317 |             var angle = (args.fov/360)*Math.PI;
318 | 
319 |             var aspect = args.width/args.height;
320 |             var top = near * Math.tan(angle);
321 |             var bottom = -top;
322 |             var right = top * aspect;
323 |             var left = -right;
324 | 
325 |             var a = (2*near)/(right-left);
326 |             var b = (right+left)/(right-left);
327 |             var c = (2*near)/(top-bottom);
328 |             var d = (top+bottom)/(top-bottom);
329 |             var e = -(far+near)/(far-near);
330 |             var f = -(2*far*near)/(far-near);
331 |             var g = -1;
332 | 
333 |             return this.set(
334 |                 a, 0, b, 0,
335 |                 0, c, d, 0,
336 |                 0, 0, e, f,
337 |                 0, 0, g, 0
338 |             ).transpose();
339 |         },
340 |         inverse_perspective: function(params){
341 |             var args = params;
342 |             //var args = $.extend({fov:60, near:1, far:100}, params);
343 |             var near = args.near;
344 |             var far = args.far;
345 |             
346 |             var aspect = args.width/args.height;
347 |             var top = near * Math.tan((args.fov*Math.PI)/360.0);
348 |             var bottom = -top;
349 |             var right = top * aspect;
350 |             var left = -right;
351 | 
352 |             var a = (right-left)/(2*near)
353 |             var b = (right+left)/(2*near)
354 |             var c = (top-bottom)/(2*near)
355 |             var d = (top+bottom)/(2*near)
356 |             var e = -1
357 |             var f = -(far-near)/(2*far*near)
358 |             var g = (far+near)/(2*far*near)
359 | 
360 |             return this.set(
361 |                 a, 0, 0, b,
362 |                 0, c, 0, d,
363 |                 0, 0, 0, e,
364 |                 0, 0, f, g
365 |             ).transpose();
366 |         },
367 |         ortho: function(params){
368 |             var args = extend({near:-1, far:1, top:-1, bottom:1, left:-1, right:1}, params);
369 |             var near = args.near;
370 |             var far = args.far;
371 |             var bottom = args.bottom;
372 |             var top = args.top;
373 |             var right = args.right;
374 |             var left = args.left;
375 | 
376 |             var a = 2/(right-left)
377 |             var b = -((right+left)/(right-left))
378 |             var c = 2/(top-bottom)
379 |             var d = -((top+bottom)/(top-bottom))
380 |             var e = -2/(far-near)
381 |             var f = -((far+near)/(far-near))
382 |             var g = 1
383 | 
384 |             return this.set(
385 |                 a, 0, 0, b,
386 |                 0, c, 0, d,
387 |                 0, 0, e, f,
388 |                 0, 0, 0, g
389 |             ).transpose()
390 |         },
391 |         inverse_ortho: function(params){
392 |             var args = extend({near:-1, far:1, top:-1, bottom:1, left:-1, right:1}, params);
393 |             var near = args.near;
394 |             var far = args.far;
395 |             var bottom = args.bottom;
396 |             var top = args.top;
397 |             var right = args.right;
398 |             var left = args.left;
399 | 
400 |             var a = (right-left)/2
401 |             var b = (right+left)/2
402 |             var c = (top-bottom)/2
403 |             var d = (top+bottom)/2
404 |             var e = (far-near)/-2
405 |             var f = (near+far)/2
406 |             var g = 1
407 | 
408 |             return this.set(
409 |                 a, 0, 0, b,
410 |                 0, c, 0, d,
411 |                 0, 0, e, f,
412 |                 0, 0, 0, g
413 |             ).transpose()
414 |         },
415 |         log: function(message){
416 |             var d = this.data;
417 |             if(!message){
418 |                 message = 'Mat4';
419 |             }
420 |             console.group(message);
421 |             console.log(fmt(d[0]), fmt(d[1]), fmt(d[2]), fmt(d[3]));
422 |             console.log(fmt(d[4]), fmt(d[5]), fmt(d[6]), fmt(d[7]));
423 |             console.log(fmt(d[8]), fmt(d[9]), fmt(d[10]), fmt(d[11]));
424 |             console.log(fmt(d[12]), fmt(d[13]), fmt(d[14]), fmt(d[15]));
425 |             console.groupEnd();
426 |             return this;
427 |         },
428 | 
429 |         // operations
430 |         translate: function(x, y, z){
431 |             return this.amul(
432 |                 1, 0, 0, 0,
433 |                 0, 1, 0, 0,
434 |                 0, 0, 1, 0,
435 |                 x, y, z, 1
436 |             );
437 |         },
438 |         rotatex: function(angle){
439 |             var s = Math.sin(angle*arc);
440 |             var c = Math.cos(angle*arc);
441 |             return this.amul(
442 |                  1,  0,  0,  0,
443 |                  0,  c,  s,  0,
444 |                  0, -s,  c,  0,
445 |                  0,  0,  0,  1
446 |             );
447 |         },
448 |         rotatey: function(angle){
449 |             var s = Math.sin(angle*arc);
450 |             var c = Math.cos(angle*arc);
451 |             return this.amul(
452 |                  c,  0, -s,  0,
453 |                  0,  1,  0,  0,
454 |                  s,  0,  c,  0,
455 |                  0,  0,  0,  1
456 |             );
457 |         },
458 |         rotatez: function(angle){
459 |             var s = Math.sin(angle*arc);
460 |             var c = Math.cos(angle*arc);
461 |             return this.amul(
462 |                  c,  s,  0,  0,
463 |                 -s,  c,  0,  0,
464 |                  0,  0,  1,  0,
465 |                  0,  0,  0,  1
466 |             );
467 |         },        
468 |         scale : function(x , y, z) {            
469 |             var a = this.data;
470 |             a[0] *= x;
471 |             a[1] *= x;
472 |             a[2] *= x;
473 |             a[3] *= x;
474 |             a[4] *= y;
475 |             a[5] *= y;
476 |             a[6] *= y;
477 |             a[7] *= y;
478 |             a[8] *= z;
479 |             a[9] *= z;
480 |             a[10] *= z;
481 |             a[11] *= z;
482 |             return this;
483 |         },        
484 |         mul: function(b){
485 |             return this.lmul(b.data);
486 |         },
487 |         amul: function(
488 |             b00, b10, b20, b30,
489 |             b01, b11, b21, b31,
490 |             b02, b12, b22, b32,
491 |             b03, b13, b23, b33
492 |         ){
493 |             var a = this.data;
494 | 
495 |             var a00 = a[0];
496 |             var a10 = a[1];
497 |             var a20 = a[2];
498 |             var a30 = a[3];
499 |             
500 |             var a01 = a[4];
501 |             var a11 = a[5];
502 |             var a21 = a[6];
503 |             var a31 = a[7];
504 |             
505 |             var a02 = a[8];
506 |             var a12 = a[9];
507 |             var a22 = a[10];
508 |             var a32 = a[11];
509 |             
510 |             var a03 = a[12];
511 |             var a13 = a[13];
512 |             var a23 = a[14];
513 |             var a33 = a[15];
514 |             
515 |             a[0]  = a00*b00 + a01*b10 + a02*b20 + a03*b30;
516 |             a[1]  = a10*b00 + a11*b10 + a12*b20 + a13*b30;
517 |             a[2]  = a20*b00 + a21*b10 + a22*b20 + a23*b30;
518 |             a[3]  = a30*b00 + a31*b10 + a32*b20 + a33*b30;
519 |             
520 |             a[4]  = a00*b01 + a01*b11 + a02*b21 + a03*b31;
521 |             a[5]  = a10*b01 + a11*b11 + a12*b21 + a13*b31;
522 |             a[6]  = a20*b01 + a21*b11 + a22*b21 + a23*b31;
523 |             a[7]  = a30*b01 + a31*b11 + a32*b21 + a33*b31;
524 |             
525 |             a[8]  = a00*b02 + a01*b12 + a02*b22 + a03*b32;
526 |             a[9]  = a10*b02 + a11*b12 + a12*b22 + a13*b32;
527 |             a[10] = a20*b02 + a21*b12 + a22*b22 + a23*b32;
528 |             a[11] = a30*b02 + a31*b12 + a32*b22 + a33*b32;
529 |             
530 |             a[12] = a00*b03 + a01*b13 + a02*b23 + a03*b33;
531 |             a[13] = a10*b03 + a11*b13 + a12*b23 + a13*b33;
532 |             a[14] = a20*b03 + a21*b13 + a22*b23 + a23*b33;
533 |             a[15] = a30*b03 + a31*b13 + a32*b23 + a33*b33;
534 | 
535 |             return this;
536 |         },
537 |         lmul: function(b){
538 |             var a = this.data;
539 | 
540 |             var a00 = a[0];
541 |             var a10 = a[1];
542 |             var a20 = a[2];
543 |             var a30 = a[3];
544 |             
545 |             var a01 = a[4];
546 |             var a11 = a[5];
547 |             var a21 = a[6];
548 |             var a31 = a[7];
549 |             
550 |             var a02 = a[8];
551 |             var a12 = a[9];
552 |             var a22 = a[10];
553 |             var a32 = a[11];
554 |             
555 |             var a03 = a[12];
556 |             var a13 = a[13];
557 |             var a23 = a[14];
558 |             var a33 = a[15];
559 |             
560 |             var b00 = b[0];
561 |             var b10 = b[1];
562 |             var b20 = b[2];
563 |             var b30 = b[3];
564 |             
565 |             var b01 = b[4];
566 |             var b11 = b[5];
567 |             var b21 = b[6];
568 |             var b31 = b[7];
569 |             
570 |             var b02 = b[8];
571 |             var b12 = b[9];
572 |             var b22 = b[10];
573 |             var b32 = b[11];
574 |             
575 |             var b03 = b[12];
576 |             var b13 = b[13];
577 |             var b23 = b[14];
578 |             var b33 = b[15];
579 | 
580 |             a[0]  = a00*b00 + a01*b10 + a02*b20 + a03*b30;
581 |             a[1]  = a10*b00 + a11*b10 + a12*b20 + a13*b30;
582 |             a[2]  = a20*b00 + a21*b10 + a22*b20 + a23*b30;
583 |             a[3]  = a30*b00 + a31*b10 + a32*b20 + a33*b30;
584 |             
585 |             a[4]  = a00*b01 + a01*b11 + a02*b21 + a03*b31;
586 |             a[5]  = a10*b01 + a11*b11 + a12*b21 + a13*b31;
587 |             a[6]  = a20*b01 + a21*b11 + a22*b21 + a23*b31;
588 |             a[7]  = a30*b01 + a31*b11 + a32*b21 + a33*b31;
589 |             
590 |             a[8]  = a00*b02 + a01*b12 + a02*b22 + a03*b32;
591 |             a[9]  = a10*b02 + a11*b12 + a12*b22 + a13*b32;
592 |             a[10] = a20*b02 + a21*b12 + a22*b22 + a23*b32;
593 |             a[11] = a30*b02 + a31*b12 + a32*b22 + a33*b32;
594 |             
595 |             a[12] = a00*b03 + a01*b13 + a02*b23 + a03*b33;
596 |             a[13] = a10*b03 + a11*b13 + a12*b23 + a13*b33;
597 |             a[14] = a20*b03 + a21*b13 + a22*b23 + a23*b33;
598 |             a[15] = a30*b03 + a31*b13 + a32*b23 + a33*b33;
599 | 
600 |             return this;
601 |         },
602 |         transpose: function(){
603 |             var d = this.data;
604 |             return this.set(
605 |                 d[0], d[4], d[8], d[12],
606 |                 d[1], d[5], d[9], d[13],
607 |                 d[2], d[6], d[10], d[14],
608 |                 d[3], d[7], d[11], d[15]
609 |             );
610 |         }
611 |     };
612 |     
613 |     var tmp4 = new Mat4();
614 |     //var tmp3 = new Mat3();
615 | })();
616 | 


--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
  1 |                     GNU AFFERO GENERAL PUBLIC LICENSE
  2 |                        Version 3, 19 November 2007
  3 | 
  4 |  Copyright (C) 2007 Free Software Foundation, Inc. 
  5 |  Everyone is permitted to copy and distribute verbatim copies
  6 |  of this license document, but changing it is not allowed.
  7 | 
  8 |                             Preamble
  9 | 
 10 |   The GNU Affero General Public License is a free, copyleft license for
 11 | software and other kinds of works, specifically designed to ensure
 12 | cooperation with the community in the case of network server software.
 13 | 
 14 |   The licenses for most software and other practical works are designed
 15 | to take away your freedom to share and change the works.  By contrast,
 16 | our General Public Licenses are intended to guarantee your freedom to
 17 | share and change all versions of a program--to make sure it remains free
 18 | software for all its users.
 19 | 
 20 |   When we speak of free software, we are referring to freedom, not
 21 | price.  Our General Public Licenses are designed to make sure that you
 22 | have the freedom to distribute copies of free software (and charge for
 23 | them if you wish), that you receive source code or can get it if you
 24 | want it, that you can change the software or use pieces of it in new
 25 | free programs, and that you know you can do these things.
 26 | 
 27 |   Developers that use our General Public Licenses protect your rights
 28 | with two steps: (1) assert copyright on the software, and (2) offer
 29 | you this License which gives you legal permission to copy, distribute
 30 | and/or modify the software.
 31 | 
 32 |   A secondary benefit of defending all users' freedom is that
 33 | improvements made in alternate versions of the program, if they
 34 | receive widespread use, become available for other developers to
 35 | incorporate.  Many developers of free software are heartened and
 36 | encouraged by the resulting cooperation.  However, in the case of
 37 | software used on network servers, this result may fail to come about.
 38 | The GNU General Public License permits making a modified version and
 39 | letting the public access it on a server without ever releasing its
 40 | source code to the public.
 41 | 
 42 |   The GNU Affero General Public License is designed specifically to
 43 | ensure that, in such cases, the modified source code becomes available
 44 | to the community.  It requires the operator of a network server to
 45 | provide the source code of the modified version running there to the
 46 | users of that server.  Therefore, public use of a modified version, on
 47 | a publicly accessible server, gives the public access to the source
 48 | code of the modified version.
 49 | 
 50 |   An older license, called the Affero General Public License and
 51 | published by Affero, was designed to accomplish similar goals.  This is
 52 | a different license, not a version of the Affero GPL, but Affero has
 53 | released a new version of the Affero GPL which permits relicensing under
 54 | this license.
 55 | 
 56 |   The precise terms and conditions for copying, distribution and
 57 | modification follow.
 58 | 
 59 |                        TERMS AND CONDITIONS
 60 | 
 61 |   0. Definitions.
 62 | 
 63 |   "This License" refers to version 3 of the GNU Affero General Public License.
 64 | 
 65 |   "Copyright" also means copyright-like laws that apply to other kinds of
 66 | works, such as semiconductor masks.
 67 | 
 68 |   "The Program" refers to any copyrightable work licensed under this
 69 | License.  Each licensee is addressed as "you".  "Licensees" and
 70 | "recipients" may be individuals or organizations.
 71 | 
 72 |   To "modify" a work means to copy from or adapt all or part of the work
 73 | in a fashion requiring copyright permission, other than the making of an
 74 | exact copy.  The resulting work is called a "modified version" of the
 75 | earlier work or a work "based on" the earlier work.
 76 | 
 77 |   A "covered work" means either the unmodified Program or a work based
 78 | on the Program.
 79 | 
 80 |   To "propagate" a work means to do anything with it that, without
 81 | permission, would make you directly or secondarily liable for
 82 | infringement under applicable copyright law, except executing it on a
 83 | computer or modifying a private copy.  Propagation includes copying,
 84 | distribution (with or without modification), making available to the
 85 | public, and in some countries other activities as well.
 86 | 
 87 |   To "convey" a work means any kind of propagation that enables other
 88 | parties to make or receive copies.  Mere interaction with a user through
 89 | a computer network, with no transfer of a copy, is not conveying.
 90 | 
 91 |   An interactive user interface displays "Appropriate Legal Notices"
 92 | to the extent that it includes a convenient and prominently visible
 93 | feature that (1) displays an appropriate copyright notice, and (2)
 94 | tells the user that there is no warranty for the work (except to the
 95 | extent that warranties are provided), that licensees may convey the
 96 | work under this License, and how to view a copy of this License.  If
 97 | the interface presents a list of user commands or options, such as a
 98 | menu, a prominent item in the list meets this criterion.
 99 | 
100 |   1. Source Code.
101 | 
102 |   The "source code" for a work means the preferred form of the work
103 | for making modifications to it.  "Object code" means any non-source
104 | form of a work.
105 | 
106 |   A "Standard Interface" means an interface that either is an official
107 | standard defined by a recognized standards body, or, in the case of
108 | interfaces specified for a particular programming language, one that
109 | is widely used among developers working in that language.
110 | 
111 |   The "System Libraries" of an executable work include anything, other
112 | than the work as a whole, that (a) is included in the normal form of
113 | packaging a Major Component, but which is not part of that Major
114 | Component, and (b) serves only to enable use of the work with that
115 | Major Component, or to implement a Standard Interface for which an
116 | implementation is available to the public in source code form.  A
117 | "Major Component", in this context, means a major essential component
118 | (kernel, window system, and so on) of the specific operating system
119 | (if any) on which the executable work runs, or a compiler used to
120 | produce the work, or an object code interpreter used to run it.
121 | 
122 |   The "Corresponding Source" for a work in object code form means all
123 | the source code needed to generate, install, and (for an executable
124 | work) run the object code and to modify the work, including scripts to
125 | control those activities.  However, it does not include the work's
126 | System Libraries, or general-purpose tools or generally available free
127 | programs which are used unmodified in performing those activities but
128 | which are not part of the work.  For example, Corresponding Source
129 | includes interface definition files associated with source files for
130 | the work, and the source code for shared libraries and dynamically
131 | linked subprograms that the work is specifically designed to require,
132 | such as by intimate data communication or control flow between those
133 | subprograms and other parts of the work.
134 | 
135 |   The Corresponding Source need not include anything that users
136 | can regenerate automatically from other parts of the Corresponding
137 | Source.
138 | 
139 |   The Corresponding Source for a work in source code form is that
140 | same work.
141 | 
142 |   2. Basic Permissions.
143 | 
144 |   All rights granted under this License are granted for the term of
145 | copyright on the Program, and are irrevocable provided the stated
146 | conditions are met.  This License explicitly affirms your unlimited
147 | permission to run the unmodified Program.  The output from running a
148 | covered work is covered by this License only if the output, given its
149 | content, constitutes a covered work.  This License acknowledges your
150 | rights of fair use or other equivalent, as provided by copyright law.
151 | 
152 |   You may make, run and propagate covered works that you do not
153 | convey, without conditions so long as your license otherwise remains
154 | in force.  You may convey covered works to others for the sole purpose
155 | of having them make modifications exclusively for you, or provide you
156 | with facilities for running those works, provided that you comply with
157 | the terms of this License in conveying all material for which you do
158 | not control copyright.  Those thus making or running the covered works
159 | for you must do so exclusively on your behalf, under your direction
160 | and control, on terms that prohibit them from making any copies of
161 | your copyrighted material outside their relationship with you.
162 | 
163 |   Conveying under any other circumstances is permitted solely under
164 | the conditions stated below.  Sublicensing is not allowed; section 10
165 | makes it unnecessary.
166 | 
167 |   3. Protecting Users' Legal Rights From Anti-Circumvention Law.
168 | 
169 |   No covered work shall be deemed part of an effective technological
170 | measure under any applicable law fulfilling obligations under article
171 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
172 | similar laws prohibiting or restricting circumvention of such
173 | measures.
174 | 
175 |   When you convey a covered work, you waive any legal power to forbid
176 | circumvention of technological measures to the extent such circumvention
177 | is effected by exercising rights under this License with respect to
178 | the covered work, and you disclaim any intention to limit operation or
179 | modification of the work as a means of enforcing, against the work's
180 | users, your or third parties' legal rights to forbid circumvention of
181 | technological measures.
182 | 
183 |   4. Conveying Verbatim Copies.
184 | 
185 |   You may convey verbatim copies of the Program's source code as you
186 | receive it, in any medium, provided that you conspicuously and
187 | appropriately publish on each copy an appropriate copyright notice;
188 | keep intact all notices stating that this License and any
189 | non-permissive terms added in accord with section 7 apply to the code;
190 | keep intact all notices of the absence of any warranty; and give all
191 | recipients a copy of this License along with the Program.
192 | 
193 |   You may charge any price or no price for each copy that you convey,
194 | and you may offer support or warranty protection for a fee.
195 | 
196 |   5. Conveying Modified Source Versions.
197 | 
198 |   You may convey a work based on the Program, or the modifications to
199 | produce it from the Program, in the form of source code under the
200 | terms of section 4, provided that you also meet all of these conditions:
201 | 
202 |     a) The work must carry prominent notices stating that you modified
203 |     it, and giving a relevant date.
204 | 
205 |     b) The work must carry prominent notices stating that it is
206 |     released under this License and any conditions added under section
207 |     7.  This requirement modifies the requirement in section 4 to
208 |     "keep intact all notices".
209 | 
210 |     c) You must license the entire work, as a whole, under this
211 |     License to anyone who comes into possession of a copy.  This
212 |     License will therefore apply, along with any applicable section 7
213 |     additional terms, to the whole of the work, and all its parts,
214 |     regardless of how they are packaged.  This License gives no
215 |     permission to license the work in any other way, but it does not
216 |     invalidate such permission if you have separately received it.
217 | 
218 |     d) If the work has interactive user interfaces, each must display
219 |     Appropriate Legal Notices; however, if the Program has interactive
220 |     interfaces that do not display Appropriate Legal Notices, your
221 |     work need not make them do so.
222 | 
223 |   A compilation of a covered work with other separate and independent
224 | works, which are not by their nature extensions of the covered work,
225 | and which are not combined with it such as to form a larger program,
226 | in or on a volume of a storage or distribution medium, is called an
227 | "aggregate" if the compilation and its resulting copyright are not
228 | used to limit the access or legal rights of the compilation's users
229 | beyond what the individual works permit.  Inclusion of a covered work
230 | in an aggregate does not cause this License to apply to the other
231 | parts of the aggregate.
232 | 
233 |   6. Conveying Non-Source Forms.
234 | 
235 |   You may convey a covered work in object code form under the terms
236 | of sections 4 and 5, provided that you also convey the
237 | machine-readable Corresponding Source under the terms of this License,
238 | in one of these ways:
239 | 
240 |     a) Convey the object code in, or embodied in, a physical product
241 |     (including a physical distribution medium), accompanied by the
242 |     Corresponding Source fixed on a durable physical medium
243 |     customarily used for software interchange.
244 | 
245 |     b) Convey the object code in, or embodied in, a physical product
246 |     (including a physical distribution medium), accompanied by a
247 |     written offer, valid for at least three years and valid for as
248 |     long as you offer spare parts or customer support for that product
249 |     model, to give anyone who possesses the object code either (1) a
250 |     copy of the Corresponding Source for all the software in the
251 |     product that is covered by this License, on a durable physical
252 |     medium customarily used for software interchange, for a price no
253 |     more than your reasonable cost of physically performing this
254 |     conveying of source, or (2) access to copy the
255 |     Corresponding Source from a network server at no charge.
256 | 
257 |     c) Convey individual copies of the object code with a copy of the
258 |     written offer to provide the Corresponding Source.  This
259 |     alternative is allowed only occasionally and noncommercially, and
260 |     only if you received the object code with such an offer, in accord
261 |     with subsection 6b.
262 | 
263 |     d) Convey the object code by offering access from a designated
264 |     place (gratis or for a charge), and offer equivalent access to the
265 |     Corresponding Source in the same way through the same place at no
266 |     further charge.  You need not require recipients to copy the
267 |     Corresponding Source along with the object code.  If the place to
268 |     copy the object code is a network server, the Corresponding Source
269 |     may be on a different server (operated by you or a third party)
270 |     that supports equivalent copying facilities, provided you maintain
271 |     clear directions next to the object code saying where to find the
272 |     Corresponding Source.  Regardless of what server hosts the
273 |     Corresponding Source, you remain obligated to ensure that it is
274 |     available for as long as needed to satisfy these requirements.
275 | 
276 |     e) Convey the object code using peer-to-peer transmission, provided
277 |     you inform other peers where the object code and Corresponding
278 |     Source of the work are being offered to the general public at no
279 |     charge under subsection 6d.
280 | 
281 |   A separable portion of the object code, whose source code is excluded
282 | from the Corresponding Source as a System Library, need not be
283 | included in conveying the object code work.
284 | 
285 |   A "User Product" is either (1) a "consumer product", which means any
286 | tangible personal property which is normally used for personal, family,
287 | or household purposes, or (2) anything designed or sold for incorporation
288 | into a dwelling.  In determining whether a product is a consumer product,
289 | doubtful cases shall be resolved in favor of coverage.  For a particular
290 | product received by a particular user, "normally used" refers to a
291 | typical or common use of that class of product, regardless of the status
292 | of the particular user or of the way in which the particular user
293 | actually uses, or expects or is expected to use, the product.  A product
294 | is a consumer product regardless of whether the product has substantial
295 | commercial, industrial or non-consumer uses, unless such uses represent
296 | the only significant mode of use of the product.
297 | 
298 |   "Installation Information" for a User Product means any methods,
299 | procedures, authorization keys, or other information required to install
300 | and execute modified versions of a covered work in that User Product from
301 | a modified version of its Corresponding Source.  The information must
302 | suffice to ensure that the continued functioning of the modified object
303 | code is in no case prevented or interfered with solely because
304 | modification has been made.
305 | 
306 |   If you convey an object code work under this section in, or with, or
307 | specifically for use in, a User Product, and the conveying occurs as
308 | part of a transaction in which the right of possession and use of the
309 | User Product is transferred to the recipient in perpetuity or for a
310 | fixed term (regardless of how the transaction is characterized), the
311 | Corresponding Source conveyed under this section must be accompanied
312 | by the Installation Information.  But this requirement does not apply
313 | if neither you nor any third party retains the ability to install
314 | modified object code on the User Product (for example, the work has
315 | been installed in ROM).
316 | 
317 |   The requirement to provide Installation Information does not include a
318 | requirement to continue to provide support service, warranty, or updates
319 | for a work that has been modified or installed by the recipient, or for
320 | the User Product in which it has been modified or installed.  Access to a
321 | network may be denied when the modification itself materially and
322 | adversely affects the operation of the network or violates the rules and
323 | protocols for communication across the network.
324 | 
325 |   Corresponding Source conveyed, and Installation Information provided,
326 | in accord with this section must be in a format that is publicly
327 | documented (and with an implementation available to the public in
328 | source code form), and must require no special password or key for
329 | unpacking, reading or copying.
330 | 
331 |   7. Additional Terms.
332 | 
333 |   "Additional permissions" are terms that supplement the terms of this
334 | License by making exceptions from one or more of its conditions.
335 | Additional permissions that are applicable to the entire Program shall
336 | be treated as though they were included in this License, to the extent
337 | that they are valid under applicable law.  If additional permissions
338 | apply only to part of the Program, that part may be used separately
339 | under those permissions, but the entire Program remains governed by
340 | this License without regard to the additional permissions.
341 | 
342 |   When you convey a copy of a covered work, you may at your option
343 | remove any additional permissions from that copy, or from any part of
344 | it.  (Additional permissions may be written to require their own
345 | removal in certain cases when you modify the work.)  You may place
346 | additional permissions on material, added by you to a covered work,
347 | for which you have or can give appropriate copyright permission.
348 | 
349 |   Notwithstanding any other provision of this License, for material you
350 | add to a covered work, you may (if authorized by the copyright holders of
351 | that material) supplement the terms of this License with terms:
352 | 
353 |     a) Disclaiming warranty or limiting liability differently from the
354 |     terms of sections 15 and 16 of this License; or
355 | 
356 |     b) Requiring preservation of specified reasonable legal notices or
357 |     author attributions in that material or in the Appropriate Legal
358 |     Notices displayed by works containing it; or
359 | 
360 |     c) Prohibiting misrepresentation of the origin of that material, or
361 |     requiring that modified versions of such material be marked in
362 |     reasonable ways as different from the original version; or
363 | 
364 |     d) Limiting the use for publicity purposes of names of licensors or
365 |     authors of the material; or
366 | 
367 |     e) Declining to grant rights under trademark law for use of some
368 |     trade names, trademarks, or service marks; or
369 | 
370 |     f) Requiring indemnification of licensors and authors of that
371 |     material by anyone who conveys the material (or modified versions of
372 |     it) with contractual assumptions of liability to the recipient, for
373 |     any liability that these contractual assumptions directly impose on
374 |     those licensors and authors.
375 | 
376 |   All other non-permissive additional terms are considered "further
377 | restrictions" within the meaning of section 10.  If the Program as you
378 | received it, or any part of it, contains a notice stating that it is
379 | governed by this License along with a term that is a further
380 | restriction, you may remove that term.  If a license document contains
381 | a further restriction but permits relicensing or conveying under this
382 | License, you may add to a covered work material governed by the terms
383 | of that license document, provided that the further restriction does
384 | not survive such relicensing or conveying.
385 | 
386 |   If you add terms to a covered work in accord with this section, you
387 | must place, in the relevant source files, a statement of the
388 | additional terms that apply to those files, or a notice indicating
389 | where to find the applicable terms.
390 | 
391 |   Additional terms, permissive or non-permissive, may be stated in the
392 | form of a separately written license, or stated as exceptions;
393 | the above requirements apply either way.
394 | 
395 |   8. Termination.
396 | 
397 |   You may not propagate or modify a covered work except as expressly
398 | provided under this License.  Any attempt otherwise to propagate or
399 | modify it is void, and will automatically terminate your rights under
400 | this License (including any patent licenses granted under the third
401 | paragraph of section 11).
402 | 
403 |   However, if you cease all violation of this License, then your
404 | license from a particular copyright holder is reinstated (a)
405 | provisionally, unless and until the copyright holder explicitly and
406 | finally terminates your license, and (b) permanently, if the copyright
407 | holder fails to notify you of the violation by some reasonable means
408 | prior to 60 days after the cessation.
409 | 
410 |   Moreover, your license from a particular copyright holder is
411 | reinstated permanently if the copyright holder notifies you of the
412 | violation by some reasonable means, this is the first time you have
413 | received notice of violation of this License (for any work) from that
414 | copyright holder, and you cure the violation prior to 30 days after
415 | your receipt of the notice.
416 | 
417 |   Termination of your rights under this section does not terminate the
418 | licenses of parties who have received copies or rights from you under
419 | this License.  If your rights have been terminated and not permanently
420 | reinstated, you do not qualify to receive new licenses for the same
421 | material under section 10.
422 | 
423 |   9. Acceptance Not Required for Having Copies.
424 | 
425 |   You are not required to accept this License in order to receive or
426 | run a copy of the Program.  Ancillary propagation of a covered work
427 | occurring solely as a consequence of using peer-to-peer transmission
428 | to receive a copy likewise does not require acceptance.  However,
429 | nothing other than this License grants you permission to propagate or
430 | modify any covered work.  These actions infringe copyright if you do
431 | not accept this License.  Therefore, by modifying or propagating a
432 | covered work, you indicate your acceptance of this License to do so.
433 | 
434 |   10. Automatic Licensing of Downstream Recipients.
435 | 
436 |   Each time you convey a covered work, the recipient automatically
437 | receives a license from the original licensors, to run, modify and
438 | propagate that work, subject to this License.  You are not responsible
439 | for enforcing compliance by third parties with this License.
440 | 
441 |   An "entity transaction" is a transaction transferring control of an
442 | organization, or substantially all assets of one, or subdividing an
443 | organization, or merging organizations.  If propagation of a covered
444 | work results from an entity transaction, each party to that
445 | transaction who receives a copy of the work also receives whatever
446 | licenses to the work the party's predecessor in interest had or could
447 | give under the previous paragraph, plus a right to possession of the
448 | Corresponding Source of the work from the predecessor in interest, if
449 | the predecessor has it or can get it with reasonable efforts.
450 | 
451 |   You may not impose any further restrictions on the exercise of the
452 | rights granted or affirmed under this License.  For example, you may
453 | not impose a license fee, royalty, or other charge for exercise of
454 | rights granted under this License, and you may not initiate litigation
455 | (including a cross-claim or counterclaim in a lawsuit) alleging that
456 | any patent claim is infringed by making, using, selling, offering for
457 | sale, or importing the Program or any portion of it.
458 | 
459 |   11. Patents.
460 | 
461 |   A "contributor" is a copyright holder who authorizes use under this
462 | License of the Program or a work on which the Program is based.  The
463 | work thus licensed is called the contributor's "contributor version".
464 | 
465 |   A contributor's "essential patent claims" are all patent claims
466 | owned or controlled by the contributor, whether already acquired or
467 | hereafter acquired, that would be infringed by some manner, permitted
468 | by this License, of making, using, or selling its contributor version,
469 | but do not include claims that would be infringed only as a
470 | consequence of further modification of the contributor version.  For
471 | purposes of this definition, "control" includes the right to grant
472 | patent sublicenses in a manner consistent with the requirements of
473 | this License.
474 | 
475 |   Each contributor grants you a non-exclusive, worldwide, royalty-free
476 | patent license under the contributor's essential patent claims, to
477 | make, use, sell, offer for sale, import and otherwise run, modify and
478 | propagate the contents of its contributor version.
479 | 
480 |   In the following three paragraphs, a "patent license" is any express
481 | agreement or commitment, however denominated, not to enforce a patent
482 | (such as an express permission to practice a patent or covenant not to
483 | sue for patent infringement).  To "grant" such a patent license to a
484 | party means to make such an agreement or commitment not to enforce a
485 | patent against the party.
486 | 
487 |   If you convey a covered work, knowingly relying on a patent license,
488 | and the Corresponding Source of the work is not available for anyone
489 | to copy, free of charge and under the terms of this License, through a
490 | publicly available network server or other readily accessible means,
491 | then you must either (1) cause the Corresponding Source to be so
492 | available, or (2) arrange to deprive yourself of the benefit of the
493 | patent license for this particular work, or (3) arrange, in a manner
494 | consistent with the requirements of this License, to extend the patent
495 | license to downstream recipients.  "Knowingly relying" means you have
496 | actual knowledge that, but for the patent license, your conveying the
497 | covered work in a country, or your recipient's use of the covered work
498 | in a country, would infringe one or more identifiable patents in that
499 | country that you have reason to believe are valid.
500 | 
501 |   If, pursuant to or in connection with a single transaction or
502 | arrangement, you convey, or propagate by procuring conveyance of, a
503 | covered work, and grant a patent license to some of the parties
504 | receiving the covered work authorizing them to use, propagate, modify
505 | or convey a specific copy of the covered work, then the patent license
506 | you grant is automatically extended to all recipients of the covered
507 | work and works based on it.
508 | 
509 |   A patent license is "discriminatory" if it does not include within
510 | the scope of its coverage, prohibits the exercise of, or is
511 | conditioned on the non-exercise of one or more of the rights that are
512 | specifically granted under this License.  You may not convey a covered
513 | work if you are a party to an arrangement with a third party that is
514 | in the business of distributing software, under which you make payment
515 | to the third party based on the extent of your activity of conveying
516 | the work, and under which the third party grants, to any of the
517 | parties who would receive the covered work from you, a discriminatory
518 | patent license (a) in connection with copies of the covered work
519 | conveyed by you (or copies made from those copies), or (b) primarily
520 | for and in connection with specific products or compilations that
521 | contain the covered work, unless you entered into that arrangement,
522 | or that patent license was granted, prior to 28 March 2007.
523 | 
524 |   Nothing in this License shall be construed as excluding or limiting
525 | any implied license or other defenses to infringement that may
526 | otherwise be available to you under applicable patent law.
527 | 
528 |   12. No Surrender of Others' Freedom.
529 | 
530 |   If conditions are imposed on you (whether by court order, agreement or
531 | otherwise) that contradict the conditions of this License, they do not
532 | excuse you from the conditions of this License.  If you cannot convey a
533 | covered work so as to satisfy simultaneously your obligations under this
534 | License and any other pertinent obligations, then as a consequence you may
535 | not convey it at all.  For example, if you agree to terms that obligate you
536 | to collect a royalty for further conveying from those to whom you convey
537 | the Program, the only way you could satisfy both those terms and this
538 | License would be to refrain entirely from conveying the Program.
539 | 
540 |   13. Remote Network Interaction; Use with the GNU General Public License.
541 | 
542 |   Notwithstanding any other provision of this License, if you modify the
543 | Program, your modified version must prominently offer all users
544 | interacting with it remotely through a computer network (if your version
545 | supports such interaction) an opportunity to receive the Corresponding
546 | Source of your version by providing access to the Corresponding Source
547 | from a network server at no charge, through some standard or customary
548 | means of facilitating copying of software.  This Corresponding Source
549 | shall include the Corresponding Source for any work covered by version 3
550 | of the GNU General Public License that is incorporated pursuant to the
551 | following paragraph.
552 | 
553 |   Notwithstanding any other provision of this License, you have
554 | permission to link or combine any covered work with a work licensed
555 | under version 3 of the GNU General Public License into a single
556 | combined work, and to convey the resulting work.  The terms of this
557 | License will continue to apply to the part which is the covered work,
558 | but the work with which it is combined will remain governed by version
559 | 3 of the GNU General Public License.
560 | 
561 |   14. Revised Versions of this License.
562 | 
563 |   The Free Software Foundation may publish revised and/or new versions of
564 | the GNU Affero General Public License from time to time.  Such new versions
565 | will be similar in spirit to the present version, but may differ in detail to
566 | address new problems or concerns.
567 | 
568 |   Each version is given a distinguishing version number.  If the
569 | Program specifies that a certain numbered version of the GNU Affero General
570 | Public License "or any later version" applies to it, you have the
571 | option of following the terms and conditions either of that numbered
572 | version or of any later version published by the Free Software
573 | Foundation.  If the Program does not specify a version number of the
574 | GNU Affero General Public License, you may choose any version ever published
575 | by the Free Software Foundation.
576 | 
577 |   If the Program specifies that a proxy can decide which future
578 | versions of the GNU Affero General Public License can be used, that proxy's
579 | public statement of acceptance of a version permanently authorizes you
580 | to choose that version for the Program.
581 | 
582 |   Later license versions may give you additional or different
583 | permissions.  However, no additional obligations are imposed on any
584 | author or copyright holder as a result of your choosing to follow a
585 | later version.
586 | 
587 |   15. Disclaimer of Warranty.
588 | 
589 |   THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
590 | APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
591 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
592 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
593 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
594 | PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
595 | IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
596 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
597 | 
598 |   16. Limitation of Liability.
599 | 
600 |   IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
601 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
602 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
603 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
604 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
605 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
606 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
607 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
608 | SUCH DAMAGES.
609 | 
610 |   17. Interpretation of Sections 15 and 16.
611 | 
612 |   If the disclaimer of warranty and limitation of liability provided
613 | above cannot be given local legal effect according to their terms,
614 | reviewing courts shall apply local law that most closely approximates
615 | an absolute waiver of all civil liability in connection with the
616 | Program, unless a warranty or assumption of liability accompanies a
617 | copy of the Program in return for a fee.
618 | 
619 |                      END OF TERMS AND CONDITIONS
620 | 
621 |             How to Apply These Terms to Your New Programs
622 | 
623 |   If you develop a new program, and you want it to be of the greatest
624 | possible use to the public, the best way to achieve this is to make it
625 | free software which everyone can redistribute and change under these terms.
626 | 
627 |   To do so, attach the following notices to the program.  It is safest
628 | to attach them to the start of each source file to most effectively
629 | state the exclusion of warranty; and each file should have at least
630 | the "copyright" line and a pointer to where the full notice is found.
631 | 
632 |     
633 |     Copyright (C)   
634 | 
635 |     This program is free software: you can redistribute it and/or modify
636 |     it under the terms of the GNU Affero General Public License as published by
637 |     the Free Software Foundation, either version 3 of the License, or
638 |     (at your option) any later version.
639 | 
640 |     This program is distributed in the hope that it will be useful,
641 |     but WITHOUT ANY WARRANTY; without even the implied warranty of
642 |     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
643 |     GNU Affero General Public License for more details.
644 | 
645 |     You should have received a copy of the GNU Affero General Public License
646 |     along with this program.  If not, see .
647 | 
648 | Also add information on how to contact you by electronic and paper mail.
649 | 
650 |   If your software can interact with users remotely through a computer
651 | network, you should also make sure that it provides a way for users to
652 | get its source.  For example, if your program is a web application, its
653 | interface could display a "Source" link that leads users to an archive
654 | of the code.  There are many ways you could offer source, and different
655 | solutions will be better for different programs; see section 13 for the
656 | specific requirements.
657 | 
658 |   You should also get your employer (if you work as a programmer) or school,
659 | if any, to sign a "copyright disclaimer" for the program, if necessary.
660 | For more information on this, and how to apply and follow the GNU AGPL, see
661 | .
662 | 


--------------------------------------------------------------------------------