diff --git a/packages/core/src/renderers/systems/shader/GLProgram.js b/packages/core/src/renderers/systems/shader/GLProgram.js new file mode 100644 index 0000000..92980ca --- /dev/null +++ b/packages/core/src/renderers/systems/shader/GLProgram.js @@ -0,0 +1,43 @@ +/** + * Helper class to create a webGL Program + * + * @class + * @private + */ +export default class GLProgram +{ + constructor(program, uniformData) + { + /** + * The shader program + * + * @member {WebGLProgram} + */ + this.program = program; + + /** + * holds the uniform data which contains uniform locations + * and current uniform values used for caching and preventing undeed GPU commands + * @type {Object} + */ + this.uniformData = uniformData; + + /** + * uniformGroups holds the various upload functions for the shader. Each uniform group + * and program have a unique upload function generated. + * @type {Object} + */ + this.uniformGroups = {}; + } + + /** + * Destroys this program + * TODO + */ + destroy() + { + this.uniformData = null; + this.uniformGroups = null; + this.program = null; + } +} diff --git a/packages/core/src/renderers/systems/shader/GLProgram.js b/packages/core/src/renderers/systems/shader/GLProgram.js new file mode 100644 index 0000000..92980ca --- /dev/null +++ b/packages/core/src/renderers/systems/shader/GLProgram.js @@ -0,0 +1,43 @@ +/** + * Helper class to create a webGL Program + * + * @class + * @private + */ +export default class GLProgram +{ + constructor(program, uniformData) + { + /** + * The shader program + * + * @member {WebGLProgram} + */ + this.program = program; + + /** + * holds the uniform data which contains uniform locations + * and current uniform values used for caching and preventing undeed GPU commands + * @type {Object} + */ + this.uniformData = uniformData; + + /** + * uniformGroups holds the various upload functions for the shader. Each uniform group + * and program have a unique upload function generated. + * @type {Object} + */ + this.uniformGroups = {}; + } + + /** + * Destroys this program + * TODO + */ + destroy() + { + this.uniformData = null; + this.uniformGroups = null; + this.program = null; + } +} diff --git a/packages/core/src/renderers/systems/shader/GLShader.js b/packages/core/src/renderers/systems/shader/GLShader.js deleted file mode 100644 index 4ae88c5..0000000 --- a/packages/core/src/renderers/systems/shader/GLShader.js +++ /dev/null @@ -1,102 +0,0 @@ -import compileProgram from './shader/compileProgram'; -import extractAttributes from './shader/extractAttributes'; -import extractUniforms from './shader/extractUniforms'; -import setPrecision from './shader/setPrecision'; -import generateUniformAccessObject from './shader/generateUniformAccessObject'; - -let ID = 0; - -/** - * @namespace PIXI.glCore - */ - -/** - * Helper class to create a webGL Shader - * - * @class - * @memberof PIXI.glCore - * @param gl {WebGLRenderingContext} - * @param vertexSrc {string|string[]} The vertex shader source as an array of strings. - * @param fragmentSrc {string|string[]} The fragment shader source as an array of strings. - * @param precision {string} The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. - * @param attributeLocations {object} A key value pair showing which location eact - * attribute should sit eg {position:0, uvs:1} - */ -export default class Shader -{ - constructor(gl, vertexSrc, fragmentSrc, precision, attributeLocations) - { - /** - * The current WebGL rendering context - * - * @member {WebGLRenderingContext} - */ - this.gl = gl; - - if (precision) - { - vertexSrc = setPrecision(vertexSrc, precision); - fragmentSrc = setPrecision(fragmentSrc, precision); - } - - /** - * The shader program - * - * @member {WebGLProgram} - */ - // First compile the program.. - this.program = compileProgram(gl, vertexSrc, fragmentSrc, attributeLocations); - - /** - * The attributes of the shader as an object containing the following properties - * { - * type, - * size, - * location, - * pointer - * } - * @member {Object} - */ - // next extract the attributes - this.attributes = extractAttributes(gl, this.program); - - this.uniformData = extractUniforms(gl, this.program); - - /** - * The uniforms of the shader as an object containing the following properties - * { - * gl, - * data - * } - * @member {Object} - */ - this.uniforms = generateUniformAccessObject(gl, this.uniformData); - - this.uniformGroups = {}; - - this.id = ID++; - } - - /** - * Uses this shader - */ - bind() - { - this.gl.useProgram(this.program); - } - - /** - * Destroys this shader - * TODO - */ - destroy() - { - this.attributes = null; - this.uniformData = null; - this.uniforms = null; - - const gl = this.gl; - - gl.deleteProgram(this.program); - } -} diff --git a/packages/core/src/renderers/systems/shader/GLProgram.js b/packages/core/src/renderers/systems/shader/GLProgram.js new file mode 100644 index 0000000..92980ca --- /dev/null +++ b/packages/core/src/renderers/systems/shader/GLProgram.js @@ -0,0 +1,43 @@ +/** + * Helper class to create a webGL Program + * + * @class + * @private + */ +export default class GLProgram +{ + constructor(program, uniformData) + { + /** + * The shader program + * + * @member {WebGLProgram} + */ + this.program = program; + + /** + * holds the uniform data which contains uniform locations + * and current uniform values used for caching and preventing undeed GPU commands + * @type {Object} + */ + this.uniformData = uniformData; + + /** + * uniformGroups holds the various upload functions for the shader. Each uniform group + * and program have a unique upload function generated. + * @type {Object} + */ + this.uniformGroups = {}; + } + + /** + * Destroys this program + * TODO + */ + destroy() + { + this.uniformData = null; + this.uniformGroups = null; + this.program = null; + } +} diff --git a/packages/core/src/renderers/systems/shader/GLShader.js b/packages/core/src/renderers/systems/shader/GLShader.js deleted file mode 100644 index 4ae88c5..0000000 --- a/packages/core/src/renderers/systems/shader/GLShader.js +++ /dev/null @@ -1,102 +0,0 @@ -import compileProgram from './shader/compileProgram'; -import extractAttributes from './shader/extractAttributes'; -import extractUniforms from './shader/extractUniforms'; -import setPrecision from './shader/setPrecision'; -import generateUniformAccessObject from './shader/generateUniformAccessObject'; - -let ID = 0; - -/** - * @namespace PIXI.glCore - */ - -/** - * Helper class to create a webGL Shader - * - * @class - * @memberof PIXI.glCore - * @param gl {WebGLRenderingContext} - * @param vertexSrc {string|string[]} The vertex shader source as an array of strings. - * @param fragmentSrc {string|string[]} The fragment shader source as an array of strings. - * @param precision {string} The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. - * @param attributeLocations {object} A key value pair showing which location eact - * attribute should sit eg {position:0, uvs:1} - */ -export default class Shader -{ - constructor(gl, vertexSrc, fragmentSrc, precision, attributeLocations) - { - /** - * The current WebGL rendering context - * - * @member {WebGLRenderingContext} - */ - this.gl = gl; - - if (precision) - { - vertexSrc = setPrecision(vertexSrc, precision); - fragmentSrc = setPrecision(fragmentSrc, precision); - } - - /** - * The shader program - * - * @member {WebGLProgram} - */ - // First compile the program.. - this.program = compileProgram(gl, vertexSrc, fragmentSrc, attributeLocations); - - /** - * The attributes of the shader as an object containing the following properties - * { - * type, - * size, - * location, - * pointer - * } - * @member {Object} - */ - // next extract the attributes - this.attributes = extractAttributes(gl, this.program); - - this.uniformData = extractUniforms(gl, this.program); - - /** - * The uniforms of the shader as an object containing the following properties - * { - * gl, - * data - * } - * @member {Object} - */ - this.uniforms = generateUniformAccessObject(gl, this.uniformData); - - this.uniformGroups = {}; - - this.id = ID++; - } - - /** - * Uses this shader - */ - bind() - { - this.gl.useProgram(this.program); - } - - /** - * Destroys this shader - * TODO - */ - destroy() - { - this.attributes = null; - this.uniformData = null; - this.uniforms = null; - - const gl = this.gl; - - gl.deleteProgram(this.program); - } -} diff --git a/packages/core/src/renderers/systems/shader/ShaderSystem.js b/packages/core/src/renderers/systems/shader/ShaderSystem.js index ebdb416..e0b98e8 100644 --- a/packages/core/src/renderers/systems/shader/ShaderSystem.js +++ b/packages/core/src/renderers/systems/shader/ShaderSystem.js @@ -1,7 +1,8 @@ import WebGLSystem from '../WebGLSystem'; -import GLShader from './GLShader'; -import { settings } from '@pixi/settings'; +import GLProgram from './GLProgram'; import generateUniformsSync from '../../../shader/generateUniformsSync'; +import defaultValue from '../../../shader/defaultValue'; +import compileProgram from './shader/compileProgram'; let UID = 0; @@ -43,15 +44,12 @@ * * @param {PIXI.Shader} shader - the new shader * @param {boolean} dontSync - false if the shader should automatically sync its uniforms. - * @returns {PIXI.glCore.GLShader} the glShader that belongs to the shader. + * @returns {PIXI.glCore.glProgram} the glProgram that belongs to the shader. */ bind(shader, dontSync) { - // maybe a better place for this... - shader.uniforms.globals = this.renderer.globalUniforms; - const program = shader.program; - const glShader = program.glShaders[this.renderer.CONTEXT_UID] || this.generateShader(shader); + const glProgram = program.glPrograms[this.renderer.CONTEXT_UID] || this.generateShader(shader); this.shader = shader; @@ -59,7 +57,7 @@ if (this.program !== program) { this.program = program; - glShader.bind(); + this.gl.useProgram(glProgram.program); } if (!dontSync) @@ -67,7 +65,7 @@ this.syncUniformGroup(shader.uniformGroup); } - return glShader; + return glProgram; } /** @@ -78,21 +76,21 @@ setUniforms(uniforms) { const shader = this.shader.program; - const glShader = shader.glShaders[this.renderer.CONTEXT_UID]; + const glProgram = shader.glPrograms[this.renderer.CONTEXT_UID]; - shader.syncUniforms(glShader.uniformData, uniforms, this.renderer); + shader.syncUniforms(glProgram.uniformData, uniforms, this.renderer); } syncUniformGroup(group) { - const glShader = this.getGLShader(); + const glProgram = this.getglProgram(); - if (!group.static || group.dirtyId !== glShader.uniformGroups[group.id]) + if (!group.static || group.dirtyId !== glProgram.uniformGroups[group.id]) { - glShader.uniformGroups[group.id] = group.dirtyId; + glProgram.uniformGroups[group.id] = group.dirtyId; const syncFunc = group.syncUniforms[this.shader.program.id] || this.createSyncGroups(group); - syncFunc(glShader.uniformData, group.uniforms, this.renderer); + syncFunc(glProgram.uniformData, group.uniforms, this.renderer); } } @@ -107,46 +105,57 @@ * Returns the underlying GLShade rof the currently bound shader. * This can be handy for when you to have a little more control over the setting of your uniforms. * - * @return {PIXI.glCore.Shader} the glShader for the currently bound Shader for this context + * @return {PIXI.glCore.Shader} the glProgram for the currently bound Shader for this context */ - getGLShader() + getglProgram() { if (this.shader) { - return this.shader.program.glShaders[this.renderer.CONTEXT_UID]; + return this.shader.program.glPrograms[this.renderer.CONTEXT_UID]; } return null; } /** - * Generates a GLShader verion of the Shader provided. + * Generates a glProgram verion of the Shader provided. * * @private - * @param {PIXI.Shader} shader the shader that the glShader will be based on. - * @return {PIXI.glCore.GLShader} A shiney new GLShader + * @param {PIXI.Shader} shader the shader that the glProgram will be based on. + * @return {PIXI.glCore.glProgram} A shiney new glProgram */ generateShader(shader) { - const program = shader.program; - const attribMap = {}; + const gl = this.gl; - // insert the global properties too! + const program = shader.program; + + const attribMap = {}; for (const i in program.attributeData) { attribMap[i] = program.attributeData[i].location; } - const glShader = new GLShader(this.gl, - program.vertexSrc, - program.fragmentSrc, - settings.PRECISION_FRAGMENT, - attribMap); + const shaderProgram = compileProgram(gl, program.vertexSrc, program.fragmentSrc, attribMap); + const uniformData = {}; - program.glShaders[this.renderer.CONTEXT_UID] = glShader; + for (const i in program.uniformData) + { + const data = program.uniformData[i]; - return glShader; + uniformData[i] = { + location: gl.getUniformLocation(shaderProgram, i), + value: defaultValue(data.type, data.size), + }; + } + + const glProgram = new GLProgram(shaderProgram, uniformData); + + program.glPrograms[this.renderer.CONTEXT_UID] = glProgram; + shader.uniforms.globals = this.renderer.globalUniforms; + + return glProgram; } /** diff --git a/packages/core/src/renderers/systems/shader/GLProgram.js b/packages/core/src/renderers/systems/shader/GLProgram.js new file mode 100644 index 0000000..92980ca --- /dev/null +++ b/packages/core/src/renderers/systems/shader/GLProgram.js @@ -0,0 +1,43 @@ +/** + * Helper class to create a webGL Program + * + * @class + * @private + */ +export default class GLProgram +{ + constructor(program, uniformData) + { + /** + * The shader program + * + * @member {WebGLProgram} + */ + this.program = program; + + /** + * holds the uniform data which contains uniform locations + * and current uniform values used for caching and preventing undeed GPU commands + * @type {Object} + */ + this.uniformData = uniformData; + + /** + * uniformGroups holds the various upload functions for the shader. Each uniform group + * and program have a unique upload function generated. + * @type {Object} + */ + this.uniformGroups = {}; + } + + /** + * Destroys this program + * TODO + */ + destroy() + { + this.uniformData = null; + this.uniformGroups = null; + this.program = null; + } +} diff --git a/packages/core/src/renderers/systems/shader/GLShader.js b/packages/core/src/renderers/systems/shader/GLShader.js deleted file mode 100644 index 4ae88c5..0000000 --- a/packages/core/src/renderers/systems/shader/GLShader.js +++ /dev/null @@ -1,102 +0,0 @@ -import compileProgram from './shader/compileProgram'; -import extractAttributes from './shader/extractAttributes'; -import extractUniforms from './shader/extractUniforms'; -import setPrecision from './shader/setPrecision'; -import generateUniformAccessObject from './shader/generateUniformAccessObject'; - -let ID = 0; - -/** - * @namespace PIXI.glCore - */ - -/** - * Helper class to create a webGL Shader - * - * @class - * @memberof PIXI.glCore - * @param gl {WebGLRenderingContext} - * @param vertexSrc {string|string[]} The vertex shader source as an array of strings. - * @param fragmentSrc {string|string[]} The fragment shader source as an array of strings. - * @param precision {string} The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. - * @param attributeLocations {object} A key value pair showing which location eact - * attribute should sit eg {position:0, uvs:1} - */ -export default class Shader -{ - constructor(gl, vertexSrc, fragmentSrc, precision, attributeLocations) - { - /** - * The current WebGL rendering context - * - * @member {WebGLRenderingContext} - */ - this.gl = gl; - - if (precision) - { - vertexSrc = setPrecision(vertexSrc, precision); - fragmentSrc = setPrecision(fragmentSrc, precision); - } - - /** - * The shader program - * - * @member {WebGLProgram} - */ - // First compile the program.. - this.program = compileProgram(gl, vertexSrc, fragmentSrc, attributeLocations); - - /** - * The attributes of the shader as an object containing the following properties - * { - * type, - * size, - * location, - * pointer - * } - * @member {Object} - */ - // next extract the attributes - this.attributes = extractAttributes(gl, this.program); - - this.uniformData = extractUniforms(gl, this.program); - - /** - * The uniforms of the shader as an object containing the following properties - * { - * gl, - * data - * } - * @member {Object} - */ - this.uniforms = generateUniformAccessObject(gl, this.uniformData); - - this.uniformGroups = {}; - - this.id = ID++; - } - - /** - * Uses this shader - */ - bind() - { - this.gl.useProgram(this.program); - } - - /** - * Destroys this shader - * TODO - */ - destroy() - { - this.attributes = null; - this.uniformData = null; - this.uniforms = null; - - const gl = this.gl; - - gl.deleteProgram(this.program); - } -} diff --git a/packages/core/src/renderers/systems/shader/ShaderSystem.js b/packages/core/src/renderers/systems/shader/ShaderSystem.js index ebdb416..e0b98e8 100644 --- a/packages/core/src/renderers/systems/shader/ShaderSystem.js +++ b/packages/core/src/renderers/systems/shader/ShaderSystem.js @@ -1,7 +1,8 @@ import WebGLSystem from '../WebGLSystem'; -import GLShader from './GLShader'; -import { settings } from '@pixi/settings'; +import GLProgram from './GLProgram'; import generateUniformsSync from '../../../shader/generateUniformsSync'; +import defaultValue from '../../../shader/defaultValue'; +import compileProgram from './shader/compileProgram'; let UID = 0; @@ -43,15 +44,12 @@ * * @param {PIXI.Shader} shader - the new shader * @param {boolean} dontSync - false if the shader should automatically sync its uniforms. - * @returns {PIXI.glCore.GLShader} the glShader that belongs to the shader. + * @returns {PIXI.glCore.glProgram} the glProgram that belongs to the shader. */ bind(shader, dontSync) { - // maybe a better place for this... - shader.uniforms.globals = this.renderer.globalUniforms; - const program = shader.program; - const glShader = program.glShaders[this.renderer.CONTEXT_UID] || this.generateShader(shader); + const glProgram = program.glPrograms[this.renderer.CONTEXT_UID] || this.generateShader(shader); this.shader = shader; @@ -59,7 +57,7 @@ if (this.program !== program) { this.program = program; - glShader.bind(); + this.gl.useProgram(glProgram.program); } if (!dontSync) @@ -67,7 +65,7 @@ this.syncUniformGroup(shader.uniformGroup); } - return glShader; + return glProgram; } /** @@ -78,21 +76,21 @@ setUniforms(uniforms) { const shader = this.shader.program; - const glShader = shader.glShaders[this.renderer.CONTEXT_UID]; + const glProgram = shader.glPrograms[this.renderer.CONTEXT_UID]; - shader.syncUniforms(glShader.uniformData, uniforms, this.renderer); + shader.syncUniforms(glProgram.uniformData, uniforms, this.renderer); } syncUniformGroup(group) { - const glShader = this.getGLShader(); + const glProgram = this.getglProgram(); - if (!group.static || group.dirtyId !== glShader.uniformGroups[group.id]) + if (!group.static || group.dirtyId !== glProgram.uniformGroups[group.id]) { - glShader.uniformGroups[group.id] = group.dirtyId; + glProgram.uniformGroups[group.id] = group.dirtyId; const syncFunc = group.syncUniforms[this.shader.program.id] || this.createSyncGroups(group); - syncFunc(glShader.uniformData, group.uniforms, this.renderer); + syncFunc(glProgram.uniformData, group.uniforms, this.renderer); } } @@ -107,46 +105,57 @@ * Returns the underlying GLShade rof the currently bound shader. * This can be handy for when you to have a little more control over the setting of your uniforms. * - * @return {PIXI.glCore.Shader} the glShader for the currently bound Shader for this context + * @return {PIXI.glCore.Shader} the glProgram for the currently bound Shader for this context */ - getGLShader() + getglProgram() { if (this.shader) { - return this.shader.program.glShaders[this.renderer.CONTEXT_UID]; + return this.shader.program.glPrograms[this.renderer.CONTEXT_UID]; } return null; } /** - * Generates a GLShader verion of the Shader provided. + * Generates a glProgram verion of the Shader provided. * * @private - * @param {PIXI.Shader} shader the shader that the glShader will be based on. - * @return {PIXI.glCore.GLShader} A shiney new GLShader + * @param {PIXI.Shader} shader the shader that the glProgram will be based on. + * @return {PIXI.glCore.glProgram} A shiney new glProgram */ generateShader(shader) { - const program = shader.program; - const attribMap = {}; + const gl = this.gl; - // insert the global properties too! + const program = shader.program; + + const attribMap = {}; for (const i in program.attributeData) { attribMap[i] = program.attributeData[i].location; } - const glShader = new GLShader(this.gl, - program.vertexSrc, - program.fragmentSrc, - settings.PRECISION_FRAGMENT, - attribMap); + const shaderProgram = compileProgram(gl, program.vertexSrc, program.fragmentSrc, attribMap); + const uniformData = {}; - program.glShaders[this.renderer.CONTEXT_UID] = glShader; + for (const i in program.uniformData) + { + const data = program.uniformData[i]; - return glShader; + uniformData[i] = { + location: gl.getUniformLocation(shaderProgram, i), + value: defaultValue(data.type, data.size), + }; + } + + const glProgram = new GLProgram(shaderProgram, uniformData); + + program.glPrograms[this.renderer.CONTEXT_UID] = glProgram; + shader.uniforms.globals = this.renderer.globalUniforms; + + return glProgram; } /** diff --git a/packages/core/src/renderers/systems/shader/shader/extractAttributes.js b/packages/core/src/renderers/systems/shader/shader/extractAttributes.js deleted file mode 100644 index 52a62f5..0000000 --- a/packages/core/src/renderers/systems/shader/shader/extractAttributes.js +++ /dev/null @@ -1,38 +0,0 @@ -import mapType from './mapType'; -import mapSize from './mapSize'; - -/** - * Extracts the attributes - * @method extractAttributes - * @memberof PIXI.glCore.shader - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param program {WebGLProgram} The shader program to get the attributes from - * @return attributes {Object} - */ -export default function extractAttributes(gl, program) -{ - const attributes = {}; - - const totalAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES); - - for (let i = 0; i < totalAttributes; i++) - { - const attribData = gl.getActiveAttrib(program, i); - const type = mapType(gl, attribData.type); - - attributes[attribData.name] = { - type, - size: mapSize(type), - location: gl.getAttribLocation(program, attribData.name), - // TODO - make an attribute object - pointer, - }; - } - - return attributes; -} - -function pointer()// type, normalized, stride, start) -{ - // gl.vertexAttribPointer(this.location, this.size, type || gl.FLOAT, normalized || false, stride || 0, start || 0); -} diff --git a/packages/core/src/renderers/systems/shader/GLProgram.js b/packages/core/src/renderers/systems/shader/GLProgram.js new file mode 100644 index 0000000..92980ca --- /dev/null +++ b/packages/core/src/renderers/systems/shader/GLProgram.js @@ -0,0 +1,43 @@ +/** + * Helper class to create a webGL Program + * + * @class + * @private + */ +export default class GLProgram +{ + constructor(program, uniformData) + { + /** + * The shader program + * + * @member {WebGLProgram} + */ + this.program = program; + + /** + * holds the uniform data which contains uniform locations + * and current uniform values used for caching and preventing undeed GPU commands + * @type {Object} + */ + this.uniformData = uniformData; + + /** + * uniformGroups holds the various upload functions for the shader. Each uniform group + * and program have a unique upload function generated. + * @type {Object} + */ + this.uniformGroups = {}; + } + + /** + * Destroys this program + * TODO + */ + destroy() + { + this.uniformData = null; + this.uniformGroups = null; + this.program = null; + } +} diff --git a/packages/core/src/renderers/systems/shader/GLShader.js b/packages/core/src/renderers/systems/shader/GLShader.js deleted file mode 100644 index 4ae88c5..0000000 --- a/packages/core/src/renderers/systems/shader/GLShader.js +++ /dev/null @@ -1,102 +0,0 @@ -import compileProgram from './shader/compileProgram'; -import extractAttributes from './shader/extractAttributes'; -import extractUniforms from './shader/extractUniforms'; -import setPrecision from './shader/setPrecision'; -import generateUniformAccessObject from './shader/generateUniformAccessObject'; - -let ID = 0; - -/** - * @namespace PIXI.glCore - */ - -/** - * Helper class to create a webGL Shader - * - * @class - * @memberof PIXI.glCore - * @param gl {WebGLRenderingContext} - * @param vertexSrc {string|string[]} The vertex shader source as an array of strings. - * @param fragmentSrc {string|string[]} The fragment shader source as an array of strings. - * @param precision {string} The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. - * @param attributeLocations {object} A key value pair showing which location eact - * attribute should sit eg {position:0, uvs:1} - */ -export default class Shader -{ - constructor(gl, vertexSrc, fragmentSrc, precision, attributeLocations) - { - /** - * The current WebGL rendering context - * - * @member {WebGLRenderingContext} - */ - this.gl = gl; - - if (precision) - { - vertexSrc = setPrecision(vertexSrc, precision); - fragmentSrc = setPrecision(fragmentSrc, precision); - } - - /** - * The shader program - * - * @member {WebGLProgram} - */ - // First compile the program.. - this.program = compileProgram(gl, vertexSrc, fragmentSrc, attributeLocations); - - /** - * The attributes of the shader as an object containing the following properties - * { - * type, - * size, - * location, - * pointer - * } - * @member {Object} - */ - // next extract the attributes - this.attributes = extractAttributes(gl, this.program); - - this.uniformData = extractUniforms(gl, this.program); - - /** - * The uniforms of the shader as an object containing the following properties - * { - * gl, - * data - * } - * @member {Object} - */ - this.uniforms = generateUniformAccessObject(gl, this.uniformData); - - this.uniformGroups = {}; - - this.id = ID++; - } - - /** - * Uses this shader - */ - bind() - { - this.gl.useProgram(this.program); - } - - /** - * Destroys this shader - * TODO - */ - destroy() - { - this.attributes = null; - this.uniformData = null; - this.uniforms = null; - - const gl = this.gl; - - gl.deleteProgram(this.program); - } -} diff --git a/packages/core/src/renderers/systems/shader/ShaderSystem.js b/packages/core/src/renderers/systems/shader/ShaderSystem.js index ebdb416..e0b98e8 100644 --- a/packages/core/src/renderers/systems/shader/ShaderSystem.js +++ b/packages/core/src/renderers/systems/shader/ShaderSystem.js @@ -1,7 +1,8 @@ import WebGLSystem from '../WebGLSystem'; -import GLShader from './GLShader'; -import { settings } from '@pixi/settings'; +import GLProgram from './GLProgram'; import generateUniformsSync from '../../../shader/generateUniformsSync'; +import defaultValue from '../../../shader/defaultValue'; +import compileProgram from './shader/compileProgram'; let UID = 0; @@ -43,15 +44,12 @@ * * @param {PIXI.Shader} shader - the new shader * @param {boolean} dontSync - false if the shader should automatically sync its uniforms. - * @returns {PIXI.glCore.GLShader} the glShader that belongs to the shader. + * @returns {PIXI.glCore.glProgram} the glProgram that belongs to the shader. */ bind(shader, dontSync) { - // maybe a better place for this... - shader.uniforms.globals = this.renderer.globalUniforms; - const program = shader.program; - const glShader = program.glShaders[this.renderer.CONTEXT_UID] || this.generateShader(shader); + const glProgram = program.glPrograms[this.renderer.CONTEXT_UID] || this.generateShader(shader); this.shader = shader; @@ -59,7 +57,7 @@ if (this.program !== program) { this.program = program; - glShader.bind(); + this.gl.useProgram(glProgram.program); } if (!dontSync) @@ -67,7 +65,7 @@ this.syncUniformGroup(shader.uniformGroup); } - return glShader; + return glProgram; } /** @@ -78,21 +76,21 @@ setUniforms(uniforms) { const shader = this.shader.program; - const glShader = shader.glShaders[this.renderer.CONTEXT_UID]; + const glProgram = shader.glPrograms[this.renderer.CONTEXT_UID]; - shader.syncUniforms(glShader.uniformData, uniforms, this.renderer); + shader.syncUniforms(glProgram.uniformData, uniforms, this.renderer); } syncUniformGroup(group) { - const glShader = this.getGLShader(); + const glProgram = this.getglProgram(); - if (!group.static || group.dirtyId !== glShader.uniformGroups[group.id]) + if (!group.static || group.dirtyId !== glProgram.uniformGroups[group.id]) { - glShader.uniformGroups[group.id] = group.dirtyId; + glProgram.uniformGroups[group.id] = group.dirtyId; const syncFunc = group.syncUniforms[this.shader.program.id] || this.createSyncGroups(group); - syncFunc(glShader.uniformData, group.uniforms, this.renderer); + syncFunc(glProgram.uniformData, group.uniforms, this.renderer); } } @@ -107,46 +105,57 @@ * Returns the underlying GLShade rof the currently bound shader. * This can be handy for when you to have a little more control over the setting of your uniforms. * - * @return {PIXI.glCore.Shader} the glShader for the currently bound Shader for this context + * @return {PIXI.glCore.Shader} the glProgram for the currently bound Shader for this context */ - getGLShader() + getglProgram() { if (this.shader) { - return this.shader.program.glShaders[this.renderer.CONTEXT_UID]; + return this.shader.program.glPrograms[this.renderer.CONTEXT_UID]; } return null; } /** - * Generates a GLShader verion of the Shader provided. + * Generates a glProgram verion of the Shader provided. * * @private - * @param {PIXI.Shader} shader the shader that the glShader will be based on. - * @return {PIXI.glCore.GLShader} A shiney new GLShader + * @param {PIXI.Shader} shader the shader that the glProgram will be based on. + * @return {PIXI.glCore.glProgram} A shiney new glProgram */ generateShader(shader) { - const program = shader.program; - const attribMap = {}; + const gl = this.gl; - // insert the global properties too! + const program = shader.program; + + const attribMap = {}; for (const i in program.attributeData) { attribMap[i] = program.attributeData[i].location; } - const glShader = new GLShader(this.gl, - program.vertexSrc, - program.fragmentSrc, - settings.PRECISION_FRAGMENT, - attribMap); + const shaderProgram = compileProgram(gl, program.vertexSrc, program.fragmentSrc, attribMap); + const uniformData = {}; - program.glShaders[this.renderer.CONTEXT_UID] = glShader; + for (const i in program.uniformData) + { + const data = program.uniformData[i]; - return glShader; + uniformData[i] = { + location: gl.getUniformLocation(shaderProgram, i), + value: defaultValue(data.type, data.size), + }; + } + + const glProgram = new GLProgram(shaderProgram, uniformData); + + program.glPrograms[this.renderer.CONTEXT_UID] = glProgram; + shader.uniforms.globals = this.renderer.globalUniforms; + + return glProgram; } /** diff --git a/packages/core/src/renderers/systems/shader/shader/extractAttributes.js b/packages/core/src/renderers/systems/shader/shader/extractAttributes.js deleted file mode 100644 index 52a62f5..0000000 --- a/packages/core/src/renderers/systems/shader/shader/extractAttributes.js +++ /dev/null @@ -1,38 +0,0 @@ -import mapType from './mapType'; -import mapSize from './mapSize'; - -/** - * Extracts the attributes - * @method extractAttributes - * @memberof PIXI.glCore.shader - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param program {WebGLProgram} The shader program to get the attributes from - * @return attributes {Object} - */ -export default function extractAttributes(gl, program) -{ - const attributes = {}; - - const totalAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES); - - for (let i = 0; i < totalAttributes; i++) - { - const attribData = gl.getActiveAttrib(program, i); - const type = mapType(gl, attribData.type); - - attributes[attribData.name] = { - type, - size: mapSize(type), - location: gl.getAttribLocation(program, attribData.name), - // TODO - make an attribute object - pointer, - }; - } - - return attributes; -} - -function pointer()// type, normalized, stride, start) -{ - // gl.vertexAttribPointer(this.location, this.size, type || gl.FLOAT, normalized || false, stride || 0, start || 0); -} diff --git a/packages/core/src/renderers/systems/shader/shader/extractUniforms.js b/packages/core/src/renderers/systems/shader/shader/extractUniforms.js deleted file mode 100644 index d1c39d6..0000000 --- a/packages/core/src/renderers/systems/shader/shader/extractUniforms.js +++ /dev/null @@ -1,33 +0,0 @@ -import mapType from './mapType'; -import defaultValue from './defaultValue'; - -/** - * Extracts the uniforms - * @method extractUniforms - * @memberof PIXI.glCore.shader - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param program {WebGLProgram} The shader program to get the uniforms from - * @return uniforms {Object} - */ -export default function extractUniforms(gl, program) -{ - const uniforms = {}; - - const totalUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS); - - for (let i = 0; i < totalUniforms; i++) - { - const uniformData = gl.getActiveUniform(program, i); - const name = uniformData.name.replace(/\[.*?\]/, ''); - const type = mapType(gl, uniformData.type); - - uniforms[name] = { - type, - size: uniformData.size, - location: gl.getUniformLocation(program, name), - value: defaultValue(type, uniformData.size), - }; - } - - return uniforms; -} diff --git a/packages/core/src/renderers/systems/shader/GLProgram.js b/packages/core/src/renderers/systems/shader/GLProgram.js new file mode 100644 index 0000000..92980ca --- /dev/null +++ b/packages/core/src/renderers/systems/shader/GLProgram.js @@ -0,0 +1,43 @@ +/** + * Helper class to create a webGL Program + * + * @class + * @private + */ +export default class GLProgram +{ + constructor(program, uniformData) + { + /** + * The shader program + * + * @member {WebGLProgram} + */ + this.program = program; + + /** + * holds the uniform data which contains uniform locations + * and current uniform values used for caching and preventing undeed GPU commands + * @type {Object} + */ + this.uniformData = uniformData; + + /** + * uniformGroups holds the various upload functions for the shader. Each uniform group + * and program have a unique upload function generated. + * @type {Object} + */ + this.uniformGroups = {}; + } + + /** + * Destroys this program + * TODO + */ + destroy() + { + this.uniformData = null; + this.uniformGroups = null; + this.program = null; + } +} diff --git a/packages/core/src/renderers/systems/shader/GLShader.js b/packages/core/src/renderers/systems/shader/GLShader.js deleted file mode 100644 index 4ae88c5..0000000 --- a/packages/core/src/renderers/systems/shader/GLShader.js +++ /dev/null @@ -1,102 +0,0 @@ -import compileProgram from './shader/compileProgram'; -import extractAttributes from './shader/extractAttributes'; -import extractUniforms from './shader/extractUniforms'; -import setPrecision from './shader/setPrecision'; -import generateUniformAccessObject from './shader/generateUniformAccessObject'; - -let ID = 0; - -/** - * @namespace PIXI.glCore - */ - -/** - * Helper class to create a webGL Shader - * - * @class - * @memberof PIXI.glCore - * @param gl {WebGLRenderingContext} - * @param vertexSrc {string|string[]} The vertex shader source as an array of strings. - * @param fragmentSrc {string|string[]} The fragment shader source as an array of strings. - * @param precision {string} The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. - * @param attributeLocations {object} A key value pair showing which location eact - * attribute should sit eg {position:0, uvs:1} - */ -export default class Shader -{ - constructor(gl, vertexSrc, fragmentSrc, precision, attributeLocations) - { - /** - * The current WebGL rendering context - * - * @member {WebGLRenderingContext} - */ - this.gl = gl; - - if (precision) - { - vertexSrc = setPrecision(vertexSrc, precision); - fragmentSrc = setPrecision(fragmentSrc, precision); - } - - /** - * The shader program - * - * @member {WebGLProgram} - */ - // First compile the program.. - this.program = compileProgram(gl, vertexSrc, fragmentSrc, attributeLocations); - - /** - * The attributes of the shader as an object containing the following properties - * { - * type, - * size, - * location, - * pointer - * } - * @member {Object} - */ - // next extract the attributes - this.attributes = extractAttributes(gl, this.program); - - this.uniformData = extractUniforms(gl, this.program); - - /** - * The uniforms of the shader as an object containing the following properties - * { - * gl, - * data - * } - * @member {Object} - */ - this.uniforms = generateUniformAccessObject(gl, this.uniformData); - - this.uniformGroups = {}; - - this.id = ID++; - } - - /** - * Uses this shader - */ - bind() - { - this.gl.useProgram(this.program); - } - - /** - * Destroys this shader - * TODO - */ - destroy() - { - this.attributes = null; - this.uniformData = null; - this.uniforms = null; - - const gl = this.gl; - - gl.deleteProgram(this.program); - } -} diff --git a/packages/core/src/renderers/systems/shader/ShaderSystem.js b/packages/core/src/renderers/systems/shader/ShaderSystem.js index ebdb416..e0b98e8 100644 --- a/packages/core/src/renderers/systems/shader/ShaderSystem.js +++ b/packages/core/src/renderers/systems/shader/ShaderSystem.js @@ -1,7 +1,8 @@ import WebGLSystem from '../WebGLSystem'; -import GLShader from './GLShader'; -import { settings } from '@pixi/settings'; +import GLProgram from './GLProgram'; import generateUniformsSync from '../../../shader/generateUniformsSync'; +import defaultValue from '../../../shader/defaultValue'; +import compileProgram from './shader/compileProgram'; let UID = 0; @@ -43,15 +44,12 @@ * * @param {PIXI.Shader} shader - the new shader * @param {boolean} dontSync - false if the shader should automatically sync its uniforms. - * @returns {PIXI.glCore.GLShader} the glShader that belongs to the shader. + * @returns {PIXI.glCore.glProgram} the glProgram that belongs to the shader. */ bind(shader, dontSync) { - // maybe a better place for this... - shader.uniforms.globals = this.renderer.globalUniforms; - const program = shader.program; - const glShader = program.glShaders[this.renderer.CONTEXT_UID] || this.generateShader(shader); + const glProgram = program.glPrograms[this.renderer.CONTEXT_UID] || this.generateShader(shader); this.shader = shader; @@ -59,7 +57,7 @@ if (this.program !== program) { this.program = program; - glShader.bind(); + this.gl.useProgram(glProgram.program); } if (!dontSync) @@ -67,7 +65,7 @@ this.syncUniformGroup(shader.uniformGroup); } - return glShader; + return glProgram; } /** @@ -78,21 +76,21 @@ setUniforms(uniforms) { const shader = this.shader.program; - const glShader = shader.glShaders[this.renderer.CONTEXT_UID]; + const glProgram = shader.glPrograms[this.renderer.CONTEXT_UID]; - shader.syncUniforms(glShader.uniformData, uniforms, this.renderer); + shader.syncUniforms(glProgram.uniformData, uniforms, this.renderer); } syncUniformGroup(group) { - const glShader = this.getGLShader(); + const glProgram = this.getglProgram(); - if (!group.static || group.dirtyId !== glShader.uniformGroups[group.id]) + if (!group.static || group.dirtyId !== glProgram.uniformGroups[group.id]) { - glShader.uniformGroups[group.id] = group.dirtyId; + glProgram.uniformGroups[group.id] = group.dirtyId; const syncFunc = group.syncUniforms[this.shader.program.id] || this.createSyncGroups(group); - syncFunc(glShader.uniformData, group.uniforms, this.renderer); + syncFunc(glProgram.uniformData, group.uniforms, this.renderer); } } @@ -107,46 +105,57 @@ * Returns the underlying GLShade rof the currently bound shader. * This can be handy for when you to have a little more control over the setting of your uniforms. * - * @return {PIXI.glCore.Shader} the glShader for the currently bound Shader for this context + * @return {PIXI.glCore.Shader} the glProgram for the currently bound Shader for this context */ - getGLShader() + getglProgram() { if (this.shader) { - return this.shader.program.glShaders[this.renderer.CONTEXT_UID]; + return this.shader.program.glPrograms[this.renderer.CONTEXT_UID]; } return null; } /** - * Generates a GLShader verion of the Shader provided. + * Generates a glProgram verion of the Shader provided. * * @private - * @param {PIXI.Shader} shader the shader that the glShader will be based on. - * @return {PIXI.glCore.GLShader} A shiney new GLShader + * @param {PIXI.Shader} shader the shader that the glProgram will be based on. + * @return {PIXI.glCore.glProgram} A shiney new glProgram */ generateShader(shader) { - const program = shader.program; - const attribMap = {}; + const gl = this.gl; - // insert the global properties too! + const program = shader.program; + + const attribMap = {}; for (const i in program.attributeData) { attribMap[i] = program.attributeData[i].location; } - const glShader = new GLShader(this.gl, - program.vertexSrc, - program.fragmentSrc, - settings.PRECISION_FRAGMENT, - attribMap); + const shaderProgram = compileProgram(gl, program.vertexSrc, program.fragmentSrc, attribMap); + const uniformData = {}; - program.glShaders[this.renderer.CONTEXT_UID] = glShader; + for (const i in program.uniformData) + { + const data = program.uniformData[i]; - return glShader; + uniformData[i] = { + location: gl.getUniformLocation(shaderProgram, i), + value: defaultValue(data.type, data.size), + }; + } + + const glProgram = new GLProgram(shaderProgram, uniformData); + + program.glPrograms[this.renderer.CONTEXT_UID] = glProgram; + shader.uniforms.globals = this.renderer.globalUniforms; + + return glProgram; } /** diff --git a/packages/core/src/renderers/systems/shader/shader/extractAttributes.js b/packages/core/src/renderers/systems/shader/shader/extractAttributes.js deleted file mode 100644 index 52a62f5..0000000 --- a/packages/core/src/renderers/systems/shader/shader/extractAttributes.js +++ /dev/null @@ -1,38 +0,0 @@ -import mapType from './mapType'; -import mapSize from './mapSize'; - -/** - * Extracts the attributes - * @method extractAttributes - * @memberof PIXI.glCore.shader - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param program {WebGLProgram} The shader program to get the attributes from - * @return attributes {Object} - */ -export default function extractAttributes(gl, program) -{ - const attributes = {}; - - const totalAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES); - - for (let i = 0; i < totalAttributes; i++) - { - const attribData = gl.getActiveAttrib(program, i); - const type = mapType(gl, attribData.type); - - attributes[attribData.name] = { - type, - size: mapSize(type), - location: gl.getAttribLocation(program, attribData.name), - // TODO - make an attribute object - pointer, - }; - } - - return attributes; -} - -function pointer()// type, normalized, stride, start) -{ - // gl.vertexAttribPointer(this.location, this.size, type || gl.FLOAT, normalized || false, stride || 0, start || 0); -} diff --git a/packages/core/src/renderers/systems/shader/shader/extractUniforms.js b/packages/core/src/renderers/systems/shader/shader/extractUniforms.js deleted file mode 100644 index d1c39d6..0000000 --- a/packages/core/src/renderers/systems/shader/shader/extractUniforms.js +++ /dev/null @@ -1,33 +0,0 @@ -import mapType from './mapType'; -import defaultValue from './defaultValue'; - -/** - * Extracts the uniforms - * @method extractUniforms - * @memberof PIXI.glCore.shader - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param program {WebGLProgram} The shader program to get the uniforms from - * @return uniforms {Object} - */ -export default function extractUniforms(gl, program) -{ - const uniforms = {}; - - const totalUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS); - - for (let i = 0; i < totalUniforms; i++) - { - const uniformData = gl.getActiveUniform(program, i); - const name = uniformData.name.replace(/\[.*?\]/, ''); - const type = mapType(gl, uniformData.type); - - uniforms[name] = { - type, - size: uniformData.size, - location: gl.getUniformLocation(program, name), - value: defaultValue(type, uniformData.size), - }; - } - - return uniforms; -} diff --git a/packages/core/src/renderers/systems/shader/shader/generateUniformAccessObject.js b/packages/core/src/renderers/systems/shader/shader/generateUniformAccessObject.js deleted file mode 100644 index ad3865f..0000000 --- a/packages/core/src/renderers/systems/shader/shader/generateUniformAccessObject.js +++ /dev/null @@ -1,143 +0,0 @@ -const getterTemplate = [ - 'return this.data.%%.value;', -].join('\n'); - -const setterTemplate = [ - 'this.data.%%.value = value;', - 'var location = this.data.%%.location;', -].join('\n'); - -const GLSL_TO_SINGLE_SETTERS = { - - float: 'uniform1f(location, value)', - - vec2: 'uniform2f(location, value[0], value[1])', - vec3: 'uniform3f(location, value[0], value[1], value[2])', - vec4: 'uniform4f(location, value[0], value[1], value[2], value[3])', - - int: 'uniform1i(location, value)', - ivec2: 'uniform2i(location, value[0], value[1])', - ivec3: 'uniform3i(location, value[0], value[1], value[2])', - ivec4: 'uniform4i(location, value[0], value[1], value[2], value[3])', - - bool: 'uniform1i(location, value)', - bvec2: 'uniform2i(location, value[0], value[1])', - bvec3: 'uniform3i(location, value[0], value[1], value[2])', - bvec4: 'uniform4i(location, value[0], value[1], value[2], value[3])', - - mat2: 'uniformMatrix2fv(location, false, value)', - mat3: 'uniformMatrix3fv(location, false, value)', - mat4: 'uniformMatrix4fv(location, false, value)', - - sampler2D: 'uniform1i(location, value)', - samplerCube: 'uniform1i(location, value)', - -}; - -const GLSL_TO_ARRAY_SETTERS = { - - float: 'uniform1fv(location, value)', - - vec2: 'uniform2fv(location, value)', - vec3: 'uniform3fv(location, value)', - vec4: 'uniform4fv(location, value)', - - int: 'uniform1iv(location, value)', - ivec2: 'uniform2iv(location, value)', - ivec3: 'uniform3iv(location, value)', - ivec4: 'uniform4iv(location, value)', - - bool: 'uniform1iv(location, value)', - bvec2: 'uniform2iv(location, value)', - bvec3: 'uniform3iv(location, value)', - bvec4: 'uniform4iv(location, value)', - - sampler2D: 'uniform1iv(location, value)', - samplerCube: 'uniform1i(location, value)', -}; - -/** - * Extracts the attributes - * @method generateUniformAccessObject - * @memberof PIXI.glCore.shader - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param uniforms {Array} @mat ? - * @return attributes {Object} - */ -export default function generateUniformAccessObject(gl, uniformData) -{ - // this is the object we will be sending back. - // an object hierachy will be created for structs - const uniforms = { data: {} }; - - uniforms.gl = gl; - - const uniformKeys = Object.keys(uniformData); - - for (let i = 0; i < uniformKeys.length; i++) - { - const fullName = uniformKeys[i]; - - const nameTokens = fullName.split('.'); - const name = nameTokens[nameTokens.length - 1]; - - const uniformGroup = getUniformGroup(nameTokens, uniforms); - - const uniform = uniformData[fullName]; - - uniformGroup.data[name] = uniform; - - uniformGroup.gl = gl; - - Object.defineProperty(uniformGroup, name, { - get: generateGetter(name), - set: generateSetter(name, uniform), - }); - } - - return uniforms; -} - -function generateGetter(name) -{ - const template = getterTemplate.replace('%%', name); - - return new Function(template); // eslint-disable-line no-new-func -} - -function generateSetter(name, uniform) -{ - let template = setterTemplate.replace(/%%/g, name); - let setTemplate; - - if (uniform.size === 1) - { - setTemplate = GLSL_TO_SINGLE_SETTERS[uniform.type]; - } - else - { - setTemplate = GLSL_TO_ARRAY_SETTERS[uniform.type]; - } - - if (setTemplate) - { - template += `\nthis.gl.${setTemplate};`; - } - - return new Function('value', template); // eslint-disable-line no-new-func -} - -function getUniformGroup(nameTokens, uniform) -{ - let cur = uniform; - - for (let i = 0; i < nameTokens.length - 1; i++) - { - const o = cur[nameTokens[i]] || { data: {} }; - - cur[nameTokens[i]] = o; - cur = o; - } - - return cur; -} diff --git a/packages/core/src/renderers/systems/shader/GLProgram.js b/packages/core/src/renderers/systems/shader/GLProgram.js new file mode 100644 index 0000000..92980ca --- /dev/null +++ b/packages/core/src/renderers/systems/shader/GLProgram.js @@ -0,0 +1,43 @@ +/** + * Helper class to create a webGL Program + * + * @class + * @private + */ +export default class GLProgram +{ + constructor(program, uniformData) + { + /** + * The shader program + * + * @member {WebGLProgram} + */ + this.program = program; + + /** + * holds the uniform data which contains uniform locations + * and current uniform values used for caching and preventing undeed GPU commands + * @type {Object} + */ + this.uniformData = uniformData; + + /** + * uniformGroups holds the various upload functions for the shader. Each uniform group + * and program have a unique upload function generated. + * @type {Object} + */ + this.uniformGroups = {}; + } + + /** + * Destroys this program + * TODO + */ + destroy() + { + this.uniformData = null; + this.uniformGroups = null; + this.program = null; + } +} diff --git a/packages/core/src/renderers/systems/shader/GLShader.js b/packages/core/src/renderers/systems/shader/GLShader.js deleted file mode 100644 index 4ae88c5..0000000 --- a/packages/core/src/renderers/systems/shader/GLShader.js +++ /dev/null @@ -1,102 +0,0 @@ -import compileProgram from './shader/compileProgram'; -import extractAttributes from './shader/extractAttributes'; -import extractUniforms from './shader/extractUniforms'; -import setPrecision from './shader/setPrecision'; -import generateUniformAccessObject from './shader/generateUniformAccessObject'; - -let ID = 0; - -/** - * @namespace PIXI.glCore - */ - -/** - * Helper class to create a webGL Shader - * - * @class - * @memberof PIXI.glCore - * @param gl {WebGLRenderingContext} - * @param vertexSrc {string|string[]} The vertex shader source as an array of strings. - * @param fragmentSrc {string|string[]} The fragment shader source as an array of strings. - * @param precision {string} The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. - * @param attributeLocations {object} A key value pair showing which location eact - * attribute should sit eg {position:0, uvs:1} - */ -export default class Shader -{ - constructor(gl, vertexSrc, fragmentSrc, precision, attributeLocations) - { - /** - * The current WebGL rendering context - * - * @member {WebGLRenderingContext} - */ - this.gl = gl; - - if (precision) - { - vertexSrc = setPrecision(vertexSrc, precision); - fragmentSrc = setPrecision(fragmentSrc, precision); - } - - /** - * The shader program - * - * @member {WebGLProgram} - */ - // First compile the program.. - this.program = compileProgram(gl, vertexSrc, fragmentSrc, attributeLocations); - - /** - * The attributes of the shader as an object containing the following properties - * { - * type, - * size, - * location, - * pointer - * } - * @member {Object} - */ - // next extract the attributes - this.attributes = extractAttributes(gl, this.program); - - this.uniformData = extractUniforms(gl, this.program); - - /** - * The uniforms of the shader as an object containing the following properties - * { - * gl, - * data - * } - * @member {Object} - */ - this.uniforms = generateUniformAccessObject(gl, this.uniformData); - - this.uniformGroups = {}; - - this.id = ID++; - } - - /** - * Uses this shader - */ - bind() - { - this.gl.useProgram(this.program); - } - - /** - * Destroys this shader - * TODO - */ - destroy() - { - this.attributes = null; - this.uniformData = null; - this.uniforms = null; - - const gl = this.gl; - - gl.deleteProgram(this.program); - } -} diff --git a/packages/core/src/renderers/systems/shader/ShaderSystem.js b/packages/core/src/renderers/systems/shader/ShaderSystem.js index ebdb416..e0b98e8 100644 --- a/packages/core/src/renderers/systems/shader/ShaderSystem.js +++ b/packages/core/src/renderers/systems/shader/ShaderSystem.js @@ -1,7 +1,8 @@ import WebGLSystem from '../WebGLSystem'; -import GLShader from './GLShader'; -import { settings } from '@pixi/settings'; +import GLProgram from './GLProgram'; import generateUniformsSync from '../../../shader/generateUniformsSync'; +import defaultValue from '../../../shader/defaultValue'; +import compileProgram from './shader/compileProgram'; let UID = 0; @@ -43,15 +44,12 @@ * * @param {PIXI.Shader} shader - the new shader * @param {boolean} dontSync - false if the shader should automatically sync its uniforms. - * @returns {PIXI.glCore.GLShader} the glShader that belongs to the shader. + * @returns {PIXI.glCore.glProgram} the glProgram that belongs to the shader. */ bind(shader, dontSync) { - // maybe a better place for this... - shader.uniforms.globals = this.renderer.globalUniforms; - const program = shader.program; - const glShader = program.glShaders[this.renderer.CONTEXT_UID] || this.generateShader(shader); + const glProgram = program.glPrograms[this.renderer.CONTEXT_UID] || this.generateShader(shader); this.shader = shader; @@ -59,7 +57,7 @@ if (this.program !== program) { this.program = program; - glShader.bind(); + this.gl.useProgram(glProgram.program); } if (!dontSync) @@ -67,7 +65,7 @@ this.syncUniformGroup(shader.uniformGroup); } - return glShader; + return glProgram; } /** @@ -78,21 +76,21 @@ setUniforms(uniforms) { const shader = this.shader.program; - const glShader = shader.glShaders[this.renderer.CONTEXT_UID]; + const glProgram = shader.glPrograms[this.renderer.CONTEXT_UID]; - shader.syncUniforms(glShader.uniformData, uniforms, this.renderer); + shader.syncUniforms(glProgram.uniformData, uniforms, this.renderer); } syncUniformGroup(group) { - const glShader = this.getGLShader(); + const glProgram = this.getglProgram(); - if (!group.static || group.dirtyId !== glShader.uniformGroups[group.id]) + if (!group.static || group.dirtyId !== glProgram.uniformGroups[group.id]) { - glShader.uniformGroups[group.id] = group.dirtyId; + glProgram.uniformGroups[group.id] = group.dirtyId; const syncFunc = group.syncUniforms[this.shader.program.id] || this.createSyncGroups(group); - syncFunc(glShader.uniformData, group.uniforms, this.renderer); + syncFunc(glProgram.uniformData, group.uniforms, this.renderer); } } @@ -107,46 +105,57 @@ * Returns the underlying GLShade rof the currently bound shader. * This can be handy for when you to have a little more control over the setting of your uniforms. * - * @return {PIXI.glCore.Shader} the glShader for the currently bound Shader for this context + * @return {PIXI.glCore.Shader} the glProgram for the currently bound Shader for this context */ - getGLShader() + getglProgram() { if (this.shader) { - return this.shader.program.glShaders[this.renderer.CONTEXT_UID]; + return this.shader.program.glPrograms[this.renderer.CONTEXT_UID]; } return null; } /** - * Generates a GLShader verion of the Shader provided. + * Generates a glProgram verion of the Shader provided. * * @private - * @param {PIXI.Shader} shader the shader that the glShader will be based on. - * @return {PIXI.glCore.GLShader} A shiney new GLShader + * @param {PIXI.Shader} shader the shader that the glProgram will be based on. + * @return {PIXI.glCore.glProgram} A shiney new glProgram */ generateShader(shader) { - const program = shader.program; - const attribMap = {}; + const gl = this.gl; - // insert the global properties too! + const program = shader.program; + + const attribMap = {}; for (const i in program.attributeData) { attribMap[i] = program.attributeData[i].location; } - const glShader = new GLShader(this.gl, - program.vertexSrc, - program.fragmentSrc, - settings.PRECISION_FRAGMENT, - attribMap); + const shaderProgram = compileProgram(gl, program.vertexSrc, program.fragmentSrc, attribMap); + const uniformData = {}; - program.glShaders[this.renderer.CONTEXT_UID] = glShader; + for (const i in program.uniformData) + { + const data = program.uniformData[i]; - return glShader; + uniformData[i] = { + location: gl.getUniformLocation(shaderProgram, i), + value: defaultValue(data.type, data.size), + }; + } + + const glProgram = new GLProgram(shaderProgram, uniformData); + + program.glPrograms[this.renderer.CONTEXT_UID] = glProgram; + shader.uniforms.globals = this.renderer.globalUniforms; + + return glProgram; } /** diff --git a/packages/core/src/renderers/systems/shader/shader/extractAttributes.js b/packages/core/src/renderers/systems/shader/shader/extractAttributes.js deleted file mode 100644 index 52a62f5..0000000 --- a/packages/core/src/renderers/systems/shader/shader/extractAttributes.js +++ /dev/null @@ -1,38 +0,0 @@ -import mapType from './mapType'; -import mapSize from './mapSize'; - -/** - * Extracts the attributes - * @method extractAttributes - * @memberof PIXI.glCore.shader - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param program {WebGLProgram} The shader program to get the attributes from - * @return attributes {Object} - */ -export default function extractAttributes(gl, program) -{ - const attributes = {}; - - const totalAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES); - - for (let i = 0; i < totalAttributes; i++) - { - const attribData = gl.getActiveAttrib(program, i); - const type = mapType(gl, attribData.type); - - attributes[attribData.name] = { - type, - size: mapSize(type), - location: gl.getAttribLocation(program, attribData.name), - // TODO - make an attribute object - pointer, - }; - } - - return attributes; -} - -function pointer()// type, normalized, stride, start) -{ - // gl.vertexAttribPointer(this.location, this.size, type || gl.FLOAT, normalized || false, stride || 0, start || 0); -} diff --git a/packages/core/src/renderers/systems/shader/shader/extractUniforms.js b/packages/core/src/renderers/systems/shader/shader/extractUniforms.js deleted file mode 100644 index d1c39d6..0000000 --- a/packages/core/src/renderers/systems/shader/shader/extractUniforms.js +++ /dev/null @@ -1,33 +0,0 @@ -import mapType from './mapType'; -import defaultValue from './defaultValue'; - -/** - * Extracts the uniforms - * @method extractUniforms - * @memberof PIXI.glCore.shader - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param program {WebGLProgram} The shader program to get the uniforms from - * @return uniforms {Object} - */ -export default function extractUniforms(gl, program) -{ - const uniforms = {}; - - const totalUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS); - - for (let i = 0; i < totalUniforms; i++) - { - const uniformData = gl.getActiveUniform(program, i); - const name = uniformData.name.replace(/\[.*?\]/, ''); - const type = mapType(gl, uniformData.type); - - uniforms[name] = { - type, - size: uniformData.size, - location: gl.getUniformLocation(program, name), - value: defaultValue(type, uniformData.size), - }; - } - - return uniforms; -} diff --git a/packages/core/src/renderers/systems/shader/shader/generateUniformAccessObject.js b/packages/core/src/renderers/systems/shader/shader/generateUniformAccessObject.js deleted file mode 100644 index ad3865f..0000000 --- a/packages/core/src/renderers/systems/shader/shader/generateUniformAccessObject.js +++ /dev/null @@ -1,143 +0,0 @@ -const getterTemplate = [ - 'return this.data.%%.value;', -].join('\n'); - -const setterTemplate = [ - 'this.data.%%.value = value;', - 'var location = this.data.%%.location;', -].join('\n'); - -const GLSL_TO_SINGLE_SETTERS = { - - float: 'uniform1f(location, value)', - - vec2: 'uniform2f(location, value[0], value[1])', - vec3: 'uniform3f(location, value[0], value[1], value[2])', - vec4: 'uniform4f(location, value[0], value[1], value[2], value[3])', - - int: 'uniform1i(location, value)', - ivec2: 'uniform2i(location, value[0], value[1])', - ivec3: 'uniform3i(location, value[0], value[1], value[2])', - ivec4: 'uniform4i(location, value[0], value[1], value[2], value[3])', - - bool: 'uniform1i(location, value)', - bvec2: 'uniform2i(location, value[0], value[1])', - bvec3: 'uniform3i(location, value[0], value[1], value[2])', - bvec4: 'uniform4i(location, value[0], value[1], value[2], value[3])', - - mat2: 'uniformMatrix2fv(location, false, value)', - mat3: 'uniformMatrix3fv(location, false, value)', - mat4: 'uniformMatrix4fv(location, false, value)', - - sampler2D: 'uniform1i(location, value)', - samplerCube: 'uniform1i(location, value)', - -}; - -const GLSL_TO_ARRAY_SETTERS = { - - float: 'uniform1fv(location, value)', - - vec2: 'uniform2fv(location, value)', - vec3: 'uniform3fv(location, value)', - vec4: 'uniform4fv(location, value)', - - int: 'uniform1iv(location, value)', - ivec2: 'uniform2iv(location, value)', - ivec3: 'uniform3iv(location, value)', - ivec4: 'uniform4iv(location, value)', - - bool: 'uniform1iv(location, value)', - bvec2: 'uniform2iv(location, value)', - bvec3: 'uniform3iv(location, value)', - bvec4: 'uniform4iv(location, value)', - - sampler2D: 'uniform1iv(location, value)', - samplerCube: 'uniform1i(location, value)', -}; - -/** - * Extracts the attributes - * @method generateUniformAccessObject - * @memberof PIXI.glCore.shader - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param uniforms {Array} @mat ? - * @return attributes {Object} - */ -export default function generateUniformAccessObject(gl, uniformData) -{ - // this is the object we will be sending back. - // an object hierachy will be created for structs - const uniforms = { data: {} }; - - uniforms.gl = gl; - - const uniformKeys = Object.keys(uniformData); - - for (let i = 0; i < uniformKeys.length; i++) - { - const fullName = uniformKeys[i]; - - const nameTokens = fullName.split('.'); - const name = nameTokens[nameTokens.length - 1]; - - const uniformGroup = getUniformGroup(nameTokens, uniforms); - - const uniform = uniformData[fullName]; - - uniformGroup.data[name] = uniform; - - uniformGroup.gl = gl; - - Object.defineProperty(uniformGroup, name, { - get: generateGetter(name), - set: generateSetter(name, uniform), - }); - } - - return uniforms; -} - -function generateGetter(name) -{ - const template = getterTemplate.replace('%%', name); - - return new Function(template); // eslint-disable-line no-new-func -} - -function generateSetter(name, uniform) -{ - let template = setterTemplate.replace(/%%/g, name); - let setTemplate; - - if (uniform.size === 1) - { - setTemplate = GLSL_TO_SINGLE_SETTERS[uniform.type]; - } - else - { - setTemplate = GLSL_TO_ARRAY_SETTERS[uniform.type]; - } - - if (setTemplate) - { - template += `\nthis.gl.${setTemplate};`; - } - - return new Function('value', template); // eslint-disable-line no-new-func -} - -function getUniformGroup(nameTokens, uniform) -{ - let cur = uniform; - - for (let i = 0; i < nameTokens.length - 1; i++) - { - const o = cur[nameTokens[i]] || { data: {} }; - - cur[nameTokens[i]] = o; - cur = o; - } - - return cur; -} diff --git a/packages/core/src/renderers/systems/shader/shader/index.js b/packages/core/src/renderers/systems/shader/shader/index.js index cdf5163..ba7a317 100644 --- a/packages/core/src/renderers/systems/shader/shader/index.js +++ b/packages/core/src/renderers/systems/shader/shader/index.js @@ -3,9 +3,6 @@ */ export { default as compileProgram } from './compileProgram'; export { default as defaultValue } from './defaultValue'; -export { default as extractAttributes } from './extractAttributes'; -export { default as extractUniforms } from './extractUniforms'; -export { default as generateUniformAccessObject } from './generateUniformAccessObject'; export { default as setPrecision } from './setPrecision'; export { default as mapSize } from './mapSize'; export { default as mapType } from './mapType'; diff --git a/packages/core/src/renderers/systems/shader/GLProgram.js b/packages/core/src/renderers/systems/shader/GLProgram.js new file mode 100644 index 0000000..92980ca --- /dev/null +++ b/packages/core/src/renderers/systems/shader/GLProgram.js @@ -0,0 +1,43 @@ +/** + * Helper class to create a webGL Program + * + * @class + * @private + */ +export default class GLProgram +{ + constructor(program, uniformData) + { + /** + * The shader program + * + * @member {WebGLProgram} + */ + this.program = program; + + /** + * holds the uniform data which contains uniform locations + * and current uniform values used for caching and preventing undeed GPU commands + * @type {Object} + */ + this.uniformData = uniformData; + + /** + * uniformGroups holds the various upload functions for the shader. Each uniform group + * and program have a unique upload function generated. + * @type {Object} + */ + this.uniformGroups = {}; + } + + /** + * Destroys this program + * TODO + */ + destroy() + { + this.uniformData = null; + this.uniformGroups = null; + this.program = null; + } +} diff --git a/packages/core/src/renderers/systems/shader/GLShader.js b/packages/core/src/renderers/systems/shader/GLShader.js deleted file mode 100644 index 4ae88c5..0000000 --- a/packages/core/src/renderers/systems/shader/GLShader.js +++ /dev/null @@ -1,102 +0,0 @@ -import compileProgram from './shader/compileProgram'; -import extractAttributes from './shader/extractAttributes'; -import extractUniforms from './shader/extractUniforms'; -import setPrecision from './shader/setPrecision'; -import generateUniformAccessObject from './shader/generateUniformAccessObject'; - -let ID = 0; - -/** - * @namespace PIXI.glCore - */ - -/** - * Helper class to create a webGL Shader - * - * @class - * @memberof PIXI.glCore - * @param gl {WebGLRenderingContext} - * @param vertexSrc {string|string[]} The vertex shader source as an array of strings. - * @param fragmentSrc {string|string[]} The fragment shader source as an array of strings. - * @param precision {string} The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. - * @param attributeLocations {object} A key value pair showing which location eact - * attribute should sit eg {position:0, uvs:1} - */ -export default class Shader -{ - constructor(gl, vertexSrc, fragmentSrc, precision, attributeLocations) - { - /** - * The current WebGL rendering context - * - * @member {WebGLRenderingContext} - */ - this.gl = gl; - - if (precision) - { - vertexSrc = setPrecision(vertexSrc, precision); - fragmentSrc = setPrecision(fragmentSrc, precision); - } - - /** - * The shader program - * - * @member {WebGLProgram} - */ - // First compile the program.. - this.program = compileProgram(gl, vertexSrc, fragmentSrc, attributeLocations); - - /** - * The attributes of the shader as an object containing the following properties - * { - * type, - * size, - * location, - * pointer - * } - * @member {Object} - */ - // next extract the attributes - this.attributes = extractAttributes(gl, this.program); - - this.uniformData = extractUniforms(gl, this.program); - - /** - * The uniforms of the shader as an object containing the following properties - * { - * gl, - * data - * } - * @member {Object} - */ - this.uniforms = generateUniformAccessObject(gl, this.uniformData); - - this.uniformGroups = {}; - - this.id = ID++; - } - - /** - * Uses this shader - */ - bind() - { - this.gl.useProgram(this.program); - } - - /** - * Destroys this shader - * TODO - */ - destroy() - { - this.attributes = null; - this.uniformData = null; - this.uniforms = null; - - const gl = this.gl; - - gl.deleteProgram(this.program); - } -} diff --git a/packages/core/src/renderers/systems/shader/ShaderSystem.js b/packages/core/src/renderers/systems/shader/ShaderSystem.js index ebdb416..e0b98e8 100644 --- a/packages/core/src/renderers/systems/shader/ShaderSystem.js +++ b/packages/core/src/renderers/systems/shader/ShaderSystem.js @@ -1,7 +1,8 @@ import WebGLSystem from '../WebGLSystem'; -import GLShader from './GLShader'; -import { settings } from '@pixi/settings'; +import GLProgram from './GLProgram'; import generateUniformsSync from '../../../shader/generateUniformsSync'; +import defaultValue from '../../../shader/defaultValue'; +import compileProgram from './shader/compileProgram'; let UID = 0; @@ -43,15 +44,12 @@ * * @param {PIXI.Shader} shader - the new shader * @param {boolean} dontSync - false if the shader should automatically sync its uniforms. - * @returns {PIXI.glCore.GLShader} the glShader that belongs to the shader. + * @returns {PIXI.glCore.glProgram} the glProgram that belongs to the shader. */ bind(shader, dontSync) { - // maybe a better place for this... - shader.uniforms.globals = this.renderer.globalUniforms; - const program = shader.program; - const glShader = program.glShaders[this.renderer.CONTEXT_UID] || this.generateShader(shader); + const glProgram = program.glPrograms[this.renderer.CONTEXT_UID] || this.generateShader(shader); this.shader = shader; @@ -59,7 +57,7 @@ if (this.program !== program) { this.program = program; - glShader.bind(); + this.gl.useProgram(glProgram.program); } if (!dontSync) @@ -67,7 +65,7 @@ this.syncUniformGroup(shader.uniformGroup); } - return glShader; + return glProgram; } /** @@ -78,21 +76,21 @@ setUniforms(uniforms) { const shader = this.shader.program; - const glShader = shader.glShaders[this.renderer.CONTEXT_UID]; + const glProgram = shader.glPrograms[this.renderer.CONTEXT_UID]; - shader.syncUniforms(glShader.uniformData, uniforms, this.renderer); + shader.syncUniforms(glProgram.uniformData, uniforms, this.renderer); } syncUniformGroup(group) { - const glShader = this.getGLShader(); + const glProgram = this.getglProgram(); - if (!group.static || group.dirtyId !== glShader.uniformGroups[group.id]) + if (!group.static || group.dirtyId !== glProgram.uniformGroups[group.id]) { - glShader.uniformGroups[group.id] = group.dirtyId; + glProgram.uniformGroups[group.id] = group.dirtyId; const syncFunc = group.syncUniforms[this.shader.program.id] || this.createSyncGroups(group); - syncFunc(glShader.uniformData, group.uniforms, this.renderer); + syncFunc(glProgram.uniformData, group.uniforms, this.renderer); } } @@ -107,46 +105,57 @@ * Returns the underlying GLShade rof the currently bound shader. * This can be handy for when you to have a little more control over the setting of your uniforms. * - * @return {PIXI.glCore.Shader} the glShader for the currently bound Shader for this context + * @return {PIXI.glCore.Shader} the glProgram for the currently bound Shader for this context */ - getGLShader() + getglProgram() { if (this.shader) { - return this.shader.program.glShaders[this.renderer.CONTEXT_UID]; + return this.shader.program.glPrograms[this.renderer.CONTEXT_UID]; } return null; } /** - * Generates a GLShader verion of the Shader provided. + * Generates a glProgram verion of the Shader provided. * * @private - * @param {PIXI.Shader} shader the shader that the glShader will be based on. - * @return {PIXI.glCore.GLShader} A shiney new GLShader + * @param {PIXI.Shader} shader the shader that the glProgram will be based on. + * @return {PIXI.glCore.glProgram} A shiney new glProgram */ generateShader(shader) { - const program = shader.program; - const attribMap = {}; + const gl = this.gl; - // insert the global properties too! + const program = shader.program; + + const attribMap = {}; for (const i in program.attributeData) { attribMap[i] = program.attributeData[i].location; } - const glShader = new GLShader(this.gl, - program.vertexSrc, - program.fragmentSrc, - settings.PRECISION_FRAGMENT, - attribMap); + const shaderProgram = compileProgram(gl, program.vertexSrc, program.fragmentSrc, attribMap); + const uniformData = {}; - program.glShaders[this.renderer.CONTEXT_UID] = glShader; + for (const i in program.uniformData) + { + const data = program.uniformData[i]; - return glShader; + uniformData[i] = { + location: gl.getUniformLocation(shaderProgram, i), + value: defaultValue(data.type, data.size), + }; + } + + const glProgram = new GLProgram(shaderProgram, uniformData); + + program.glPrograms[this.renderer.CONTEXT_UID] = glProgram; + shader.uniforms.globals = this.renderer.globalUniforms; + + return glProgram; } /** diff --git a/packages/core/src/renderers/systems/shader/shader/extractAttributes.js b/packages/core/src/renderers/systems/shader/shader/extractAttributes.js deleted file mode 100644 index 52a62f5..0000000 --- a/packages/core/src/renderers/systems/shader/shader/extractAttributes.js +++ /dev/null @@ -1,38 +0,0 @@ -import mapType from './mapType'; -import mapSize from './mapSize'; - -/** - * Extracts the attributes - * @method extractAttributes - * @memberof PIXI.glCore.shader - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param program {WebGLProgram} The shader program to get the attributes from - * @return attributes {Object} - */ -export default function extractAttributes(gl, program) -{ - const attributes = {}; - - const totalAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES); - - for (let i = 0; i < totalAttributes; i++) - { - const attribData = gl.getActiveAttrib(program, i); - const type = mapType(gl, attribData.type); - - attributes[attribData.name] = { - type, - size: mapSize(type), - location: gl.getAttribLocation(program, attribData.name), - // TODO - make an attribute object - pointer, - }; - } - - return attributes; -} - -function pointer()// type, normalized, stride, start) -{ - // gl.vertexAttribPointer(this.location, this.size, type || gl.FLOAT, normalized || false, stride || 0, start || 0); -} diff --git a/packages/core/src/renderers/systems/shader/shader/extractUniforms.js b/packages/core/src/renderers/systems/shader/shader/extractUniforms.js deleted file mode 100644 index d1c39d6..0000000 --- a/packages/core/src/renderers/systems/shader/shader/extractUniforms.js +++ /dev/null @@ -1,33 +0,0 @@ -import mapType from './mapType'; -import defaultValue from './defaultValue'; - -/** - * Extracts the uniforms - * @method extractUniforms - * @memberof PIXI.glCore.shader - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param program {WebGLProgram} The shader program to get the uniforms from - * @return uniforms {Object} - */ -export default function extractUniforms(gl, program) -{ - const uniforms = {}; - - const totalUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS); - - for (let i = 0; i < totalUniforms; i++) - { - const uniformData = gl.getActiveUniform(program, i); - const name = uniformData.name.replace(/\[.*?\]/, ''); - const type = mapType(gl, uniformData.type); - - uniforms[name] = { - type, - size: uniformData.size, - location: gl.getUniformLocation(program, name), - value: defaultValue(type, uniformData.size), - }; - } - - return uniforms; -} diff --git a/packages/core/src/renderers/systems/shader/shader/generateUniformAccessObject.js b/packages/core/src/renderers/systems/shader/shader/generateUniformAccessObject.js deleted file mode 100644 index ad3865f..0000000 --- a/packages/core/src/renderers/systems/shader/shader/generateUniformAccessObject.js +++ /dev/null @@ -1,143 +0,0 @@ -const getterTemplate = [ - 'return this.data.%%.value;', -].join('\n'); - -const setterTemplate = [ - 'this.data.%%.value = value;', - 'var location = this.data.%%.location;', -].join('\n'); - -const GLSL_TO_SINGLE_SETTERS = { - - float: 'uniform1f(location, value)', - - vec2: 'uniform2f(location, value[0], value[1])', - vec3: 'uniform3f(location, value[0], value[1], value[2])', - vec4: 'uniform4f(location, value[0], value[1], value[2], value[3])', - - int: 'uniform1i(location, value)', - ivec2: 'uniform2i(location, value[0], value[1])', - ivec3: 'uniform3i(location, value[0], value[1], value[2])', - ivec4: 'uniform4i(location, value[0], value[1], value[2], value[3])', - - bool: 'uniform1i(location, value)', - bvec2: 'uniform2i(location, value[0], value[1])', - bvec3: 'uniform3i(location, value[0], value[1], value[2])', - bvec4: 'uniform4i(location, value[0], value[1], value[2], value[3])', - - mat2: 'uniformMatrix2fv(location, false, value)', - mat3: 'uniformMatrix3fv(location, false, value)', - mat4: 'uniformMatrix4fv(location, false, value)', - - sampler2D: 'uniform1i(location, value)', - samplerCube: 'uniform1i(location, value)', - -}; - -const GLSL_TO_ARRAY_SETTERS = { - - float: 'uniform1fv(location, value)', - - vec2: 'uniform2fv(location, value)', - vec3: 'uniform3fv(location, value)', - vec4: 'uniform4fv(location, value)', - - int: 'uniform1iv(location, value)', - ivec2: 'uniform2iv(location, value)', - ivec3: 'uniform3iv(location, value)', - ivec4: 'uniform4iv(location, value)', - - bool: 'uniform1iv(location, value)', - bvec2: 'uniform2iv(location, value)', - bvec3: 'uniform3iv(location, value)', - bvec4: 'uniform4iv(location, value)', - - sampler2D: 'uniform1iv(location, value)', - samplerCube: 'uniform1i(location, value)', -}; - -/** - * Extracts the attributes - * @method generateUniformAccessObject - * @memberof PIXI.glCore.shader - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param uniforms {Array} @mat ? - * @return attributes {Object} - */ -export default function generateUniformAccessObject(gl, uniformData) -{ - // this is the object we will be sending back. - // an object hierachy will be created for structs - const uniforms = { data: {} }; - - uniforms.gl = gl; - - const uniformKeys = Object.keys(uniformData); - - for (let i = 0; i < uniformKeys.length; i++) - { - const fullName = uniformKeys[i]; - - const nameTokens = fullName.split('.'); - const name = nameTokens[nameTokens.length - 1]; - - const uniformGroup = getUniformGroup(nameTokens, uniforms); - - const uniform = uniformData[fullName]; - - uniformGroup.data[name] = uniform; - - uniformGroup.gl = gl; - - Object.defineProperty(uniformGroup, name, { - get: generateGetter(name), - set: generateSetter(name, uniform), - }); - } - - return uniforms; -} - -function generateGetter(name) -{ - const template = getterTemplate.replace('%%', name); - - return new Function(template); // eslint-disable-line no-new-func -} - -function generateSetter(name, uniform) -{ - let template = setterTemplate.replace(/%%/g, name); - let setTemplate; - - if (uniform.size === 1) - { - setTemplate = GLSL_TO_SINGLE_SETTERS[uniform.type]; - } - else - { - setTemplate = GLSL_TO_ARRAY_SETTERS[uniform.type]; - } - - if (setTemplate) - { - template += `\nthis.gl.${setTemplate};`; - } - - return new Function('value', template); // eslint-disable-line no-new-func -} - -function getUniformGroup(nameTokens, uniform) -{ - let cur = uniform; - - for (let i = 0; i < nameTokens.length - 1; i++) - { - const o = cur[nameTokens[i]] || { data: {} }; - - cur[nameTokens[i]] = o; - cur = o; - } - - return cur; -} diff --git a/packages/core/src/renderers/systems/shader/shader/index.js b/packages/core/src/renderers/systems/shader/shader/index.js index cdf5163..ba7a317 100644 --- a/packages/core/src/renderers/systems/shader/shader/index.js +++ b/packages/core/src/renderers/systems/shader/shader/index.js @@ -3,9 +3,6 @@ */ export { default as compileProgram } from './compileProgram'; export { default as defaultValue } from './defaultValue'; -export { default as extractAttributes } from './extractAttributes'; -export { default as extractUniforms } from './extractUniforms'; -export { default as generateUniformAccessObject } from './generateUniformAccessObject'; export { default as setPrecision } from './setPrecision'; export { default as mapSize } from './mapSize'; export { default as mapType } from './mapType'; diff --git a/packages/core/src/shader/Program.js b/packages/core/src/shader/Program.js index f0c15a9..4f9971e 100644 --- a/packages/core/src/shader/Program.js +++ b/packages/core/src/shader/Program.js @@ -1,9 +1,9 @@ -import extractUniformsFromSrc from './extractUniformsFromSrc'; import * as shaderUtils from '../renderers/systems/shader/shader'; import { ProgramCache } from '@pixi/utils'; import getTestContext from './getTestContext'; import defaultFragment from './defaultProgram.frag'; import defaultVertex from './defaultProgram.vert'; +import { settings } from '@pixi/settings'; let UID = 0; @@ -34,11 +34,14 @@ */ this.fragmentSrc = fragmentSrc || Program.defaultFragmentSrc; + this.vertexSrc = shaderUtils.setPrecision(this.vertexSrc, settings.PRECISION_VERTEX); + this.fragmentSrc = shaderUtils.setPrecision(this.fragmentSrc, settings.PRECISION_FRAGMENT); + // currently this does not extract structs only default types this.extractData(this.vertexSrc, this.fragmentSrc); // this is where we store shader references.. - this.glShaders = {}; + this.glPrograms = {}; this.syncUniforms = null; @@ -57,22 +60,19 @@ { const gl = getTestContext(); - if (!gl) + if (gl) { - // uh oh! no webGL.. lets read uniforms from the strings.. - this.attributeData = {}; - this.uniformData = extractUniformsFromSrc(vertexSrc, fragmentSrc); - } - else - { - vertexSrc = shaderUtils.setPrecision(vertexSrc, 'mediump'); - fragmentSrc = shaderUtils.setPrecision(fragmentSrc, 'mediump'); - const program = shaderUtils.compileProgram(gl, vertexSrc, fragmentSrc); this.attributeData = this.getAttributeData(program, gl); this.uniformData = this.getUniformData(program, gl); - // gl.deleteProgram(program); + + gl.deleteProgram(program); + } + else + { + this.uniformData = {}; + this.attributeData = {}; } }