├── README.md ├── bower.json ├── package.json └── OESVertexArrayObject-polyfill.js /README.md: -------------------------------------------------------------------------------- 1 | # oes-vertex-array-object polyfill 2 | 3 | This is from the [Khronos WebGL repo](https://github.com/KhronosGroup/WebGL/blob/master/sdk/demos/google/resources/OESVertexArrayObject.js) just slightly modified 4 | to just work rather than need explicit initialization. 5 | 6 | Just include it on your page and assume getting the extension will succeed. 7 | 8 | Also available in npm and bower 9 | 10 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "oes-vertex-attrib-array-polyfill", 3 | "version": "1.0.1", 4 | "homepage": "https://github.com/greggman/oes-vertex-attrib-array-polyfill", 5 | "authors": [ 6 | "Google" 7 | ], 8 | "description": "OES_vertex_array_object polyfill for GPUs/drivers/browsers missing it", 9 | "main": "OESVertexArrayObject-polyfill.js", 10 | "moduleType": [ 11 | "globals" 12 | ], 13 | "keywords": [ 14 | "WebGL", 15 | "OES_vertex_array_object" 16 | ], 17 | "license": "MIT", 18 | "ignore": [ 19 | "package.json" 20 | ] 21 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "oes-vertex-attrib-array-polyfill", 3 | "version": "1.0.1", 4 | "description": "OES_vertex_array_object polyfill for GPUs/drivers/browsers missing it", 5 | "main": "OESVertexArrayObject-polyfill.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/greggman/oes-vertex-array-object-polyfill.git" 12 | }, 13 | "keywords": [ 14 | "WebGL", 15 | "OES_vertex_array_object" 16 | ], 17 | "files": [ 18 | "OESVertexArrayObject-polyfill.js" 19 | ], 20 | "author": "Google", 21 | "license": "MIT", 22 | "bugs": { 23 | "url": "https://github.com/greggman/oes-vertex-array-object-polyfill/issues" 24 | }, 25 | "homepage": "https://github.com/greggman/oes-vertex-array-object-polyfill#readme" 26 | } 27 | -------------------------------------------------------------------------------- /OESVertexArrayObject-polyfill.js: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2015 The Khronos Group Inc. 3 | ** 4 | ** Permission is hereby granted, free of charge, to any person obtaining a 5 | ** copy of this software and/or associated documentation files (the 6 | ** "Materials"), to deal in the Materials without restriction, including 7 | ** without limitation the rights to use, copy, modify, merge, publish, 8 | ** distribute, sublicense, and/or sell copies of the Materials, and to 9 | ** permit persons to whom the Materials are furnished to do so, subject to 10 | ** the following conditions: 11 | ** 12 | ** The above copyright notice and this permission notice shall be included 13 | ** in all copies or substantial portions of the Materials. 14 | ** 15 | ** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 22 | */ 23 | (function() { 24 | "use strict"; 25 | 26 | var glErrorShadow = { }; 27 | 28 | function error(msg) { 29 | if (window.console && window.console.error) { 30 | window.console.error(msg); 31 | } 32 | } 33 | 34 | function log(msg) { 35 | if (window.console && window.console.log) { 36 | window.console.log(msg); 37 | } 38 | } 39 | 40 | function synthesizeGLError(err, opt_msg) { 41 | glErrorShadow[err] = true; 42 | if (opt_msg !== undefined) { 43 | error(opt_msg) 44 | } 45 | } 46 | 47 | function wrapGLError(gl) { 48 | var f = gl.getError; 49 | gl.getError = function() { 50 | var err; 51 | do { 52 | err = f.apply(gl); 53 | if (err != gl.NO_ERROR) { 54 | glErrorShadow[err] = true; 55 | } 56 | } while (err != gl.NO_ERROR); 57 | for (var err in glErrorShadow) { 58 | if (glErrorShadow[err]) { 59 | delete glErrorShadow[err]; 60 | return parseInt(err); 61 | } 62 | } 63 | return gl.NO_ERROR; 64 | }; 65 | } 66 | 67 | var WebGLVertexArrayObjectOES = function WebGLVertexArrayObjectOES(ext) { 68 | var gl = ext.gl; 69 | 70 | this.ext = ext; 71 | this.isAlive = true; 72 | this.hasBeenBound = false; 73 | 74 | this.elementArrayBuffer = null; 75 | this.attribs = new Array(ext.maxVertexAttribs); 76 | for (var n = 0; n < this.attribs.length; n++) { 77 | var attrib = new WebGLVertexArrayObjectOES.VertexAttrib(gl); 78 | this.attribs[n] = attrib; 79 | } 80 | 81 | this.maxAttrib = 0; 82 | }; 83 | 84 | WebGLVertexArrayObjectOES.VertexAttrib = function VertexAttrib(gl) { 85 | this.enabled = false; 86 | this.buffer = null; 87 | this.size = 4; 88 | this.type = gl.FLOAT; 89 | this.normalized = false; 90 | this.stride = 16; 91 | this.offset = 0; 92 | 93 | this.cached = ""; 94 | this.recache(); 95 | }; 96 | WebGLVertexArrayObjectOES.VertexAttrib.prototype.recache = function recache() { 97 | this.cached = [this.size, this.type, this.normalized, this.stride, this.offset].join(":"); 98 | }; 99 | 100 | var OESVertexArrayObject = function OESVertexArrayObject(gl) { 101 | var self = this; 102 | this.gl = gl; 103 | 104 | wrapGLError(gl); 105 | 106 | var original = this.original = { 107 | getParameter: gl.getParameter, 108 | enableVertexAttribArray: gl.enableVertexAttribArray, 109 | disableVertexAttribArray: gl.disableVertexAttribArray, 110 | bindBuffer: gl.bindBuffer, 111 | getVertexAttrib: gl.getVertexAttrib, 112 | vertexAttribPointer: gl.vertexAttribPointer 113 | }; 114 | 115 | gl.getParameter = function getParameter(pname) { 116 | if (pname == self.VERTEX_ARRAY_BINDING_OES) { 117 | if (self.currentVertexArrayObject == self.defaultVertexArrayObject) { 118 | return null; 119 | } else { 120 | return self.currentVertexArrayObject; 121 | } 122 | } 123 | return original.getParameter.apply(this, arguments); 124 | }; 125 | 126 | gl.enableVertexAttribArray = function enableVertexAttribArray(index) { 127 | var vao = self.currentVertexArrayObject; 128 | vao.maxAttrib = Math.max(vao.maxAttrib, index); 129 | var attrib = vao.attribs[index]; 130 | attrib.enabled = true; 131 | return original.enableVertexAttribArray.apply(this, arguments); 132 | }; 133 | gl.disableVertexAttribArray = function disableVertexAttribArray(index) { 134 | var vao = self.currentVertexArrayObject; 135 | vao.maxAttrib = Math.max(vao.maxAttrib, index); 136 | var attrib = vao.attribs[index]; 137 | attrib.enabled = false; 138 | return original.disableVertexAttribArray.apply(this, arguments); 139 | }; 140 | 141 | gl.bindBuffer = function bindBuffer(target, buffer) { 142 | switch (target) { 143 | case gl.ARRAY_BUFFER: 144 | self.currentArrayBuffer = buffer; 145 | break; 146 | case gl.ELEMENT_ARRAY_BUFFER: 147 | self.currentVertexArrayObject.elementArrayBuffer = buffer; 148 | break; 149 | } 150 | return original.bindBuffer.apply(this, arguments); 151 | }; 152 | 153 | gl.getVertexAttrib = function getVertexAttrib(index, pname) { 154 | var vao = self.currentVertexArrayObject; 155 | var attrib = vao.attribs[index]; 156 | switch (pname) { 157 | case gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: 158 | return attrib.buffer; 159 | case gl.VERTEX_ATTRIB_ARRAY_ENABLED: 160 | return attrib.enabled; 161 | case gl.VERTEX_ATTRIB_ARRAY_SIZE: 162 | return attrib.size; 163 | case gl.VERTEX_ATTRIB_ARRAY_STRIDE: 164 | return attrib.stride; 165 | case gl.VERTEX_ATTRIB_ARRAY_TYPE: 166 | return attrib.type; 167 | case gl.VERTEX_ATTRIB_ARRAY_NORMALIZED: 168 | return attrib.normalized; 169 | default: 170 | return original.getVertexAttrib.apply(this, arguments); 171 | } 172 | }; 173 | 174 | gl.vertexAttribPointer = function vertexAttribPointer(indx, size, type, normalized, stride, offset) { 175 | var vao = self.currentVertexArrayObject; 176 | vao.maxAttrib = Math.max(vao.maxAttrib, indx); 177 | var attrib = vao.attribs[indx]; 178 | attrib.buffer = self.currentArrayBuffer; 179 | attrib.size = size; 180 | attrib.type = type; 181 | attrib.normalized = normalized; 182 | attrib.stride = stride; 183 | attrib.offset = offset; 184 | attrib.recache(); 185 | return original.vertexAttribPointer.apply(this, arguments); 186 | }; 187 | 188 | if (gl.instrumentExtension) { 189 | gl.instrumentExtension(this, "OES_vertex_array_object"); 190 | } 191 | 192 | gl.canvas.addEventListener('webglcontextrestored', function() { 193 | log("OESVertexArrayObject emulation library context restored"); 194 | self.reset_(); 195 | }, true); 196 | 197 | this.reset_(); 198 | }; 199 | 200 | OESVertexArrayObject.prototype.VERTEX_ARRAY_BINDING_OES = 0x85B5; 201 | 202 | OESVertexArrayObject.prototype.reset_ = function reset_() { 203 | var contextWasLost = this.vertexArrayObjects !== undefined; 204 | if (contextWasLost) { 205 | for (var ii = 0; ii < this.vertexArrayObjects.length; ++ii) { 206 | this.vertexArrayObjects.isAlive = false; 207 | } 208 | } 209 | var gl = this.gl; 210 | this.maxVertexAttribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS); 211 | 212 | this.defaultVertexArrayObject = new WebGLVertexArrayObjectOES(this); 213 | this.currentVertexArrayObject = null; 214 | this.currentArrayBuffer = null; 215 | this.vertexArrayObjects = [this.defaultVertexArrayObject]; 216 | 217 | this.bindVertexArrayOES(null); 218 | }; 219 | 220 | OESVertexArrayObject.prototype.createVertexArrayOES = function createVertexArrayOES() { 221 | var arrayObject = new WebGLVertexArrayObjectOES(this); 222 | this.vertexArrayObjects.push(arrayObject); 223 | return arrayObject; 224 | }; 225 | 226 | OESVertexArrayObject.prototype.deleteVertexArrayOES = function deleteVertexArrayOES(arrayObject) { 227 | arrayObject.isAlive = false; 228 | this.vertexArrayObjects.splice(this.vertexArrayObjects.indexOf(arrayObject), 1); 229 | if (this.currentVertexArrayObject == arrayObject) { 230 | this.bindVertexArrayOES(null); 231 | } 232 | }; 233 | 234 | OESVertexArrayObject.prototype.isVertexArrayOES = function isVertexArrayOES(arrayObject) { 235 | if (arrayObject && arrayObject instanceof WebGLVertexArrayObjectOES) { 236 | if (arrayObject.hasBeenBound && arrayObject.ext == this) { 237 | return true; 238 | } 239 | } 240 | return false; 241 | }; 242 | 243 | OESVertexArrayObject.prototype.bindVertexArrayOES = function bindVertexArrayOES(arrayObject) { 244 | var gl = this.gl; 245 | if (arrayObject && !arrayObject.isAlive) { 246 | synthesizeGLError(gl.INVALID_OPERATION, "bindVertexArrayOES: attempt to bind deleted arrayObject"); 247 | return; 248 | } 249 | var original = this.original; 250 | 251 | var oldVAO = this.currentVertexArrayObject; 252 | this.currentVertexArrayObject = arrayObject || this.defaultVertexArrayObject; 253 | this.currentVertexArrayObject.hasBeenBound = true; 254 | var newVAO = this.currentVertexArrayObject; 255 | 256 | if (oldVAO == newVAO) { 257 | return; 258 | } 259 | 260 | if (!oldVAO || newVAO.elementArrayBuffer != oldVAO.elementArrayBuffer) { 261 | original.bindBuffer.call(gl, gl.ELEMENT_ARRAY_BUFFER, newVAO.elementArrayBuffer); 262 | } 263 | 264 | var currentBinding = this.currentArrayBuffer; 265 | var maxAttrib = Math.max(oldVAO ? oldVAO.maxAttrib : 0, newVAO.maxAttrib); 266 | for (var n = 0; n <= maxAttrib; n++) { 267 | var attrib = newVAO.attribs[n]; 268 | var oldAttrib = oldVAO ? oldVAO.attribs[n] : null; 269 | 270 | if (!oldVAO || attrib.enabled != oldAttrib.enabled) { 271 | if (attrib.enabled) { 272 | original.enableVertexAttribArray.call(gl, n); 273 | } else { 274 | original.disableVertexAttribArray.call(gl, n); 275 | } 276 | } 277 | 278 | if (attrib.enabled) { 279 | var bufferChanged = false; 280 | if (!oldVAO || attrib.buffer != oldAttrib.buffer) { 281 | if (currentBinding != attrib.buffer) { 282 | original.bindBuffer.call(gl, gl.ARRAY_BUFFER, attrib.buffer); 283 | currentBinding = attrib.buffer; 284 | } 285 | bufferChanged = true; 286 | } 287 | 288 | if (bufferChanged || attrib.cached != oldAttrib.cached) { 289 | original.vertexAttribPointer.call(gl, n, attrib.size, attrib.type, attrib.normalized, attrib.stride, attrib.offset); 290 | } 291 | } 292 | } 293 | 294 | if (this.currentArrayBuffer != currentBinding) { 295 | original.bindBuffer.call(gl, gl.ARRAY_BUFFER, this.currentArrayBuffer); 296 | } 297 | }; 298 | 299 | 300 | function setupVertexArrayObject() { 301 | var original_getSupportedExtensions = WebGLRenderingContext.prototype.getSupportedExtensions; 302 | WebGLRenderingContext.prototype.getSupportedExtensions = function getSupportedExtensions() { 303 | var list = original_getSupportedExtensions.call(this) || []; 304 | if (list.indexOf("OES_vertex_array_object") < 0) { 305 | list.push("OES_vertex_array_object"); 306 | } 307 | return list; 308 | }; 309 | 310 | var original_getExtension = WebGLRenderingContext.prototype.getExtension; 311 | WebGLRenderingContext.prototype.getExtension = function getExtension(name) { 312 | var ext = original_getExtension.call(this, name); 313 | if (ext) { 314 | return ext; 315 | } 316 | if (name !== "OES_vertex_array_object") { 317 | return null; 318 | } 319 | 320 | if (!this.__OESVertexArrayObject) { 321 | console.log("Setup OES_vertex_array_object polyfill"); 322 | this.__OESVertexArrayObject = new OESVertexArrayObject(this); 323 | } 324 | return this.__OESVertexArrayObject; 325 | }; 326 | } 327 | 328 | if (typeof WebGLRenderingContext !== 'undefined') { 329 | setupVertexArrayObject(); 330 | } 331 | 332 | }()); 333 | --------------------------------------------------------------------------------