├── ASHIMA.md ├── LICENSE ├── README.md └── awe0.js /ASHIMA.md: -------------------------------------------------------------------------------- 1 | # Ashima webgl-engine 2 | 3 | Ashima webgl-engine (AWE) provides a thin layer of polish to the 4 | JavaScript WebGL API. The software is free and open source under the MIT 5 | Expat license which can be found in the LICENSE file. 6 | 7 | ###License 8 | [MIT Expat](http://ashimagroup.net/os/license/mit-expat) 9 | 10 | 11 | ###Tags 12 | [webGL](http://ashimagroup.net/os/tag/webgl) 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2011 Ashima Arts 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ashima webgl-engine 2 | 3 | Ashima webgl-engine (AWE) provides a thin layer of polish to the 4 | JavaScript WebGL API. The software is free and open source under the MIT 5 | Expat license which can be found in the LICENSE file. 6 | -------------------------------------------------------------------------------- /awe0.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Description : Ring 0 WebGL wrapper. 3 | * Author : Ian McEwan, Ashima Arts. 4 | * @license : Copyright (C) 2011 Ashima Arts. All rights reserved. 5 | * Distributed under the MIT License. See LICENSE file. 6 | */ 7 | 8 | var ashimaWebGLEngine0 = new function() { 9 | var A = this; 10 | var gl; 11 | 12 | function isDefined(x) { return (typeof (x) != "undefined") } 13 | function isUndefined(x) { return (typeof (x) == "undefined") } 14 | 15 | function conOut(s) { 16 | if (typeof(console)!="undefined") 17 | console.log(s ); 18 | } 19 | 20 | var glRevLookup = new Object; 21 | var protogl = window.WebGLRenderingContext; 22 | for (var i in protogl) 23 | glRevLookup[ protogl[i] ] = i ; 24 | 25 | function glThrow( s ) { 26 | var e = gl.getError(); 27 | if (e) 28 | throw (s + "(#"+e+" : "+ glRevLookup[e] +")" ); 29 | } 30 | 31 | 32 | /* 33 | * WebGL context init part 34 | */ 35 | 36 | var addEvent = (document.addEventListener) 37 | ? function (e, v, f, c) { e.addEventListener(v,f,c); } 38 | : function (e, v, f) { e.attachEvent("on"+v,f); } 39 | 40 | this.getGlContext = function (_c,ops) { 41 | var c; 42 | switch (typeof(_c)) { 43 | case "object": c = _c; break; 44 | case "string": c = document.getElementById(_c); break; 45 | default: throw "Bad type for ID. Must be object or string." 46 | } 47 | var n = [ "webgl", "experimental-webgl", "moz-webgl", "webkit-3d" ]; 48 | gl = null; 49 | if (c) { 50 | if (typeof(ops) != "undefined") { 51 | if (ops.hasOwnProperty("aweErrorFun")) 52 | addEvent(c,"webglcontextcreationerror", ops.aweErrorFun, false); 53 | if (ops.hasOwnProperty("aweLostFun") ) 54 | addEvent(c,"webglcontextlost", ops.aweLostFun, false); 55 | if (ops.hasOwnProperty("aweFoundFun") ) 56 | addEvent(c,"webglcontextrestored", ops.aweFoundFun, false); 57 | } 58 | 59 | for (var i=0; (gl = c.getContext(n[i],ops)) == null && i < n.length ; i++) 60 | {} 61 | 62 | if ( gl != null ) { 63 | gl.viewportWidth = c.width; 64 | gl.viewportHeight = c.height; 65 | gl.canvasElement = c; 66 | } 67 | } 68 | 69 | if (ops.hasOwnProperty("warningsAsErrors")) 70 | A.warningsAsErrors = true; 71 | 72 | return gl; 73 | } 74 | 75 | /* 76 | * Shader compiling. 77 | */ 78 | 79 | function compile(src,type) { 80 | if ( !gl ) 81 | throw "No current GL context."; 82 | if ( !src ) 83 | throw "Invalid or missing shader source."; 84 | if ( !type ) 85 | throw "Invalid or missing shader type."; 86 | 87 | var shader = gl.createShader(type); 88 | glThrow("Unable to create a shader"); 89 | 90 | gl.shaderSource(shader,src); 91 | glThrow("Shader source invalid"); 92 | 93 | gl.compileShader(shader); 94 | glThrow("Shader invalid"); 95 | 96 | var log = gl.getShaderInfoLog(shader); 97 | 98 | if (gl.getShaderParameter(shader, gl.COMPILE_STATUS) == false 99 | || (A.warningsAsErrors && log) ) 100 | throw ("Compile failed: " + log ); 101 | 102 | return shader; 103 | } 104 | 105 | function link(v, f) { 106 | if ( !gl ) 107 | throw "No current GL context."; 108 | var p = gl.createProgram(); 109 | if ( !p ) 110 | return ("gl.createProgram returned null!"); 111 | 112 | gl.attachShader(p, v); 113 | glThrow("Shader (vertex) invalid"); 114 | 115 | gl.attachShader(p, f); 116 | glThrow("Shader (fragment) invalid"); 117 | 118 | gl.linkProgram(p); 119 | glThrow("Program invalid"); 120 | 121 | var log = gl.getProgramInfoLog(p) ; 122 | 123 | if ( gl.getProgramParameter(p, gl.LINK_STATUS) == false 124 | || (A.warningsAsErrors && log) ) 125 | throw ("Link failed : " + log) ; 126 | 127 | p.awe_gl = gl; 128 | p.aweUse = function() { p.awe_gl.useProgram(p); } 129 | return p; 130 | } 131 | 132 | function exportNames(p) 133 | { 134 | p.aweSym = new Object; 135 | for (var i = gl.getProgramParameter(p, gl.ACTIVE_UNIFORMS);i--;) { 136 | var name = gl.getActiveUniform(p, i).name; 137 | var loc = gl.getUniformLocation(p,name); 138 | p.aweSym[''+name] = loc; 139 | } 140 | 141 | for (var i = gl.getProgramParameter(p,gl.ACTIVE_ATTRIBUTES);i--;) { 142 | var name = gl.getActiveAttrib(p, i).name ; 143 | var loc = gl.getAttribLocation(p,name) ; 144 | p.aweSym[''+name] = loc; 145 | } 146 | 147 | return p; 148 | }; 149 | 150 | function compileAndLink(vsrc, fsrc) { 151 | var vs = compile(vsrc, gl.VERTEX_SHADER); 152 | var fs = compile(fsrc, gl.FRAGMENT_SHADER); 153 | var p = link(vs, fs); 154 | 155 | return exportNames(p); 156 | } 157 | 158 | 159 | /* 160 | * Request Animation Frame. 161 | */ 162 | A.raf = window.requestAnimationFrame || 163 | window.webkitRequestAnimationFrame || 164 | window.mozRequestAnimationFrame || 165 | window.oRequestAnimationFrame || 166 | window.msRequestAnimationFrame || 167 | function(fun, elem, dt) { window.setTimeout(fun, dt); }; 168 | 169 | A.animationStart = function animationStart(fun, elem, dt, paused) { 170 | var raf = A.raf; 171 | var noloop = new Function; 172 | var loop = noloop; 173 | var F = { 174 | play: function() { 175 | if (loop==noloop) { 176 | loop = function() { 177 | if (loop!=noloop) { fun() || raf(loop,elem,dt); } 178 | }; 179 | loop(); 180 | } 181 | }, 182 | pause: function() { 183 | loop = noloop; 184 | }, 185 | isPlaying: function() { 186 | return (loop != noloop); 187 | } 188 | } 189 | if (!paused) 190 | F.play(); 191 | return F; 192 | }; 193 | /* 194 | * Texture stuff. 195 | */ 196 | 197 | this.textureCreate = function(eng) 198 | { 199 | var T = gl.createTexture(); 200 | 201 | if (eng == undefined) 202 | eng = gl.TEXTURE_2D ; 203 | 204 | function bind() { gl.bindTexture(eng, T); } 205 | function unbind() { gl.bindTexture(eng, null); } 206 | function destroy() { gl.deleteTexture(T); } 207 | 208 | function set(engnum, where) { 209 | gl.activeTexture(gl.TEXTURE0 + engnum); 210 | bind(); 211 | gl.uniform1i(where, engnum); 212 | } 213 | 214 | function params(min_f, mag_f, wrap_s, wrap_t, flip) { 215 | bind(); 216 | if (isDefined(flip)) 217 | gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flip); 218 | 219 | gl.texParameteri(eng, gl.TEXTURE_MIN_FILTER, min_f ); 220 | gl.texParameteri(eng, gl.TEXTURE_MAG_FILTER, mag_f ); 221 | gl.texParameteri(eng, gl.TEXTURE_WRAP_S, wrap_s ); 222 | gl.texParameteri(eng, gl.TEXTURE_WRAP_T, wrap_t ); 223 | } 224 | 225 | 226 | function fromArray(w, h, arr, type, fmt) { 227 | if (isUndefined(type)) 228 | type = gl.UNSIGNED_BYTE; 229 | if (isUndefined(fmt)) 230 | fmt = gl.RGBA; 231 | bind(); 232 | gl.texImage2D(eng, 0, fmt, w, h, 0, fmt, type, arr); 233 | } 234 | 235 | function fromElement(e, type) { 236 | if (isUndefined(type)) 237 | type = gl.UNSIGNED_BYTE; 238 | bind(); 239 | gl.texImage2D(eng,0, gl.RGBA, gl.RGBA, type ,e); 240 | } 241 | 242 | T.awe_gl = gl; 243 | T.awe_eng = eng; 244 | T.aweBind = bind; 245 | T.aweUnbind = unbind; 246 | T.aweDestroy = destroy; 247 | T.aweFromArray = fromArray; 248 | T.aweSet = set; 249 | T.aweFromElem = fromElement; 250 | T.aweParams = params; 251 | 252 | return T; 253 | } 254 | 255 | A.textureUnbindAll = function (g) { 256 | for (var i = 0; i < 16; ++i) { 257 | g.activeTexture(g.TEXTURE0 + i); 258 | g.bindTexture(g.TEXTURE_2D,null); 259 | } 260 | } 261 | 262 | /* 263 | * Renderbuffer stuff 264 | */ 265 | A.renderBufferCreate = function (att, width, height) { 266 | var rb = gl.createRenderbuffer(); 267 | rb.awe_gl = gl; 268 | rb.awe_eng = gl.RENDERBUFFER; 269 | rb.aweDestroy = function() { gl.deleteRenderbuffer(rb); } 270 | 271 | gl.bindRenderbuffer(gl.RENDERBUFFER, rb); 272 | gl.renderbufferStorage(gl.RENDERBUFFER, att, width, height); 273 | gl.bindRenderbuffer(gl.RENDERBUFFER, null); 274 | return rb; 275 | } 276 | 277 | /* 278 | * Framebuffer stuff 279 | */ 280 | 281 | A.frameBufferCreate = function () { 282 | var fb = gl.createFramebuffer(); 283 | 284 | fb.attachTexture = function(att, tex, level) { 285 | fb.aweAtts[att] = tex; 286 | gl.framebufferTexture2D(gl.FRAMEBUFFER, att, tex.awe_eng, tex, level); 287 | } 288 | 289 | fb.attachRenderbuffer = function(att, rb) { 290 | fb.aweAtts[att] = rb; 291 | gl.framebufferRenderbuffer(gl.FRAMEBUFFER, att, rb.awe_eng, rb); 292 | } 293 | 294 | fb.awe_gl = gl; 295 | fb.aweAtts = new Object(); 296 | fb.aweBind = function() { gl.bindFramebuffer(gl.FRAMEBUFFER, fb); } 297 | fb.aweUnBind = function() { gl.bindFramebuffer(gl.FRAMEBUFFER, null); } 298 | fb.aweUnbind = unbind; 299 | fb.aweDestroy = function() { gl.deleteFramebuffer(fb); } 300 | 301 | return fb; 302 | } 303 | 304 | /* 305 | * Array buffers. 306 | */ 307 | A.makeBuffer = function(buftype, datatype, stride, hint, arr) { 308 | var b = gl.createBuffer(); 309 | var warr; 310 | var N = arr.length / stride; 311 | 312 | if (datatype == gl.FLOAT) 313 | warr = new Float32Array(arr) 314 | else if (datatype == gl.UNSIGNED_SHORT) 315 | warr = new Uint16Array(arr) 316 | else 317 | throw "Unsuported buffer type."; 318 | function bind() { gl.bindBuffer(buftype, b); } 319 | function unbind() { gl.bindBuffer(buftype, null); } 320 | 321 | bind(); 322 | gl.bufferData(buftype, warr, hint); 323 | unbind(); 324 | 325 | b.awe_gl = gl; 326 | b.aweNumItems = N; 327 | b.aweStride = stride; 328 | b.aweDType = datatype; 329 | b.aweBType = buftype; 330 | b.aweBind = bind; 331 | b.aweUnbind = unbind; 332 | b.aweSetVertexAttPtr = function (where,x,y) { 333 | if (buftype != gl.ARRAY_BUFFER) 334 | throw("set vertex attributes must be of ARRAY_BUFFER type"); 335 | else { 336 | bind(); 337 | gl.vertexAttribPointer(where, stride, datatype, false, x, y); 338 | gl.enableVertexAttribArray(where); 339 | } 340 | } 341 | 342 | b.drawElements = function (type,n) { // should make this have start,end 343 | if (buftype != gl.ELEMENT_ARRAY_BUFFER) 344 | throw("draw elements must must be of ELEMENT_ARRAY_BUFFER type"); 345 | else { 346 | gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, b); 347 | gl.drawElements(type, (n || N*stride), datatype, 0 ); 348 | } 349 | } 350 | 351 | return b; 352 | } 353 | 354 | A.glThrow = glThrow; 355 | A.exportNames = exportNames ; 356 | A.compile = compile ; 357 | A.link = link ; 358 | A.compileAndLink = compileAndLink; 359 | }; 360 | 361 | --------------------------------------------------------------------------------