diff --git a/src/core/index.js b/src/core/index.js index f7a817c..dfda36d 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -44,6 +44,7 @@ export { default as Quad } from './renderers/webgl/utils/Quad'; export { default as Shader } from './shader/Shader'; export { default as Program } from './shader/Program'; +export { default as UniformGroup } from './shader/UniformGroup'; export { default as SpriteMaskFilter } from './renderers/webgl/filters/spriteMask/SpriteMaskFilter'; export { default as Filter } from './renderers/webgl/filters/Filter'; export { default as Application } from './Application'; diff --git a/src/core/index.js b/src/core/index.js index f7a817c..dfda36d 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -44,6 +44,7 @@ export { default as Quad } from './renderers/webgl/utils/Quad'; export { default as Shader } from './shader/Shader'; export { default as Program } from './shader/Program'; +export { default as UniformGroup } from './shader/UniformGroup'; export { default as SpriteMaskFilter } from './renderers/webgl/filters/spriteMask/SpriteMaskFilter'; export { default as Filter } from './renderers/webgl/filters/Filter'; export { default as Application } from './Application'; diff --git a/src/core/renderers/webgl/ShaderManager.js b/src/core/renderers/webgl/ShaderManager.js index b4fdfc9..290d4ba 100644 --- a/src/core/renderers/webgl/ShaderManager.js +++ b/src/core/renderers/webgl/ShaderManager.js @@ -1,5 +1,8 @@ import { GLShader } from 'pixi-gl-core'; import { PRECISION } from '../../const'; +import generateUniformsSync from '../../shader/generateUniformsSync2'; + +let UID = 0; /** * Helper class to create a webGL Texture @@ -29,6 +32,8 @@ this.gl = renderer.gl; this.shader = null; + + this.id = UID++; } /** @@ -71,6 +76,38 @@ shader.syncUniforms(glShader.uniformData, uniforms, this.renderer); } + setUniformsGroups(uniformGroups) + { + + const glShader = this.getGLShader(); + + const group = uniformGroups[0]; + const syncFunc = group.syncUniforms[this.shader.program.id] || this.createSynGroups(group); + + syncFunc(glShader.uniformD1ata, group.uniforms, this.renderer); + + } + + syncUniformGroup(group) + { + const glShader = this.getGLShader(); + + if(!group.static || group.dirtyId !== glShader.uniformGroups[group.id]) + { + glShader.uniformGroups[group.id] = group.dirtyId; + const syncFunc = group.syncUniforms[this.shader.program.id] || this.createSynGroups(group); + + syncFunc(glShader.uniformData, group.uniforms, this.renderer); + } + + } + + createSynGroups(group) + { + group.syncUniforms[this.shader.program.id] = generateUniformsSync(group, this.shader.program.uniformData); + + return group.syncUniforms[this.shader.program.id]; + } /** * 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. diff --git a/src/core/index.js b/src/core/index.js index f7a817c..dfda36d 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -44,6 +44,7 @@ export { default as Quad } from './renderers/webgl/utils/Quad'; export { default as Shader } from './shader/Shader'; export { default as Program } from './shader/Program'; +export { default as UniformGroup } from './shader/UniformGroup'; export { default as SpriteMaskFilter } from './renderers/webgl/filters/spriteMask/SpriteMaskFilter'; export { default as Filter } from './renderers/webgl/filters/Filter'; export { default as Application } from './Application'; diff --git a/src/core/renderers/webgl/ShaderManager.js b/src/core/renderers/webgl/ShaderManager.js index b4fdfc9..290d4ba 100644 --- a/src/core/renderers/webgl/ShaderManager.js +++ b/src/core/renderers/webgl/ShaderManager.js @@ -1,5 +1,8 @@ import { GLShader } from 'pixi-gl-core'; import { PRECISION } from '../../const'; +import generateUniformsSync from '../../shader/generateUniformsSync2'; + +let UID = 0; /** * Helper class to create a webGL Texture @@ -29,6 +32,8 @@ this.gl = renderer.gl; this.shader = null; + + this.id = UID++; } /** @@ -71,6 +76,38 @@ shader.syncUniforms(glShader.uniformData, uniforms, this.renderer); } + setUniformsGroups(uniformGroups) + { + + const glShader = this.getGLShader(); + + const group = uniformGroups[0]; + const syncFunc = group.syncUniforms[this.shader.program.id] || this.createSynGroups(group); + + syncFunc(glShader.uniformD1ata, group.uniforms, this.renderer); + + } + + syncUniformGroup(group) + { + const glShader = this.getGLShader(); + + if(!group.static || group.dirtyId !== glShader.uniformGroups[group.id]) + { + glShader.uniformGroups[group.id] = group.dirtyId; + const syncFunc = group.syncUniforms[this.shader.program.id] || this.createSynGroups(group); + + syncFunc(glShader.uniformData, group.uniforms, this.renderer); + } + + } + + createSynGroups(group) + { + group.syncUniforms[this.shader.program.id] = generateUniformsSync(group, this.shader.program.uniformData); + + return group.syncUniforms[this.shader.program.id]; + } /** * 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. diff --git a/src/core/shader/UniformGroup.js b/src/core/shader/UniformGroup.js new file mode 100644 index 0000000..89bc2ef --- /dev/null +++ b/src/core/shader/UniformGroup.js @@ -0,0 +1,43 @@ +import Program from './Program'; +import generateUniformsSync from './generateUniformsSync'; + +let UID = 0; + +// let math = require('../../../math'); +/** + * @class + * @memberof PIXI + * @extends PIXI.UniformGroup + */ +class UniformGroup +{ + /** + * @param {PIXI.Program} [program] - The program the shader will use. + * @param {object} [uniforms] - Custom uniforms to use to augment the built-in ones. + */ + constructor(uniforms, _static) + { + this.uniforms = uniforms; + this.group = true; + // lets generate this when the shader ? + this.syncUniforms = {}; + this.dirtyId = 0; + this.id = UID++; + + this.static = !!_static; + + console.log(this.static + "<<<<<<<") + } + + update() + { + this.dirtyId++; + } + + static from(uniforms, _static) + { + return new UniformGroup(uniforms, _static); + } +} + +export default UniformGroup; diff --git a/src/core/index.js b/src/core/index.js index f7a817c..dfda36d 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -44,6 +44,7 @@ export { default as Quad } from './renderers/webgl/utils/Quad'; export { default as Shader } from './shader/Shader'; export { default as Program } from './shader/Program'; +export { default as UniformGroup } from './shader/UniformGroup'; export { default as SpriteMaskFilter } from './renderers/webgl/filters/spriteMask/SpriteMaskFilter'; export { default as Filter } from './renderers/webgl/filters/Filter'; export { default as Application } from './Application'; diff --git a/src/core/renderers/webgl/ShaderManager.js b/src/core/renderers/webgl/ShaderManager.js index b4fdfc9..290d4ba 100644 --- a/src/core/renderers/webgl/ShaderManager.js +++ b/src/core/renderers/webgl/ShaderManager.js @@ -1,5 +1,8 @@ import { GLShader } from 'pixi-gl-core'; import { PRECISION } from '../../const'; +import generateUniformsSync from '../../shader/generateUniformsSync2'; + +let UID = 0; /** * Helper class to create a webGL Texture @@ -29,6 +32,8 @@ this.gl = renderer.gl; this.shader = null; + + this.id = UID++; } /** @@ -71,6 +76,38 @@ shader.syncUniforms(glShader.uniformData, uniforms, this.renderer); } + setUniformsGroups(uniformGroups) + { + + const glShader = this.getGLShader(); + + const group = uniformGroups[0]; + const syncFunc = group.syncUniforms[this.shader.program.id] || this.createSynGroups(group); + + syncFunc(glShader.uniformD1ata, group.uniforms, this.renderer); + + } + + syncUniformGroup(group) + { + const glShader = this.getGLShader(); + + if(!group.static || group.dirtyId !== glShader.uniformGroups[group.id]) + { + glShader.uniformGroups[group.id] = group.dirtyId; + const syncFunc = group.syncUniforms[this.shader.program.id] || this.createSynGroups(group); + + syncFunc(glShader.uniformData, group.uniforms, this.renderer); + } + + } + + createSynGroups(group) + { + group.syncUniforms[this.shader.program.id] = generateUniformsSync(group, this.shader.program.uniformData); + + return group.syncUniforms[this.shader.program.id]; + } /** * 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. diff --git a/src/core/shader/UniformGroup.js b/src/core/shader/UniformGroup.js new file mode 100644 index 0000000..89bc2ef --- /dev/null +++ b/src/core/shader/UniformGroup.js @@ -0,0 +1,43 @@ +import Program from './Program'; +import generateUniformsSync from './generateUniformsSync'; + +let UID = 0; + +// let math = require('../../../math'); +/** + * @class + * @memberof PIXI + * @extends PIXI.UniformGroup + */ +class UniformGroup +{ + /** + * @param {PIXI.Program} [program] - The program the shader will use. + * @param {object} [uniforms] - Custom uniforms to use to augment the built-in ones. + */ + constructor(uniforms, _static) + { + this.uniforms = uniforms; + this.group = true; + // lets generate this when the shader ? + this.syncUniforms = {}; + this.dirtyId = 0; + this.id = UID++; + + this.static = !!_static; + + console.log(this.static + "<<<<<<<") + } + + update() + { + this.dirtyId++; + } + + static from(uniforms, _static) + { + return new UniformGroup(uniforms, _static); + } +} + +export default UniformGroup; diff --git a/src/core/shader/generateUniformsSync2.js b/src/core/shader/generateUniformsSync2.js new file mode 100644 index 0000000..5a1da3b --- /dev/null +++ b/src/core/shader/generateUniformsSync2.js @@ -0,0 +1,165 @@ +const GLSL_TO_SINGLE_SETTERS_CACHED = { + + float: `if(cacheValue !== value) +{ + cacheValue.value = value; + gl.uniform1f(location, value) +}`, + + vec2: `if(cacheValue[0] !== value[0] || cacheValue[1] !== value[1]) +{ + cacheValue[0] = value[0]; + cacheValue[1] = value[1]; + gl.uniform2f(location, value[0], value[1]) +}`, + vec3: `if(cacheValue[0] !== value[0] || cacheValue[1] !== value[1] || cacheValue[2] !== value[2]) +{ + cacheValue[0] = value[0]; + cacheValue[1] = value[1]; + cacheValue[2] = value[2]; + + gl.uniform3f(location, value[0], value[1], value[2]) +}`, + vec4: 'gl.uniform4f(location, value[0], value[1], value[2], value[3])', + + int: 'gl.uniform1i(location, value)', + ivec2: 'gl.uniform2i(location, value[0], value[1])', + ivec3: 'gl.uniform3i(location, value[0], value[1], value[2])', + ivec4: 'gl.uniform4i(location, value[0], value[1], value[2], value[3])', + + bool: 'gl.uniform1i(location, value)', + bvec2: 'gl.uniform2i(location, value[0], value[1])', + bvec3: 'gl.uniform3i(location, value[0], value[1], value[2])', + bvec4: 'gl.uniform4i(location, value[0], value[1], value[2], value[3])', + + mat2: 'gl.uniformMatrix2fv(location, false, value)', + mat3: 'gl.uniformMatrix3fv(location, false, value)', + mat4: 'gl.uniformMatrix4fv(location, false, value)', + + sampler2D: 'uniform1i(location, value)', +}; + +const GLSL_TO_ARRAY_SETTERS = { + + float: `gl.uniform1fv(location, value)`, + + vec2: `gl.uniform2fv(location, value)`, + vec3: `gl.uniform3fv(location, value)`, + vec4: 'gl.uniform4fv(location, value)', + + int: 'gl.uniform1iv(location, value)', + ivec2: 'gl.uniform2iv(location, value)', + ivec3: 'gl.uniform3iv(location, value)', + ivec4: 'gl.uniform4iv(location, value)', + + bool: 'gl.uniform1iv(location, value)', + bvec2: 'gl.uniform2iv(location, value)', + bvec3: 'gl.uniform3iv(location, value)', + bvec4: 'gl.uniform4iv(location, value)', + + sampler2D: 'uniform1i(location, value)', +}; + +export default function generateUniformsSync2(group, uniformData) +{ + let textureCount = 1; + let func = `var value = null; + var cacheValue = null + var gl = renderer.gl`; + + + for (const i in group.uniforms) + { + const data = uniformData[i]; + //group.uniforms[i]; + // console.log(i, data); + if(!data) + { + if(group.uniforms[i].group) + { + func += ` + renderer.shaderManager.syncUniformGroup(uniformValues.${i}); + ` + } + + continue; + } + + // TODO && uniformData[i].value !== 0 <-- do we still need this? + if (data.type === 'float' && data.size === 1) + { + func += `\nif(uniformValues.${i} !== uniformData.${i}.value) +{ + uniformData.${i}.value = uniformValues.${i} + gl.uniform1f(uniformData.${i}.location, uniformValues.${i}) +}\n`; + } + else if (data.type === 'sampler2D' && data.size === 1) + { + func += `\nif (uniformValues.${i}.baseTexture) +{ + var location = renderer.bindTexture(uniformValues.${i}.baseTexture, ${textureCount++}, false); + + if(uniformData.${i}.value !== location) + { + uniformData.${i}.value = location; + gl.uniform1i(uniformData.${i}.location, location);\n; // eslint-disable-line max-len + } +} +else +{ + uniformData.${i}.value = ${textureCount}; + renderer.boundTextures[${textureCount}] = renderer.emptyTextures[${textureCount}]; + gl.activeTexture(gl.TEXTURE0 + ${textureCount++}); + + uniformValues.${i}.bind(); +}`; + } + else if (data.type === 'mat3' && data.size === 1) + { + func += `\nvalue = uniformValues.${i}; +gl.uniformMatrix3fv(uniformData.${i}.location, false, (value.a === undefined) ? value : value.toArray(true));\n`; + } + else if (data.type === 'vec2' && data.size === 1) + { + // TODO - do we need both here? + // maybe we can get away with only using points? + func += `\ncacheValue = uniformData.${i}.value; +value = uniformValues.${i}; + +if(value.x !== undefined) +{ + if(cacheValue[0] !== value.x || cacheValue[1] !== value.y) + { + cacheValue[0] = value.x; + cacheValue[1] = value.y; + gl.uniform2f(uniformData.${i}.location, value.x, value.y); + } +} +else +{ + if(cacheValue[0] !== value[0] || cacheValue[1] !== value[1]) + { + cacheValue[0] = value[0]; + cacheValue[1] = value[1]; + gl.uniform2f(uniformData.${i}.location, value[0], value[1]); + } +}\n`; + } + else + { + const templateType = (data.size === 1) ? GLSL_TO_SINGLE_SETTERS_CACHED : GLSL_TO_ARRAY_SETTERS; + + const template = templateType[data.type].replace('location', `uniformData.${i}.location`); + + func += `\ncacheValue = uniformData.${i}.value; +value = uniformValues.${i}; +${template};\n`; + } + } + + //console.log(' --------------- ') + //console.log(func); + + return new Function('uniformData', 'uniformValues', 'renderer', func); // eslint-disable-line no-new-func +} diff --git a/src/core/index.js b/src/core/index.js index f7a817c..dfda36d 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -44,6 +44,7 @@ export { default as Quad } from './renderers/webgl/utils/Quad'; export { default as Shader } from './shader/Shader'; export { default as Program } from './shader/Program'; +export { default as UniformGroup } from './shader/UniformGroup'; export { default as SpriteMaskFilter } from './renderers/webgl/filters/spriteMask/SpriteMaskFilter'; export { default as Filter } from './renderers/webgl/filters/Filter'; export { default as Application } from './Application'; diff --git a/src/core/renderers/webgl/ShaderManager.js b/src/core/renderers/webgl/ShaderManager.js index b4fdfc9..290d4ba 100644 --- a/src/core/renderers/webgl/ShaderManager.js +++ b/src/core/renderers/webgl/ShaderManager.js @@ -1,5 +1,8 @@ import { GLShader } from 'pixi-gl-core'; import { PRECISION } from '../../const'; +import generateUniformsSync from '../../shader/generateUniformsSync2'; + +let UID = 0; /** * Helper class to create a webGL Texture @@ -29,6 +32,8 @@ this.gl = renderer.gl; this.shader = null; + + this.id = UID++; } /** @@ -71,6 +76,38 @@ shader.syncUniforms(glShader.uniformData, uniforms, this.renderer); } + setUniformsGroups(uniformGroups) + { + + const glShader = this.getGLShader(); + + const group = uniformGroups[0]; + const syncFunc = group.syncUniforms[this.shader.program.id] || this.createSynGroups(group); + + syncFunc(glShader.uniformD1ata, group.uniforms, this.renderer); + + } + + syncUniformGroup(group) + { + const glShader = this.getGLShader(); + + if(!group.static || group.dirtyId !== glShader.uniformGroups[group.id]) + { + glShader.uniformGroups[group.id] = group.dirtyId; + const syncFunc = group.syncUniforms[this.shader.program.id] || this.createSynGroups(group); + + syncFunc(glShader.uniformData, group.uniforms, this.renderer); + } + + } + + createSynGroups(group) + { + group.syncUniforms[this.shader.program.id] = generateUniformsSync(group, this.shader.program.uniformData); + + return group.syncUniforms[this.shader.program.id]; + } /** * 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. diff --git a/src/core/shader/UniformGroup.js b/src/core/shader/UniformGroup.js new file mode 100644 index 0000000..89bc2ef --- /dev/null +++ b/src/core/shader/UniformGroup.js @@ -0,0 +1,43 @@ +import Program from './Program'; +import generateUniformsSync from './generateUniformsSync'; + +let UID = 0; + +// let math = require('../../../math'); +/** + * @class + * @memberof PIXI + * @extends PIXI.UniformGroup + */ +class UniformGroup +{ + /** + * @param {PIXI.Program} [program] - The program the shader will use. + * @param {object} [uniforms] - Custom uniforms to use to augment the built-in ones. + */ + constructor(uniforms, _static) + { + this.uniforms = uniforms; + this.group = true; + // lets generate this when the shader ? + this.syncUniforms = {}; + this.dirtyId = 0; + this.id = UID++; + + this.static = !!_static; + + console.log(this.static + "<<<<<<<") + } + + update() + { + this.dirtyId++; + } + + static from(uniforms, _static) + { + return new UniformGroup(uniforms, _static); + } +} + +export default UniformGroup; diff --git a/src/core/shader/generateUniformsSync2.js b/src/core/shader/generateUniformsSync2.js new file mode 100644 index 0000000..5a1da3b --- /dev/null +++ b/src/core/shader/generateUniformsSync2.js @@ -0,0 +1,165 @@ +const GLSL_TO_SINGLE_SETTERS_CACHED = { + + float: `if(cacheValue !== value) +{ + cacheValue.value = value; + gl.uniform1f(location, value) +}`, + + vec2: `if(cacheValue[0] !== value[0] || cacheValue[1] !== value[1]) +{ + cacheValue[0] = value[0]; + cacheValue[1] = value[1]; + gl.uniform2f(location, value[0], value[1]) +}`, + vec3: `if(cacheValue[0] !== value[0] || cacheValue[1] !== value[1] || cacheValue[2] !== value[2]) +{ + cacheValue[0] = value[0]; + cacheValue[1] = value[1]; + cacheValue[2] = value[2]; + + gl.uniform3f(location, value[0], value[1], value[2]) +}`, + vec4: 'gl.uniform4f(location, value[0], value[1], value[2], value[3])', + + int: 'gl.uniform1i(location, value)', + ivec2: 'gl.uniform2i(location, value[0], value[1])', + ivec3: 'gl.uniform3i(location, value[0], value[1], value[2])', + ivec4: 'gl.uniform4i(location, value[0], value[1], value[2], value[3])', + + bool: 'gl.uniform1i(location, value)', + bvec2: 'gl.uniform2i(location, value[0], value[1])', + bvec3: 'gl.uniform3i(location, value[0], value[1], value[2])', + bvec4: 'gl.uniform4i(location, value[0], value[1], value[2], value[3])', + + mat2: 'gl.uniformMatrix2fv(location, false, value)', + mat3: 'gl.uniformMatrix3fv(location, false, value)', + mat4: 'gl.uniformMatrix4fv(location, false, value)', + + sampler2D: 'uniform1i(location, value)', +}; + +const GLSL_TO_ARRAY_SETTERS = { + + float: `gl.uniform1fv(location, value)`, + + vec2: `gl.uniform2fv(location, value)`, + vec3: `gl.uniform3fv(location, value)`, + vec4: 'gl.uniform4fv(location, value)', + + int: 'gl.uniform1iv(location, value)', + ivec2: 'gl.uniform2iv(location, value)', + ivec3: 'gl.uniform3iv(location, value)', + ivec4: 'gl.uniform4iv(location, value)', + + bool: 'gl.uniform1iv(location, value)', + bvec2: 'gl.uniform2iv(location, value)', + bvec3: 'gl.uniform3iv(location, value)', + bvec4: 'gl.uniform4iv(location, value)', + + sampler2D: 'uniform1i(location, value)', +}; + +export default function generateUniformsSync2(group, uniformData) +{ + let textureCount = 1; + let func = `var value = null; + var cacheValue = null + var gl = renderer.gl`; + + + for (const i in group.uniforms) + { + const data = uniformData[i]; + //group.uniforms[i]; + // console.log(i, data); + if(!data) + { + if(group.uniforms[i].group) + { + func += ` + renderer.shaderManager.syncUniformGroup(uniformValues.${i}); + ` + } + + continue; + } + + // TODO && uniformData[i].value !== 0 <-- do we still need this? + if (data.type === 'float' && data.size === 1) + { + func += `\nif(uniformValues.${i} !== uniformData.${i}.value) +{ + uniformData.${i}.value = uniformValues.${i} + gl.uniform1f(uniformData.${i}.location, uniformValues.${i}) +}\n`; + } + else if (data.type === 'sampler2D' && data.size === 1) + { + func += `\nif (uniformValues.${i}.baseTexture) +{ + var location = renderer.bindTexture(uniformValues.${i}.baseTexture, ${textureCount++}, false); + + if(uniformData.${i}.value !== location) + { + uniformData.${i}.value = location; + gl.uniform1i(uniformData.${i}.location, location);\n; // eslint-disable-line max-len + } +} +else +{ + uniformData.${i}.value = ${textureCount}; + renderer.boundTextures[${textureCount}] = renderer.emptyTextures[${textureCount}]; + gl.activeTexture(gl.TEXTURE0 + ${textureCount++}); + + uniformValues.${i}.bind(); +}`; + } + else if (data.type === 'mat3' && data.size === 1) + { + func += `\nvalue = uniformValues.${i}; +gl.uniformMatrix3fv(uniformData.${i}.location, false, (value.a === undefined) ? value : value.toArray(true));\n`; + } + else if (data.type === 'vec2' && data.size === 1) + { + // TODO - do we need both here? + // maybe we can get away with only using points? + func += `\ncacheValue = uniformData.${i}.value; +value = uniformValues.${i}; + +if(value.x !== undefined) +{ + if(cacheValue[0] !== value.x || cacheValue[1] !== value.y) + { + cacheValue[0] = value.x; + cacheValue[1] = value.y; + gl.uniform2f(uniformData.${i}.location, value.x, value.y); + } +} +else +{ + if(cacheValue[0] !== value[0] || cacheValue[1] !== value[1]) + { + cacheValue[0] = value[0]; + cacheValue[1] = value[1]; + gl.uniform2f(uniformData.${i}.location, value[0], value[1]); + } +}\n`; + } + else + { + const templateType = (data.size === 1) ? GLSL_TO_SINGLE_SETTERS_CACHED : GLSL_TO_ARRAY_SETTERS; + + const template = templateType[data.type].replace('location', `uniformData.${i}.location`); + + func += `\ncacheValue = uniformData.${i}.value; +value = uniformValues.${i}; +${template};\n`; + } + } + + //console.log(' --------------- ') + //console.log(func); + + return new Function('uniformData', 'uniformValues', 'renderer', func); // eslint-disable-line no-new-func +} diff --git a/src/mesh/webgl/MeshRenderer.js b/src/mesh/webgl/MeshRenderer.js index eaa0279..0ba2687 100644 --- a/src/mesh/webgl/MeshRenderer.js +++ b/src/mesh/webgl/MeshRenderer.js @@ -54,7 +54,7 @@ } // set unifomrs.. - this.renderer.shaderManager.setUniforms(mesh.shader.uniforms); + this.renderer.shaderManager.syncUniformGroup(mesh.shader.uniforms); // sync uniforms.. this.renderer.state.setState(mesh.state);