diff --git a/src/gameobjects/shader/Shader.js b/src/gameobjects/shader/Shader.js index 52c2e5c68..78a9ea1ee 100644 --- a/src/gameobjects/shader/Shader.js +++ b/src/gameobjects/shader/Shader.js @@ -625,7 +625,6 @@ var Shader = new Class({ */ initUniforms: function () { - var gl = this.gl; var map = this.renderer.glFuncMap; var program = this.program; @@ -638,7 +637,7 @@ var Shader = new Class({ var type = uniform.type; var data = map[type]; - uniform.uniformLocation = gl.getUniformLocation(program.webGLProgram, key); + uniform.uniformLocation = this.renderer.createUniformLocation(program, key); if (type !== 'sampler2D') { @@ -959,7 +958,7 @@ var Shader = new Class({ this.renderer.setProgram(this.program); - gl.uniform1i(uniform.uniformLocation, this._textureCount); + gl.uniform1i(uniform.uniformLocation.webGLUniformLocation, this._textureCount); this._textureCount++; }, @@ -1002,24 +1001,24 @@ var Shader = new Class({ { if (uniform.glMatrix) { - glFunc.call(gl, location, uniform.transpose, value); + glFunc.call(gl, location.webGLUniformLocation, uniform.transpose, value); } else { - glFunc.call(gl, location, value); + glFunc.call(gl, location.webGLUniformLocation, value); } } else if (length === 2) { - glFunc.call(gl, location, value.x, value.y); + glFunc.call(gl, location.webGLUniformLocation, value.x, value.y); } else if (length === 3) { - glFunc.call(gl, location, value.x, value.y, value.z); + glFunc.call(gl, location.webGLUniformLocation, value.x, value.y, value.z); } else if (length === 4) { - glFunc.call(gl, location, value.x, value.y, value.z, value.w); + glFunc.call(gl, location.webGLUniformLocation, value.x, value.y, value.z, value.w); } else if (uniform.type === 'sampler2D') { @@ -1027,7 +1026,7 @@ var Shader = new Class({ gl.bindTexture(gl.TEXTURE_2D, value.webGLTexture); - gl.uniform1i(location, textureCount); + gl.uniform1i(location.webGLUniformLocation, textureCount); textureCount++; } diff --git a/src/renderer/webgl/WebGLRenderer.js b/src/renderer/webgl/WebGLRenderer.js index cb8c6d69c..b33925702 100644 --- a/src/renderer/webgl/WebGLRenderer.js +++ b/src/renderer/webgl/WebGLRenderer.js @@ -24,6 +24,8 @@ var WebGLBufferWrapper = require('./wrappers/WebGLBufferWrapper'); var WebGLProgramWrapper = require('./wrappers/WebGLProgramWrapper'); var WebGLTextureWrapper = require('./wrappers/WebGLTextureWrapper'); var WebGLFramebufferWrapper = require('./wrappers/WebGLFramebufferWrapper'); +var WebGLAttribLocationWrapper = require('./wrappers/WebGLAttribLocationWrapper'); +var WebGLUniformLocationWrapper = require('./wrappers/WebGLUniformLocationWrapper'); var DEBUG = false; @@ -268,6 +270,24 @@ var WebGLRenderer = new Class({ */ this.glFramebufferWrappers = []; + /** + * A list of all WebGLAttribLocationWrappers that have been created by this renderer. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#glAttribLocationWrappers + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLAttribLocationWrapper[]} + * @since 3.80.0 + */ + this.glAttribLocationWrappers = []; + + /** + * A list of all WebGLUniformLocationWrappers that have been created by this renderer. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#glUniformLocationWrappers + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLUniformLocationWrapper[]} + * @since 3.80.0 + */ + this.glUniformLocationWrappers = []; + /** * The currently bound framebuffer in use. * @@ -2144,6 +2164,38 @@ var WebGLRenderer = new Class({ return vertexBuffer; }, + /** + * Creates a WebGLAttribLocationWrapper instance based on the given WebGLProgramWrapper and attribute name. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#createAttribLocation + * @since 3.80.0 + * + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper} program - The WebGLProgramWrapper instance. + * @param {string} name - The name of the attribute. + */ + createAttribLocation: function (program, name) + { + var attrib = new WebGLAttribLocationWrapper(this.gl, program, name); + this.glAttribLocationWrappers.push(attrib); + return attrib; + }, + + /** + * Creates a WebGLUniformLocationWrapper instance based on the given WebGLProgramWrapper and uniform name. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#createUniformLocation + * @since 3.80.0 + * + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper} program - The WebGLProgramWrapper instance. + * @param {string} name - The name of the uniform. + */ + createUniformLocation: function (program, name) + { + var uniform = new WebGLUniformLocationWrapper(this.gl, program, name); + this.glUniformLocationWrappers.push(uniform); + return uniform; + }, + /** * Wrapper for creating a vertex buffer. * diff --git a/src/renderer/webgl/WebGLShader.js b/src/renderer/webgl/WebGLShader.js index c6d8b433e..a32fbb923 100644 --- a/src/renderer/webgl/WebGLShader.js +++ b/src/renderer/webgl/WebGLShader.js @@ -313,29 +313,29 @@ var WebGLShader = new Class({ if (reset) { - var attribLocation = gl.getAttribLocation(program.webGLProgram, element.name); + var attribLocation = this.renderer.createAttribLocation(program, element.name); - if (attribLocation >= 0) + if (attribLocation.webGLAttribLocation >= 0) { - gl.enableVertexAttribArray(attribLocation); + gl.enableVertexAttribArray(attribLocation.webGLAttribLocation); - gl.vertexAttribPointer(attribLocation, size, type, normalized, vertexSize, offset); + gl.vertexAttribPointer(attribLocation.webGLAttribLocation, size, type, normalized, vertexSize, offset); element.enabled = true; element.location = attribLocation; } - else if (attribLocation !== -1) + else if (attribLocation.webGLAttribLocation !== -1) { - gl.disableVertexAttribArray(attribLocation); + gl.disableVertexAttribArray(attribLocation.webGLAttribLocation); } } else if (enabled) { - gl.vertexAttribPointer(location, size, type, normalized, vertexSize, offset); + gl.vertexAttribPointer(location.webGLAttribLocation, size, type, normalized, vertexSize, offset); } - else if (!enabled && location > -1) + else if (!enabled && location !== -1 && location.webGLAttribLocation > -1) { - gl.disableVertexAttribArray(location); + gl.disableVertexAttribArray(location.webGLAttribLocation); element.location = -1; } @@ -382,7 +382,7 @@ var WebGLShader = new Class({ { name = info.name; - location = gl.getUniformLocation(program.webGLProgram, name); + location = this.renderer.createUniformLocation(program, name); if (location !== null) { @@ -409,7 +409,7 @@ var WebGLShader = new Class({ if (!uniforms.hasOwnProperty(name)) { - location = gl.getUniformLocation(program.webGLProgram, name); + location = this.renderer.createUniformLocation(program, name); if (location !== null) { @@ -507,7 +507,7 @@ var WebGLShader = new Class({ this.renderer.setProgram(this.program); - setter.call(this.gl, uniform.location, value1); + setter.call(this.gl, uniform.location.webGLUniformLocation, value1); this.pipeline.currentShader = this; } @@ -553,7 +553,7 @@ var WebGLShader = new Class({ this.renderer.setProgram(this.program); - setter.call(this.gl, uniform.location, value1, value2); + setter.call(this.gl, uniform.location.webGLUniformLocation, value1, value2); this.pipeline.currentShader = this; } @@ -601,7 +601,7 @@ var WebGLShader = new Class({ this.renderer.setProgram(this.program); - setter.call(this.gl, uniform.location, value1, value2, value3); + setter.call(this.gl, uniform.location.webGLUniformLocation, value1, value2, value3); this.pipeline.currentShader = this; } @@ -651,7 +651,7 @@ var WebGLShader = new Class({ this.renderer.setProgram(this.program); - setter.call(this.gl, uniform.location, value1, value2, value3, value4); + setter.call(this.gl, uniform.location.webGLUniformLocation, value1, value2, value3, value4); this.pipeline.currentShader = this; } diff --git a/src/renderer/webgl/wrappers/WebGLAttribLocationWrapper.js b/src/renderer/webgl/wrappers/WebGLAttribLocationWrapper.js new file mode 100644 index 000000000..4e607a91a --- /dev/null +++ b/src/renderer/webgl/wrappers/WebGLAttribLocationWrapper.js @@ -0,0 +1,101 @@ +var Class = require('../../../utils/Class'); + +/** + * @classdesc + * Wrapper for a WebGL attribute location, containing all the information that was used to create it. + * + * A WebGLAttribLocation should never be exposed outside the WebGLRenderer, + * so the WebGLRenderer can handle context loss and other events without other systems having to be aware of it. + * Always use WebGLAttribLocationWrapper instead. + * + * @class WebGLAttribLocationWrapper + * @memberof Phaser.Renderer.WebGL.Wrappers + * @constructor + * @since 3.80.0 + * + * @param {WebGLRenderingContext} gl - The WebGLRenderingContext to create the WebGLAttribLocation for. + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper} program - The WebGLProgram that this location refers to. This must be created first. + * @param {string} name - The name of this location, as defined in the shader source code. + */ +var WebGLAttribLocationWrapper = new Class({ + + initialize: + + function WebGLAttribLocationWrapper (gl, program, name) + { + /** + * The WebGLAttribLocation being wrapped by this class. + * + * This property could change at any time. + * Therefore, you should never store a reference to this value. + * It should only be passed directly to the WebGL API for drawing. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLAttribLocationWrapper#webGLAttribLocation + * @type {WebGLAttribLocation} + * @default -1 + * @since 3.80.0 + */ + this.webGLAttribLocation = -1; + + /** + * The WebGLRenderingContext that owns this location. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper#gl + * @type {WebGLRenderingContext} + * @since 3.80.0 + */ + this.gl = gl; + + /** + * The WebGLProgram that this location refers to. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLAttribLocationWrapper#program + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper} + * @since 3.80.0 + */ + this.program = program; + + /** + * The name of this location, as defined in the shader source code. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLAttribLocationWrapper#name + * @type {string} + * @since 3.80.0 + */ + this.name = name; + + this.createResource(); + }, + + /** + * Creates the WebGLAttribLocation. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLAttribLocationWrapper#createResource + * @since 3.80.0 + */ + createResource: function () + { + if (this.program.webGLProgram === null) + { + this.webGLAttribLocation = -1; + return; + } + this.webGLAttribLocation = this.gl.getAttribLocation(this.program.webGLProgram, this.name); + }, + + /** + * Destroys this WebGLAttribLocationWrapper. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLAttribLocationWrapper#destroy + * @since 3.80.0 + */ + destroy: function () + { + this.gl = null; + this.program = null; + this.name = null; + this.webGLAttribLocation = -1; + } +}); + +module.exports = WebGLAttribLocationWrapper; diff --git a/src/renderer/webgl/wrappers/WebGLUniformLocationWrapper.js b/src/renderer/webgl/wrappers/WebGLUniformLocationWrapper.js new file mode 100644 index 000000000..6520b53dc --- /dev/null +++ b/src/renderer/webgl/wrappers/WebGLUniformLocationWrapper.js @@ -0,0 +1,101 @@ +var Class = require('../../../utils/Class'); + +/** + * @classdesc + * Wrapper for a WebGL uniform location, containing all the information that was used to create it. + * + * A WebGLUniformLocation should never be exposed outside the WebGLRenderer, + * so the WebGLRenderer can handle context loss and other events without other systems having to be aware of it. + * Always use WebGLUniformLocationWrapper instead. + * + * @class WebGLUniformLocationWrapper + * @memberof Phaser.Renderer.WebGL.Wrappers + * @constructor + * @since 3.80.0 + * + * @param {WebGLRenderingContext} gl - The WebGLRenderingContext to create the WebGLUniformLocation for. + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper} program - The WebGLProgram that this location refers to. This must be created first. + * @param {string} name - The name of this location, as defined in the shader source code. + */ +var WebGLUniformLocationWrapper = new Class({ + + initialize: + + function WebGLUniformLocationWrapper (gl, program, name) + { + /** + * The WebGLUniformLocation being wrapped by this class. + * + * This property could change at any time. + * Therefore, you should never store a reference to this value. + * It should only be passed directly to the WebGL API for drawing. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLUniformLocationWrapper#webGLUniformLocation + * @type {?WebGLUniformLocation} + * @default null + * @since 3.80.0 + */ + this.webGLUniformLocation = null; + + /** + * The WebGLRenderingContext that owns this location. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper#gl + * @type {WebGLRenderingContext} + * @since 3.80.0 + */ + this.gl = gl; + + /** + * The WebGLProgram that this location refers to. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLUniformLocationWrapper#program + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper} + * @since 3.80.0 + */ + this.program = program; + + /** + * The name of this location, as defined in the shader source code. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLUniformLocationWrapper#name + * @type {string} + * @since 3.80.0 + */ + this.name = name; + + this.createResource(); + }, + + /** + * Creates the WebGLUniformLocation. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLUniformLocationWrapper#createResource + * @since 3.80.0 + */ + createResource: function () + { + if (this.program.webGLProgram === null) + { + this.webGLUniformLocation = null; + return; + } + this.webGLUniformLocation = this.gl.getUniformLocation(this.program.webGLProgram, this.name); + }, + + /** + * Destroys this WebGLUniformLocationWrapper. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLUniformLocationWrapper#destroy + * @since 3.80.0 + */ + destroy: function () + { + this.gl = null; + this.program = null; + this.name = null; + this.webGLUniformLocation = null; + } +}); + +module.exports = WebGLUniformLocationWrapper;