import WebGLManager from './WebGLManager'; import { GLFramebuffer, GLTexture } from 'pixi-gl-core'; /** * @class * @extends PIXI.WebGLManager * @memberof PIXI */ export default class TextureManager extends WebGLManager { /** * @param {PIXI.WebGLRenderer} renderer - The renderer this manager works for. */ constructor(renderer) { super(renderer); this.boundTextures = [ null, null, null, null, null, null, null, null, null ]; } /** * Sets up the renderer context and necessary buffers. * * @private */ onContextChange() { const gl = this.gl = this.renderer.gl; this.CONTEXT_UID = this.renderer.CONTEXT_UID; // TODO move this.. to a nice make empty textures class.. this.emptyTextures = {} this.emptyTextures[gl.TEXTURE_2D] = new GLTexture.fromData(this.gl, null, 1, 1); this.emptyTextures[gl.TEXTURE_CUBE_MAP] = new GLTexture(this.gl); gl.bindTexture(gl.TEXTURE_CUBE_MAP, this.emptyTextures[gl.TEXTURE_CUBE_MAP].texture); for (var i = 0; i < 6; i++) { gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); } gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR); } bindTexture(texture, location) { const gl = this.gl; location = location || 0; gl.activeTexture(gl.TEXTURE0 + location); if(texture && texture.valid) { const glTexture = texture.glTextures[this.CONTEXT_UID] || this.initTexture(texture); gl.bindTexture(texture.type, glTexture.texture); if(glTexture.dirtyId !== texture.dirtyId) { glTexture.dirtyId = texture.dirtyId; this.updateTexture(texture); } this.boundTextures[location] = texture; } else { gl.bindTexture(texture.type, this.emptyTextures[texture.type].texture); this.boundTextures[location] = null; } } unbindTexture(texture) { const gl = this.gl; for (var i = 0; i < this.boundTextures.length; i++) { if(this.boundTextures[i] === texture) { gl.activeTexture(gl.TEXTURE0 + i); gl.bindTexture(gl.TEXTURE_2D, this.emptyGLTexture.texture); this.boundTextures[i] = null; } } } initTexture(texture) { const gl = this.gl; var glTexture = new GLTexture(this.gl); // guarentee an update.. glTexture.dirtyId = -1; texture.glTextures[this.CONTEXT_UID] = glTexture; return glTexture; } updateTexture(texture) { const glTexture = texture.glTextures[this.CONTEXT_UID]; const gl = this.gl; // TODO there are only 3 textures as far as im aware? // Cube / 2D and later 3d. (the latter is WebGL2, we will get to that soon!) if(texture.type === gl.TEXTURE_CUBE_MAP) { for (var i = 0; i < texture.sides.length; i++) { // TODO - we should only upload what changed.. // but im sure this is not going to be a problem just yet! var texturePart = texture.sides[i]; if(texturePart.resource) { gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + texturePart.side, 0, glTexture.format, glTexture.format, glTexture.type, texturePart.resource.source); } else { gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + texturePart.side, 0, gl.RGBA, texture.width, texture.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); } } } else { if(texture.resource) { glTexture.upload(texture.resource.source); } else { glTexture.uploadData(null, texture.width, texture.height); } } // lets only update what changes.. this.setStyle(texture); } setStyle(texture) { const gl = this.gl; const style = texture.style; gl.texParameteri(texture.type, gl.TEXTURE_WRAP_S, style.wrapMode); gl.texParameteri(texture.type, gl.TEXTURE_WRAP_T, style.wrapMode); if(texture.mipmap) { gl.texParameteri(texture.type, gl.TEXTURE_MIN_FILTER, style.scaleMode ? gl.LINEAR_MIPMAP_LINEAR : gl.NEAREST_MIPMAP_NEAREST); } else { gl.texParameteri(texture.type, gl.TEXTURE_MIN_FILTER, style.scaleMode ? gl.LINEAR : gl.NEAREST); } gl.texParameteri(texture.type, gl.TEXTURE_MAG_FILTER, style.scaleMode ? gl.LINEAR : gl.NEAREST); } }