1 /** 2 * The MIT License (MIT) 3 * 4 * Copyright (c) 2016 DeNA Co., Ltd. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 */ 24 25 /// <reference path="base.js"/> 26 /// <reference path="renderer.js"/> 27 /// <reference path="bounding_box.js"/> 28 /// <reference path="color.js"/> 29 /// <reference path="counter.js"/> 30 /// <reference path="config.js"/> 31 32 /** 33 * A class that implements the createjs.Renderer interface with the WebGL API. 34 * @param {HTMLCanvasElement} canvas 35 * @param {Object} context 36 * @param {createjs.BoundingBox} viewport 37 * @extends {createjs.Renderer} 38 * @implements {EventListener} 39 * @constructor 40 */ 41 createjs.WebGLRenderer = function(canvas, context, viewport) { 42 /// <param type="HTMLCanvasElement" name="canvas"/> 43 /// <param type="Object" name="context"/> 44 /// <param type="createjs.BoundingBox" name="viewport"/> 45 createjs.Renderer.call(this, canvas, canvas.width, canvas.height); 46 47 /** 48 * The rendering context attached to the output <canvas> element. 49 * @type {createjs.WebGLRenderer.Context} 50 * @private 51 */ 52 this.context_ = new createjs.WebGLRenderer.Context( 53 /** @type {WebGLRenderingContext} */ (context)); 54 55 /** 56 * The horizontal scale that converts an x position of Canvas 2D, i.e. 57 * [0,width), to one of WebGL, i.e. [-1,1]. 58 * @type {number} 59 * @private 60 */ 61 this.scaleX_ = 2 / this.getWidth(); 62 63 /** 64 * The vertical scale that converts a y position of Canvas 2D, i.e. 65 * [0,height), to one of WebGL, i.e. [-1,1]. 66 * @type {number} 67 * @private 68 */ 69 this.scaleY_ = 2 / this.getHeight(); 70 71 /** 72 * The viewport rectangle specified by a game. (This rectangle is used for 73 * rendering only the specified part of the output <canvas> element.) 74 * @type {createjs.BoundingBox} 75 * @private 76 */ 77 this.viewport_ = viewport; 78 79 // Listen the context events of WebGL. 80 canvas.addEventListener('webglcontextlost', this, false); 81 canvas.addEventListener('webglcontextrestored', this, false); 82 if (createjs.DEBUG) { 83 document.addEventListener('keyup', this, false); 84 } 85 86 // Write the context used by this renderer. 87 canvas.setAttribute('dena-context', createjs.WebGLRenderer.context); 88 89 // Set the given viewport rectangle to the scissor rectangle now so this 90 // renderer can render only its inside. 91 if (viewport) { 92 this.context_.enableClip(); 93 this.context_.updateClip(viewport, this.getHeight()); 94 } 95 }; 96 createjs.inherits('WebGLRenderer', createjs.WebGLRenderer, createjs.Renderer); 97 98 /** 99 * The context name for retrieving a WebGLRenderingContext object. 100 * @type {string} 101 */ 102 createjs.WebGLRenderer.context = ''; 103 104 /** 105 * An ID assigned to createjs.WebGLRenderer.Context objects. 106 * @type {number} 107 */ 108 createjs.WebGLRenderer.id = 0; 109 110 /** 111 * The clipping rectangle of an object. 112 * @type {createjs.BoundingBox} 113 * @private 114 */ 115 createjs.WebGLRenderer.prototype.scissor_ = null; 116 117 /** 118 * The shader program (and its variables) that draws images onto the drawing 119 * buffer (or an off-screen framebuffer). 120 * @type {createjs.WebGLRenderer.Program} 121 * @private 122 */ 123 createjs.WebGLRenderer.prototype.program_ = null; 124 125 /** 126 * Whether this renderer has render objects. 127 * @type {boolean} 128 * @private 129 */ 130 createjs.WebGLRenderer.prototype.dirty_ = false; 131 132 /** 133 * An off-screen framebuffer that draws masked objects. 134 * @type {createjs.WebGLRenderer.Frame} 135 * @private 136 */ 137 createjs.WebGLRenderer.prototype.mask_ = null; 138 139 if (createjs.DEBUG) { 140 /** 141 * The interval period or the FPS of the 'createjs.Ticker' object. 142 * @type {number} 143 * @private 144 */ 145 createjs.WebGLRenderer.ticker_ = 0; 146 } 147 148 /** 149 * Constants used by WebGL. These constants are copied from the 150 * WebGLRenderingContext interface so the closure compiler can inline them. 151 * (Although it is dirty to use numbers, it is faster to use numbers than to 152 * read object properties.) 153 * @enum {number} 154 * @const 155 */ 156 createjs.WebGLRenderer.gl = { 157 /* ClearBufferMask */ 158 DEPTH_BUFFER_BIT: 0x00000100, 159 STENCIL_BUFFER_BIT: 0x00000400, 160 COLOR_BUFFER_BIT: 0x00004000, 161 162 /* BeginMode */ 163 POINTS: 0x0000, 164 LINES: 0x0001, 165 LINE_LOOP: 0x0002, 166 LINE_STRIP: 0x0003, 167 TRIANGLES: 0x0004, 168 TRIANGLE_STRIP: 0x0005, 169 TRIANGLE_FAN: 0x0006, 170 171 /* BlendingFactor */ 172 ZERO: 0, 173 ONE: 1, 174 SRC_COLOR: 0x0300, 175 ONE_MINUS_SRC_COLOR: 0x0301, 176 SRC_ALPHA: 0x0302, 177 ONE_MINUS_SRC_ALPHA: 0x0303, 178 DST_ALPHA: 0x0304, 179 ONE_MINUS_DST_ALPHA: 0x0305, 180 DST_COLOR: 0x0306, 181 ONE_MINUS_DST_COLOR: 0x0307, 182 SRC_ALPHA_SATURATE: 0x0308, 183 184 /* BlendEquationSeparate */ 185 FUNC_ADD: 0x8006, 186 BLEND_EQUATION: 0x8009, 187 BLEND_EQUATION_RGB: 0x8009, /* same as BLEND_EQUATION */ 188 BLEND_EQUATION_ALPHA: 0x883D, 189 190 /* BlendSubtract */ 191 FUNC_SUBTRACT: 0x800A, 192 FUNC_REVERSE_SUBTRACT: 0x800B, 193 194 /* Separate Blend Functions */ 195 BLEND_DST_RGB: 0x80C8, 196 BLEND_SRC_RGB: 0x80C9, 197 BLEND_DST_ALPHA: 0x80CA, 198 BLEND_SRC_ALPHA: 0x80CB, 199 CONSTANT_COLOR: 0x8001, 200 ONE_MINUS_CONSTANT_COLOR: 0x8002, 201 CONSTANT_ALPHA: 0x8003, 202 ONE_MINUS_CONSTANT_ALPHA: 0x8004, 203 BLEND_COLOR: 0x8005, 204 205 /* Buffer Objects */ 206 ARRAY_BUFFER: 0x8892, 207 ELEMENT_ARRAY_BUFFER: 0x8893, 208 ARRAY_BUFFER_BINDING: 0x8894, 209 ELEMENT_ARRAY_BUFFER_BINDING: 0x8895, 210 211 STREAM_DRAW: 0x88E0, 212 STATIC_DRAW: 0x88E4, 213 DYNAMIC_DRAW: 0x88E8, 214 215 BUFFER_SIZE: 0x8764, 216 BUFFER_USAGE: 0x8765, 217 218 CURRENT_VERTEX_ATTRIB: 0x8626, 219 220 /* CullFaceMode */ 221 FRONT: 0x0404, 222 BACK: 0x0405, 223 FRONT_AND_BACK: 0x0408, 224 225 /* DepthFunction */ 226 /* NEVER: 0x0200, */ 227 /* LESS: 0x0201, */ 228 /* EQUAL: 0x0202, */ 229 /* LEQUAL: 0x0203, */ 230 /* GREATER: 0x0204, */ 231 /* NOTEQUAL: 0x0205, */ 232 /* GEQUAL: 0x0206, */ 233 /* ALWAYS: 0x0207, */ 234 235 /* EnableCap */ 236 /* TEXTURE_2D: 0x0DE1, */ 237 CULL_FACE: 0x0B44, 238 BLEND: 0x0BE2, 239 DITHER: 0x0BD0, 240 STENCIL_TEST: 0x0B90, 241 DEPTH_TEST: 0x0B71, 242 SCISSOR_TEST: 0x0C11, 243 POLYGON_OFFSET_FILL: 0x8037, 244 SAMPLE_ALPHA_TO_COVERAGE: 0x809E, 245 SAMPLE_COVERAGE: 0x80A0, 246 247 /* ErrorCode */ 248 NO_ERROR: 0, 249 INVALID_ENUM: 0x0500, 250 INVALID_VALUE: 0x0501, 251 INVALID_OPERATION: 0x0502, 252 OUT_OF_MEMORY: 0x0505, 253 254 /* FrontFaceDirection */ 255 CW: 0x0900, 256 CCW: 0x0901, 257 258 /* GetPName */ 259 LINE_WIDTH: 0x0B21, 260 ALIASED_POINT_SIZE_RANGE: 0x846D, 261 ALIASED_LINE_WIDTH_RANGE: 0x846E, 262 CULL_FACE_MODE: 0x0B45, 263 FRONT_FACE: 0x0B46, 264 DEPTH_RANGE: 0x0B70, 265 DEPTH_WRITEMASK: 0x0B72, 266 DEPTH_CLEAR_VALUE: 0x0B73, 267 DEPTH_FUNC: 0x0B74, 268 STENCIL_CLEAR_VALUE: 0x0B91, 269 STENCIL_FUNC: 0x0B92, 270 STENCIL_FAIL: 0x0B94, 271 STENCIL_PASS_DEPTH_FAIL: 0x0B95, 272 STENCIL_PASS_DEPTH_PASS: 0x0B96, 273 STENCIL_REF: 0x0B97, 274 STENCIL_VALUE_MASK: 0x0B93, 275 STENCIL_WRITEMASK: 0x0B98, 276 STENCIL_BACK_FUNC: 0x8800, 277 STENCIL_BACK_FAIL: 0x8801, 278 STENCIL_BACK_PASS_DEPTH_FAIL: 0x8802, 279 STENCIL_BACK_PASS_DEPTH_PASS: 0x8803, 280 STENCIL_BACK_REF: 0x8CA3, 281 STENCIL_BACK_VALUE_MASK: 0x8CA4, 282 STENCIL_BACK_WRITEMASK: 0x8CA5, 283 VIEWPORT: 0x0BA2, 284 SCISSOR_BOX: 0x0C10, 285 /* SCISSOR_TEST: 0x0C11, */ 286 COLOR_CLEAR_VALUE: 0x0C22, 287 COLOR_WRITEMASK: 0x0C23, 288 UNPACK_ALIGNMENT: 0x0CF5, 289 PACK_ALIGNMENT: 0x0D05, 290 MAX_TEXTURE_SIZE: 0x0D33, 291 MAX_VIEWPORT_DIMS: 0x0D3A, 292 SUBPIXEL_BITS: 0x0D50, 293 RED_BITS: 0x0D52, 294 GREEN_BITS: 0x0D53, 295 BLUE_BITS: 0x0D54, 296 ALPHA_BITS: 0x0D55, 297 DEPTH_BITS: 0x0D56, 298 STENCIL_BITS: 0x0D57, 299 POLYGON_OFFSET_UNITS: 0x2A00, 300 /* POLYGON_OFFSET_FILL: 0x8037, */ 301 POLYGON_OFFSET_FACTOR: 0x8038, 302 TEXTURE_BINDING_2D: 0x8069, 303 SAMPLE_BUFFERS: 0x80A8, 304 SAMPLES: 0x80A9, 305 SAMPLE_COVERAGE_VALUE: 0x80AA, 306 SAMPLE_COVERAGE_INVERT: 0x80AB, 307 308 /* DataType */ 309 BYTE: 0x1400, 310 UNSIGNED_BYTE: 0x1401, 311 SHORT: 0x1402, 312 UNSIGNED_SHORT: 0x1403, 313 INT: 0x1404, 314 UNSIGNED_INT: 0x1405, 315 FLOAT: 0x1406, 316 317 /* PixelFormat */ 318 DEPTH_COMPONENT: 0x1902, 319 ALPHA: 0x1906, 320 RGB: 0x1907, 321 RGBA: 0x1908, 322 LUMINANCE: 0x1909, 323 LUMINANCE_ALPHA: 0x190A, 324 325 /* PixelType */ 326 /* UNSIGNED_BYTE: 0x1401, */ 327 UNSIGNED_SHORT_4_4_4_4: 0x8033, 328 UNSIGNED_SHORT_5_5_5_1: 0x8034, 329 UNSIGNED_SHORT_5_6_5: 0x8363, 330 331 /* Shaders */ 332 FRAGMENT_SHADER: 0x8B30, 333 VERTEX_SHADER: 0x8B31, 334 MAX_VERTEX_ATTRIBS: 0x8869, 335 MAX_VERTEX_UNIFORM_VECTORS: 0x8DFB, 336 MAX_VARYING_VECTORS: 0x8DFC, 337 MAX_COMBINED_TEXTURE_IMAGE_UNITS: 0x8B4D, 338 MAX_VERTEX_TEXTURE_IMAGE_UNITS: 0x8B4C, 339 MAX_TEXTURE_IMAGE_UNITS: 0x8872, 340 MAX_FRAGMENT_UNIFORM_VECTORS: 0x8DFD, 341 SHADER_TYPE: 0x8B4F, 342 DELETE_STATUS: 0x8B80, 343 LINK_STATUS: 0x8B82, 344 VALIDATE_STATUS: 0x8B83, 345 ATTACHED_SHADERS: 0x8B85, 346 ACTIVE_UNIFORMS: 0x8B86, 347 ACTIVE_ATTRIBUTES: 0x8B89, 348 SHADING_LANGUAGE_VERSION: 0x8B8C, 349 CURRENT_PROGRAM: 0x8B8D, 350 351 /* StencilFunction */ 352 NEVER: 0x0200, 353 LESS: 0x0201, 354 EQUAL: 0x0202, 355 LEQUAL: 0x0203, 356 GREATER: 0x0204, 357 NOTEQUAL: 0x0205, 358 GEQUAL: 0x0206, 359 ALWAYS: 0x0207, 360 361 /* StencilOp */ 362 /* ZERO: 0, */ 363 KEEP: 0x1E00, 364 REPLACE: 0x1E01, 365 INCR: 0x1E02, 366 DECR: 0x1E03, 367 INVERT: 0x150A, 368 INCR_WRAP: 0x8507, 369 DECR_WRAP: 0x8508, 370 371 /* StringName */ 372 VENDOR: 0x1F00, 373 RENDERER: 0x1F01, 374 VERSION: 0x1F02, 375 376 /* TextureMagFilter */ 377 NEAREST: 0x2600, 378 LINEAR: 0x2601, 379 380 /* TextureMinFilter */ 381 /* NEAREST: 0x2600, */ 382 /* LINEAR: 0x2601, */ 383 NEAREST_MIPMAP_NEAREST: 0x2700, 384 LINEAR_MIPMAP_NEAREST: 0x2701, 385 NEAREST_MIPMAP_LINEAR: 0x2702, 386 LINEAR_MIPMAP_LINEAR: 0x2703, 387 388 /* TextureParameterName */ 389 TEXTURE_MAG_FILTER: 0x2800, 390 TEXTURE_MIN_FILTER: 0x2801, 391 TEXTURE_WRAP_S: 0x2802, 392 TEXTURE_WRAP_T: 0x2803, 393 394 /* TextureTarget */ 395 TEXTURE_2D: 0x0DE1, 396 TEXTURE: 0x1702, 397 398 TEXTURE_CUBE_MAP: 0x8513, 399 TEXTURE_BINDING_CUBE_MAP: 0x8514, 400 TEXTURE_CUBE_MAP_POSITIVE_X: 0x8515, 401 TEXTURE_CUBE_MAP_NEGATIVE_X: 0x8516, 402 TEXTURE_CUBE_MAP_POSITIVE_Y: 0x8517, 403 TEXTURE_CUBE_MAP_NEGATIVE_Y: 0x8518, 404 TEXTURE_CUBE_MAP_POSITIVE_Z: 0x8519, 405 TEXTURE_CUBE_MAP_NEGATIVE_Z: 0x851A, 406 MAX_CUBE_MAP_TEXTURE_SIZE: 0x851C, 407 408 /* TextureUnit */ 409 TEXTURE0: 0x84C0, 410 TEXTURE1: 0x84C1, 411 TEXTURE2: 0x84C2, 412 TEXTURE3: 0x84C3, 413 TEXTURE4: 0x84C4, 414 TEXTURE5: 0x84C5, 415 TEXTURE6: 0x84C6, 416 TEXTURE7: 0x84C7, 417 TEXTURE8: 0x84C8, 418 TEXTURE9: 0x84C9, 419 TEXTURE10: 0x84CA, 420 TEXTURE11: 0x84CB, 421 TEXTURE12: 0x84CC, 422 TEXTURE13: 0x84CD, 423 TEXTURE14: 0x84CE, 424 TEXTURE15: 0x84CF, 425 TEXTURE16: 0x84D0, 426 TEXTURE17: 0x84D1, 427 TEXTURE18: 0x84D2, 428 TEXTURE19: 0x84D3, 429 TEXTURE20: 0x84D4, 430 TEXTURE21: 0x84D5, 431 TEXTURE22: 0x84D6, 432 TEXTURE23: 0x84D7, 433 TEXTURE24: 0x84D8, 434 TEXTURE25: 0x84D9, 435 TEXTURE26: 0x84DA, 436 TEXTURE27: 0x84DB, 437 TEXTURE28: 0x84DC, 438 TEXTURE29: 0x84DD, 439 TEXTURE30: 0x84DE, 440 TEXTURE31: 0x84DF, 441 ACTIVE_TEXTURE: 0x84E0, 442 443 /* TextureWrapMode */ 444 REPEAT: 0x2901, 445 CLAMP_TO_EDGE: 0x812F, 446 MIRRORED_REPEAT: 0x8370, 447 448 /* Uniform Types */ 449 FLOAT_VEC2: 0x8B50, 450 FLOAT_VEC3: 0x8B51, 451 FLOAT_VEC4: 0x8B52, 452 INT_VEC2: 0x8B53, 453 INT_VEC3: 0x8B54, 454 INT_VEC4: 0x8B55, 455 BOOL: 0x8B56, 456 BOOL_VEC2: 0x8B57, 457 BOOL_VEC3: 0x8B58, 458 BOOL_VEC4: 0x8B59, 459 FLOAT_MAT2: 0x8B5A, 460 FLOAT_MAT3: 0x8B5B, 461 FLOAT_MAT4: 0x8B5C, 462 SAMPLER_2D: 0x8B5E, 463 SAMPLER_CUBE: 0x8B60, 464 465 /* Vertex Arrays */ 466 VERTEX_ATTRIB_ARRAY_ENABLED: 0x8622, 467 VERTEX_ATTRIB_ARRAY_SIZE: 0x8623, 468 VERTEX_ATTRIB_ARRAY_STRIDE: 0x8624, 469 VERTEX_ATTRIB_ARRAY_TYPE: 0x8625, 470 VERTEX_ATTRIB_ARRAY_NORMALIZED: 0x886A, 471 VERTEX_ATTRIB_ARRAY_POINTER: 0x8645, 472 VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: 0x889F, 473 474 /* Shader Source */ 475 COMPILE_STATUS: 0x8B81, 476 477 /* Shader Precision-Specified Types */ 478 LOW_FLOAT: 0x8DF0, 479 MEDIUM_FLOAT: 0x8DF1, 480 HIGH_FLOAT: 0x8DF2, 481 LOW_INT: 0x8DF3, 482 MEDIUM_INT: 0x8DF4, 483 HIGH_INT: 0x8DF5, 484 485 /* Framebuffer Object. */ 486 FRAMEBUFFER: 0x8D40, 487 RENDERBUFFER: 0x8D41, 488 489 RGBA4: 0x8056, 490 RGB5_A1: 0x8057, 491 RGB565: 0x8D62, 492 DEPTH_COMPONENT16: 0x81A5, 493 STENCIL_INDEX: 0x1901, 494 STENCIL_INDEX8: 0x8D48, 495 DEPTH_STENCIL: 0x84F9, 496 497 RENDERBUFFER_WIDTH: 0x8D42, 498 RENDERBUFFER_HEIGHT: 0x8D43, 499 RENDERBUFFER_INTERNAL_FORMAT: 0x8D44, 500 RENDERBUFFER_RED_SIZE: 0x8D50, 501 RENDERBUFFER_GREEN_SIZE: 0x8D51, 502 RENDERBUFFER_BLUE_SIZE: 0x8D52, 503 RENDERBUFFER_ALPHA_SIZE: 0x8D53, 504 RENDERBUFFER_DEPTH_SIZE: 0x8D54, 505 RENDERBUFFER_STENCIL_SIZE: 0x8D55, 506 507 FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: 0x8CD0, 508 FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: 0x8CD1, 509 FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: 0x8CD2, 510 FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: 0x8CD3, 511 512 COLOR_ATTACHMENT0: 0x8CE0, 513 DEPTH_ATTACHMENT: 0x8D00, 514 STENCIL_ATTACHMENT: 0x8D20, 515 DEPTH_STENCIL_ATTACHMENT: 0x821A, 516 517 NONE: 0, 518 519 FRAMEBUFFER_COMPLETE: 0x8CD5, 520 FRAMEBUFFER_INCOMPLETE_ATTACHMENT: 0x8CD6, 521 FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: 0x8CD7, 522 FRAMEBUFFER_INCOMPLETE_DIMENSIONS: 0x8CD9, 523 FRAMEBUFFER_UNSUPPORTED: 0x8CDD, 524 525 FRAMEBUFFER_BINDING: 0x8CA6, 526 RENDERBUFFER_BINDING: 0x8CA7, 527 MAX_RENDERBUFFER_SIZE: 0x84E8, 528 529 INVALID_FRAMEBUFFER_OPERATION: 0x0506, 530 531 /* WebGL-specific enums */ 532 UNPACK_FLIP_Y_WEBGL: 0x9240, 533 UNPACK_PREMULTIPLY_ALPHA_WEBGL: 0x9241, 534 CONTEXT_LOST_WEBGL: 0x9242, 535 UNPACK_COLORSPACE_CONVERSION_WEBGL: 0x9243, 536 BROWSER_DEFAULT_WEBGL: 0x9244 537 }; 538 539 /** 540 * An inner class that encapsulates the WebGL API to draw 2D shapes. 541 * @param {WebGLRenderingContext} context 542 * @constructor 543 */ 544 createjs.WebGLRenderer.Context = function(context) { 545 /// <param type="WebGLRenderingContext" name="context"/> 546 // This renderer uses premultiplied alpha due to color composition. 547 context.pixelStorei( 548 createjs.WebGLRenderer.gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 1); 549 550 /** 551 * The WebGL rendering context used by this object. 552 * @type {WebGLRenderingContext} 553 * @private 554 */ 555 this.context_ = context; 556 557 /** 558 * An ID assigned to this context. 559 * @type {number} 560 * @private 561 */ 562 this.id_ = ++createjs.WebGLRenderer.id; 563 }; 564 565 /** 566 * The WebGLTexture object bound to this context. 567 * @type {WebGLTexture} 568 * @private 569 */ 570 createjs.WebGLRenderer.Context.prototype.texture_ = null; 571 572 /** 573 * Returns the WebGLRenderingContext object associated with this object. 574 * @return {WebGLRenderingContext} 575 * @const 576 */ 577 createjs.WebGLRenderer.Context.prototype.getContext_ = function() { 578 /// <returns type="WebGLRenderingContext"/> 579 return this.context_; 580 }; 581 582 /** 583 * Returns the ID assigned to this context. Returning 0 represents this context 584 * does not have a drawing buffer. 585 * @return {number} 586 * @const 587 */ 588 createjs.WebGLRenderer.Context.prototype.getId = function() { 589 /// <return type="number"/> 590 return this.id_; 591 }; 592 593 /** 594 * Sets an ID to this context. 595 * @param {number} id 596 * @const 597 */ 598 createjs.WebGLRenderer.Context.prototype.setId = function(id) { 599 /// <param type="number" name="id"/> 600 this.id_ = id; 601 }; 602 603 /** 604 * Creates a vertex shader or a fragment shader and compiles it. 605 * @param {number} type 606 * @param {string} source 607 * @return {WebGLShader} 608 * @const 609 */ 610 createjs.WebGLRenderer.Context.prototype.createShader = function(type, source) { 611 /// <param type="number" name="type"/> 612 /// <param type="string" name="source"/> 613 /// <returns type="WebGLShader"/> 614 var context = this.getContext_(); 615 var shader = context.createShader(type); 616 context.shaderSource(shader, source); 617 context.compileShader(shader); 618 createjs.assert(!!context.getShaderParameter( 619 shader, createjs.WebGLRenderer.gl.COMPILE_STATUS)); 620 return shader; 621 }; 622 623 /** 624 * Creates a vertex shader and compiles it. 625 * @param {string} source 626 * @return {WebGLShader} 627 * @const 628 */ 629 createjs.WebGLRenderer.Context.prototype.createVertexShader = function(source) { 630 /// <param type="string" name="source"/> 631 /// <returns type="WebGLShader"/> 632 return this.createShader(createjs.WebGLRenderer.gl.VERTEX_SHADER, source); 633 }; 634 635 /** 636 * Creates a fragment shader and compiles it. 637 * @param {string} source 638 * @return {WebGLShader} 639 * @const 640 */ 641 createjs.WebGLRenderer.Context.prototype.createFragmentShader = 642 function(source) { 643 /// <param type="string" name="source"/> 644 /// <returns type="WebGLShader"/> 645 return this.createShader(createjs.WebGLRenderer.gl.FRAGMENT_SHADER, source); 646 }; 647 648 /** 649 * Deletes a shader. 650 * @param {WebGLShader} shader 651 * @const 652 */ 653 createjs.WebGLRenderer.Context.prototype.deleteShader = function(shader) { 654 this.getContext_().deleteShader(shader); 655 }; 656 657 /** 658 * Creates a shader program. 659 * @param {WebGLShader} vertex 660 * @param {WebGLShader} fragment 661 * @return {WebGLProgram} 662 * @const 663 */ 664 createjs.WebGLRenderer.Context.prototype.createProgram = 665 function(vertex, fragment) { 666 /// <param type="WebGLShader" name="vertex"/> 667 /// <param type="WebGLShader" name="fragment"/> 668 /// <returns type="WebGLProgram"/> 669 var context = this.getContext_(); 670 var program = context.createProgram(); 671 context.attachShader(program, vertex); 672 context.attachShader(program, fragment); 673 context.linkProgram(program); 674 context.useProgram(program); 675 return program; 676 }; 677 678 /** 679 * Deletes a shader program. 680 * @param {WebGLProgram} program 681 * @const 682 */ 683 createjs.WebGLRenderer.Context.prototype.deleteProgram = function(program) { 684 /// <param type="WebGLProgram" name="program"/> 685 this.getContext_().deleteProgram(program); 686 }; 687 688 /** 689 * Binds the specified shader program and uses it. 690 * @param {WebGLProgram} program 691 * @const 692 */ 693 createjs.WebGLRenderer.Context.prototype.useProgram = function(program) { 694 /// <param type="WebGLProgram" name="program"/> 695 this.getContext_().useProgram(program); 696 }; 697 698 /** 699 * Returns the location to the specified color. 700 * @param {WebGLProgram} program 701 * @param {string} key 702 * @return {WebGLUniformLocation} 703 * @const 704 */ 705 createjs.WebGLRenderer.Context.prototype.getColor = function(program, key) { 706 /// <param type="WebGLProgram" name="program"/> 707 /// <param type="string" name="key"/> 708 /// <returns type="WebGLUniformLocation"/> 709 return this.getContext_().getUniformLocation(program, key); 710 }; 711 712 /** 713 * Sets the values of the specified color. 714 * @param {WebGLUniformLocation} color 715 * @param {number} red 716 * @param {number} green 717 * @param {number} blue 718 * @param {number} alpha 719 * @const 720 */ 721 createjs.WebGLRenderer.Context.prototype.setColor = 722 function(color, red, green, blue, alpha) { 723 /// <param type="WebGLUniformLocation" name="color"/> 724 /// <param type="number" name="red"/> 725 /// <param type="number" name="green"/> 726 /// <param type="number" name="blue"/> 727 /// <param type="number" name="alpha"/> 728 this.getContext_().uniform4f(color, red, green, blue, alpha); 729 }; 730 731 /** 732 * Returns the location to the specified point. 733 * @param {WebGLProgram} program 734 * @param {string} key 735 * @return {WebGLUniformLocation} 736 * @const 737 */ 738 createjs.WebGLRenderer.Context.prototype.getPoint = function(program, key) { 739 /// <param type="WebGLProgram" name="program"/> 740 /// <param type="string" name="key"/> 741 /// <returns type="WebGLUniformLocation"/> 742 return this.getContext_().getUniformLocation(program, key); 743 }; 744 745 /** 746 * Sets the values of the specified point. 747 * @param {WebGLUniformLocation} point 748 * @param {number} x 749 * @param {number} y 750 * @const 751 */ 752 createjs.WebGLRenderer.Context.prototype.setPoint = function(point, x, y) { 753 /// <param type="WebGLUniformLocation" name="point"/> 754 /// <param type="number" name="x"/> 755 /// <param type="number" name="y"/> 756 this.getContext_().uniform2f(point, x, y); 757 }; 758 759 /** 760 * Creates an array buffer used by rectangles with the specified values. 761 * @param {Float32Array} points 762 * @return {WebGLBuffer} 763 * @const 764 */ 765 createjs.WebGLRenderer.Context.prototype.createRectangleBuffer = 766 function(points) { 767 /// <returns type="WebGLBuffer"/> 768 var buffer = this.getContext_().createBuffer(); 769 this.setRectangleBuffer(buffer, points); 770 return buffer; 771 }; 772 773 /** 774 * Deletes a WebGLBuffer object used by rectangles. 775 * @param {WebGLBuffer} buffer 776 * @const 777 */ 778 createjs.WebGLRenderer.Context.prototype.deleteRectangleBuffer = 779 function(buffer) { 780 /// <param type="WebGLBuffer" name="buffer"/> 781 this.getContext_().deleteBuffer(buffer); 782 }; 783 784 /** 785 * Sets the specified values to the array buffer. 786 * @param {WebGLBuffer} buffer 787 * @param {Float32Array} points 788 * @const 789 */ 790 createjs.WebGLRenderer.Context.prototype.setRectangleBuffer = 791 function(buffer, points) { 792 /// <param type="WebGLBuffer" name="buffer"/> 793 /// <param type="Float32Array" name="points"/> 794 var context = this.getContext_(); 795 context.bindBuffer(createjs.WebGLRenderer.gl.ARRAY_BUFFER, buffer); 796 context.bufferData( 797 createjs.WebGLRenderer.gl.ARRAY_BUFFER, 798 points, 799 createjs.WebGLRenderer.gl.STATIC_DRAW); 800 }; 801 802 /** 803 * Retrieves the location to an attribute and assigns it to the WebGLBuffer 804 * object currently bound to this context. (This method expects to be called 805 * after a createRectangleBuffer() call or a setRectangleBuffer() call.) 806 * @param {WebGLProgram} program 807 * @param {string} key 808 * @return {number} 809 * @const 810 */ 811 createjs.WebGLRenderer.Context.prototype.getRectangleAttribute = 812 function(program, key) { 813 /// <param type="WebGLProgram" name="program"/> 814 /// <param type="string" name="key"/> 815 /// <returns type="number"/> 816 var context = this.getContext_(); 817 var attribute = context.getAttribLocation(program, key); 818 context.enableVertexAttribArray(attribute); 819 context.vertexAttribPointer( 820 attribute, 2, createjs.WebGLRenderer.gl.FLOAT, false, 0, 0); 821 return attribute; 822 }; 823 824 /** 825 * Retrieves the location to the specified transform. 826 * @param {WebGLProgram} program 827 * @param {string} key 828 * @return {WebGLUniformLocation} 829 * @const 830 */ 831 createjs.WebGLRenderer.Context.prototype.getTransform = function(program, key) { 832 /// <param type="WebGLProgram" name="program"/> 833 /// <param type="string" name="key"/> 834 /// <returns type="WebGLUniformLocation"/> 835 return this.getContext_().getUniformLocation(program, key); 836 }; 837 838 /** 839 * Sets the values to the specified transform. 840 * @param {WebGLUniformLocation} transform 841 * @param {Float32Array} matrix 842 * @const 843 */ 844 createjs.WebGLRenderer.Context.prototype.setTransform = 845 function(transform, matrix) { 846 /// <param type="WebGLUniformLocation" name="transform"/> 847 /// <param type="Float32Array" name="matrix"/> 848 this.getContext_().uniformMatrix3fv(transform, false, matrix); 849 }; 850 851 /** 852 * Retrieves the location to the specified color matrix. 853 * @param {WebGLProgram} program 854 * @param {string} key 855 * @return {WebGLUniformLocation} 856 * @const 857 */ 858 createjs.WebGLRenderer.Context.prototype.getColorMatrix = 859 function(program, key) { 860 /// <param type="WebGLProgram" name="program"/> 861 /// <param type="string" name="key"/> 862 /// <returns type="WebGLUniformLocation"/> 863 return this.getContext_().getUniformLocation(program, key); 864 }; 865 866 /** 867 * Sets the values to the specified color matrix. 868 * @param {WebGLUniformLocation} color 869 * @param {Float32Array} matrix 870 * @const 871 */ 872 createjs.WebGLRenderer.Context.prototype.setColorMatrix = 873 function(color, matrix) { 874 /// <param type="WebGLUniformLocation" name="color"/> 875 /// <param type="Float32Array" name="matrix"/> 876 this.getContext_().uniformMatrix4fv(color, false, matrix); 877 }; 878 879 /** 880 * Retrieves the texture type for the specified image. 881 * @param {HTMLImageElement|HTMLCanvasElement|HTMLVideoElement} image 882 * @return {number} 883 * @const 884 */ 885 createjs.WebGLRenderer.Context.prototype.getTextureType = function(image) { 886 /// <signature> 887 /// <param type="HTMLImageElement" name="image"/> 888 /// <returns type="number"/> 889 /// </signature> 890 /// <signature> 891 /// <param type="HTMLCanvasElement" name="canvas"/> 892 /// <returns type="number"/> 893 /// </signature> 894 /// <signature> 895 /// <param type="HTMLVideoElement" name="video"/> 896 /// <returns type="number"/> 897 /// </signature> 898 var TYPES = [ 899 createjs.WebGLRenderer.gl.UNSIGNED_BYTE, 900 createjs.WebGLRenderer.gl.UNSIGNED_SHORT_4_4_4_4, 901 createjs.WebGLRenderer.gl.UNSIGNED_SHORT_5_5_5_1, 902 createjs.WebGLRenderer.gl.UNSIGNED_SHORT_5_6_5 903 ]; 904 var format = image.format_ || 0; 905 return TYPES[format]; 906 }; 907 908 /** 909 * Creates a new texture from an HTMLImageElement object, an HTMLCanvasElement 910 * object, or an HTMLVideoElement object. 911 * @param {HTMLImageElement|HTMLCanvasElement|HTMLVideoElement} image 912 * @return {WebGLTexture} 913 * @const 914 */ 915 createjs.WebGLRenderer.Context.prototype.createTexture = function(image) { 916 /// <signature> 917 /// <param type="HTMLImageElement" name="image"/> 918 /// <returns type="WebGLTexture"/> 919 /// </signature> 920 /// <signature> 921 /// <param type="HTMLCanvasElement" name="canvas"/> 922 /// <returns type="WebGLTexture"/> 923 /// </signature> 924 /// <signature> 925 /// <param type="HTMLVideoElement" name="video"/> 926 /// <returns type="WebGLTexture"/> 927 /// </signature> 928 var context = this.getContext_(); 929 var texture = context.createTexture(); 930 var type = this.getTextureType(image); 931 context.bindTexture(createjs.WebGLRenderer.gl.TEXTURE_2D, texture); 932 context.texParameteri(createjs.WebGLRenderer.gl.TEXTURE_2D, 933 createjs.WebGLRenderer.gl.TEXTURE_WRAP_S, 934 createjs.WebGLRenderer.gl.CLAMP_TO_EDGE); 935 context.texParameteri(createjs.WebGLRenderer.gl.TEXTURE_2D, 936 createjs.WebGLRenderer.gl.TEXTURE_WRAP_T, 937 createjs.WebGLRenderer.gl.CLAMP_TO_EDGE); 938 context.texParameteri(createjs.WebGLRenderer.gl.TEXTURE_2D, 939 createjs.WebGLRenderer.gl.TEXTURE_MIN_FILTER, 940 createjs.WebGLRenderer.gl.LINEAR); 941 context.texParameteri(createjs.WebGLRenderer.gl.TEXTURE_2D, 942 createjs.WebGLRenderer.gl.TEXTURE_MAG_FILTER, 943 createjs.WebGLRenderer.gl.LINEAR); 944 context.texImage2D(createjs.WebGLRenderer.gl.TEXTURE_2D, 945 0, 946 createjs.WebGLRenderer.gl.RGBA, 947 createjs.WebGLRenderer.gl.RGBA, 948 type, 949 image); 950 this.texture_ = texture; 951 return texture; 952 }; 953 954 /** 955 * Deletes a texture. 956 * @param {WebGLTexture} texture 957 * @const 958 */ 959 createjs.WebGLRenderer.Context.prototype.deleteTexture = function(texture) { 960 /// <param type="WebGLTexture" name="texture"/> 961 this.getContext_().deleteTexture(texture); 962 }; 963 964 /** 965 * Binds the specified texture. 966 * @param {WebGLTexture} texture 967 * @const 968 */ 969 createjs.WebGLRenderer.Context.prototype.bindTexture = function(texture) { 970 /// <param type="WebGLTexture" name="texture"/> 971 if (this.texture_ === texture) { 972 return; 973 } 974 this.getContext_().bindTexture(createjs.WebGLRenderer.gl.TEXTURE_2D, texture); 975 this.texture_ = texture; 976 }; 977 978 /** 979 * Sets the filters of the texture bound to this context. 980 * @param {boolean} smoothing 981 * @const 982 */ 983 createjs.WebGLRenderer.Context.prototype.setFilter = function(smoothing) { 984 /// <param type="boolean" name="filter"/> 985 var context = this.getContext_(); 986 var filter = smoothing ? 987 createjs.WebGLRenderer.gl.LINEAR : createjs.WebGLRenderer.gl.NEAREST; 988 context.texParameteri(createjs.WebGLRenderer.gl.TEXTURE_2D, 989 createjs.WebGLRenderer.gl.TEXTURE_MIN_FILTER, 990 filter); 991 context.texParameteri(createjs.WebGLRenderer.gl.TEXTURE_2D, 992 createjs.WebGLRenderer.gl.TEXTURE_MAG_FILTER, 993 filter); 994 }; 995 996 /** 997 * Updates the image of the texture bound to this context. 998 * @param {HTMLImageElement|HTMLCanvasElement|HTMLVideoElement} image 999 * @const 1000 */ 1001 createjs.WebGLRenderer.Context.prototype.updateTexture = function(image) { 1002 /// <signature> 1003 /// <param type="HTMLImageElement" name="image"/> 1004 /// </signature> 1005 /// <signature> 1006 /// <param type="HTMLCanvasElement" name="canvas"/> 1007 /// </signature> 1008 /// <signature> 1009 /// <param type="HTMLVideoElement" name="video"/> 1010 /// </signature> 1011 var type = this.getTextureType(image); 1012 this.getContext_().texImage2D(createjs.WebGLRenderer.gl.TEXTURE_2D, 1013 0, 1014 createjs.WebGLRenderer.gl.RGBA, 1015 createjs.WebGLRenderer.gl.RGBA, 1016 type, 1017 image); 1018 }; 1019 1020 /** 1021 * Creates a texture to be bound to a frame buffer. 1022 * @param {number} width 1023 * @param {number} height 1024 * @param {number} type 1025 * @return {WebGLTexture} 1026 * @const 1027 */ 1028 createjs.WebGLRenderer.Context.prototype.createFrameTexture = 1029 function(width, height, type) { 1030 /// <param type="number" name="width"/> 1031 /// <param type="number" name="height"/> 1032 /// <param type="number" name="type"/> 1033 /// <returns type="WebGLTexture"/> 1034 var context = this.getContext_(); 1035 var texture = context.createTexture(); 1036 context.bindTexture(createjs.WebGLRenderer.gl.TEXTURE_2D, texture); 1037 context.texParameteri(createjs.WebGLRenderer.gl.TEXTURE_2D, 1038 createjs.WebGLRenderer.gl.TEXTURE_WRAP_S, 1039 createjs.WebGLRenderer.gl.CLAMP_TO_EDGE); 1040 context.texParameteri(createjs.WebGLRenderer.gl.TEXTURE_2D, 1041 createjs.WebGLRenderer.gl.TEXTURE_WRAP_T, 1042 createjs.WebGLRenderer.gl.CLAMP_TO_EDGE); 1043 context.texParameteri(createjs.WebGLRenderer.gl.TEXTURE_2D, 1044 createjs.WebGLRenderer.gl.TEXTURE_MIN_FILTER, 1045 createjs.WebGLRenderer.gl.LINEAR); 1046 context.texParameteri(createjs.WebGLRenderer.gl.TEXTURE_2D, 1047 createjs.WebGLRenderer.gl.TEXTURE_MAG_FILTER, 1048 createjs.WebGLRenderer.gl.LINEAR); 1049 context.texImage2D(createjs.WebGLRenderer.gl.TEXTURE_2D, 1050 0, 1051 createjs.WebGLRenderer.gl.RGBA, 1052 width, 1053 height, 1054 0, 1055 createjs.WebGLRenderer.gl.RGBA, 1056 type, 1057 null); 1058 this.texture_ = texture; 1059 return texture; 1060 }; 1061 1062 /** 1063 * Creates a new frame buffer and binds the specified texture to it. 1064 * @param {WebGLTexture} texture 1065 * @return {WebGLFramebuffer} 1066 * @const 1067 */ 1068 createjs.WebGLRenderer.Context.prototype.createFramebuffer = function(texture) { 1069 /// <param type="WebGLTexture" name="texture"/> 1070 /// <returns type="WebGLFramebuffer"/> 1071 var context = this.getContext_(); 1072 var buffer = context.createFramebuffer(); 1073 context.bindFramebuffer(createjs.WebGLRenderer.gl.FRAMEBUFFER, buffer); 1074 context.framebufferTexture2D(createjs.WebGLRenderer.gl.FRAMEBUFFER, 1075 createjs.WebGLRenderer.gl.COLOR_ATTACHMENT0, 1076 createjs.WebGLRenderer.gl.TEXTURE_2D, 1077 texture, 1078 0); 1079 return buffer; 1080 }; 1081 1082 /** 1083 * Deletes a frame buffer. 1084 * @param {WebGLFramebuffer} buffer 1085 * @const 1086 */ 1087 createjs.WebGLRenderer.Context.prototype.deleteFramebuffer = function(buffer) { 1088 /// <param type="WebGLFramebuffer" name="buffer"/> 1089 this.getContext_().deleteFramebuffer(buffer); 1090 }; 1091 1092 /** 1093 * Binds the specified frame buffer. 1094 * @param {WebGLFramebuffer} buffer 1095 * @const 1096 */ 1097 createjs.WebGLRenderer.Context.prototype.bindFramebuffer = function(buffer) { 1098 /// <param type="WebGLFramebuffer" name="buffer"/> 1099 var context = this.getContext_(); 1100 context.bindFramebuffer(createjs.WebGLRenderer.gl.FRAMEBUFFER, buffer); 1101 }; 1102 1103 /** 1104 * Enables clipping. 1105 * @const 1106 */ 1107 createjs.WebGLRenderer.Context.prototype.enableClip = function() { 1108 this.getContext_().enable(createjs.WebGLRenderer.gl.SCISSOR_TEST); 1109 }; 1110 1111 /** 1112 * Updates the clipping rectangle. This method converts the given bounding box 1113 * (in the HTML coordinate) to a scissor rectangle (in the WebGL coordinate) and 1114 * uses the converted rectangle for the scissor test. (WebGL uses the bottom-up 1115 * coordinate system for scissor rectangles, i.e. (0,0) represents the 1116 * bottom-left corner of a scissor rectangle and (width,height) represents its 1117 * top-right corner, respectively.) 1118 * @param {createjs.BoundingBox} clip 1119 * @param {number} height 1120 * @const 1121 */ 1122 createjs.WebGLRenderer.Context.prototype.updateClip = function(clip, height) { 1123 /// <param type="createjs.BoundingBox" name="clip"/> 1124 /// <param type="number" name="height"/> 1125 var minX = clip.minX; 1126 var minY = clip.minY; 1127 var maxX = clip.maxX; 1128 var maxY = clip.maxY; 1129 this.getContext_().scissor(minX, height - maxY, maxX - minX, maxY - minY); 1130 }; 1131 1132 /** 1133 * Disables clipping. 1134 * @const 1135 */ 1136 createjs.WebGLRenderer.Context.prototype.disableClip = function() { 1137 this.getContext_().disable(createjs.WebGLRenderer.gl.SCISSOR_TEST); 1138 }; 1139 1140 /** 1141 * Clears the drawing buffer (or a framebuffer) bound to this context. 1142 * @const 1143 */ 1144 createjs.WebGLRenderer.Context.prototype.clear = function() { 1145 this.getContext_().clear(createjs.WebGLRenderer.gl.COLOR_BUFFER_BIT); 1146 }; 1147 1148 /** 1149 * Draws a rectangle. (This renderer uses a triangle strip as a rectangle.) 1150 * @const 1151 */ 1152 createjs.WebGLRenderer.Context.prototype.drawRectangle = function() { 1153 this.getContext_().drawArrays(createjs.WebGLRenderer.gl.TRIANGLE_STRIP, 0, 4); 1154 }; 1155 1156 /** 1157 * Enables color blending and initializes its equations. 1158 * @const 1159 */ 1160 createjs.WebGLRenderer.Context.prototype.enableBlend = function() { 1161 var context = this.getContext_(); 1162 context.enable(createjs.WebGLRenderer.gl.BLEND); 1163 context.blendEquation(createjs.WebGLRenderer.gl.FUNC_ADD); 1164 }; 1165 1166 /** 1167 * Sets a blending function that emulates the specified composite operation. 1168 * This renderer renders only the region inside of a display object to be 1169 * rendered, i.e. it does not change its outside. This means it is hard to 1170 * emulate composite operations that needs to change the outside of a display 1171 * object, e.g. source-in, source-out, etc. 1172 * @param {number} operation 1173 * @const 1174 */ 1175 createjs.WebGLRenderer.Context.prototype.setBlend = function(operation) { 1176 /// <param type="number" name="operation"/> 1177 var BLEND = [ 1178 // source-over 1179 createjs.WebGLRenderer.gl.ONE, 1180 createjs.WebGLRenderer.gl.ONE_MINUS_SRC_ALPHA, 1181 // source-atop 1182 createjs.WebGLRenderer.gl.DST_ALPHA, 1183 createjs.WebGLRenderer.gl.ONE, 1184 // source-in (*) 1185 createjs.WebGLRenderer.gl.DST_ALPHA, 1186 createjs.WebGLRenderer.gl.ZERO, 1187 // source-out (*) 1188 createjs.WebGLRenderer.gl.ONE_MINUS_DST_ALPHA, 1189 createjs.WebGLRenderer.gl.ZERO, 1190 // destination-over 1191 createjs.WebGLRenderer.gl.ONE_MINUS_DST_ALPHA, 1192 createjs.WebGLRenderer.gl.ONE, 1193 // destination-atop (*) 1194 createjs.WebGLRenderer.gl.ONE, 1195 createjs.WebGLRenderer.gl.SRC_ALPHA, 1196 // destination-in (*) 1197 createjs.WebGLRenderer.gl.ZERO, 1198 createjs.WebGLRenderer.gl.SRC_ALPHA, 1199 // destination-out 1200 createjs.WebGLRenderer.gl.ZERO, 1201 createjs.WebGLRenderer.gl.ONE_MINUS_SRC_ALPHA, 1202 // lighter 1203 createjs.WebGLRenderer.gl.ONE, 1204 createjs.WebGLRenderer.gl.ONE, 1205 // copy 1206 createjs.WebGLRenderer.gl.ONE, 1207 createjs.WebGLRenderer.gl.ZERO, 1208 // xor 1209 createjs.WebGLRenderer.gl.ONE_MINUS_DST_ALPHA, 1210 createjs.WebGLRenderer.gl.ONE_MINUS_SRC_ALPHA, 1211 // darker (*) 1212 createjs.WebGLRenderer.gl.DST_COLOR, 1213 createjs.WebGLRenderer.gl.ONE, 1214 // multiply (*) 1215 createjs.WebGLRenderer.gl.ZERO, 1216 createjs.WebGLRenderer.gl.SRC_COLOR 1217 ]; 1218 operation <<= 1; 1219 this.getContext_().blendFunc(BLEND[operation], BLEND[operation + 1]); 1220 }; 1221 1222 /** 1223 * Sets the viewport rectangle. 1224 * @param {number} width 1225 * @param {number} height 1226 * @const 1227 */ 1228 createjs.WebGLRenderer.Context.prototype.setViewport = function(width, height) { 1229 /// <param type="number" name="width"/> 1230 /// <param type="number" name="height"/> 1231 this.getContext_().viewport(0, 0, width, height); 1232 }; 1233 1234 /** 1235 * An inner class that encapsulates a composite alpha used by this renderer. 1236 * This renderer uses a uniform vector (alpha, alpha, alpha, alpha) so it can 1237 * pre-multiply this composite alpha to RGB colors. 1238 * @param {createjs.WebGLRenderer.Context} context 1239 * @param {WebGLProgram} program 1240 * @param {string} key 1241 * @param {number} alpha 1242 * @constructor 1243 */ 1244 createjs.WebGLRenderer.Alpha = 1245 function(context, program, key, alpha) { 1246 /// <param type="createjs.WebGLRenderer.Context" name="context"/> 1247 /// <param type="WebGLProgram" name="program"/> 1248 /// <param type="string" name="key"/> 1249 /// <param type="number" name="alpha"/> 1250 /** 1251 * The dirty flag. 1252 * @type {boolean} 1253 * @private 1254 */ 1255 this.dirty_ = true; 1256 1257 /** 1258 * The uniform location representing this color. 1259 * @type {WebGLUniformLocation} 1260 * @private 1261 */ 1262 this.color_ = context.getColor(program, key); 1263 1264 /** 1265 * The alpha component. 1266 * @type {number} 1267 * @private 1268 */ 1269 this.alpha_ = alpha; 1270 }; 1271 1272 /** 1273 * Changes the alpha value of this color. 1274 * @param {number} alpha 1275 * @const 1276 */ 1277 createjs.WebGLRenderer.Alpha.prototype.setAlpha = function(alpha) { 1278 /// <param type="number" name="alpha"/> 1279 if (this.alpha_ != alpha) { 1280 this.dirty_ = true; 1281 this.alpha_ = alpha; 1282 } 1283 }; 1284 1285 /** 1286 * Binds this color to the specified context. 1287 * @param {createjs.WebGLRenderer.Context} context 1288 */ 1289 createjs.WebGLRenderer.Alpha.prototype.bindContext = function(context) { 1290 /// <param type="createjs.WebGLRenderer.Context" name="context"/> 1291 if (this.dirty_) { 1292 this.dirty_ = false; 1293 context.setColor( 1294 this.color_, this.alpha_, this.alpha_, this.alpha_, this.alpha_); 1295 } 1296 }; 1297 1298 /** 1299 * An inner class that encapsulates a point used by this renderer. This renderer 1300 * uses a uniform vector (x, y) to represent a point. 1301 * @param {createjs.WebGLRenderer.Context} context 1302 * @param {WebGLProgram} program 1303 * @param {string} key 1304 * @param {number} x 1305 * @param {number} y 1306 * @constructor 1307 */ 1308 createjs.WebGLRenderer.Vector = function(context, program, key, x, y) { 1309 /// <param type="createjs.WebGLRenderer.Context" name="context"/> 1310 /// <param type="WebGLProgram" name="program"/> 1311 /// <param type="string" name="key"/> 1312 /// <param type="number" name="x"/> 1313 /// <param type="number" name="y"/> 1314 /** 1315 * The dirty flag. 1316 * @type {boolean} 1317 * @private 1318 */ 1319 this.dirty_ = true; 1320 1321 /** 1322 * The uniform location representing this vector. 1323 * @type {WebGLUniformLocation} 1324 * @private 1325 */ 1326 this.point_ = context.getPoint(program, key); 1327 1328 /** 1329 * The x coordinate. 1330 * @type {number} 1331 * @private 1332 */ 1333 this.x_ = x; 1334 1335 /** 1336 * The y coordinate. 1337 * @type {number} 1338 * @private 1339 */ 1340 this.y_ = y; 1341 }; 1342 1343 /** 1344 * Changes this point. 1345 * @param {number} x 1346 * @param {number} y 1347 */ 1348 createjs.WebGLRenderer.Vector.prototype.set = function(x, y) { 1349 /// <param type="number" name="x"/> 1350 /// <param type="number" name="y"/> 1351 if (this.x_ != x || this.y_ != y) { 1352 this.dirty_ = true; 1353 this.x_ = x; 1354 this.y_ = y; 1355 } 1356 }; 1357 1358 /** 1359 * Binds this point to the specified context. 1360 * @param {createjs.WebGLRenderer.Context} context 1361 */ 1362 createjs.WebGLRenderer.Vector.prototype.bindContext = function(context) { 1363 /// <param type="createjs.WebGLRenderer.Context" name="context"/> 1364 if (this.dirty_) { 1365 this.dirty_ = false; 1366 context.setPoint(this.point_, this.x_, this.y_); 1367 } 1368 }; 1369 1370 /** 1371 * An inner class that encapsulates a rectangle used by this renderer. This 1372 * renderer uses a couple of triangles (0,0)-(width,0)-(0,height) and 1373 * (width,0)-(0,height)-(width,height) to represent a rectangle. 1374 * (0,0) +--+ (width,0) 1375 * | /| 1376 * |/ | 1377 * (0,height) +--+ (width,height) 1378 * @param {createjs.WebGLRenderer.Context} context 1379 * @param {WebGLProgram} program 1380 * @param {string} key 1381 * @param {number} width 1382 * @param {number} height 1383 * @constructor 1384 */ 1385 createjs.WebGLRenderer.Rectangle = 1386 function(context, program, key, width, height) { 1387 /// <param type="createjs.WebGLRenderer.Context" name="context"/> 1388 /// <param type="WebGLProgram" name="program"/> 1389 /// <param type="string" name="key"/> 1390 /// <param type="number" name="width"/> 1391 /// <param type="number" name="height"/> 1392 /** 1393 * An array representing this triable strip. 1394 * @type {Float32Array} 1395 * @private 1396 */ 1397 this.points_ = new Float32Array([ 1398 0, 0, 1399 width, 0, 1400 0, height, 1401 width, height 1402 ]); 1403 1404 /** 1405 * The WebGL buffer (or GPU memory) stores the above array. 1406 * @type {WebGLBuffer} 1407 * @private 1408 */ 1409 this.buffer_ = context.createRectangleBuffer(this.points_); 1410 1411 /** 1412 * The attribute representing this rectangle. 1413 * @type {number} 1414 * @private 1415 */ 1416 this.attribute_ = context.getRectangleAttribute(program, key); 1417 }; 1418 1419 /** 1420 * Deletes all resources used by this rectangle. 1421 * @param {createjs.WebGLRenderer.Context} context 1422 * @const 1423 */ 1424 createjs.WebGLRenderer.Rectangle.prototype.destroy = function(context) { 1425 /// <param type="createjs.WebGLRenderer.Context" name="context"/> 1426 context.deleteRectangleBuffer(this.buffer_); 1427 }; 1428 1429 /** 1430 * Sets this rectangle. 1431 * @param {number} x 1432 * @param {number} y 1433 * @param {number} width 1434 * @param {number} height 1435 * @const 1436 */ 1437 createjs.WebGLRenderer.Rectangle.prototype.set = function(x, y, width, height) { 1438 /// <param type="number" name="x"/> 1439 /// <param type="number" name="y"/> 1440 /// <param type="number" name="width"/> 1441 /// <param type="number" name="height"/> 1442 var minX = x; 1443 var minY = y; 1444 var maxX = x + width; 1445 var maxY = y + height; 1446 this.points_[0] = minX; 1447 this.points_[1] = minY; 1448 this.points_[2] = maxX; 1449 this.points_[3] = minY; 1450 this.points_[4] = minX; 1451 this.points_[5] = maxY; 1452 this.points_[6] = maxX; 1453 this.points_[7] = maxY; 1454 }; 1455 1456 /** 1457 * Binds this rectangle to the specified context. 1458 * @param {createjs.WebGLRenderer.Context} context 1459 */ 1460 createjs.WebGLRenderer.Rectangle.prototype.bindContext = function(context) { 1461 /// <param type="createjs.WebGLRenderer.Context" name="context"/> 1462 context.setRectangleBuffer(this.buffer_, this.points_); 1463 }; 1464 1465 /** 1466 * An inner class that encapsulates an affine transform used by this renderer. 1467 * This renderer uses a 3x3 matrix listed below to apply an affine 1468 * transform used by the Canvas 2D API in its vertex shader. (This class uses 1469 * transposed matrices because WebGL uses them by default.) 1470 * | a b 0 | 1471 * | c d 0 | 1472 * | tx ty 1 | 1473 * @param {createjs.WebGLRenderer.Context} context 1474 * @param {WebGLProgram} program 1475 * @param {string} key 1476 * @constructor 1477 */ 1478 createjs.WebGLRenderer.Transform = function(context, program, key) { 1479 /// <param type="createjs.WebGLRenderer.Context" name="context"/> 1480 /// <param type="WebGLProgram" name="program"/> 1481 /// <param type="string" name="key"/> 1482 /** 1483 * The uniform location representing this transform. 1484 * @type {WebGLUniformLocation} 1485 * @private 1486 */ 1487 this.transform_ = context.getTransform(program, key); 1488 1489 /** 1490 * The transformation matrix. 1491 * @type {Float32Array} 1492 * @private 1493 */ 1494 this.matrix_ = new Float32Array([ 1495 1, 0, 0, 1496 0, 1, 0, 1497 0, 0, 1 1498 ]); 1499 }; 1500 1501 /** 1502 * Sets this transform. 1503 * @param {number} a 1504 * @param {number} b 1505 * @param {number} c 1506 * @param {number} d 1507 * @param {number} tx 1508 * @param {number} ty 1509 */ 1510 createjs.WebGLRenderer.Transform.prototype.set = function(a, b, c, d, tx, ty) { 1511 /// <param type="number" name="a"/> 1512 /// <param type="number" name="b"/> 1513 /// <param type="number" name="c"/> 1514 /// <param type="number" name="d"/> 1515 /// <param type="number" name="tx"/> 1516 /// <param type="number" name="ty"/> 1517 this.matrix_[0] = a; 1518 this.matrix_[1] = b; 1519 this.matrix_[2] = 0; 1520 this.matrix_[3] = c; 1521 this.matrix_[4] = d; 1522 this.matrix_[5] = 0; 1523 this.matrix_[6] = tx; 1524 this.matrix_[7] = ty; 1525 this.matrix_[8] = 1; 1526 }; 1527 1528 /** 1529 * Binds this transform to the specified context. 1530 * @param {createjs.WebGLRenderer.Context} context 1531 * @const 1532 */ 1533 createjs.WebGLRenderer.Transform.prototype.bindContext = function(context) { 1534 /// <param type="createjs.WebGLRenderer.Context" name="context"/> 1535 context.setTransform(this.transform_, this.matrix_); 1536 }; 1537 1538 /** 1539 * An inner class that encapsulates a color-transform matrix used by a 1540 * color-matrix filter. This matrix is a transposed 4x4 matrix as listed below. 1541 * (The uniformMatrix4fv() method needs a transposed matrix on Chrome and 1542 * Firefox.) 1543 * | m00 m10 m20 m30 | 1544 * | m01 m11 m21 m31 | 1545 * | m02 m12 m22 m32 | 1546 * | m03 m13 m23 m33 | 1547 * @param {createjs.WebGLRenderer.Context} context 1548 * @param {WebGLProgram} program 1549 * @param {string} key 1550 * @constructor 1551 */ 1552 createjs.WebGLRenderer.ColorMatrix = function(context, program, key) { 1553 /// <param type="createjs.WebGLRenderer.Context" name="context"/> 1554 /// <param type="WebGLProgram" name="program"/> 1555 /// <param type="string" name="key"/> 1556 /** 1557 * The dirty flag. 1558 * @type {boolean} 1559 * @private 1560 */ 1561 this.dirty_ = true; 1562 1563 /** 1564 * The OpenGL attribute representing this matrix. 1565 * @type {WebGLUniformLocation} 1566 * @private 1567 */ 1568 this.transform_ = context.getColorMatrix(program, key); 1569 1570 /** 1571 * The values of this matrix. 1572 * @type {Float32Array} 1573 * @private 1574 */ 1575 this.matrix_ = new Float32Array([ 1576 1, 0, 0, 0, 1577 0, 1, 0, 0, 1578 0, 0, 1, 0, 1579 0, 0, 0, 1 1580 ]); 1581 }; 1582 1583 /** 1584 * Sets the values of this matrix. This method transposes the top-left 3x3 1585 * sub-matrix of the input matrix and copies its values. (The input matrix is a 1586 * matrix used by a color-matrix filter, i.e. a 5x5 matrix.) 1587 * @param {Array.<number>} matrix 1588 * @const 1589 */ 1590 createjs.WebGLRenderer.ColorMatrix.prototype.set = function(matrix) { 1591 /// <param type="Array" elementType="number" name="matrix"/> 1592 this.dirty_ = true; 1593 this.matrix_[0 * 4 + 0] = matrix[0 * 5 + 0]; 1594 this.matrix_[0 * 4 + 1] = matrix[1 * 5 + 0]; 1595 this.matrix_[0 * 4 + 2] = matrix[2 * 5 + 0]; 1596 // this.matrix_[0 * 4 + 3] = matrix[3 * 5 + 0]; 1597 this.matrix_[1 * 4 + 0] = matrix[0 * 5 + 1]; 1598 this.matrix_[1 * 4 + 1] = matrix[1 * 5 + 1]; 1599 this.matrix_[1 * 4 + 2] = matrix[2 * 5 + 1]; 1600 // this.matrix_[1 * 4 + 3] = matrix[3 * 5 + 1]; 1601 this.matrix_[2 * 4 + 0] = matrix[0 * 5 + 2]; 1602 this.matrix_[2 * 4 + 1] = matrix[1 * 5 + 2]; 1603 this.matrix_[2 * 4 + 2] = matrix[2 * 5 + 2]; 1604 // this.matrix_[2 * 4 + 3] = matrix[3 * 5 + 2]; 1605 // this.matrix_[3 * 4 + 0] = matrix[0 * 5 + 3]; 1606 // this.matrix_[3 * 4 + 1] = matrix[1 * 5 + 3]; 1607 // this.matrix_[3 * 4 + 2] = matrix[2 * 5 + 3]; 1608 // this.matrix_[3 * 4 + 3] = matrix[3 * 5 + 3]; 1609 }; 1610 1611 /** 1612 * Resets this matrix to the initial one, i.e. the identify matrix. 1613 * @const 1614 */ 1615 createjs.WebGLRenderer.ColorMatrix.prototype.reset = function() { 1616 this.matrix_[0 * 4 + 0] = 1; 1617 this.matrix_[0 * 4 + 1] = 0; 1618 this.matrix_[0 * 4 + 2] = 0; 1619 // this.matrix_[0 * 4 + 3] = 0; 1620 this.matrix_[1 * 4 + 0] = 0; 1621 this.matrix_[1 * 4 + 1] = 1; 1622 this.matrix_[1 * 4 + 2] = 0; 1623 // this.matrix_[1 * 4 + 3] = 0; 1624 this.matrix_[2 * 4 + 0] = 0; 1625 this.matrix_[2 * 4 + 1] = 0; 1626 this.matrix_[2 * 4 + 2] = 1; 1627 // this.matrix_[2 * 4 + 3] = 0; 1628 // this.matrix_[3 * 4 + 0] = 0; 1629 // this.matrix_[3 * 4 + 1] = 0; 1630 // this.matrix_[3 * 4 + 2] = 0; 1631 // this.matrix_[3 * 4 + 3] = 1; 1632 }; 1633 1634 /** 1635 * Binds this transform to the specified context. 1636 * @param {createjs.WebGLRenderer.Context} context 1637 * @const 1638 */ 1639 createjs.WebGLRenderer.ColorMatrix.prototype.bindContext = function(context) { 1640 /// <param type="createjs.WebGLRenderer.Context" name="context"/> 1641 if (this.dirty_) { 1642 this.dirty_ = false; 1643 context.setColorMatrix(this.transform_, this.matrix_); 1644 } 1645 }; 1646 1647 /** 1648 * An inner class that encapsulates a color offset used by a color-matrix 1649 * filter. This renderer uses a uniform vector (red, green, blue, 0) to 1650 * represent a color. 1651 * @param {createjs.WebGLRenderer.Context} context 1652 * @param {WebGLProgram} program 1653 * @param {string} key 1654 * @param {number} red 1655 * @param {number} green 1656 * @param {number} blue 1657 * @constructor 1658 */ 1659 createjs.WebGLRenderer.Color = 1660 function(context, program, key, red, green, blue) { 1661 /// <param type="createjs.WebGLRenderer.Context" name="context"/> 1662 /// <param type="WebGLProgram" name="program"/> 1663 /// <param type="string" name="key"/> 1664 /// <param type="number" name="red"/> 1665 /// <param type="number" name="green"/> 1666 /// <param type="number" name="blue"/> 1667 /** 1668 * The dirty flag. 1669 * @type {boolean} 1670 * @private 1671 */ 1672 this.dirty_ = true; 1673 1674 /** 1675 * The uniform location representing this color. 1676 * @type {WebGLUniformLocation} 1677 * @private 1678 */ 1679 this.color_ = context.getColor(program, key); 1680 1681 /** 1682 * The red component. 1683 * @type {number} 1684 * @private 1685 */ 1686 this.red_ = red; 1687 1688 /** 1689 * The green component. 1690 * @type {number} 1691 * @private 1692 */ 1693 this.green_ = green; 1694 1695 /** 1696 * The blue component. 1697 * @type {number} 1698 * @private 1699 */ 1700 this.blue_ = blue; 1701 }; 1702 1703 /** 1704 * Changes this color. 1705 * @param {number} red 1706 * @param {number} green 1707 * @param {number} blue 1708 * @const 1709 */ 1710 createjs.WebGLRenderer.Color.prototype.set = function(red, green, blue) { 1711 /// <param type="number" name="red"/> 1712 /// <param type="number" name="green"/> 1713 /// <param type="number" name="blue"/> 1714 if (this.red_ != red || this.green_ != green || this.blue_ != blue) { 1715 this.dirty_ = true; 1716 this.red_ = red; 1717 this.green_ = green; 1718 this.blue_ = blue; 1719 } 1720 }; 1721 1722 /** 1723 * Binds this color to the specified context. 1724 * @param {createjs.WebGLRenderer.Context} context 1725 */ 1726 createjs.WebGLRenderer.Color.prototype.bindContext = function(context) { 1727 /// <param type="createjs.WebGLRenderer.Context" name="context"/> 1728 if (this.dirty_) { 1729 this.dirty_ = false; 1730 context.setColor(this.color_, this.red_, this.green_, this.blue_, 0); 1731 } 1732 }; 1733 1734 /** 1735 * An inner class that blends colors used by this renderer. 1736 * @param {createjs.WebGLRenderer.Context} context 1737 * @constructor 1738 */ 1739 createjs.WebGLRenderer.Blend = function(context) { 1740 /// <param type="createjs.WebGLRenderer.Context" name="context"/> 1741 /** 1742 * The dirty flag. 1743 * @type {boolean} 1744 * @private 1745 */ 1746 this.dirty_ = true; 1747 1748 /** 1749 * The composition ID. 1750 * @type {number} 1751 * @private 1752 */ 1753 this.operation_ = createjs.Renderer.Composition.SOURCE_OVER; 1754 1755 // Enable blending now to avoid enabling it every time when changing blend 1756 // functions. (This renderer always use blending with the add equation.) 1757 context.enableBlend(); 1758 }; 1759 1760 /** 1761 * Sets the color-blend operation. 1762 * @param {number} operation 1763 * @const 1764 */ 1765 createjs.WebGLRenderer.Blend.prototype.setComposition = function(operation) { 1766 /// <param type="number" name="operation"/> 1767 if (this.operation_ != operation) { 1768 this.dirty_ = true; 1769 this.operation_ = operation; 1770 } 1771 }; 1772 1773 /** 1774 * Binds this color-blending operation to the specified context. 1775 * @param {createjs.WebGLRenderer.Context} context 1776 * @const 1777 */ 1778 createjs.WebGLRenderer.Blend.prototype.bindContext = function(context) { 1779 /// <param type="createjs.WebGLRenderer.Context" name="context"/> 1780 if (this.dirty_) { 1781 this.dirty_ = false; 1782 context.setBlend(this.operation_); 1783 } 1784 }; 1785 1786 /** 1787 * An inner class that encapsulates a frame buffer with an attached texture. 1788 * @param {createjs.WebGLRenderer.Context} context 1789 * @param {number} width 1790 * @param {number} height 1791 * @param {number} mask 1792 * @constructor 1793 */ 1794 createjs.WebGLRenderer.Frame = function(context, width, height, mask) { 1795 /// <param type="createjs.WebGLRenderer.Context" name="context"/> 1796 /// <param type="number" name="width"/> 1797 /// <param type="number" name="height"/> 1798 /// <param type="number" name="mask"/> 1799 /** 1800 * The texture that stores the pixels of this framebuffer. 1801 * @type {WebGLTexture} 1802 * @private 1803 */ 1804 this.texture_ = context.createFrameTexture(width, height, mask); 1805 1806 /** 1807 * The framebuffer. 1808 * @type {WebGLFramebuffer} 1809 * @private 1810 */ 1811 this.buffer_ = context.createFramebuffer(this.texture_); 1812 }; 1813 1814 /** 1815 * Returns the texture associated with this frame buffer. 1816 * @return {WebGLTexture} 1817 * @const 1818 */ 1819 createjs.WebGLRenderer.Frame.prototype.getTexture = function() { 1820 /// <returns type="WebGLTexture"/> 1821 return this.texture_; 1822 }; 1823 1824 /** 1825 * Returns the frame buffer itself. 1826 * @return {WebGLFramebuffer} 1827 * @const 1828 */ 1829 createjs.WebGLRenderer.Frame.prototype.getBuffer = function() { 1830 /// <returns type="WebGLFramebuffer"/> 1831 return this.buffer_; 1832 }; 1833 1834 /** 1835 * Deletes the resources owned by this frame buffer. 1836 * @param {createjs.WebGLRenderer.Context} context 1837 * @const 1838 */ 1839 createjs.WebGLRenderer.Frame.prototype.destroy = function(context) { 1840 /// <param type="createjs.WebGLRenderer.Context" name="context"/> 1841 context.deleteFramebuffer(this.buffer_); 1842 context.deleteTexture(this.texture_); 1843 if (createjs.DEBUG) { 1844 this.buffer_ = null; 1845 this.texture_ = null; 1846 } 1847 }; 1848 1849 /** 1850 * An inner class that encapsulates a vertex shader and a fragment shader used 1851 * by this renderer. 1852 * @param {createjs.WebGLRenderer.Context} context 1853 * @param {string} vertex 1854 * @param {string} fragment 1855 * @constructor 1856 */ 1857 createjs.WebGLRenderer.Shaders = function(context, vertex, fragment) { 1858 /// <param type="createjs.WebGLRenderer.Context" name="context"/> 1859 /// <param type="string" name="vertex"/> 1860 /// <param type="string" name="fragment"/> 1861 /** 1862 * @const {WebGLShader} 1863 * @private 1864 */ 1865 this.vertex_ = context.createVertexShader(vertex); 1866 1867 /** 1868 * @const {WebGLShader} 1869 * @private 1870 */ 1871 this.fragment_ = context.createFragmentShader(fragment); 1872 }; 1873 1874 /** 1875 * Deletes the vertex shader and the fragment shader owned by this object. 1876 * @param {createjs.WebGLRenderer.Context} context 1877 * @const 1878 */ 1879 createjs.WebGLRenderer.Shaders.prototype.destroy = function(context) { 1880 /// <param type="createjs.WebGLRenderer.Context" name="context"/> 1881 context.deleteShader(this.vertex_); 1882 context.deleteShader(this.fragment_); 1883 }; 1884 1885 /** 1886 * Returns the vertex shader owned by this object. 1887 * @return {WebGLShader} 1888 * @const 1889 */ 1890 createjs.WebGLRenderer.Shaders.prototype.getVertex = function() { 1891 /// <returns type="WebGLShader"/> 1892 return this.vertex_; 1893 }; 1894 1895 /** 1896 * Returns the vertex shader owned by this object. 1897 * @return {WebGLShader} 1898 * @const 1899 */ 1900 createjs.WebGLRenderer.Shaders.prototype.getFragment = function() { 1901 /// <returns type="WebGLShader"/> 1902 return this.fragment_; 1903 }; 1904 1905 /** 1906 * An inner class that encapsulates the shader program and its parameters used 1907 * by this renderer. 1908 * @param {createjs.WebGLRenderer.Context} context 1909 * @param {number} scaleX 1910 * @param {number} scaleY 1911 * @constructor 1912 */ 1913 createjs.WebGLRenderer.Program = function(context, scaleX, scaleY) { 1914 /// <param type="createjs.WebGLRenderer.Context" name="context"/> 1915 /// <param type="number" name="scaleX"/> 1916 /// <param type="number" name="scaleY"/> 1917 var POSITION = 'p'; 1918 var TEXTURE = 't'; 1919 var SCREEN = 's'; 1920 var TRANSFORM = 'x'; 1921 var UVPOINT = 'u'; 1922 var COLOR = 'c'; 1923 var IMAGE = 'i'; 1924 var MATRIX = 'm'; 1925 var OFFSET = 'o'; 1926 var PIXEL = 'v'; 1927 var VERTEX = 1928 'attribute vec2 ' + POSITION + ';' + 1929 'attribute vec2 ' + TEXTURE + ';' + 1930 'uniform vec2 ' + SCREEN + ';' + 1931 'uniform mat3 ' + TRANSFORM + ';' + 1932 'varying vec2 ' + UVPOINT + ';' + 1933 'void main(){' + 1934 'vec3 v=' + TRANSFORM + '*' + 1935 'vec3(' + POSITION + '[0],' + POSITION + '[1],1);' + 1936 'gl_Position=vec4(' + 1937 'v[0]*' + SCREEN + '[0]-1.0,' + 1938 'v[1]*' + SCREEN + '[1]+1.0,' + 1939 '0,' + 1940 '1);' + 1941 UVPOINT + '=' + TEXTURE + ';' + 1942 '}'; 1943 var FRAGMENT = 1944 'precision mediump float;' + 1945 'varying vec2 ' + UVPOINT + ';' + 1946 'uniform vec4 ' + COLOR + ';' + 1947 'uniform mat4 ' + MATRIX + ';' + 1948 'uniform vec4 ' + OFFSET + ';' + 1949 'uniform sampler2D ' + IMAGE + ';' + 1950 'void main(){' + 1951 'vec4 ' + PIXEL + '=texture2D(' + IMAGE + ',' + UVPOINT + ');' + 1952 'gl_FragColor=' + COLOR + '*' + 1953 '(' + MATRIX + '*' + PIXEL + '+' + OFFSET + '*' + PIXEL + '[3]);' + 1954 '}'; 1955 1956 /** 1957 * The rendering context that owns this program. 1958 * @type {createjs.WebGLRenderer.Context} 1959 * @private 1960 */ 1961 this.context_ = context; 1962 1963 /** 1964 * The vertex shader and the fragment shader. (This program uses one vertex 1965 * shader and one fragment shader.) 1966 * @type {createjs.WebGLRenderer.Shaders} 1967 * @private 1968 */ 1969 this.shaders_ = new createjs.WebGLRenderer.Shaders( 1970 context, VERTEX, FRAGMENT); 1971 1972 /** 1973 * The shader program. 1974 * @type {WebGLProgram} 1975 * @private 1976 */ 1977 this.program_ = context.createProgram(this.shaders_.getVertex(), 1978 this.shaders_.getFragment()); 1979 1980 /** 1981 * The vector representing the output <canvas> element of this program. 1982 * @type {createjs.WebGLRenderer.Vector} 1983 * @private 1984 */ 1985 this.screen_ = new createjs.WebGLRenderer.Vector( 1986 context, this.program_, SCREEN, scaleX, -scaleY); 1987 1988 /** 1989 * The affine transform used by CreateJS. 1990 * @type {createjs.WebGLRenderer.Transform} 1991 * @private 1992 */ 1993 this.transform_ = new createjs.WebGLRenderer.Transform( 1994 context, this.program_, TRANSFORM); 1995 1996 /** 1997 * The destination rectangle. 1998 * @type {createjs.WebGLRenderer.Rectangle} 1999 * @private 2000 */ 2001 this.position_ = new createjs.WebGLRenderer.Rectangle( 2002 context, this.program_, POSITION, 0, 0); 2003 2004 /** 2005 * The source rectangle. 2006 * @type {createjs.WebGLRenderer.Rectangle} 2007 * @private 2008 */ 2009 this.texture_ = new createjs.WebGLRenderer.Rectangle( 2010 context, this.program_, TEXTURE, 1, 1); 2011 2012 /** 2013 * The alpha-composition value. 2014 * @type {createjs.WebGLRenderer.Alpha} 2015 * @private 2016 */ 2017 this.alpha_ = new createjs.WebGLRenderer.Alpha( 2018 context, this.program_, COLOR, 1); 2019 2020 /** 2021 * The color matrix. 2022 * @type {createjs.WebGLRenderer.ColorMatrix} 2023 * @private 2024 */ 2025 this.matrix_ = new createjs.WebGLRenderer.ColorMatrix( 2026 context, this.program_, MATRIX); 2027 2028 /** 2029 * The color offset. 2030 * @type {createjs.WebGLRenderer.Color} 2031 * @private 2032 */ 2033 this.offset_ = new createjs.WebGLRenderer.Color( 2034 context, this.program_, OFFSET, 0, 0, 0); 2035 2036 /** 2037 * The blending operation. 2038 * @type {createjs.WebGLRenderer.Blend} 2039 * @private 2040 */ 2041 this.blend_ = new createjs.WebGLRenderer.Blend(context); 2042 2043 if (createjs.DEBUG) { 2044 /** 2045 * The images that have their textures created by this program. 2046 * @type {Object.<string,number>} 2047 * @private 2048 */ 2049 this.ids_ = {}; 2050 } 2051 }; 2052 2053 /** 2054 * Returns the rendering context who owns this program. 2055 * @return {createjs.WebGLRenderer.Context} 2056 * @private 2057 */ 2058 createjs.WebGLRenderer.Program.prototype.getContext_ = function() { 2059 /// <returns type="createjs.WebGLRenderer.Context"/> 2060 return this.context_; 2061 }; 2062 2063 /** 2064 * Binds the texture attached to the specified image to this context. This 2065 * method creates a new one if the specified image does not have a texture. (It 2066 * is very slow to create a texture from an image. To avoid creating textures 2067 * every time when this renderer renders the image, this method caches the 2068 * created textures and re-uses them.) 2069 * @param {HTMLImageElement|HTMLCanvasElement|HTMLVideoElement} image 2070 * @private 2071 */ 2072 createjs.WebGLRenderer.Program.prototype.bindImage_ = function(image) { 2073 /// <param type="HTMLImageElement" name="image"/> 2074 // Try creating a cache for this image and return if the cache() method 2075 // actually creates one and binds it to this context. 2076 if (this.cache(image)) { 2077 return; 2078 } 2079 var context = this.getContext_(); 2080 context.bindTexture(/** @type {WebGLTexture} */ (image.texture_)); 2081 if (image.dirty_) { 2082 image.dirty_ = false; 2083 context.updateTexture(image); 2084 } 2085 }; 2086 2087 /** 2088 * Draws the texture bound to this program. 2089 * @private 2090 */ 2091 createjs.WebGLRenderer.Program.prototype.drawTexture_ = function() { 2092 var context = this.getContext_(); 2093 this.transform_.bindContext(context); 2094 this.position_.bindContext(context); 2095 this.texture_.bindContext(context); 2096 this.alpha_.bindContext(context); 2097 this.matrix_.bindContext(context); 2098 this.offset_.bindContext(context); 2099 this.blend_.bindContext(context); 2100 context.drawRectangle(); 2101 }; 2102 2103 /** 2104 * Deletes the resources owned by this program. 2105 * @param {createjs.WebGLRenderer.Context} context 2106 * @const 2107 */ 2108 createjs.WebGLRenderer.Program.prototype.destroy = function(context) { 2109 /// <param type="createjs.WebGLRenderer.Context" name="context"/> 2110 this.position_.destroy(context); 2111 this.texture_.destroy(context); 2112 context.deleteProgram(this.program_); 2113 this.shaders_.destroy(context); 2114 if (createjs.DEBUG) { 2115 this.position_ = null; 2116 this.texture_ = null; 2117 this.shaders_ = null; 2118 this.program_ = null; 2119 this.context_ = null; 2120 } 2121 }; 2122 2123 /** 2124 * Sets the specified transform. 2125 * @param {number} a 2126 * @param {number} b 2127 * @param {number} c 2128 * @param {number} d 2129 * @param {number} tx 2130 * @param {number} ty 2131 * @const 2132 */ 2133 createjs.WebGLRenderer.Program.prototype.setTransform = 2134 function(a, b, c, d, tx, ty) { 2135 /// <param type="number" name="a"/> 2136 /// <param type="number" name="b"/> 2137 /// <param type="number" name="c"/> 2138 /// <param type="number" name="d"/> 2139 /// <param type="number" name="tx"/> 2140 /// <param type="number" name="ty"/> 2141 this.transform_.set(a, b, c, d, tx, ty); 2142 }; 2143 2144 /** 2145 * Sets the alpha value. 2146 * @param {number} alpha 2147 * @const 2148 */ 2149 createjs.WebGLRenderer.Program.prototype.setAlpha = function(alpha) { 2150 /// <param type="number" name="alpha"/> 2151 this.alpha_.setAlpha(alpha); 2152 }; 2153 2154 /** 2155 * Sets the color matrix used by the color-matrix filter. 2156 * @param {Array.<number>} matrix 2157 * @const 2158 */ 2159 createjs.WebGLRenderer.Program.prototype.setColorMatrix = function(matrix) { 2160 /// <param type="Array" elementType="number" name="matrix"/> 2161 if (matrix) { 2162 var COLOR_SCALE = 1 / 255; 2163 this.matrix_.set(matrix); 2164 this.offset_.set(matrix[0 * 5 + 4] * COLOR_SCALE, 2165 matrix[1 * 5 + 4] * COLOR_SCALE, 2166 matrix[2 * 5 + 4] * COLOR_SCALE); 2167 } else { 2168 this.matrix_.reset(); 2169 this.offset_.set(0, 0, 0); 2170 } 2171 }; 2172 2173 /** 2174 * Sets the composition value. 2175 * @param {number} operation 2176 * @const 2177 */ 2178 createjs.WebGLRenderer.Program.prototype.setComposition = function(operation) { 2179 /// <param type="number" name="operation"/> 2180 this.blend_.setComposition(operation); 2181 }; 2182 2183 /** 2184 * Draws the specified image. 2185 * @param {HTMLImageElement|HTMLCanvasElement|HTMLVideoElement} image 2186 * @param {number} x 2187 * @param {number} y 2188 * @param {number} width 2189 * @param {number} height 2190 * @const 2191 */ 2192 createjs.WebGLRenderer.Program.prototype.drawImage = 2193 function(image, x, y, width, height) { 2194 /// <param type="HTMLImageElement" name="image"/> 2195 /// <param type="number" name="x"/> 2196 /// <param type="number" name="y"/> 2197 /// <param type="number" name="width"/> 2198 /// <param type="number" name="height"/> 2199 this.position_.set(x, y, width, height); 2200 this.texture_.set(0, 0, 1, 1); 2201 2202 // Bind the given image and draw it. 2203 this.bindImage_(image); 2204 this.drawTexture_(); 2205 }; 2206 2207 /** 2208 * Draws the specified part of an image. 2209 * @param {HTMLImageElement|HTMLCanvasElement} image 2210 * @param {number} srcX 2211 * @param {number} srcY 2212 * @param {number} srcWidth 2213 * @param {number} srcHeight 2214 * @param {number} x 2215 * @param {number} y 2216 * @param {number} width 2217 * @param {number} height 2218 * @const 2219 */ 2220 createjs.WebGLRenderer.Program.prototype.drawPartial = 2221 function(image, srcX, srcY, srcWidth, srcHeight, x, y, width, height) { 2222 /// <param type="HTMLImageElement" name="image"/> 2223 /// <param type="number" name="srcX"/> 2224 /// <param type="number" name="srcY"/> 2225 /// <param type="number" name="srcWidth"/> 2226 /// <param type="number" name="srcHeight"/> 2227 /// <param type="number" name="x"/> 2228 /// <param type="number" name="y"/> 2229 /// <param type="number" name="width"/> 2230 /// <param type="number" name="height"/> 2231 this.position_.set(x, y, width, height); 2232 var scaleX = 1 / image.width; 2233 var scaleY = 1 / image.height; 2234 this.texture_.set( 2235 srcX * scaleX, srcY * scaleY, srcWidth * scaleX, srcHeight * scaleY); 2236 2237 // Bind the given image and draw it. 2238 this.bindImage_(image); 2239 this.drawTexture_(); 2240 }; 2241 2242 /** 2243 * Creates a cache texture for the specified image and attaches it to the image. 2244 * @param {HTMLImageElement|HTMLCanvasElement|HTMLVideoElement} image 2245 * @return {boolean} 2246 * @const 2247 */ 2248 createjs.WebGLRenderer.Program.prototype.cache = function(image) { 2249 /// <param type="HTMLImageElement" name="image"/> 2250 /// <returns type="boolean"/> 2251 var context = this.getContext_(); 2252 var texture = /** @type {WebGLTexture} */ (image.texture_); 2253 var tid = /** @type {number} */ (image.tid_); 2254 if (texture && tid == context.getId()) { 2255 return false; 2256 } 2257 // Create a texture and attach it to the given image. Also attach an ID of the 2258 // context that creates this texture to release the texture when the context 2259 // is lost. 2260 if (createjs.DEBUG) { 2261 if (!this.ids_[image.id]) { 2262 this.ids_[image.id] = 0; 2263 } 2264 this.ids_[image.id]++; 2265 } 2266 texture = context.createTexture(image); 2267 image.texture_ = texture; 2268 image.tid_ = context.getId(); 2269 return true; 2270 }; 2271 2272 /** 2273 * Deletes the cache texture attached to the specified image. 2274 * @param {HTMLImageElement|HTMLCanvasElement|HTMLVideoElement} image 2275 * @const 2276 */ 2277 createjs.WebGLRenderer.Program.prototype.uncache = function(image) { 2278 /// <param type="HTMLImageElement" name="image"/> 2279 var texture = /** @type {WebGLTexture} */ (image.texture_); 2280 image.texture_ = null; 2281 var context = this.getContext_(); 2282 if (texture && context) { 2283 context.deleteTexture(texture); 2284 if (createjs.DEBUG) { 2285 --this.ids_[image.id]; 2286 } 2287 } 2288 }; 2289 2290 /** 2291 * Draws the specified frame buffer. 2292 * @param {createjs.WebGLRenderer.Frame} frame 2293 * @param {number} width 2294 * @param {number} height 2295 * @param {number} composition 2296 * @private 2297 * @const 2298 */ 2299 createjs.WebGLRenderer.Program.prototype.drawFrame = 2300 function(frame, width, height, composition) { 2301 /// <param type="createjs.WebGLRenderer.Frame" name="frame"/> 2302 /// <param type="number" name="width"/> 2303 /// <param type="number" name="height"/> 2304 /// <param type="number" name="composition"/> 2305 2306 // Reset all variables used by the shader program. The texture of a frame 2307 // buffer is an OpenGL texture and its origin is its bottom-left corner. On 2308 // the other hand, this program is for rendering HTML objects and assumes 2309 // their origins are their top-left corners. This code applies the following 2310 // affine transformation (a vertical flip) to absorb this coordinate 2311 // difference. 2312 // | 1 0 0 | 2313 // | 0 -1 0 | 2314 // | 0 height 1 | 2315 this.position_.set(0, 0, width, height); 2316 this.texture_.set(0, 0, 1, 1); 2317 this.setTransform(1, 0, 0, -1, 0, height); 2318 this.setAlpha(1); 2319 this.setComposition(composition); 2320 2321 // Bind the given frame buffer and draw it. 2322 this.getContext_().bindTexture(frame.getTexture()); 2323 this.drawTexture_(); 2324 }; 2325 2326 /** 2327 * Starts drawing to the drawing buffer with this program. 2328 * @param {number} scaleX 2329 * @param {number} scaleY 2330 * @private 2331 */ 2332 createjs.WebGLRenderer.Program.prototype.beginPaint_ = 2333 function(scaleX, scaleY) { 2334 /// <param type="number" name="scaleX"/> 2335 /// <param type="number" name="scaleY"/> 2336 this.screen_.set(scaleX, -scaleY); 2337 this.screen_.bindContext(this.getContext_()); 2338 }; 2339 2340 /** 2341 * Ends drawing to the drawing buffer with this program. 2342 * @private 2343 */ 2344 createjs.WebGLRenderer.Program.prototype.endPaint_ = function() { 2345 }; 2346 2347 /** 2348 * Returns the rendering context attached to this renderer. 2349 * @return {createjs.WebGLRenderer.Context} 2350 * @private 2351 */ 2352 createjs.WebGLRenderer.prototype.getContext_ = function() { 2353 /// <returns type="createjs.WebGLRenderer.Context"/> 2354 return this.context_; 2355 }; 2356 2357 /** 2358 * Returns the shader program used for drawing images or canvases. 2359 * @return {createjs.WebGLRenderer.Program} 2360 * @private 2361 */ 2362 createjs.WebGLRenderer.prototype.getProgram_ = function() { 2363 /// <returns type="createjs.WebGLRenderer.Program"/> 2364 if (!this.program_) { 2365 this.program_ = new createjs.WebGLRenderer.Program( 2366 this.context_, this.scaleX_, this.scaleY_); 2367 } 2368 return this.program_; 2369 }; 2370 2371 /** 2372 * Returns the framebuffer used for rendering a masked object. 2373 * @param {createjs.WebGLRenderer.Context} context 2374 * @return {createjs.WebGLRenderer.Frame} 2375 * @private 2376 * @const 2377 */ 2378 createjs.WebGLRenderer.prototype.getMask_ = function(context) { 2379 /// <param type="createjs.WebGLRenderer.Frame" name="context"/> 2380 /// <returns type="createjs.WebGLRenderer.Frame"/> 2381 if (!this.mask_) { 2382 this.mask_ = new createjs.WebGLRenderer.Frame( 2383 context, 2384 this.getWidth(), 2385 this.getHeight(), 2386 createjs.WebGLRenderer.gl.UNSIGNED_SHORT_4_4_4_4); 2387 } else { 2388 context.bindFramebuffer(this.mask_.getBuffer()); 2389 } 2390 context.clear(); 2391 return this.mask_; 2392 }; 2393 2394 /** 2395 * Draws a masked object to the drawing buffer. This method copies the pixels of 2396 * the off-screen framebuffer used for rendering masked objects to the drawing 2397 * buffer. 2398 * @param {createjs.WebGLRenderer.Frame} frame 2399 * @param {number} width 2400 * @param {number} height 2401 * @param {number} composition 2402 * @private 2403 */ 2404 createjs.WebGLRenderer.prototype.drawMask_ = 2405 function(frame, width, height, composition) { 2406 /// <param type="createjs.WebGLRenderer.Frame" name="frame"/> 2407 /// <param type="number" name="width"/> 2408 /// <param type="number" name="height"/> 2409 /// <param type="number" name="composition"/> 2410 this.program_.drawFrame( 2411 frame, width, height, createjs.Renderer.Composition.SOURCE_OVER); 2412 }; 2413 2414 /** 2415 * Changes the scissor rectangle. This renderer uses two scissor rectangles: 2416 * * A viewport rectangle used by a game to render only the specified part of 2417 * the output <canvas> element, and; 2418 * * A bounding box of a mask. 2419 * This method automatically enables the scissor test and sets the specified 2420 * rectangle. (A scissor test is not so fast on some Android 4.0 devices and 2421 * this renderer uses it only when it has to.) 2422 * @param {createjs.WebGLRenderer.Context} context 2423 * @param {createjs.BoundingBox} scissor 2424 * @param {number} height 2425 * @private 2426 */ 2427 createjs.WebGLRenderer.prototype.updateScissor_ = 2428 function(context, scissor, height) { 2429 /// <param type="createjs.WebGLRenderer.Context" name="context"/> 2430 /// <param type="createjs.BoundingBox" name="scissor"/> 2431 /// <param type="number" name="height"/> 2432 if (this.scissor_ && this.scissor_.isEqual(scissor)) { 2433 return; 2434 } 2435 // Enable the scissor test when this renderer has not enabled it, i.e. this 2436 // renderer does not have either a scissor rectangle or a clipping rectangle. 2437 if (!this.scissor_ && !this.viewport_) { 2438 context.enableClip(); 2439 } 2440 this.scissor_ = scissor; 2441 context.updateClip(scissor, height); 2442 }; 2443 2444 /** 2445 * Destroys the scissor rectangle. This method also restores the scissor 2446 * rectangle to the viewport rectangle. 2447 * @param {createjs.WebGLRenderer.Context} context 2448 * @param {number} height 2449 * @private 2450 */ 2451 createjs.WebGLRenderer.prototype.destroyScissor_ = function(context, height) { 2452 /// <param type="createjs.WebGLRenderer.Context" name="context"/> 2453 /// <param type="number" name="height"/> 2454 if (this.scissor_) { 2455 if (!this.viewport_) { 2456 context.disableClip(); 2457 } else { 2458 context.updateClip(this.viewport_, height); 2459 } 2460 this.scissor_ = null; 2461 } 2462 }; 2463 2464 /** 2465 * Draws a render object to the output framebuffer. 2466 * @param {createjs.WebGLRenderer.Context} context 2467 * @param {number} width 2468 * @param {number} height 2469 * @param {createjs.Renderer.RenderObject} object 2470 * @private 2471 */ 2472 createjs.WebGLRenderer.prototype.drawObject_ = 2473 function(context, width, height, object) { 2474 /// <param type="createjs.WebGLRenderer.Context" name="context"/> 2475 /// <param type="number" name="width"/> 2476 /// <param type="number" name="height"/> 2477 /// <param type="createjs.Renderer.RenderObject" name="object"/> 2478 if (createjs.DEBUG) { 2479 ++createjs.Counter.paintedObjects; 2480 } 2481 var scissor = object.getClip(); 2482 if (!scissor || !scissor.getMethod()) { 2483 this.destroyScissor_(context, height); 2484 } else if (!scissor.getShape()) { 2485 this.updateScissor_(context, scissor.getBox(), height); 2486 } else { 2487 // It is tricky to draw a masked object. This code draws a masked object 2488 // with the steps listed below. 2489 // 1. Get an empty frame buffer used for composing a render object with a 2490 // mask; 2491 // 2. Enable a scissor test with the bounding box of the mask to prevent 2492 // the render object from being rendered outside of the mask; 2493 // 3. Draw the render object with the SOURCE_OVER operation; 2494 // 4. Draw the mask bitmap (a bitmap filled in white) with the 2495 // DESTINATION-IN operation to get the intersection between the render 2496 // object and the mask, and; 2497 // 5. Draw the frame buffer to this frame buffer. 2498 var frame = this.getMask_(context); 2499 if (!this.scissor_) { 2500 context.enableClip(); 2501 } 2502 context.updateClip(scissor.getBox(), height); 2503 object.beginPaintObject(this); 2504 object.paintObject(this); 2505 var shape = scissor.getShape(); 2506 shape.beginPaintObject(this); 2507 shape.paintObject(this); 2508 if (!this.scissor_) { 2509 context.disableClip(); 2510 } else { 2511 context.updateClip(this.scissor_, height); 2512 } 2513 context.bindFramebuffer(null); 2514 this.drawMask_(frame, width, height, scissor.getComposition()); 2515 return; 2516 } 2517 object.beginPaintObject(this); 2518 object.paintObject(this); 2519 }; 2520 2521 /** @override */ 2522 createjs.WebGLRenderer.prototype.destroy = function() { 2523 var canvas = this.getCanvas(); 2524 if (canvas) { 2525 canvas.removeEventListener('webglcontextlost', this, false); 2526 canvas.removeEventListener('webglcontextrestored', this, false); 2527 if (createjs.DEBUG) { 2528 document.removeEventListener('keyup', this, false); 2529 } 2530 } 2531 var context = this.getContext_(); 2532 if (context) { 2533 if (this.mask_) { 2534 this.mask_.destroy(context); 2535 this.mask_ = null; 2536 } 2537 var layer = this.layer_; 2538 if (layer) { 2539 layer.destroy(context); 2540 this.layer_ = null; 2541 } 2542 var program = this.program_; 2543 if (program) { 2544 program.destroy(context); 2545 this.program_ = null; 2546 } 2547 } 2548 }; 2549 2550 /** @override */ 2551 createjs.WebGLRenderer.prototype.setTransformation = 2552 function(a, b, c, d, tx, ty) { 2553 /// <param type="number" name="a"/> 2554 /// <param type="number" name="b"/> 2555 /// <param type="number" name="c"/> 2556 /// <param type="number" name="d"/> 2557 /// <param type="number" name="tx"/> 2558 /// <param type="number" name="ty"/> 2559 this.getProgram_().setTransform(a, b, c, d, tx, ty); 2560 }; 2561 2562 /** @override */ 2563 createjs.WebGLRenderer.prototype.setAlpha = function(alpha) { 2564 /// <param type="number" name="alpha"/> 2565 this.getProgram_().setAlpha(alpha); 2566 }; 2567 2568 /** @override */ 2569 createjs.WebGLRenderer.prototype.setColorMatrix = function(matrix) { 2570 /// <param type="Array" elementType="number" name="matrix"/> 2571 this.getProgram_().setColorMatrix(matrix); 2572 }; 2573 2574 /** @override */ 2575 createjs.WebGLRenderer.prototype.setComposition = function(operation) { 2576 /// <param type="number" name="operation"/> 2577 this.getProgram_().setComposition(operation); 2578 }; 2579 2580 /** @override */ 2581 createjs.WebGLRenderer.prototype.drawCanvas = 2582 function(canvas, x, y, width, height) { 2583 /// <param type="HTMLCanvasElement" name="canvas"/> 2584 /// <param type="number" name="x"/> 2585 /// <param type="number" name="y"/> 2586 /// <param type="number" name="width"/> 2587 /// <param type="number" name="height"/> 2588 this.getProgram_().drawImage(canvas, x, y, width, height); 2589 }; 2590 2591 /** @override */ 2592 createjs.WebGLRenderer.prototype.getExtensions = function() { 2593 /// <returns type="number"/> 2594 if (createjs.UserAgent.isMSIE()) { 2595 return 0; 2596 } 2597 return createjs.Renderer.Extension.VIDEO; 2598 }; 2599 2600 /** @override */ 2601 createjs.WebGLRenderer.prototype.drawVideo = 2602 function (video, x, y, width, height) { 2603 /// <param type="HTMLVideoElement" name="video"/> 2604 /// <param type="number" name="x"/> 2605 /// <param type="number" name="y"/> 2606 /// <param type="number" name="width"/> 2607 /// <param type="number" name="height"/> 2608 this.getProgram_().drawImage(video, x, y, width, height); 2609 }; 2610 2611 /** @override */ 2612 createjs.WebGLRenderer.prototype.drawPartial = 2613 function(image, srcX, srcY, srcWidth, srcHeight, x, y, width, height) { 2614 /// <param type="HTMLImageElement" name="image"/> 2615 /// <param type="number" name="srcX"/> 2616 /// <param type="number" name="srcY"/> 2617 /// <param type="number" name="srcWidth"/> 2618 /// <param type="number" name="srcHeight"/> 2619 /// <param type="number" name="x"/> 2620 /// <param type="number" name="y"/> 2621 /// <param type="number" name="width"/> 2622 /// <param type="number" name="height"/> 2623 this.getProgram_().drawPartial( 2624 image, srcX, srcY, srcWidth, srcHeight, x, y, width, height); 2625 }; 2626 2627 /** @override */ 2628 createjs.WebGLRenderer.prototype.addObject = function(object) { 2629 /// <param type="createjs.Renderer.RenderObject" name="object"/> 2630 var context = this.getContext_(); 2631 if (context.getId()) { 2632 this.drawObject_( 2633 context, this.getWidth(), this.getHeight(), object); 2634 this.dirty_ = true; 2635 if (createjs.DEBUG) { 2636 ++createjs.Counter.visibleObjects; 2637 } 2638 } 2639 }; 2640 2641 /** @override */ 2642 createjs.WebGLRenderer.prototype.uncache = function(image) { 2643 /// <param type="HTMLImageElement" name="image"/> 2644 this.getProgram_().uncache(image); 2645 }; 2646 2647 /** @override */ 2648 createjs.WebGLRenderer.prototype.begin = function() { 2649 // Synchronize the viewport (and a uniform vector) with the <canvas> width and 2650 // its height. 2651 var canvas = this.getCanvas(); 2652 var width = canvas.width; 2653 var height = canvas.height; 2654 if (width != this.getWidth() || height != this.getHeight()) { 2655 this.setWidth(width); 2656 this.setHeight(height); 2657 this.scaleX_ = 2 / width; 2658 this.scaleY_ = 2 / height; 2659 this.getContext_().setViewport(width, height); 2660 } 2661 this.getProgram_().beginPaint_(this.scaleX_, this.scaleY_); 2662 }; 2663 2664 /** @override */ 2665 createjs.WebGLRenderer.prototype.paint = function(time) { 2666 /// <param type="number" name="time"/> 2667 // Exit this renderer loses its WebGL context. 2668 if (!this.getContext_().getId()) { 2669 return; 2670 } 2671 // Clear the drawing buffer only when this renderer have to draw a blank 2672 // page. (Some Android 4.1.x browsers needs to trigger DOM reflow in clearing 2673 // the drawing buffer, i.e. it is very slow to manually clear the output 2674 // framebuffer. This renderer clears the output framebuffer only when this 2675 // renderer has to clear it to avoid DOM reflow.) 2676 var program = this.getProgram_(); 2677 var context = this.getContext_(); 2678 if (!this.dirty_) { 2679 context.clear(); 2680 // Trigger DOM reflow on Android 4.1.x browsers that have the bug: 2681 // <https://code.google.com/p/android/issues/detail?id=39247>. 2682 // This bug happens in clearing the drawing buffer on Android 4.1.x browsers 2683 // that implement WebGL (e.g. Softbank Mobile ARROWS A 101F, ASUS Memo Pad 2684 // ME173X). 2685 this.updateCanvas('webgl'); 2686 } 2687 if (this.scissor_) { 2688 context.disableClip(); 2689 this.scissor_ = null; 2690 } 2691 program.endPaint_(); 2692 this.dirty_ = false; 2693 }; 2694 2695 /** @override */ 2696 createjs.WebGLRenderer.prototype.handleEvent = function(event) { 2697 /// <param type="KeyboardEvent" name="event"/> 2698 if (createjs.DEBUG && event.type == 'keyup') { 2699 var keyEvent = /** @type {KeyboardEvent} */ (event); 2700 var keyCode = keyEvent.keyCode; 2701 if (keyCode == createjs.Event.KeyCodes.E) { 2702 if (!createjs.WebGLRenderer.ticker_) { 2703 createjs.WebGLRenderer.ticker_ = createjs.Ticker.getInterval(); 2704 createjs.Ticker.setInterval(1000); 2705 } else { 2706 createjs.Ticker.setInterval(createjs.WebGLRenderer.ticker_); 2707 createjs.WebGLRenderer.ticker_ = 0; 2708 } 2709 } 2710 return; 2711 } 2712 createjs.assert(event.type == 'webglcontextlost' || 2713 event.type == 'webglcontextrestored'); 2714 if (event.type == 'webglcontextlost') { 2715 // Release the shader program and the frame buffers used by this renderer. 2716 // (Textures will be released the next time when this renderer accesses 2717 // them.) 2718 this.layer_ = null; 2719 this.program_ = null; 2720 this.getContext_().setId(0); 2721 2722 // Wait for a drawing buffer to be restored. 2723 event.preventDefault(); 2724 } else { 2725 // Assign a new context ID to recreate the textures created by the released 2726 // context. 2727 this.getContext_().setId(++createjs.WebGLRenderer.id); 2728 } 2729 }; 2730