diff --git a/src/core/renderers/webgl/ShaderManager.js b/src/core/renderers/webgl/ShaderManager.js new file mode 100644 index 0000000..369d7d3 --- /dev/null +++ b/src/core/renderers/webgl/ShaderManager.js @@ -0,0 +1,142 @@ +import { GLTexture } from 'pixi-gl-core'; +import { WRAP_MODES, SCALE_MODES } from '../../const'; +import RenderTarget from './utils/RenderTarget'; +import { removeItems } from '../../utils'; + +/** + * Helper class to create a webGL Texture + * + * @class + * @memberof PIXI + */ +export default class ShaderManager +{ + /** + * @param {PIXI.WebGLRenderer} renderer - A reference to the current renderer + */ + constructor(renderer) + { + /** + * A reference to the current renderer + * + * @member {PIXI.WebGLRenderer} + */ + this.renderer = renderer; + + /** + * The current WebGL rendering context + * + * @member {WebGLRenderingContext} + */ + this.gl = renderer.gl; + } + + bindShader(shader) + { + let glShader = shader.glShaders[renderer.CONTEXT_UID] || this.generateShader(shader); + + this.syncUniforms(glShader, shader); + + this.renderer._bindGLShader(glShader); + } + + generateShader(shader) + { + const glShader = new GLShader(this.gl, filter.vertexSrc, filter.fragmentSrc, PRECISION.DEFAULT); + shader.glShaders[renderer.CONTEXT_UID] = glShader; + + return glShader + } + + /** + * Uploads the uniforms of the filter. + * + * @param {GLShader} shader - The underlying gl shader. + * @param {PIXI.Filter} filter - The filter we are synchronizing. + */ + syncUniforms(shader, filter) + { + const uniformData = filter.uniformData; + const uniforms = filter.uniforms; + + // 0 is reserverd for the pixi texture so we start at 1! + let textureCount = 1; + let currentState; + + // TODO Cacheing layer.. + for (const i in uniformData) + { + if (uniformData[i].type === 'sampler2D' && uniforms[i] !== 0) + { + shader.uniforms[i] = textureCount; + + if (uniforms[i].baseTexture) + { + this.renderer.bindTexture(uniforms[i].baseTexture, textureCount); + } + else + { + // TODO + // this is helpful as renderTargets can also be set. + // Although thinking about it, we could probably + // make the filter texture cache return a RenderTexture + // rather than a renderTarget + const gl = this.renderer.gl; + + gl.activeTexture(gl.TEXTURE0 + textureCount); + uniforms[i].texture.bind(); + } + + textureCount++; + } + else if (uniformData[i].type === 'mat3') + { + // check if its pixi matrix.. + if (uniforms[i].a !== undefined) + { + shader.uniforms[i] = uniforms[i].toArray(true); + } + else + { + shader.uniforms[i] = uniforms[i]; + } + } + else if (uniformData[i].type === 'vec2') + { + // check if its a point.. + if (uniforms[i].x !== undefined) + { + const val = shader.uniforms[i] || new Float32Array(2); + + val[0] = uniforms[i].x; + val[1] = uniforms[i].y; + shader.uniforms[i] = val; + } + else + { + shader.uniforms[i] = uniforms[i]; + } + } + else if (uniformData[i].type === 'float') + { + if (shader.uniforms.data[i].value !== uniformData[i]) + { + shader.uniforms[i] = uniforms[i]; + } + } + else + { + shader.uniforms[i] = uniforms[i]; + } + } + } + + + /** + * Destroys this manager and removes all its textures + */ + destroy() + { + + } +} diff --git a/src/core/renderers/webgl/ShaderManager.js b/src/core/renderers/webgl/ShaderManager.js new file mode 100644 index 0000000..369d7d3 --- /dev/null +++ b/src/core/renderers/webgl/ShaderManager.js @@ -0,0 +1,142 @@ +import { GLTexture } from 'pixi-gl-core'; +import { WRAP_MODES, SCALE_MODES } from '../../const'; +import RenderTarget from './utils/RenderTarget'; +import { removeItems } from '../../utils'; + +/** + * Helper class to create a webGL Texture + * + * @class + * @memberof PIXI + */ +export default class ShaderManager +{ + /** + * @param {PIXI.WebGLRenderer} renderer - A reference to the current renderer + */ + constructor(renderer) + { + /** + * A reference to the current renderer + * + * @member {PIXI.WebGLRenderer} + */ + this.renderer = renderer; + + /** + * The current WebGL rendering context + * + * @member {WebGLRenderingContext} + */ + this.gl = renderer.gl; + } + + bindShader(shader) + { + let glShader = shader.glShaders[renderer.CONTEXT_UID] || this.generateShader(shader); + + this.syncUniforms(glShader, shader); + + this.renderer._bindGLShader(glShader); + } + + generateShader(shader) + { + const glShader = new GLShader(this.gl, filter.vertexSrc, filter.fragmentSrc, PRECISION.DEFAULT); + shader.glShaders[renderer.CONTEXT_UID] = glShader; + + return glShader + } + + /** + * Uploads the uniforms of the filter. + * + * @param {GLShader} shader - The underlying gl shader. + * @param {PIXI.Filter} filter - The filter we are synchronizing. + */ + syncUniforms(shader, filter) + { + const uniformData = filter.uniformData; + const uniforms = filter.uniforms; + + // 0 is reserverd for the pixi texture so we start at 1! + let textureCount = 1; + let currentState; + + // TODO Cacheing layer.. + for (const i in uniformData) + { + if (uniformData[i].type === 'sampler2D' && uniforms[i] !== 0) + { + shader.uniforms[i] = textureCount; + + if (uniforms[i].baseTexture) + { + this.renderer.bindTexture(uniforms[i].baseTexture, textureCount); + } + else + { + // TODO + // this is helpful as renderTargets can also be set. + // Although thinking about it, we could probably + // make the filter texture cache return a RenderTexture + // rather than a renderTarget + const gl = this.renderer.gl; + + gl.activeTexture(gl.TEXTURE0 + textureCount); + uniforms[i].texture.bind(); + } + + textureCount++; + } + else if (uniformData[i].type === 'mat3') + { + // check if its pixi matrix.. + if (uniforms[i].a !== undefined) + { + shader.uniforms[i] = uniforms[i].toArray(true); + } + else + { + shader.uniforms[i] = uniforms[i]; + } + } + else if (uniformData[i].type === 'vec2') + { + // check if its a point.. + if (uniforms[i].x !== undefined) + { + const val = shader.uniforms[i] || new Float32Array(2); + + val[0] = uniforms[i].x; + val[1] = uniforms[i].y; + shader.uniforms[i] = val; + } + else + { + shader.uniforms[i] = uniforms[i]; + } + } + else if (uniformData[i].type === 'float') + { + if (shader.uniforms.data[i].value !== uniformData[i]) + { + shader.uniforms[i] = uniforms[i]; + } + } + else + { + shader.uniforms[i] = uniforms[i]; + } + } + } + + + /** + * Destroys this manager and removes all its textures + */ + destroy() + { + + } +} diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 7949d2c..d82f0a4 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -5,6 +5,7 @@ import RenderTarget from './utils/RenderTarget'; import ObjectRenderer from './utils/ObjectRenderer'; import TextureManager from './TextureManager'; +import ShaderManager from './ShaderManager'; import BaseTexture from '../../textures/BaseTexture'; import TextureGarbageCollector from './TextureGarbageCollector'; import WebGLState from './WebGLState'; @@ -98,6 +99,7 @@ */ this.stencilManager = new StencilManager(this); + /** * An empty renderer. * @@ -200,6 +202,8 @@ this.textureManager = new TextureManager(this); this.textureGC = new TextureGarbageCollector(this); + this.shaderManager = new ShaderManager(this); + this.state.resetToDefault(); this.rootRenderTarget = new RenderTarget(gl, this.width, this.height, null, this.resolution, true); @@ -435,6 +439,11 @@ return this; } + bindShader(shader) + { + this.shaderManager.bindShader(shader); + } + /** * Changes the current shader to the one given in parameter *