import { GLShader } from 'pixi-gl-core'; import { WRAP_MODES, SCALE_MODES, PRECISION} 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.renderer._bindGLShader(glShader); this.syncUniforms(glShader, shader); } generateShader(shader) { const attribMap = {}; for (const i in shader.attributeData) { attribMap[i] = shader.attributeData[i].location; } const glShader = new GLShader(this.gl, shader.vertexSrc, shader.fragmentSrc, PRECISION.DEFAULT, attribMap); //TODO should I add this a s a prototype glShader.dirtyFlags = {}; for (var i in shader.realUniforms) { glShader.dirtyFlags[i] = 0; }; console.log(glShader.dirtyFlags) 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(glShader, shader) { const uniformData = shader.uniformData; const realUniforms = shader.realUniforms; const dirtyFlags = glShader.dirtyFlags; // 0 is reserverd for the pixi texture so we start at 1! let textureCount = 1; // TODO don't need to use the uniform for (const i in uniformData) { if(dirtyFlags[i] === uniformData[i].dirtyId) { continue; } dirtyFlags[i] = uniformData[i].dirtyId; if (uniformData[i].type === 'sampler2D' && uniformData[i].value !== 0) { if (uniformData[i].value.baseTexture) { glShader.uniforms[i] = this.renderer.bindTexture(uniformData[i].value, textureCount); } else { glShader.uniforms[i] = textureCount; // 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 (uniformData[i].value.a !== undefined) { glShader.uniforms[i] = uniformData[i].value.toArray(true); } else { glShader.uniforms[i] = uniformData[i].value; } } else if (uniformData[i].type === 'vec2') { // check if its a point.. if (uniformData[i].value.x !== undefined) { const val = glShader.uniforms[i] || new Float32Array(2); val[0] = uniformData[i].value.x; val[1] = uniformData[i].value.y; glShader.uniforms[i] = val; } else { glShader.uniforms[i] = uniformData[i].value; } } else if (uniformData[i].type === 'float') { if (glShader.uniforms.data[i].value !== uniformData[i].value) { glShader.uniforms[i] = uniformData[i].value; } } else { glShader.uniforms[i] = uniformData[i].value; } } } /** * Destroys this manager and removes all its textures */ destroy() { } }