UNPKG

odin

Version:

Node.js Canvas/WebGL Javascript Game Framework

1,160 lines (884 loc) 41.8 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>JSDoc: Source: core/renderer/renderer_2d.js</title> <script src="scripts/prettify/prettify.js"> </script> <script src="scripts/prettify/lang-css.js"> </script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css"> </head> <body> <div id="main"> <h1 class="page-title">Source: core/renderer/renderer_2d.js</h1> <section> <article> <pre class="prettyprint source"><code>if (typeof(define) !== "function") { var define = require("amdefine")(module); } define([ "odin/base/event_emitter", "odin/base/device", "odin/base/dom", "odin/base/util", "odin/math/mathf", "odin/math/color", "odin/math/vec2", "odin/math/vec4", "odin/math/mat4", "odin/core/enums", "odin/core/game/log", "odin/core/renderer/canvas" ], function(EventEmitter, Device, Dom, util, Mathf, Color, Vec2, Vec4, Mat4, Enums, Log, Canvas) { "use strict"; var Blending = Enums.Blending, ShadowMapType = Enums.ShadowMapType, CullFace = Enums.CullFace, Side = Enums.Side, LightType = Enums.LightType, Shading = Enums.Shading, FilterMode = Enums.FilterMode, TextureFormat = Enums.TextureFormat, TextureWrap = Enums.TextureWrap, getWebGLContext = Dom.getWebGLContext, addEvent = Dom.addEvent, removeEvent = Dom.removeEvent, createProgram = Dom.createProgram, parseUniformsAttributes = Dom.parseUniformsAttributes, getUniformsAttributes = Dom.getUniformsAttributes, merge = util.merge, copy = util.copy, max = Math.max, floor = Math.floor, clamp = Mathf.clamp, isPowerOfTwo = Mathf.isPowerOfTwo, defineProperty = Object.defineProperty; function Renderer(opts) { opts || (opts = {}); EventEmitter.call(this); var _this = this, _projScreenMatrix = new Mat4, _mat4 = new Mat4, _gl, _extensions, _canvas, _element, _context = false; this.attributes = merge(opts.attributes || {}, { alpha: true, antialias: true, depth: false, premultipliedAlpha: true, preserveDrawingBuffer: false, stencil: true }); this.autoClear = opts.autoClear != undefined ? opts.autoClear : true; this.autoClearColor = opts.autoClearColor != undefined ? opts.autoClearColor : true; this.autoClearDepth = opts.autoClearDepth != undefined ? opts.autoClearDepth : false; this.autoClearStencil = opts.autoClearStencil != undefined ? opts.autoClearStencil : true; var _spriteShader, _spriteBuffers; this.init = function(canvas) { if (_canvas) this.clear(); _canvas = canvas; _element = canvas.element; _lastUniforms = {}; initGL(); _context = true; setDefaultGLState(); addEvent(_element, "webglcontextlost", handleWebGLContextLost, this); addEvent(_element, "webglcontextrestored", handleWebGLContextRestored, this); _spriteBuffers = {}; createBuffer(_spriteBuffers, "vertexBuffer", new Float32Array([-0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, -0.5 ])); createBuffer(_spriteBuffers, "uvBuffer", new Float32Array([ 0, 0, 0, 1, 1, 0, 1, 1 ])); _spriteBuffers.vertexCount = 4; _spriteShader = createShader(sprite_vertex, sprite_fragment); return this; }; this.clear = function() { if (!_canvas) return this; removeEvent(element, "webglcontextlost", handleWebGLContextLost, this); removeEvent(element, "webglcontextrestored", handleWebGLContextRestored, this); _gl = undefined _canvas = undefined; _element = undefined; _context = false; _extensions = undefined; _spriteBuffers = undefined; _spriteShader = undefined; _precision = "highp"; _maxAnisotropy = 0; _maxTextures = 0; _maxVertexTextures = 0; _maxTextureSize = 0; _maxCubeTextureSize = 0; _maxRenderBufferSize = 0; _maxUniforms = 0; _maxVaryings = 0; _maxAttributes = 0; _lastCamera = undefined; _lastResizeFn = undefined; _lastScene = undefined; _viewportX = 0; _viewportY = 0; _viewportWidth = 1; _viewportHeight = 1; _lastBlending = -1; _lastClearColor.set(0, 0, 0); _lastCullFace = -1; _lastDepthTest = -1; _lastDepthWrite = -1; _lastLineWidth = -1; _lastUniforms = undefined; _lastBuffer = undefined, _lastShader = undefined; return this; }; defineProperty(this, "gl", { get: function() { return _gl; } }); defineProperty(this, "canvas", { get: function() { return _canvas; } }); defineProperty(this, "element", { get: function() { return _element; } }); defineProperty(this, "precision", { get: function() { return _precision; } }); defineProperty(this, "maxAnisotropy", { get: function() { return _maxAnisotropy; } }); defineProperty(this, "maxTextures", { get: function() { return _maxTextures; } }); defineProperty(this, "maxVertexTextures", { get: function() { return _maxVertexTextures; } }); defineProperty(this, "maxTextureSize", { get: function() { return _maxTextureSize; } }); defineProperty(this, "maxCubeTextureSize", { get: function() { return _maxCubeTextureSize; } }); defineProperty(this, "maxRenderBufferSize", { get: function() { return _maxRenderBufferSize; } }); defineProperty(this, "maxUniforms", { get: function() { return _maxUniforms; } }); defineProperty(this, "maxVaryings", { get: function() { return _maxVaryings; } }); defineProperty(this, "maxAttributes", { get: function() { return _maxAttributes; } }); var _viewportX = 0, _viewportY = 0, _viewportWidth = 1, _viewportHeight = 1; function setViewport(x, y, width, height) { x || (x = 0); y || (y = 0); width || (width = _canvas.pixelWidth); height || (height = _canvas.pixelHeight); if (_viewportX !== x || _viewportY !== y || _viewportWidth !== width || _viewportHeight !== height) { _viewportX = x; _viewportY = y; _viewportWidth = width; _viewportHeight = height; _gl.viewport(x, y, width, height); } } this.setViewport = setViewport; var _lastDepthTest = -1; function setDepthTest(depthTest) { if (_lastDepthTest !== depthTest) { if (depthTest) { _gl.enable(_gl.DEPTH_TEST); } else { _gl.disable(_gl.DEPTH_TEST); } _lastDepthTest = depthTest; } } this.setDepthTest = setDepthTest; var _lastDepthWrite = -1; function setDepthWrite(depthWrite) { if (_lastDepthWrite !== depthWrite) { _gl.depthMask(depthWrite); _lastDepthWrite = depthWrite; } } this.setDepthWrite = setDepthWrite; var _lastLineWidth = 1; function setLineWidth(width) { if (_lastLineWidth !== width) { _gl.lineWidth(width); _lastLineWidth = width; } } this.setLineWidth = setLineWidth; var _lastCullFace = -1, _cullFaceDisabled = true; function setCullFace(cullFace) { if (_lastCullFace !== cullFace) { if (!_lastCullFace || _lastCullFace === CullFace.None) _cullFaceDisabled = true; if (cullFace === CullFace.Front) { if (_cullFaceDisabled) _gl.enable(_gl.CULL_FACE); _gl.cullFace(_gl.FRONT); } else if (cullFace === CullFace.Back) { if (_cullFaceDisabled) _gl.enable(_gl.CULL_FACE); _gl.cullFace(_gl.BACK); } else if (cullFace === CullFace.FrontBack) { if (_cullFaceDisabled) _gl.enable(_gl.CULL_FACE); _gl.cullFace(_gl.FRONT_AND_BACK); } else { _gl.disable(_gl.CULL_FACE); _lastCullFace = CullFace.None; return; } _lastCullFace = cullFace; } } this.setCullFace = setCullFace; var _lastBlending = -1; function setBlending(blending) { if (blending !== _lastBlending) { if (blending === Blending.None) { _gl.disable(_gl.BLEND); } else if (blending === Blending.Additive) { _gl.enable(_gl.BLEND); _gl.blendEquation(_gl.FUNC_ADD); _gl.blendFunc(_gl.SRC_ALPHA, _gl.ONE); } else if (blending === Blending.Subtractive) { _gl.enable(_gl.BLEND); _gl.blendEquation(_gl.FUNC_ADD); _gl.blendFunc(_gl.ZERO, _gl.ONE_MINUS_SRC_COLOR); } else if (blending === Blending.Muliply) { _gl.enable(_gl.BLEND); _gl.blendEquation(_gl.FUNC_ADD); _gl.blendFunc(_gl.ZERO, _gl.SRC_COLOR); } else if (blending === Blending.Default) { _gl.enable(_gl.BLEND); _gl.blendEquationSeparate(_gl.FUNC_ADD, _gl.FUNC_ADD); _gl.blendFuncSeparate(_gl.SRC_ALPHA, _gl.ONE_MINUS_SRC_ALPHA, _gl.ONE, _gl.ONE_MINUS_SRC_ALPHA); _lastBlending = Blending.Default; return; } _lastBlending = blending; } } this.setBlending = setBlending; function setScissor(x, y, width, height) { _gl.scissor(x, y, width, height); }; this.setScissor = setScissor; var _clearColor = new Color, _clearAlpha = 1; function setClearColor(color, alpha) { alpha || (alpha = 1); if (!_clearColor.equals(color) || alpha !== _clearAlpha) { _clearColor.copy(color); _clearAlpha = alpha; this.context.clearColor(_clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha); } } this.setClearColor = setClearColor; function clearCanvas(color, depth, stencil) { var bits = 0; if (color === undefined || color) bits |= _gl.COLOR_BUFFER_BIT; if (depth === undefined || depth) bits |= _gl.DEPTH_BUFFER_BIT; if (stencil === undefined || stencil) bits |= _gl.STENCIL_BUFFER_BIT; _gl.clear(bits); } this.clearCanvas = clearCanvas; function clearColor() { _gl.clear(_gl.COLOR_BUFFER_BIT); } this.clearColor = clearColor; function clearDepth() { _gl.clear(_gl.DEPTH_BUFFER_BIT); } this.clearDepth = clearDepth; function clearStencil() { _gl.clear(_gl.STENCIL_BUFFER_BIT); } this.clearStencil = clearStencil; var _lastUniforms; function setUniform(force, location, value, key, type, isArray, index) { var lastUniforms = _lastUniforms, state; if (isArray) { lastUniforms = lastUniforms[key] || (lastUniforms[key] = []); key = index; } state = lastUniforms[key]; if (type === "int") { if (force || state !== value) { _gl.uniform1i(location, value); lastUniforms[key] = value; } } else if (type === "float") { if (force || state !== value) { _gl.uniform1f(location, value); lastUniforms[key] = value; } } else if (type === "vec2") { if (force || !state || (state.x !== value.x || state.y !== value.y)) { _gl.uniform2f(location, value.x, value.y); state || (lastUniforms[key] = state = value.clone()); state.x = value.x; state.y = value.y; } } else if (type === "vec3") { if (force || !state || (state.x !== value.x || state.y !== value.y || state.z !== value.z)) { _gl.uniform3f(location, value.x, value.y, value.z); state || (lastUniforms[key] = state = value.clone()); state.x = value.x; state.y = value.y; state.z = value.z; } } else if (type === "vec4") { if (force || !state || (state.x !== value.x || state.y !== value.y || state.z !== value.z || state.w !== value.w)) { _gl.uniform3f(location, value.x, value.y, value.z, value.w); state || (lastUniforms[key] = state = value.clone()); state.x = value.x; state.y = value.y; state.z = value.z; state.w = value.w; } } else if (type === "mat2") { if (force || !state || !state.equals(value)) { _gl.uniformMatrix2fv(force, location, false, value.elements); (state || (lastUniforms[key] = state = value.clone())).copy(value); } } else if (type === "mat3") { if (force || !state || !state.equals(value)) { _gl.uniformMatrix3fv(force, location, false, value.elements); (state || (lastUniforms[key] = state = value.clone())).copy(value); } } else if (type === "mat4") { if (force || !state || !state.equals(value)) { _gl.uniformMatrix4fv(force, location, false, value.elements); (state || (lastUniforms[key] = state = value.clone())).copy(value); } } else if (type === "sampler2D") { setTexture(force, location, value, key); } } function setUniform1i(force, location, value, key, isArray, index) { var lastUniforms = _lastUniforms, state; if (isArray) { lastUniforms = lastUniforms[key] || (lastUniforms[key] = []); key = index; } state = lastUniforms[key]; if (force || state !== value) { _gl.uniform1i(location, value); lastUniforms[key] = value; } } function setUniform1f(force, location, value, key, isArray, index) { var lastUniforms = _lastUniforms, state; if (isArray) { lastUniforms = lastUniforms[key] || (lastUniforms[key] = []); key = index; } state = lastUniforms[key]; if (force || state !== value) { _gl.uniform1f(location, value); lastUniforms[key] = value; } } function setUniform2f(force, location, value, key, isArray, index) { var lastUniforms = _lastUniforms, state; if (isArray) { lastUniforms = lastUniforms[key] || (lastUniforms[key] = []); key = index; } state = lastUniforms[key]; if (force || !state || (state.x !== value.x || state.y !== value.y)) { _gl.uniform2f(location, value.x, value.y); state || (lastUniforms[key] = state = value.clone()); state.x = value.x; state.y = value.y; } } function setUniform3f(force, location, value, key, isArray, index) { var lastUniforms = _lastUniforms, state; if (isArray) { lastUniforms = lastUniforms[key] || (lastUniforms[key] = []); key = index; } state = lastUniforms[key]; if (force || !state || (state.x !== value.x || state.y !== value.y || state.z !== value.z)) { _gl.uniform3f(location, value.x, value.y, value.z); state || (lastUniforms[key] = state = value.clone()); state.x = value.x; state.y = value.y; state.z = value.z; } } function setUniform4f(force, location, value, key, isArray, index) { var lastUniforms = _lastUniforms, state; if (isArray) { lastUniforms = lastUniforms[key] || (lastUniforms[key] = []); key = index; } state = lastUniforms[key]; if (force || !state || (state.x !== value.x || state.y !== value.y || state.z !== value.z || state.w !== value.w)) { _gl.uniform4f(location, value.x, value.y, value.z, value.w); state || (lastUniforms[key] = state = value.clone()); state.x = value.x; state.y = value.y; state.z = value.z; state.w = value.w; } } function setUniformMatrix2fv(force, location, value, key, isArray, index) { var lastUniforms = _lastUniforms, state; if (isArray) { lastUniforms = lastUniforms[key] || (lastUniforms[key] = []); key = index; } state = lastUniforms[key]; if (force || !state || !state.equals(value)) { _gl.uniformMatrix2fv(location, false, value.elements); (state || (lastUniforms[key] = state = value.clone())).copy(value); } } function setUniformMatrix3fv(force, location, value, key, isArray, index) { var lastUniforms = _lastUniforms, state; if (isArray) { lastUniforms = lastUniforms[key] || (lastUniforms[key] = []); key = index; } state = lastUniforms[key]; if (force || !state || !state.equals(value)) { _gl.uniformMatrix3fv(location, false, value.elements); (state || (lastUniforms[key] = state = value.clone())).copy(value); } } function setUniformMatrix4fv(force, location, value, key, isArray, index) { var lastUniforms = _lastUniforms, state; if (isArray) { lastUniforms = lastUniforms[key] || (lastUniforms[key] = []); key = index; } state = lastUniforms[key]; if (force || !state || !state.equals(value)) { _gl.uniformMatrix4fv(location, false, value.elements); (state || (lastUniforms[key] = state = value.clone())).copy(value); } } var _textureIndex = 0; function setTexture(force, location, texture, key) { if (!texture || !texture.raw) return; var index, glTexture; if (_textureIndex >= _maxTextures) Log.warn("Renderer setTexure: using " + _textureIndex + " texture units, GPU only supports " + _maxTextures); if (!texture.needsUpdate && (glTexture = texture._webgl)) { index = _textureIndex++; _gl.activeTexture(_gl.TEXTURE0 + index); _gl.bindTexture(_gl.TEXTURE_2D, glTexture); setUniform1i(force, location, index, key); return; } glTexture = texture._webgl || (texture._webgl = _gl.createTexture()); index = _textureIndex++; var raw = texture.raw, TFA = _extensions.EXT_texture_filter_anisotropic, isPOT = isPowerOfTwo(raw.width) && isPowerOfTwo(raw.height), anisotropy = clamp(texture.anisotropy || 1, 1, _maxAnisotropy), TEXTURE_2D = _gl.TEXTURE_2D, mipmap = texture.mipmap, filter = texture.filter, format = texture.format, wrap = texture.wrap, WRAP, MAG_FILTER, MIN_FILTER, FORMAT; if (filter === FilterMode.None) { MAG_FILTER = _gl.NEAREST; if (mipmap && isPOT) { MIN_FILTER = _gl.LINEAR_MIPMAP_NEAREST; } else { MIN_FILTER = _gl.NEAREST; } } else { //FilterMode.Linear MAG_FILTER = _gl.LINEAR; if (mipmap && isPOT) { MIN_FILTER = _gl.LINEAR_MIPMAP_LINEAR; } else { MIN_FILTER = _gl.LINEAR; } } if (format === TextureFormat.RGB) { FORMAT = _gl.RGB; } else if (format === TextureFormat.RGBA) { FORMAT = _gl.RGBA; } else if (format === TextureFormat.LuminanceAlpha) { FORMAT = _gl.LUMINANCE_ALPHA; } else if (format === TextureFormat.Luminance) { FORMAT = _gl.LUMINANCE; } else if (format === TextureFormat.Alpha) { FORMAT = _gl.ALPHA; } if (wrap === TextureWrap.Clamp) { WRAP = _gl.CLAMP_TO_EDGE; } else if (wrap === TextureWrap.MirrorRepeat) { WRAP = isPOT ? _gl.MIRRORED_REPEAT : _gl.CLAMP_TO_EDGE; } else { //TextureWrap.Repeat WRAP = isPOT ? _gl.REPEAT : _gl.CLAMP_TO_EDGE; } _gl.activeTexture(_gl.TEXTURE0 + index); _gl.bindTexture(TEXTURE_2D, glTexture); _gl.uniform1i(location, index); _gl.pixelStorei(_gl.UNPACK_FLIP_Y_WEBGL, texture.flipY ? 0 : 1); _gl.pixelStorei(_gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha ? 1 : 0); _gl.texImage2D(TEXTURE_2D, 0, FORMAT, FORMAT, _gl.UNSIGNED_BYTE, clampToMaxSize(raw, _maxTextureSize)); _gl.texParameteri(TEXTURE_2D, _gl.TEXTURE_MAG_FILTER, MAG_FILTER); _gl.texParameteri(TEXTURE_2D, _gl.TEXTURE_MIN_FILTER, MIN_FILTER); _gl.texParameteri(TEXTURE_2D, _gl.TEXTURE_WRAP_S, WRAP); _gl.texParameteri(TEXTURE_2D, _gl.TEXTURE_WRAP_T, WRAP); if (TFA) _gl.texParameterf(TEXTURE_2D, TFA.TEXTURE_MAX_ANISOTROPY_EXT, anisotropy); if (mipmap && isPOT) _gl.generateMipmap(TEXTURE_2D); texture.needsUpdate = false; } function clampToMaxSize(image, maxSize) { if (image.height &lt;= maxSize && image.width &lt;= maxSize) return image; var maxDim = 1 / max(image.width, image.height), newWidth = floor(image.width * maxSize * maxDim), newHeight = floor(image.height * maxSize * maxDim), canvas = document.createElement("canvas"), ctx = canvas.getContext("2d"); canvas.width = newWidth; canvas.height = newHeight; ctx.drawImage(image, 0, 0, image.width, image.height, 0, 0, newWidth, newHeight); Log.once("Renderer clampToMaxSize: image height larger than machines max cube texture size (max = " + maxSize + ")"); return canvas; } function createBuffer(obj, name, array) { obj[name] = obj[name] || _gl.createBuffer(); _gl.bindBuffer(_gl.ARRAY_BUFFER, obj[name]); _gl.bufferData(_gl.ARRAY_BUFFER, array, _gl.STATIC_DRAW); } function createShader(vertex, fragment) { var precision = [ "precision " + _precision + " float;", "precision " + _precision + " int;", "", ].join("\n"), glVertexShader = precision + vertex, glFragmentShader = precision + fragment, webglProgram = createProgram(_gl, glVertexShader, glFragmentShader), shader = { program: webglProgram, uniforms: {}, attributes: {} }; parseUniformsAttributes(_gl, webglProgram, glVertexShader, glFragmentShader, shader.attributes, shader.uniforms); return shader; } var _lastBuffer = undefined, _lastShader = undefined; function bindBuffer(buffers, attributes) { if (_lastBuffer === buffers) return; var ARRAY_BUFFER = _gl.ARRAY_BUFFER, FLOAT = _gl.FLOAT; _gl.bindBuffer(ARRAY_BUFFER, buffers.vertexBuffer); _gl.enableVertexAttribArray(attributes.position); _gl.vertexAttribPointer(attributes.position, 2, FLOAT, false, 0, 0); _gl.bindBuffer(ARRAY_BUFFER, buffers.uvBuffer); _gl.enableVertexAttribArray(attributes.uv); _gl.vertexAttribPointer(attributes.uv, 2, FLOAT, false, 0, 0); _lastBuffer = buffers; } var _lastCamera = undefined, _lastResizeFn = undefined, _lastScene = undefined; this.preRender = function(gui, scene, camera) { if (!_context) return; var background = camera.background; if (_clearColor.r !== background.r || _clearColor.g !== background.g || _clearColor.b !== background.b) { _clearColor.copy(background); _gl.clearColor(background.r, background.g, background.b, 1); if (!this.autoClear) clearCanvas(true, this.autoClearDepth, this.autoClearStencil); } if (_lastCamera !== camera) { var w = _canvas.pixelWidth, h = _canvas.pixelHeight; camera.set(w, h); this.setViewport(0, 0, w, h); if (_lastResizeFn) _canvas.off("resize", _lastResizeFn); _lastResizeFn = function() { var w = this.pixelWidth, h = this.pixelHeight; camera.set(w, h); _this.setViewport(0, 0, w, h); _projScreenMatrix.mmul(camera.projection, camera.view); }; _canvas.on("resize", _lastResizeFn); _lastCamera = camera; _projScreenMatrix.mmul(camera.projection, camera.view); } if (scene && _lastScene !== scene) { _lastScene = scene; } if (this.autoClear) clearCanvas(this.autoClearColor, this.autoClearDepth, this.autoClearStencil); }; this.renderGUI = function(gui, camera) { if (!_context) return; var components = gui.components, transform, i; }; var EMPTY_ARRAY = []; /** * @method render * @memberof Renderer * @brief renderers scene from camera's perspective * @param Scene scene * @param Camera camera */ this.render = function(scene, camera) { if (!_context) return; var lineWidth = _lastLineWidth, blending = _lastBlending, cullFace = _lastCullFace, components = scene.components, sprites = components.Sprite || EMPTY_ARRAY, particleSystems = components.ParticleSystem || EMPTY_ARRAY, sprite2d, particleSystem, transform2d, i; for (i = sprites.length; i--;) { sprite2d = sprites[i]; transform2d = sprite2d.transform2d; if (!transform2d || !sprite2d.visible) continue; transform2d.updateModelViewMat32(camera.view); renderSprite(camera, transform2d, sprite2d); } setCullFace(cullFace); setBlending(blending); setLineWidth(lineWidth); }; var VEC2 = new Vec2, VEC4 = new Vec4, MAT4 = new Mat4; function renderSprite(camera, transform2d, sprite2d) { var texture = sprite2d.texture, uniforms = _spriteShader.uniforms, force = false, w, h; if (texture && texture.raw) { w = texture.invWidth; h = texture.invHeight; } else { return; } MAT4.mmul(camera._projectionMat4, MAT4.fromMat32(transform2d.modelView)); if (_lastShader !== _spriteShader) { _gl.useProgram(_spriteShader.program); force = true; _lastShader = _spriteShader; } bindBuffer(_spriteBuffers, _spriteShader.attributes); setUniformMatrix4fv(force, uniforms.matrix.location, MAT4, "matrix"); setUniform4f(force, uniforms.crop.location, VEC4.set(sprite2d.x * w, sprite2d.y * h, sprite2d.w * w, sprite2d.h * h), "crop"); setUniform2f(force, uniforms.size.location, VEC2.set(sprite2d.width, sprite2d.height), "size"); setUniform1f(force, uniforms.alpha.location, sprite2d.alpha, "alpha"); setTexture(force, uniforms.texture.location, texture, "texture"); _gl.drawArrays(_gl.TRIANGLE_STRIP, 0, _spriteBuffers.vertexCount); _textureIndex = 0; }; function initGL() { try { _gl = getWebGLContext(_element, _this.attributes); if (_gl === null) throw "Error creating WebGL context"; } catch (e) { Log.error(e); } if (_gl.getShaderPrecisionFormat == undefined) { _gl.getShaderPrecisionFormat = function() { return { rangeMin: 1, rangeMax: 1, precision: 1 }; } } getExtensions(); getGPUInfo(); } function setDefaultGLState() { _gl.clearColor(0, 0, 0, 1); _gl.clearDepth(1); _gl.clearStencil(0); setDepthTest(true); _gl.depthFunc(_gl.LEQUAL); _gl.frontFace(_gl.CCW); setCullFace(CullFace.Back); setBlending(Blending.Default); setViewport(); } function handleWebGLContextLost(e) { e.preventDefault(); Log.warn("Renderer: webgl context was lost"); _context = false; this.emit("webglcontextlost", e); } function handleWebGLContextRestored(e) { Log.log("Renderer: webgl context was restored"); initGL(); setDefaultGLState(); _context = true; this.emit("webglcontextrestored", e); } var _precision = "highp", _maxAnisotropy = 0, _maxTextures = 0, _maxVertexTextures = 0, _maxTextureSize = 0, _maxCubeTextureSize = 0, _maxRenderBufferSize = 0, _maxUniforms = 0, _maxVaryings = 0, _maxAttributes = 0; function getGPUInfo() { var VERTEX_SHADER = _gl.VERTEX_SHADER, FRAGMENT_SHADER = _gl.FRAGMENT_SHADER, HIGH_FLOAT = _gl.HIGH_FLOAT, MEDIUM_FLOAT = _gl.MEDIUM_FLOAT, EXT_texture_filter_anisotropic = _extensions.EXT_texture_filter_anisotropic, vsHighpFloat = _gl.getShaderPrecisionFormat(VERTEX_SHADER, HIGH_FLOAT), vsMediumpFloat = _gl.getShaderPrecisionFormat(VERTEX_SHADER, MEDIUM_FLOAT), fsHighpFloat = _gl.getShaderPrecisionFormat(FRAGMENT_SHADER, HIGH_FLOAT), fsMediumpFloat = _gl.getShaderPrecisionFormat(FRAGMENT_SHADER, MEDIUM_FLOAT), highpAvailable = vsHighpFloat.precision > 0 && fsHighpFloat.precision > 0, mediumpAvailable = vsMediumpFloat.precision > 0 && fsMediumpFloat.precision > 0, precision = "highp"; if (!highpAvailable || Device.mobile) { if (mediumpAvailable) { precision = "mediump"; } else { precision = "lowp"; } } _precision = precision; _maxAnisotropy = EXT_texture_filter_anisotropic ? _gl.getParameter(EXT_texture_filter_anisotropic.MAX_TEXTURE_MAX_ANISOTROPY_EXT) : 1; _maxTextures = _gl.getParameter(_gl.MAX_TEXTURE_IMAGE_UNITS); _maxVertexTextures = _gl.getParameter(_gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS); _maxTextureSize = _gl.getParameter(_gl.MAX_TEXTURE_SIZE); _maxCubeTextureSize = _gl.getParameter(_gl.MAX_CUBE_MAP_TEXTURE_SIZE); _maxRenderBufferSize = _gl.getParameter(_gl.MAX_RENDERBUFFER_SIZE); _maxUniforms = max(_gl.getParameter(_gl.MAX_FRAGMENT_UNIFORM_VECTORS), _gl.getParameter(_gl.MAX_VERTEX_UNIFORM_VECTORS)) * 4; _maxVaryings = _gl.getParameter(_gl.MAX_VARYING_VECTORS) * 4; _maxAttributes = _gl.getParameter(_gl.MAX_VERTEX_ATTRIBS); } function getExtensions() { _extensions = {}; getExtension("EXT_texture_filter_anisotropic"); getExtension("WEBGL_compressed_texture_s3tc"); _extensions.WEBGL_compressed_texture_s3tc_formats = _extensions.WEBGL_compressed_texture_s3tc ? _gl.getParameter(_gl.COMPRESSED_TEXTURE_FORMATS) : null; getExtension("OES_standard_derivatives"); getExtension("OES_texture_float"); getExtension("OES_texture_float_linear"); } var getExtension_prefixes = ["WEBKIT", "MOZ", "O", "MS", "webkit", "moz", "o", "ms"], getExtension_length = getExtension_prefixes.length; function getExtension(name) { var extension = _extensions[name] || (_extensions[name] = _gl.getExtension(name)); if (extension == undefined) { var i = getExtension_length; while (i--) { if ((extension = _gl.getExtension(getExtension_prefixes[i] + "_" + name))) return (_extensions[name] = extension); } } return extension; } this.getExtension = getExtension; } EventEmitter.extend(Renderer); var sprite_vertex = [ "uniform mat4 matrix;", "uniform vec4 crop;", "uniform vec2 size;", "attribute vec2 position;", "attribute vec2 uv;", "varying vec2 vUv;", "void main() {", " vUv = vec2(uv.x * crop.z, uv.y * crop.w) + crop.xy;", " gl_Position = matrix * vec4(position * size, 0.0, 1.0);", "}" ].join("\n"), sprite_fragment = [ "uniform float alpha;", "uniform sampler2D texture;", "varying vec2 vUv;", "void main() {", " vec4 finalColor = texture2D(texture, vUv);", " finalColor.w *= alpha;", " gl_FragColor = finalColor;", "}" ].join("\n"); return Renderer; } ); </code></pre> </article> </section> </div> <nav> <h2><a href="index.html">Index</a></h2><h3>Classes</h3><ul><li><a href="Canvas.html">Canvas</a></li><li><a href="GUIObject.html">GUIObject</a></li><li><a href="MeshFilter.html">MeshFilter</a></li><li><a href="Odin.html">Odin</a></li><li><a href="Odin.Class.html">Class</a></li><li><a href="Odin.EventEmitter.html">EventEmitter</a></li><li><a href="Odin.GameObject.html">GameObject</a></li><li><a href="Odin.Scene.html">Scene</a></li><li><a href="P2Contact.html">P2Contact</a></li><li><a href="P2Equation.html">P2Equation</a></li><li><a href="P2Friction.html">P2Friction</a></li><li><a href="P2Solver.html">P2Solver</a></li><li><a href="ParticleSystem.html">ParticleSystem</a></li><li><a href="Renderer.html">Renderer</a></li><li><a href="SpriteAnimation.html">SpriteAnimation</a></li><li><a href="WebGLRenderer.html">WebGLRenderer</a></li><li><a href="WebGLRenderer2D.html">WebGLRenderer2D</a></li></ul> </nav> <br clear="both"> <footer> Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.2.2</a> on Mon Feb 24 2014 16:15:46 GMT-0600 (CST) </footer> <script> prettyPrint(); </script> <script src="scripts/linenumber.js"> </script> </body> </html>