diff --git a/src/core/renderers/webgl/ShaderManager.js b/src/core/renderers/webgl/ShaderManager.js index 4524008..df55793 100644 --- a/src/core/renderers/webgl/ShaderManager.js +++ b/src/core/renderers/webgl/ShaderManager.js @@ -55,6 +55,11 @@ shader.syncUniforms(glShader.uniformData, uniforms, this.gl); } + getGLShader() + { + return this.shader.glShaders[this.renderer.CONTEXT_UID] || this.generateShader(shader); + } + generateShader(shader) { const attribMap = {}; diff --git a/src/core/renderers/webgl/ShaderManager.js b/src/core/renderers/webgl/ShaderManager.js index 4524008..df55793 100644 --- a/src/core/renderers/webgl/ShaderManager.js +++ b/src/core/renderers/webgl/ShaderManager.js @@ -55,6 +55,11 @@ shader.syncUniforms(glShader.uniformData, uniforms, this.gl); } + getGLShader() + { + return this.shader.glShaders[this.renderer.CONTEXT_UID] || this.generateShader(shader); + } + generateShader(shader) { const attribMap = {}; diff --git a/src/core/renderers/webgl/managers/FilterManager.js b/src/core/renderers/webgl/managers/FilterManager.js index a6a891a..381238a 100644 --- a/src/core/renderers/webgl/managers/FilterManager.js +++ b/src/core/renderers/webgl/managers/FilterManager.js @@ -24,6 +24,8 @@ this.filters = []; this.target = null; this.resolution = 1; + + this.firstRun = true; } } @@ -45,6 +47,7 @@ // know about sprites! this.quad = new Quad(this.gl, renderer.state.attribState); + this.shaderCache = {}; // todo add default! this.pool = {}; @@ -136,6 +139,8 @@ // bind the render target renderer.bindRenderTarget(renderTarget); renderTarget.clear(); + + } /** @@ -212,6 +217,7 @@ const renderer = this.renderer; const gl = renderer.gl; +/* let shader = filter.glShaders[renderer.CONTEXT_UID]; // cacheing.. @@ -239,6 +245,22 @@ this.quad.initVao(shader); } +*/ + renderer.bindShader(filter, true); + + // TODO theres a better way! + // quad can be a mesh and we then should be able to pull this off without accessing the shader directly + const shader = renderer.shaderManager.getGLShader(); +// renderer.shaderManager.upd + + if(!this.firstRun) + { + this.firstRun = true; + renderer.bindVao(null); + + this.quad.initVao(shader); + } + renderer.bindVao(this.quad.vao); @@ -257,10 +279,43 @@ renderer.maskManager.pushScissorMask(null, renderer.maskManager.scissorData); } - renderer._bindGLShader(shader); + // renderer._bindGLShader(shader); + + let currentState; // this syncs the pixi filters uniforms with glsl uniforms - this.syncUniforms(shader, filter); + + if (shader.uniforms.data.filterArea) + { + currentState = this.filterData.stack[this.filterData.index]; + const filterArea = shader.uniforms.filterArea; + + filterArea[0] = currentState.renderTarget.size.width; + filterArea[1] = currentState.renderTarget.size.height; + filterArea[2] = currentState.sourceFrame.x; + filterArea[3] = currentState.sourceFrame.y; + + filter.uniforms.filterArea = filterArea; + } + + // use this to clamp displaced texture coords so they belong to filterArea + // see displacementFilter fragment shader for an example + if (shader.uniforms.data.filterClamp) + { + currentState = this.filterData.stack[this.filterData.index]; + + const filterClamp = shader.uniforms.filterClamp; + + filterClamp[0] = 0; + filterClamp[1] = 0; + filterClamp[2] = (currentState.sourceFrame.width - 1) / currentState.renderTarget.size.width; + filterClamp[3] = (currentState.sourceFrame.height - 1) / currentState.renderTarget.size.height; + + filter.uniforms.filterClamp = filterClamp; + } + + renderer.shaderManager.setUniforms(filter.uniforms); + // this.syncUniforms(shader, filter); renderer.state.setBlendMode(filter.blendMode); @@ -364,7 +419,7 @@ { // check if its a point.. if (uniforms[i].x !== undefined) - { + { const val = shader.uniforms[i] || new Float32Array(2); val[0] = uniforms[i].x; diff --git a/src/core/renderers/webgl/ShaderManager.js b/src/core/renderers/webgl/ShaderManager.js index 4524008..df55793 100644 --- a/src/core/renderers/webgl/ShaderManager.js +++ b/src/core/renderers/webgl/ShaderManager.js @@ -55,6 +55,11 @@ shader.syncUniforms(glShader.uniformData, uniforms, this.gl); } + getGLShader() + { + return this.shader.glShaders[this.renderer.CONTEXT_UID] || this.generateShader(shader); + } + generateShader(shader) { const attribMap = {}; diff --git a/src/core/renderers/webgl/managers/FilterManager.js b/src/core/renderers/webgl/managers/FilterManager.js index a6a891a..381238a 100644 --- a/src/core/renderers/webgl/managers/FilterManager.js +++ b/src/core/renderers/webgl/managers/FilterManager.js @@ -24,6 +24,8 @@ this.filters = []; this.target = null; this.resolution = 1; + + this.firstRun = true; } } @@ -45,6 +47,7 @@ // know about sprites! this.quad = new Quad(this.gl, renderer.state.attribState); + this.shaderCache = {}; // todo add default! this.pool = {}; @@ -136,6 +139,8 @@ // bind the render target renderer.bindRenderTarget(renderTarget); renderTarget.clear(); + + } /** @@ -212,6 +217,7 @@ const renderer = this.renderer; const gl = renderer.gl; +/* let shader = filter.glShaders[renderer.CONTEXT_UID]; // cacheing.. @@ -239,6 +245,22 @@ this.quad.initVao(shader); } +*/ + renderer.bindShader(filter, true); + + // TODO theres a better way! + // quad can be a mesh and we then should be able to pull this off without accessing the shader directly + const shader = renderer.shaderManager.getGLShader(); +// renderer.shaderManager.upd + + if(!this.firstRun) + { + this.firstRun = true; + renderer.bindVao(null); + + this.quad.initVao(shader); + } + renderer.bindVao(this.quad.vao); @@ -257,10 +279,43 @@ renderer.maskManager.pushScissorMask(null, renderer.maskManager.scissorData); } - renderer._bindGLShader(shader); + // renderer._bindGLShader(shader); + + let currentState; // this syncs the pixi filters uniforms with glsl uniforms - this.syncUniforms(shader, filter); + + if (shader.uniforms.data.filterArea) + { + currentState = this.filterData.stack[this.filterData.index]; + const filterArea = shader.uniforms.filterArea; + + filterArea[0] = currentState.renderTarget.size.width; + filterArea[1] = currentState.renderTarget.size.height; + filterArea[2] = currentState.sourceFrame.x; + filterArea[3] = currentState.sourceFrame.y; + + filter.uniforms.filterArea = filterArea; + } + + // use this to clamp displaced texture coords so they belong to filterArea + // see displacementFilter fragment shader for an example + if (shader.uniforms.data.filterClamp) + { + currentState = this.filterData.stack[this.filterData.index]; + + const filterClamp = shader.uniforms.filterClamp; + + filterClamp[0] = 0; + filterClamp[1] = 0; + filterClamp[2] = (currentState.sourceFrame.width - 1) / currentState.renderTarget.size.width; + filterClamp[3] = (currentState.sourceFrame.height - 1) / currentState.renderTarget.size.height; + + filter.uniforms.filterClamp = filterClamp; + } + + renderer.shaderManager.setUniforms(filter.uniforms); + // this.syncUniforms(shader, filter); renderer.state.setBlendMode(filter.blendMode); @@ -364,7 +419,7 @@ { // check if its a point.. if (uniforms[i].x !== undefined) - { + { const val = shader.uniforms[i] || new Float32Array(2); val[0] = uniforms[i].x; diff --git a/src/core/shader/extractUniformsFromSrc.js b/src/core/shader/extractUniformsFromSrc.js index bbc0f1f..2d0e81e 100644 --- a/src/core/shader/extractUniformsFromSrc.js +++ b/src/core/shader/extractUniformsFromSrc.js @@ -12,7 +12,7 @@ function extractUniformsFromString(string) { - const maskRegex = new RegExp('^(projectionMatrix|uSampler|filterArea)$'); + const maskRegex = new RegExp('^(projectionMatrix|uSampler)$'); const uniforms = {}; let nameSplit; diff --git a/src/core/renderers/webgl/ShaderManager.js b/src/core/renderers/webgl/ShaderManager.js index 4524008..df55793 100644 --- a/src/core/renderers/webgl/ShaderManager.js +++ b/src/core/renderers/webgl/ShaderManager.js @@ -55,6 +55,11 @@ shader.syncUniforms(glShader.uniformData, uniforms, this.gl); } + getGLShader() + { + return this.shader.glShaders[this.renderer.CONTEXT_UID] || this.generateShader(shader); + } + generateShader(shader) { const attribMap = {}; diff --git a/src/core/renderers/webgl/managers/FilterManager.js b/src/core/renderers/webgl/managers/FilterManager.js index a6a891a..381238a 100644 --- a/src/core/renderers/webgl/managers/FilterManager.js +++ b/src/core/renderers/webgl/managers/FilterManager.js @@ -24,6 +24,8 @@ this.filters = []; this.target = null; this.resolution = 1; + + this.firstRun = true; } } @@ -45,6 +47,7 @@ // know about sprites! this.quad = new Quad(this.gl, renderer.state.attribState); + this.shaderCache = {}; // todo add default! this.pool = {}; @@ -136,6 +139,8 @@ // bind the render target renderer.bindRenderTarget(renderTarget); renderTarget.clear(); + + } /** @@ -212,6 +217,7 @@ const renderer = this.renderer; const gl = renderer.gl; +/* let shader = filter.glShaders[renderer.CONTEXT_UID]; // cacheing.. @@ -239,6 +245,22 @@ this.quad.initVao(shader); } +*/ + renderer.bindShader(filter, true); + + // TODO theres a better way! + // quad can be a mesh and we then should be able to pull this off without accessing the shader directly + const shader = renderer.shaderManager.getGLShader(); +// renderer.shaderManager.upd + + if(!this.firstRun) + { + this.firstRun = true; + renderer.bindVao(null); + + this.quad.initVao(shader); + } + renderer.bindVao(this.quad.vao); @@ -257,10 +279,43 @@ renderer.maskManager.pushScissorMask(null, renderer.maskManager.scissorData); } - renderer._bindGLShader(shader); + // renderer._bindGLShader(shader); + + let currentState; // this syncs the pixi filters uniforms with glsl uniforms - this.syncUniforms(shader, filter); + + if (shader.uniforms.data.filterArea) + { + currentState = this.filterData.stack[this.filterData.index]; + const filterArea = shader.uniforms.filterArea; + + filterArea[0] = currentState.renderTarget.size.width; + filterArea[1] = currentState.renderTarget.size.height; + filterArea[2] = currentState.sourceFrame.x; + filterArea[3] = currentState.sourceFrame.y; + + filter.uniforms.filterArea = filterArea; + } + + // use this to clamp displaced texture coords so they belong to filterArea + // see displacementFilter fragment shader for an example + if (shader.uniforms.data.filterClamp) + { + currentState = this.filterData.stack[this.filterData.index]; + + const filterClamp = shader.uniforms.filterClamp; + + filterClamp[0] = 0; + filterClamp[1] = 0; + filterClamp[2] = (currentState.sourceFrame.width - 1) / currentState.renderTarget.size.width; + filterClamp[3] = (currentState.sourceFrame.height - 1) / currentState.renderTarget.size.height; + + filter.uniforms.filterClamp = filterClamp; + } + + renderer.shaderManager.setUniforms(filter.uniforms); + // this.syncUniforms(shader, filter); renderer.state.setBlendMode(filter.blendMode); @@ -364,7 +419,7 @@ { // check if its a point.. if (uniforms[i].x !== undefined) - { + { const val = shader.uniforms[i] || new Float32Array(2); val[0] = uniforms[i].x; diff --git a/src/core/shader/extractUniformsFromSrc.js b/src/core/shader/extractUniformsFromSrc.js index bbc0f1f..2d0e81e 100644 --- a/src/core/shader/extractUniformsFromSrc.js +++ b/src/core/shader/extractUniformsFromSrc.js @@ -12,7 +12,7 @@ function extractUniformsFromString(string) { - const maskRegex = new RegExp('^(projectionMatrix|uSampler|filterArea)$'); + const maskRegex = new RegExp('^(projectionMatrix|uSampler)$'); const uniforms = {}; let nameSplit; diff --git a/src/core/shader/generateUniformsSync.js b/src/core/shader/generateUniformsSync.js index 3e2b0ac..04180d5 100644 --- a/src/core/shader/generateUniformsSync.js +++ b/src/core/shader/generateUniformsSync.js @@ -58,7 +58,29 @@ } else if (data.type === 'sampler2D') { - func += `\nvar location = renderer.bindTexture(uniformValues.${i}, ${textureCount++}, true); + func += `\n + +if (uniforms.${i}.baseTexture) +{ + var location = renderer.bindTexture(uniformValues.${i}, ${textureCount++}, true); + + 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); + + uniforms.${i}.value.bind(); +} + + + var location = renderer.bindTexture(uniformValues.${i}, ${textureCount++}, true); if(uniformData.${i}.value !== location) { @@ -73,9 +95,29 @@ } else if (data.type === 'vec2') { - func += `\nvalue = uniformValues.${i}; -if(value.x !== undefined)gl.uniform2f(uniformData.${i}.location, value.x, value.y); -else gl.uniform2f(uniformData.'+i+'.location, value[0], value[1]);\n`; + // 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 { @@ -87,8 +129,8 @@ } } - console.log(' --------------- ') - console.log(func); + // console.log(' --------------- ') + // console.log(func); return new Function('uniformData', 'uniformValues', 'gl', func); // eslint-disable-line no-new-func } diff --git a/src/core/renderers/webgl/ShaderManager.js b/src/core/renderers/webgl/ShaderManager.js index 4524008..df55793 100644 --- a/src/core/renderers/webgl/ShaderManager.js +++ b/src/core/renderers/webgl/ShaderManager.js @@ -55,6 +55,11 @@ shader.syncUniforms(glShader.uniformData, uniforms, this.gl); } + getGLShader() + { + return this.shader.glShaders[this.renderer.CONTEXT_UID] || this.generateShader(shader); + } + generateShader(shader) { const attribMap = {}; diff --git a/src/core/renderers/webgl/managers/FilterManager.js b/src/core/renderers/webgl/managers/FilterManager.js index a6a891a..381238a 100644 --- a/src/core/renderers/webgl/managers/FilterManager.js +++ b/src/core/renderers/webgl/managers/FilterManager.js @@ -24,6 +24,8 @@ this.filters = []; this.target = null; this.resolution = 1; + + this.firstRun = true; } } @@ -45,6 +47,7 @@ // know about sprites! this.quad = new Quad(this.gl, renderer.state.attribState); + this.shaderCache = {}; // todo add default! this.pool = {}; @@ -136,6 +139,8 @@ // bind the render target renderer.bindRenderTarget(renderTarget); renderTarget.clear(); + + } /** @@ -212,6 +217,7 @@ const renderer = this.renderer; const gl = renderer.gl; +/* let shader = filter.glShaders[renderer.CONTEXT_UID]; // cacheing.. @@ -239,6 +245,22 @@ this.quad.initVao(shader); } +*/ + renderer.bindShader(filter, true); + + // TODO theres a better way! + // quad can be a mesh and we then should be able to pull this off without accessing the shader directly + const shader = renderer.shaderManager.getGLShader(); +// renderer.shaderManager.upd + + if(!this.firstRun) + { + this.firstRun = true; + renderer.bindVao(null); + + this.quad.initVao(shader); + } + renderer.bindVao(this.quad.vao); @@ -257,10 +279,43 @@ renderer.maskManager.pushScissorMask(null, renderer.maskManager.scissorData); } - renderer._bindGLShader(shader); + // renderer._bindGLShader(shader); + + let currentState; // this syncs the pixi filters uniforms with glsl uniforms - this.syncUniforms(shader, filter); + + if (shader.uniforms.data.filterArea) + { + currentState = this.filterData.stack[this.filterData.index]; + const filterArea = shader.uniforms.filterArea; + + filterArea[0] = currentState.renderTarget.size.width; + filterArea[1] = currentState.renderTarget.size.height; + filterArea[2] = currentState.sourceFrame.x; + filterArea[3] = currentState.sourceFrame.y; + + filter.uniforms.filterArea = filterArea; + } + + // use this to clamp displaced texture coords so they belong to filterArea + // see displacementFilter fragment shader for an example + if (shader.uniforms.data.filterClamp) + { + currentState = this.filterData.stack[this.filterData.index]; + + const filterClamp = shader.uniforms.filterClamp; + + filterClamp[0] = 0; + filterClamp[1] = 0; + filterClamp[2] = (currentState.sourceFrame.width - 1) / currentState.renderTarget.size.width; + filterClamp[3] = (currentState.sourceFrame.height - 1) / currentState.renderTarget.size.height; + + filter.uniforms.filterClamp = filterClamp; + } + + renderer.shaderManager.setUniforms(filter.uniforms); + // this.syncUniforms(shader, filter); renderer.state.setBlendMode(filter.blendMode); @@ -364,7 +419,7 @@ { // check if its a point.. if (uniforms[i].x !== undefined) - { + { const val = shader.uniforms[i] || new Float32Array(2); val[0] = uniforms[i].x; diff --git a/src/core/shader/extractUniformsFromSrc.js b/src/core/shader/extractUniformsFromSrc.js index bbc0f1f..2d0e81e 100644 --- a/src/core/shader/extractUniformsFromSrc.js +++ b/src/core/shader/extractUniformsFromSrc.js @@ -12,7 +12,7 @@ function extractUniformsFromString(string) { - const maskRegex = new RegExp('^(projectionMatrix|uSampler|filterArea)$'); + const maskRegex = new RegExp('^(projectionMatrix|uSampler)$'); const uniforms = {}; let nameSplit; diff --git a/src/core/shader/generateUniformsSync.js b/src/core/shader/generateUniformsSync.js index 3e2b0ac..04180d5 100644 --- a/src/core/shader/generateUniformsSync.js +++ b/src/core/shader/generateUniformsSync.js @@ -58,7 +58,29 @@ } else if (data.type === 'sampler2D') { - func += `\nvar location = renderer.bindTexture(uniformValues.${i}, ${textureCount++}, true); + func += `\n + +if (uniforms.${i}.baseTexture) +{ + var location = renderer.bindTexture(uniformValues.${i}, ${textureCount++}, true); + + 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); + + uniforms.${i}.value.bind(); +} + + + var location = renderer.bindTexture(uniformValues.${i}, ${textureCount++}, true); if(uniformData.${i}.value !== location) { @@ -73,9 +95,29 @@ } else if (data.type === 'vec2') { - func += `\nvalue = uniformValues.${i}; -if(value.x !== undefined)gl.uniform2f(uniformData.${i}.location, value.x, value.y); -else gl.uniform2f(uniformData.'+i+'.location, value[0], value[1]);\n`; + // 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 { @@ -87,8 +129,8 @@ } } - console.log(' --------------- ') - console.log(func); + // console.log(' --------------- ') + // console.log(func); return new Function('uniformData', 'uniformValues', 'gl', func); // eslint-disable-line no-new-func } diff --git a/src/mesh/Plane.js b/src/mesh/Plane.js index 2478458..975c513 100644 --- a/src/mesh/Plane.js +++ b/src/mesh/Plane.js @@ -5,7 +5,6 @@ import { join } from 'path'; let meshShader; -const temp = [0, 0, 0]; /** * The Plane allows you to draw a texture across several points and them manipulate these points @@ -29,7 +28,7 @@ * @param {number} verticesX - The number of vertices in the x-axis * @param {number} verticesY - The number of vertices in the y-axis */ - constructor(texture, verticesX, verticesY, data) + constructor(texture, verticesX, verticesY) { const geometry = new Geometry(); @@ -44,11 +43,11 @@ .addIndex(new Uint16Array(2)); const uniforms = { - uSampler2:texture, - alpha:1, - translationMatrix:null, - tint:new Float32Array([1, 1, 1]) - } + uSampler2: texture, + alpha: 1, + translationMatrix: null, + tint: new Float32Array([1, 1, 1]), + }; super(geometry, meshShader, uniforms, 4); @@ -57,9 +56,6 @@ this.segmentsX = this.verticesX = verticesX || 10; this.segmentsY = this.verticesY = verticesY || 10; - this.meshWidth = data.meshWidth; - this.meshHeight = data.meshHeight; - if (texture.baseTexture.hasLoaded) { this.refresh(); @@ -73,23 +69,47 @@ this.tint = 0xFFFFFF; } + /** + * The tint applied to the Rope. This is a hex value. A value of + * 0xFFFFFF will remove any tint effect. + * + * @member {number} + * @memberof PIXI.Sprite# + * @default 0xFFFFFF + */ + get tint() + { + return this._tint; + } + + /** + * Sets the tint of the rope. + * + * @param {number} value - The value to set to. + */ set tint(value) { this._tint = value; core.utils.hex2rgb(this._tint, this.uniforms.tint); } - get tint() - { - return this._tint; - } - + /** + * Sets the texture of the rope. + * + * @param {PIXI.Texture} value - The value to set to. + */ set texture(value) { this._texture = value; - this.uniforms.uSample2 = this.texture; + this.uniforms.uSampler2 = this.texture; } + /** + * The texture that the rope is using + * + * @member {PIXI.Texture} + * @memberof PIXI.Sprite# + */ get texture() { return this._texture; @@ -110,8 +130,8 @@ const segmentsX = this.verticesX - 1; const segmentsY = this.verticesY - 1; - const sizeX = this.meshWidth / segmentsX; - const sizeY = this.meshHeight / segmentsY; + const sizeX = texture.width / segmentsX; + const sizeY = texture.height / segmentsY; for (let i = 0; i < total; i++) { @@ -168,6 +188,11 @@ this.geometry.data.indexBuffer.update(); } + /** + * Updates the object transform for rendering + * + * @private + */ updateTransform() { this.geometry.getAttribute('aVertexPosition').update(); diff --git a/src/core/renderers/webgl/ShaderManager.js b/src/core/renderers/webgl/ShaderManager.js index 4524008..df55793 100644 --- a/src/core/renderers/webgl/ShaderManager.js +++ b/src/core/renderers/webgl/ShaderManager.js @@ -55,6 +55,11 @@ shader.syncUniforms(glShader.uniformData, uniforms, this.gl); } + getGLShader() + { + return this.shader.glShaders[this.renderer.CONTEXT_UID] || this.generateShader(shader); + } + generateShader(shader) { const attribMap = {}; diff --git a/src/core/renderers/webgl/managers/FilterManager.js b/src/core/renderers/webgl/managers/FilterManager.js index a6a891a..381238a 100644 --- a/src/core/renderers/webgl/managers/FilterManager.js +++ b/src/core/renderers/webgl/managers/FilterManager.js @@ -24,6 +24,8 @@ this.filters = []; this.target = null; this.resolution = 1; + + this.firstRun = true; } } @@ -45,6 +47,7 @@ // know about sprites! this.quad = new Quad(this.gl, renderer.state.attribState); + this.shaderCache = {}; // todo add default! this.pool = {}; @@ -136,6 +139,8 @@ // bind the render target renderer.bindRenderTarget(renderTarget); renderTarget.clear(); + + } /** @@ -212,6 +217,7 @@ const renderer = this.renderer; const gl = renderer.gl; +/* let shader = filter.glShaders[renderer.CONTEXT_UID]; // cacheing.. @@ -239,6 +245,22 @@ this.quad.initVao(shader); } +*/ + renderer.bindShader(filter, true); + + // TODO theres a better way! + // quad can be a mesh and we then should be able to pull this off without accessing the shader directly + const shader = renderer.shaderManager.getGLShader(); +// renderer.shaderManager.upd + + if(!this.firstRun) + { + this.firstRun = true; + renderer.bindVao(null); + + this.quad.initVao(shader); + } + renderer.bindVao(this.quad.vao); @@ -257,10 +279,43 @@ renderer.maskManager.pushScissorMask(null, renderer.maskManager.scissorData); } - renderer._bindGLShader(shader); + // renderer._bindGLShader(shader); + + let currentState; // this syncs the pixi filters uniforms with glsl uniforms - this.syncUniforms(shader, filter); + + if (shader.uniforms.data.filterArea) + { + currentState = this.filterData.stack[this.filterData.index]; + const filterArea = shader.uniforms.filterArea; + + filterArea[0] = currentState.renderTarget.size.width; + filterArea[1] = currentState.renderTarget.size.height; + filterArea[2] = currentState.sourceFrame.x; + filterArea[3] = currentState.sourceFrame.y; + + filter.uniforms.filterArea = filterArea; + } + + // use this to clamp displaced texture coords so they belong to filterArea + // see displacementFilter fragment shader for an example + if (shader.uniforms.data.filterClamp) + { + currentState = this.filterData.stack[this.filterData.index]; + + const filterClamp = shader.uniforms.filterClamp; + + filterClamp[0] = 0; + filterClamp[1] = 0; + filterClamp[2] = (currentState.sourceFrame.width - 1) / currentState.renderTarget.size.width; + filterClamp[3] = (currentState.sourceFrame.height - 1) / currentState.renderTarget.size.height; + + filter.uniforms.filterClamp = filterClamp; + } + + renderer.shaderManager.setUniforms(filter.uniforms); + // this.syncUniforms(shader, filter); renderer.state.setBlendMode(filter.blendMode); @@ -364,7 +419,7 @@ { // check if its a point.. if (uniforms[i].x !== undefined) - { + { const val = shader.uniforms[i] || new Float32Array(2); val[0] = uniforms[i].x; diff --git a/src/core/shader/extractUniformsFromSrc.js b/src/core/shader/extractUniformsFromSrc.js index bbc0f1f..2d0e81e 100644 --- a/src/core/shader/extractUniformsFromSrc.js +++ b/src/core/shader/extractUniformsFromSrc.js @@ -12,7 +12,7 @@ function extractUniformsFromString(string) { - const maskRegex = new RegExp('^(projectionMatrix|uSampler|filterArea)$'); + const maskRegex = new RegExp('^(projectionMatrix|uSampler)$'); const uniforms = {}; let nameSplit; diff --git a/src/core/shader/generateUniformsSync.js b/src/core/shader/generateUniformsSync.js index 3e2b0ac..04180d5 100644 --- a/src/core/shader/generateUniformsSync.js +++ b/src/core/shader/generateUniformsSync.js @@ -58,7 +58,29 @@ } else if (data.type === 'sampler2D') { - func += `\nvar location = renderer.bindTexture(uniformValues.${i}, ${textureCount++}, true); + func += `\n + +if (uniforms.${i}.baseTexture) +{ + var location = renderer.bindTexture(uniformValues.${i}, ${textureCount++}, true); + + 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); + + uniforms.${i}.value.bind(); +} + + + var location = renderer.bindTexture(uniformValues.${i}, ${textureCount++}, true); if(uniformData.${i}.value !== location) { @@ -73,9 +95,29 @@ } else if (data.type === 'vec2') { - func += `\nvalue = uniformValues.${i}; -if(value.x !== undefined)gl.uniform2f(uniformData.${i}.location, value.x, value.y); -else gl.uniform2f(uniformData.'+i+'.location, value[0], value[1]);\n`; + // 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 { @@ -87,8 +129,8 @@ } } - console.log(' --------------- ') - console.log(func); + // console.log(' --------------- ') + // console.log(func); return new Function('uniformData', 'uniformValues', 'gl', func); // eslint-disable-line no-new-func } diff --git a/src/mesh/Plane.js b/src/mesh/Plane.js index 2478458..975c513 100644 --- a/src/mesh/Plane.js +++ b/src/mesh/Plane.js @@ -5,7 +5,6 @@ import { join } from 'path'; let meshShader; -const temp = [0, 0, 0]; /** * The Plane allows you to draw a texture across several points and them manipulate these points @@ -29,7 +28,7 @@ * @param {number} verticesX - The number of vertices in the x-axis * @param {number} verticesY - The number of vertices in the y-axis */ - constructor(texture, verticesX, verticesY, data) + constructor(texture, verticesX, verticesY) { const geometry = new Geometry(); @@ -44,11 +43,11 @@ .addIndex(new Uint16Array(2)); const uniforms = { - uSampler2:texture, - alpha:1, - translationMatrix:null, - tint:new Float32Array([1, 1, 1]) - } + uSampler2: texture, + alpha: 1, + translationMatrix: null, + tint: new Float32Array([1, 1, 1]), + }; super(geometry, meshShader, uniforms, 4); @@ -57,9 +56,6 @@ this.segmentsX = this.verticesX = verticesX || 10; this.segmentsY = this.verticesY = verticesY || 10; - this.meshWidth = data.meshWidth; - this.meshHeight = data.meshHeight; - if (texture.baseTexture.hasLoaded) { this.refresh(); @@ -73,23 +69,47 @@ this.tint = 0xFFFFFF; } + /** + * The tint applied to the Rope. This is a hex value. A value of + * 0xFFFFFF will remove any tint effect. + * + * @member {number} + * @memberof PIXI.Sprite# + * @default 0xFFFFFF + */ + get tint() + { + return this._tint; + } + + /** + * Sets the tint of the rope. + * + * @param {number} value - The value to set to. + */ set tint(value) { this._tint = value; core.utils.hex2rgb(this._tint, this.uniforms.tint); } - get tint() - { - return this._tint; - } - + /** + * Sets the texture of the rope. + * + * @param {PIXI.Texture} value - The value to set to. + */ set texture(value) { this._texture = value; - this.uniforms.uSample2 = this.texture; + this.uniforms.uSampler2 = this.texture; } + /** + * The texture that the rope is using + * + * @member {PIXI.Texture} + * @memberof PIXI.Sprite# + */ get texture() { return this._texture; @@ -110,8 +130,8 @@ const segmentsX = this.verticesX - 1; const segmentsY = this.verticesY - 1; - const sizeX = this.meshWidth / segmentsX; - const sizeY = this.meshHeight / segmentsY; + const sizeX = texture.width / segmentsX; + const sizeY = texture.height / segmentsY; for (let i = 0; i < total; i++) { @@ -168,6 +188,11 @@ this.geometry.data.indexBuffer.update(); } + /** + * Updates the object transform for rendering + * + * @private + */ updateTransform() { this.geometry.getAttribute('aVertexPosition').update(); diff --git a/src/mesh/webgl/MeshRenderer.js b/src/mesh/webgl/MeshRenderer.js index c7c0a33..142f9f5 100644 --- a/src/mesh/webgl/MeshRenderer.js +++ b/src/mesh/webgl/MeshRenderer.js @@ -46,6 +46,8 @@ // bind the shader.. this.renderer.shaderManager.bindShader(mesh.shader, true); + var glShader = this.renderer.shaderManager.getGLShader(); + // set unifomrs.. this.renderer.shaderManager.setUniforms(mesh.uniforms); @@ -145,6 +147,7 @@ }, gl.FLOAT, false, attribute.stride, attribute.start); } + geometry.glVertexArrayObjects[this.CONTEXT_UID] = vao; return vao;