diff --git a/src/core/index.js b/src/core/index.js index 9e4f1f1..f282dd9 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -32,6 +32,9 @@ export { default as CanvasGraphicsRenderer } from './graphics/canvas/CanvasGraphicsRenderer'; export { default as Spritesheet } from './textures/Spritesheet'; export { default as Texture } from './textures/Texture'; +export { default as NewTexture } from './textures/new/Texture'; +export { default as NewFrameBuffer } from './textures/new/FrameBuffer'; +export { default as NewCubeTexture } from './textures/new/CubeTexture'; export { default as BaseTexture } from './textures/BaseTexture'; export { default as RenderTexture } from './textures/RenderTexture'; export { default as BaseRenderTexture } from './textures/BaseRenderTexture'; diff --git a/src/core/index.js b/src/core/index.js index 9e4f1f1..f282dd9 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -32,6 +32,9 @@ export { default as CanvasGraphicsRenderer } from './graphics/canvas/CanvasGraphicsRenderer'; export { default as Spritesheet } from './textures/Spritesheet'; export { default as Texture } from './textures/Texture'; +export { default as NewTexture } from './textures/new/Texture'; +export { default as NewFrameBuffer } from './textures/new/FrameBuffer'; +export { default as NewCubeTexture } from './textures/new/CubeTexture'; export { default as BaseTexture } from './textures/BaseTexture'; export { default as RenderTexture } from './textures/RenderTexture'; export { default as BaseRenderTexture } from './textures/BaseRenderTexture'; diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 830b382..3a70cf2 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -2,6 +2,8 @@ import MaskManager from './managers/MaskManager'; import StencilManager from './managers/StencilManager'; import FilterManager from './managers/FilterManager'; +import FramebufferManager from './managers/FramebufferManager'; +import NewTextureManager from './managers/NewTextureManager'; import RenderTarget from './utils/RenderTarget'; import ObjectRenderer from './utils/ObjectRenderer'; import TextureManager from './TextureManager'; @@ -115,6 +117,9 @@ */ this.emptyRenderer = new ObjectRenderer(this); + this.framebufferManager = new FramebufferManager(this); + this.newTextureManager = new NewTextureManager(this); + /** * The currently active ObjectRenderer. * @@ -559,7 +564,16 @@ } const gl = this.gl; - const glTexture = texture._glTextures[this.CONTEXT_UID]; + let glTexture = texture._glTextures[this.CONTEXT_UID]; + + if(texture._newTexture) + { + this.newTextureManager.bindTexture(texture._newTexture, location); + glTexture = texture._newTexture.glTextures[this.CONTEXT_UID]; + console.log("!!!") + + return; + } if (!glTexture) { diff --git a/src/core/index.js b/src/core/index.js index 9e4f1f1..f282dd9 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -32,6 +32,9 @@ export { default as CanvasGraphicsRenderer } from './graphics/canvas/CanvasGraphicsRenderer'; export { default as Spritesheet } from './textures/Spritesheet'; export { default as Texture } from './textures/Texture'; +export { default as NewTexture } from './textures/new/Texture'; +export { default as NewFrameBuffer } from './textures/new/FrameBuffer'; +export { default as NewCubeTexture } from './textures/new/CubeTexture'; export { default as BaseTexture } from './textures/BaseTexture'; export { default as RenderTexture } from './textures/RenderTexture'; export { default as BaseRenderTexture } from './textures/BaseRenderTexture'; diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 830b382..3a70cf2 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -2,6 +2,8 @@ import MaskManager from './managers/MaskManager'; import StencilManager from './managers/StencilManager'; import FilterManager from './managers/FilterManager'; +import FramebufferManager from './managers/FramebufferManager'; +import NewTextureManager from './managers/NewTextureManager'; import RenderTarget from './utils/RenderTarget'; import ObjectRenderer from './utils/ObjectRenderer'; import TextureManager from './TextureManager'; @@ -115,6 +117,9 @@ */ this.emptyRenderer = new ObjectRenderer(this); + this.framebufferManager = new FramebufferManager(this); + this.newTextureManager = new NewTextureManager(this); + /** * The currently active ObjectRenderer. * @@ -559,7 +564,16 @@ } const gl = this.gl; - const glTexture = texture._glTextures[this.CONTEXT_UID]; + let glTexture = texture._glTextures[this.CONTEXT_UID]; + + if(texture._newTexture) + { + this.newTextureManager.bindTexture(texture._newTexture, location); + glTexture = texture._newTexture.glTextures[this.CONTEXT_UID]; + console.log("!!!") + + return; + } if (!glTexture) { diff --git a/src/core/renderers/webgl/managers/FramebufferManager.js b/src/core/renderers/webgl/managers/FramebufferManager.js new file mode 100644 index 0000000..308e959 --- /dev/null +++ b/src/core/renderers/webgl/managers/FramebufferManager.js @@ -0,0 +1,121 @@ +import WebGLManager from './WebGLManager'; +import { GLFramebuffer, GLTexture } from 'pixi-gl-core'; + +/** + * @class + * @extends PIXI.WebGLManager + * @memberof PIXI + */ +export default class FramebufferManager extends WebGLManager +{ + /** + * @param {PIXI.WebGLRenderer} renderer - The renderer this manager works for. + */ + constructor(renderer) + { + super(renderer); + } + + /** + * Sets up the renderer context and necessary buffers. + * + * @private + */ + onContextChange() + { + this.gl = this.renderer.gl; + this.CONTEXT_UID = this.renderer.CONTEXT_UID; + + this.drawBufferExtension = this.gl.getExtension('WEBGL_draw_buffers'); + } + + bindFramebuffer(framebuffer) + { + const gl = this.gl; + + if(framebuffer) + { + // TODO cacheing layer! + const fbo = framebuffer.glFrameBuffers[this.CONTEXT_UID] || this.initFramebuffer(framebuffer); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo.framebuffer); + // makesure all textures are unbound.. + + // now check for updates... + if(fbo.dirtyId !== framebuffer.dirtyId) + { + fbo.dirtyId = framebuffer.dirtyId; + + this.updateFramebuffer(framebuffer); + } + + this.renderer.newTextureManager.unbindTexture(framebuffer.colorTextures[0].glTextures[this.CONTEXT_UID]._bound) + } + else + { + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + } + } + + clearFramebuffer(r, g, b, a) + { + var gl = this.gl; + + // TODO clear color can be set only one right? + gl.clearColor(r, g, b, a); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + } + + initFramebuffer(framebuffer) + { + var fbo = GLFramebuffer.createRGBA(this.gl, framebuffer.width, framebuffer.height); + + framebuffer.glFrameBuffers[this.CONTEXT_UID] = fbo; + + console.log('framebuffer created!', fbo) + + return fbo; + } + + updateFramebuffer(framebuffer) + { + const gl = this.gl; + + const fbo = framebuffer.glFrameBuffers[this.CONTEXT_UID]; + + // bind the color texture + const colorTextures = framebuffer.colorTextures; + + let count = colorTextures.length; + + if(!this.drawBufferExtension) + { + count = Math.min(count, 1); + } + + const activeTextures = []; + + for (var i = 0; i < count; i++) + { + const texture = framebuffer.colorTextures[i]; + + this.renderer.newTextureManager.bindTexture(texture, 0); + + const glTexture = texture.glTextures[this.CONTEXT_UID]; + + activeTextures.push(gl.COLOR_ATTACHMENT0 + i); + + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i, gl.TEXTURE_2D, glTexture.texture, 0); + } + + if(this.drawBufferExtension && activeTextures.length > 1) + { + this.drawBufferExtension.drawBuffersWEBGL(activeTextures); + } + + if(framebuffer.stencil || framebuffer.depth) + { + fbo.enableStencil(); + } + } + +} \ No newline at end of file diff --git a/src/core/index.js b/src/core/index.js index 9e4f1f1..f282dd9 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -32,6 +32,9 @@ export { default as CanvasGraphicsRenderer } from './graphics/canvas/CanvasGraphicsRenderer'; export { default as Spritesheet } from './textures/Spritesheet'; export { default as Texture } from './textures/Texture'; +export { default as NewTexture } from './textures/new/Texture'; +export { default as NewFrameBuffer } from './textures/new/FrameBuffer'; +export { default as NewCubeTexture } from './textures/new/CubeTexture'; export { default as BaseTexture } from './textures/BaseTexture'; export { default as RenderTexture } from './textures/RenderTexture'; export { default as BaseRenderTexture } from './textures/BaseRenderTexture'; diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 830b382..3a70cf2 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -2,6 +2,8 @@ import MaskManager from './managers/MaskManager'; import StencilManager from './managers/StencilManager'; import FilterManager from './managers/FilterManager'; +import FramebufferManager from './managers/FramebufferManager'; +import NewTextureManager from './managers/NewTextureManager'; import RenderTarget from './utils/RenderTarget'; import ObjectRenderer from './utils/ObjectRenderer'; import TextureManager from './TextureManager'; @@ -115,6 +117,9 @@ */ this.emptyRenderer = new ObjectRenderer(this); + this.framebufferManager = new FramebufferManager(this); + this.newTextureManager = new NewTextureManager(this); + /** * The currently active ObjectRenderer. * @@ -559,7 +564,16 @@ } const gl = this.gl; - const glTexture = texture._glTextures[this.CONTEXT_UID]; + let glTexture = texture._glTextures[this.CONTEXT_UID]; + + if(texture._newTexture) + { + this.newTextureManager.bindTexture(texture._newTexture, location); + glTexture = texture._newTexture.glTextures[this.CONTEXT_UID]; + console.log("!!!") + + return; + } if (!glTexture) { diff --git a/src/core/renderers/webgl/managers/FramebufferManager.js b/src/core/renderers/webgl/managers/FramebufferManager.js new file mode 100644 index 0000000..308e959 --- /dev/null +++ b/src/core/renderers/webgl/managers/FramebufferManager.js @@ -0,0 +1,121 @@ +import WebGLManager from './WebGLManager'; +import { GLFramebuffer, GLTexture } from 'pixi-gl-core'; + +/** + * @class + * @extends PIXI.WebGLManager + * @memberof PIXI + */ +export default class FramebufferManager extends WebGLManager +{ + /** + * @param {PIXI.WebGLRenderer} renderer - The renderer this manager works for. + */ + constructor(renderer) + { + super(renderer); + } + + /** + * Sets up the renderer context and necessary buffers. + * + * @private + */ + onContextChange() + { + this.gl = this.renderer.gl; + this.CONTEXT_UID = this.renderer.CONTEXT_UID; + + this.drawBufferExtension = this.gl.getExtension('WEBGL_draw_buffers'); + } + + bindFramebuffer(framebuffer) + { + const gl = this.gl; + + if(framebuffer) + { + // TODO cacheing layer! + const fbo = framebuffer.glFrameBuffers[this.CONTEXT_UID] || this.initFramebuffer(framebuffer); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo.framebuffer); + // makesure all textures are unbound.. + + // now check for updates... + if(fbo.dirtyId !== framebuffer.dirtyId) + { + fbo.dirtyId = framebuffer.dirtyId; + + this.updateFramebuffer(framebuffer); + } + + this.renderer.newTextureManager.unbindTexture(framebuffer.colorTextures[0].glTextures[this.CONTEXT_UID]._bound) + } + else + { + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + } + } + + clearFramebuffer(r, g, b, a) + { + var gl = this.gl; + + // TODO clear color can be set only one right? + gl.clearColor(r, g, b, a); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + } + + initFramebuffer(framebuffer) + { + var fbo = GLFramebuffer.createRGBA(this.gl, framebuffer.width, framebuffer.height); + + framebuffer.glFrameBuffers[this.CONTEXT_UID] = fbo; + + console.log('framebuffer created!', fbo) + + return fbo; + } + + updateFramebuffer(framebuffer) + { + const gl = this.gl; + + const fbo = framebuffer.glFrameBuffers[this.CONTEXT_UID]; + + // bind the color texture + const colorTextures = framebuffer.colorTextures; + + let count = colorTextures.length; + + if(!this.drawBufferExtension) + { + count = Math.min(count, 1); + } + + const activeTextures = []; + + for (var i = 0; i < count; i++) + { + const texture = framebuffer.colorTextures[i]; + + this.renderer.newTextureManager.bindTexture(texture, 0); + + const glTexture = texture.glTextures[this.CONTEXT_UID]; + + activeTextures.push(gl.COLOR_ATTACHMENT0 + i); + + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i, gl.TEXTURE_2D, glTexture.texture, 0); + } + + if(this.drawBufferExtension && activeTextures.length > 1) + { + this.drawBufferExtension.drawBuffersWEBGL(activeTextures); + } + + if(framebuffer.stencil || framebuffer.depth) + { + fbo.enableStencil(); + } + } + +} \ No newline at end of file diff --git a/src/core/renderers/webgl/managers/NewTextureManager.js b/src/core/renderers/webgl/managers/NewTextureManager.js new file mode 100644 index 0000000..0b9e282 --- /dev/null +++ b/src/core/renderers/webgl/managers/NewTextureManager.js @@ -0,0 +1,132 @@ +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() + { + this.gl = this.renderer.gl; + this.CONTEXT_UID = this.renderer.CONTEXT_UID; + } + + bindTexture(texture, location) + { + const gl = this.gl; + + location = location || 0; + + gl.activeTexture(gl.TEXTURE0 + location); + + if(texture) + { + const glTexture = texture.glTextures[this.CONTEXT_UID] || this.initTexture(texture); + + if(texture.isCube) + { + gl.bindTexture(gl.TEXTURE_CUBE_MAP, glTexture.texture); + } + else + { + gl.bindTexture(gl.TEXTURE_2D, glTexture.texture); + } + + this.boundTextures[location] = texture; + } + else + { + gl.bindTexture(gl.TEXTURE_2D, null); + this.boundTextures[location] = null; + } + } + + unbindTexture(texture) + { + for (var i = 0; i < this.boundTextures.length; i++) { + + if(this.boundTextures[i] === texture) + { + gl.activeTexture(gl.TEXTURE0 + location); + gl.bindTexture(gl.TEXTURE_2D, null); + this.boundTextures[i] = null; + } + } + } + + initTexture(texture) + { + const gl = this.gl; + + var glTexture = new GLTexture(this.gl); + + if(texture.isCube) + { + gl.bindTexture(gl.TEXTURE_CUBE_MAP, glTexture.texture); + + glTexture.width = texture.width; + glTexture.height = texture.height; + + // upload the 6 faces.. + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, glTexture.format, glTexture.format, glTexture.type, window.tex1); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, glTexture.format, glTexture.format, glTexture.type, window.tex2); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, glTexture.format, glTexture.format, glTexture.type, window.tex3); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, glTexture.format, glTexture.format, glTexture.type, window.tex4); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, glTexture.format, glTexture.format, glTexture.type, window.tex5); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, glTexture.format, glTexture.format, glTexture.type, window.tex6); + + + gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + } + else + { + glTexture.uploadData(null, texture.width, texture.height); + + // settings.. + glTexture.enableNearestScaling(); + glTexture.enableWrapClamp(); + } + + + + texture.glTextures[this.CONTEXT_UID] = glTexture; + + return glTexture; + } +} \ No newline at end of file diff --git a/src/core/index.js b/src/core/index.js index 9e4f1f1..f282dd9 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -32,6 +32,9 @@ export { default as CanvasGraphicsRenderer } from './graphics/canvas/CanvasGraphicsRenderer'; export { default as Spritesheet } from './textures/Spritesheet'; export { default as Texture } from './textures/Texture'; +export { default as NewTexture } from './textures/new/Texture'; +export { default as NewFrameBuffer } from './textures/new/FrameBuffer'; +export { default as NewCubeTexture } from './textures/new/CubeTexture'; export { default as BaseTexture } from './textures/BaseTexture'; export { default as RenderTexture } from './textures/RenderTexture'; export { default as BaseRenderTexture } from './textures/BaseRenderTexture'; diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 830b382..3a70cf2 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -2,6 +2,8 @@ import MaskManager from './managers/MaskManager'; import StencilManager from './managers/StencilManager'; import FilterManager from './managers/FilterManager'; +import FramebufferManager from './managers/FramebufferManager'; +import NewTextureManager from './managers/NewTextureManager'; import RenderTarget from './utils/RenderTarget'; import ObjectRenderer from './utils/ObjectRenderer'; import TextureManager from './TextureManager'; @@ -115,6 +117,9 @@ */ this.emptyRenderer = new ObjectRenderer(this); + this.framebufferManager = new FramebufferManager(this); + this.newTextureManager = new NewTextureManager(this); + /** * The currently active ObjectRenderer. * @@ -559,7 +564,16 @@ } const gl = this.gl; - const glTexture = texture._glTextures[this.CONTEXT_UID]; + let glTexture = texture._glTextures[this.CONTEXT_UID]; + + if(texture._newTexture) + { + this.newTextureManager.bindTexture(texture._newTexture, location); + glTexture = texture._newTexture.glTextures[this.CONTEXT_UID]; + console.log("!!!") + + return; + } if (!glTexture) { diff --git a/src/core/renderers/webgl/managers/FramebufferManager.js b/src/core/renderers/webgl/managers/FramebufferManager.js new file mode 100644 index 0000000..308e959 --- /dev/null +++ b/src/core/renderers/webgl/managers/FramebufferManager.js @@ -0,0 +1,121 @@ +import WebGLManager from './WebGLManager'; +import { GLFramebuffer, GLTexture } from 'pixi-gl-core'; + +/** + * @class + * @extends PIXI.WebGLManager + * @memberof PIXI + */ +export default class FramebufferManager extends WebGLManager +{ + /** + * @param {PIXI.WebGLRenderer} renderer - The renderer this manager works for. + */ + constructor(renderer) + { + super(renderer); + } + + /** + * Sets up the renderer context and necessary buffers. + * + * @private + */ + onContextChange() + { + this.gl = this.renderer.gl; + this.CONTEXT_UID = this.renderer.CONTEXT_UID; + + this.drawBufferExtension = this.gl.getExtension('WEBGL_draw_buffers'); + } + + bindFramebuffer(framebuffer) + { + const gl = this.gl; + + if(framebuffer) + { + // TODO cacheing layer! + const fbo = framebuffer.glFrameBuffers[this.CONTEXT_UID] || this.initFramebuffer(framebuffer); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo.framebuffer); + // makesure all textures are unbound.. + + // now check for updates... + if(fbo.dirtyId !== framebuffer.dirtyId) + { + fbo.dirtyId = framebuffer.dirtyId; + + this.updateFramebuffer(framebuffer); + } + + this.renderer.newTextureManager.unbindTexture(framebuffer.colorTextures[0].glTextures[this.CONTEXT_UID]._bound) + } + else + { + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + } + } + + clearFramebuffer(r, g, b, a) + { + var gl = this.gl; + + // TODO clear color can be set only one right? + gl.clearColor(r, g, b, a); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + } + + initFramebuffer(framebuffer) + { + var fbo = GLFramebuffer.createRGBA(this.gl, framebuffer.width, framebuffer.height); + + framebuffer.glFrameBuffers[this.CONTEXT_UID] = fbo; + + console.log('framebuffer created!', fbo) + + return fbo; + } + + updateFramebuffer(framebuffer) + { + const gl = this.gl; + + const fbo = framebuffer.glFrameBuffers[this.CONTEXT_UID]; + + // bind the color texture + const colorTextures = framebuffer.colorTextures; + + let count = colorTextures.length; + + if(!this.drawBufferExtension) + { + count = Math.min(count, 1); + } + + const activeTextures = []; + + for (var i = 0; i < count; i++) + { + const texture = framebuffer.colorTextures[i]; + + this.renderer.newTextureManager.bindTexture(texture, 0); + + const glTexture = texture.glTextures[this.CONTEXT_UID]; + + activeTextures.push(gl.COLOR_ATTACHMENT0 + i); + + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i, gl.TEXTURE_2D, glTexture.texture, 0); + } + + if(this.drawBufferExtension && activeTextures.length > 1) + { + this.drawBufferExtension.drawBuffersWEBGL(activeTextures); + } + + if(framebuffer.stencil || framebuffer.depth) + { + fbo.enableStencil(); + } + } + +} \ No newline at end of file diff --git a/src/core/renderers/webgl/managers/NewTextureManager.js b/src/core/renderers/webgl/managers/NewTextureManager.js new file mode 100644 index 0000000..0b9e282 --- /dev/null +++ b/src/core/renderers/webgl/managers/NewTextureManager.js @@ -0,0 +1,132 @@ +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() + { + this.gl = this.renderer.gl; + this.CONTEXT_UID = this.renderer.CONTEXT_UID; + } + + bindTexture(texture, location) + { + const gl = this.gl; + + location = location || 0; + + gl.activeTexture(gl.TEXTURE0 + location); + + if(texture) + { + const glTexture = texture.glTextures[this.CONTEXT_UID] || this.initTexture(texture); + + if(texture.isCube) + { + gl.bindTexture(gl.TEXTURE_CUBE_MAP, glTexture.texture); + } + else + { + gl.bindTexture(gl.TEXTURE_2D, glTexture.texture); + } + + this.boundTextures[location] = texture; + } + else + { + gl.bindTexture(gl.TEXTURE_2D, null); + this.boundTextures[location] = null; + } + } + + unbindTexture(texture) + { + for (var i = 0; i < this.boundTextures.length; i++) { + + if(this.boundTextures[i] === texture) + { + gl.activeTexture(gl.TEXTURE0 + location); + gl.bindTexture(gl.TEXTURE_2D, null); + this.boundTextures[i] = null; + } + } + } + + initTexture(texture) + { + const gl = this.gl; + + var glTexture = new GLTexture(this.gl); + + if(texture.isCube) + { + gl.bindTexture(gl.TEXTURE_CUBE_MAP, glTexture.texture); + + glTexture.width = texture.width; + glTexture.height = texture.height; + + // upload the 6 faces.. + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, glTexture.format, glTexture.format, glTexture.type, window.tex1); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, glTexture.format, glTexture.format, glTexture.type, window.tex2); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, glTexture.format, glTexture.format, glTexture.type, window.tex3); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, glTexture.format, glTexture.format, glTexture.type, window.tex4); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, glTexture.format, glTexture.format, glTexture.type, window.tex5); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, glTexture.format, glTexture.format, glTexture.type, window.tex6); + + + gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + } + else + { + glTexture.uploadData(null, texture.width, texture.height); + + // settings.. + glTexture.enableNearestScaling(); + glTexture.enableWrapClamp(); + } + + + + texture.glTextures[this.CONTEXT_UID] = glTexture; + + return glTexture; + } +} \ No newline at end of file diff --git a/src/core/renderers/webgl/utils/RenderTarget.js b/src/core/renderers/webgl/utils/RenderTarget.js index 6d2467f..6c165f2 100644 --- a/src/core/renderers/webgl/utils/RenderTarget.js +++ b/src/core/renderers/webgl/utils/RenderTarget.js @@ -228,7 +228,7 @@ // TODO add a check as them may be the same! if (this.destinationFrame !== this.sourceFrame) { - gl.enable(gl.SCISSOR_TEST); +// gl.enable(gl.SCISSOR_TEST); gl.scissor( this.destinationFrame.x | 0, this.destinationFrame.y | 0, @@ -238,7 +238,7 @@ } else { - gl.disable(gl.SCISSOR_TEST); + // gl.disable(gl.SCISSOR_TEST); } // TODO - does not need to be updated all the time?? diff --git a/src/core/index.js b/src/core/index.js index 9e4f1f1..f282dd9 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -32,6 +32,9 @@ export { default as CanvasGraphicsRenderer } from './graphics/canvas/CanvasGraphicsRenderer'; export { default as Spritesheet } from './textures/Spritesheet'; export { default as Texture } from './textures/Texture'; +export { default as NewTexture } from './textures/new/Texture'; +export { default as NewFrameBuffer } from './textures/new/FrameBuffer'; +export { default as NewCubeTexture } from './textures/new/CubeTexture'; export { default as BaseTexture } from './textures/BaseTexture'; export { default as RenderTexture } from './textures/RenderTexture'; export { default as BaseRenderTexture } from './textures/BaseRenderTexture'; diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 830b382..3a70cf2 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -2,6 +2,8 @@ import MaskManager from './managers/MaskManager'; import StencilManager from './managers/StencilManager'; import FilterManager from './managers/FilterManager'; +import FramebufferManager from './managers/FramebufferManager'; +import NewTextureManager from './managers/NewTextureManager'; import RenderTarget from './utils/RenderTarget'; import ObjectRenderer from './utils/ObjectRenderer'; import TextureManager from './TextureManager'; @@ -115,6 +117,9 @@ */ this.emptyRenderer = new ObjectRenderer(this); + this.framebufferManager = new FramebufferManager(this); + this.newTextureManager = new NewTextureManager(this); + /** * The currently active ObjectRenderer. * @@ -559,7 +564,16 @@ } const gl = this.gl; - const glTexture = texture._glTextures[this.CONTEXT_UID]; + let glTexture = texture._glTextures[this.CONTEXT_UID]; + + if(texture._newTexture) + { + this.newTextureManager.bindTexture(texture._newTexture, location); + glTexture = texture._newTexture.glTextures[this.CONTEXT_UID]; + console.log("!!!") + + return; + } if (!glTexture) { diff --git a/src/core/renderers/webgl/managers/FramebufferManager.js b/src/core/renderers/webgl/managers/FramebufferManager.js new file mode 100644 index 0000000..308e959 --- /dev/null +++ b/src/core/renderers/webgl/managers/FramebufferManager.js @@ -0,0 +1,121 @@ +import WebGLManager from './WebGLManager'; +import { GLFramebuffer, GLTexture } from 'pixi-gl-core'; + +/** + * @class + * @extends PIXI.WebGLManager + * @memberof PIXI + */ +export default class FramebufferManager extends WebGLManager +{ + /** + * @param {PIXI.WebGLRenderer} renderer - The renderer this manager works for. + */ + constructor(renderer) + { + super(renderer); + } + + /** + * Sets up the renderer context and necessary buffers. + * + * @private + */ + onContextChange() + { + this.gl = this.renderer.gl; + this.CONTEXT_UID = this.renderer.CONTEXT_UID; + + this.drawBufferExtension = this.gl.getExtension('WEBGL_draw_buffers'); + } + + bindFramebuffer(framebuffer) + { + const gl = this.gl; + + if(framebuffer) + { + // TODO cacheing layer! + const fbo = framebuffer.glFrameBuffers[this.CONTEXT_UID] || this.initFramebuffer(framebuffer); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo.framebuffer); + // makesure all textures are unbound.. + + // now check for updates... + if(fbo.dirtyId !== framebuffer.dirtyId) + { + fbo.dirtyId = framebuffer.dirtyId; + + this.updateFramebuffer(framebuffer); + } + + this.renderer.newTextureManager.unbindTexture(framebuffer.colorTextures[0].glTextures[this.CONTEXT_UID]._bound) + } + else + { + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + } + } + + clearFramebuffer(r, g, b, a) + { + var gl = this.gl; + + // TODO clear color can be set only one right? + gl.clearColor(r, g, b, a); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + } + + initFramebuffer(framebuffer) + { + var fbo = GLFramebuffer.createRGBA(this.gl, framebuffer.width, framebuffer.height); + + framebuffer.glFrameBuffers[this.CONTEXT_UID] = fbo; + + console.log('framebuffer created!', fbo) + + return fbo; + } + + updateFramebuffer(framebuffer) + { + const gl = this.gl; + + const fbo = framebuffer.glFrameBuffers[this.CONTEXT_UID]; + + // bind the color texture + const colorTextures = framebuffer.colorTextures; + + let count = colorTextures.length; + + if(!this.drawBufferExtension) + { + count = Math.min(count, 1); + } + + const activeTextures = []; + + for (var i = 0; i < count; i++) + { + const texture = framebuffer.colorTextures[i]; + + this.renderer.newTextureManager.bindTexture(texture, 0); + + const glTexture = texture.glTextures[this.CONTEXT_UID]; + + activeTextures.push(gl.COLOR_ATTACHMENT0 + i); + + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i, gl.TEXTURE_2D, glTexture.texture, 0); + } + + if(this.drawBufferExtension && activeTextures.length > 1) + { + this.drawBufferExtension.drawBuffersWEBGL(activeTextures); + } + + if(framebuffer.stencil || framebuffer.depth) + { + fbo.enableStencil(); + } + } + +} \ No newline at end of file diff --git a/src/core/renderers/webgl/managers/NewTextureManager.js b/src/core/renderers/webgl/managers/NewTextureManager.js new file mode 100644 index 0000000..0b9e282 --- /dev/null +++ b/src/core/renderers/webgl/managers/NewTextureManager.js @@ -0,0 +1,132 @@ +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() + { + this.gl = this.renderer.gl; + this.CONTEXT_UID = this.renderer.CONTEXT_UID; + } + + bindTexture(texture, location) + { + const gl = this.gl; + + location = location || 0; + + gl.activeTexture(gl.TEXTURE0 + location); + + if(texture) + { + const glTexture = texture.glTextures[this.CONTEXT_UID] || this.initTexture(texture); + + if(texture.isCube) + { + gl.bindTexture(gl.TEXTURE_CUBE_MAP, glTexture.texture); + } + else + { + gl.bindTexture(gl.TEXTURE_2D, glTexture.texture); + } + + this.boundTextures[location] = texture; + } + else + { + gl.bindTexture(gl.TEXTURE_2D, null); + this.boundTextures[location] = null; + } + } + + unbindTexture(texture) + { + for (var i = 0; i < this.boundTextures.length; i++) { + + if(this.boundTextures[i] === texture) + { + gl.activeTexture(gl.TEXTURE0 + location); + gl.bindTexture(gl.TEXTURE_2D, null); + this.boundTextures[i] = null; + } + } + } + + initTexture(texture) + { + const gl = this.gl; + + var glTexture = new GLTexture(this.gl); + + if(texture.isCube) + { + gl.bindTexture(gl.TEXTURE_CUBE_MAP, glTexture.texture); + + glTexture.width = texture.width; + glTexture.height = texture.height; + + // upload the 6 faces.. + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, glTexture.format, glTexture.format, glTexture.type, window.tex1); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, glTexture.format, glTexture.format, glTexture.type, window.tex2); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, glTexture.format, glTexture.format, glTexture.type, window.tex3); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, glTexture.format, glTexture.format, glTexture.type, window.tex4); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, glTexture.format, glTexture.format, glTexture.type, window.tex5); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, glTexture.format, glTexture.format, glTexture.type, window.tex6); + + + gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + } + else + { + glTexture.uploadData(null, texture.width, texture.height); + + // settings.. + glTexture.enableNearestScaling(); + glTexture.enableWrapClamp(); + } + + + + texture.glTextures[this.CONTEXT_UID] = glTexture; + + return glTexture; + } +} \ No newline at end of file diff --git a/src/core/renderers/webgl/utils/RenderTarget.js b/src/core/renderers/webgl/utils/RenderTarget.js index 6d2467f..6c165f2 100644 --- a/src/core/renderers/webgl/utils/RenderTarget.js +++ b/src/core/renderers/webgl/utils/RenderTarget.js @@ -228,7 +228,7 @@ // TODO add a check as them may be the same! if (this.destinationFrame !== this.sourceFrame) { - gl.enable(gl.SCISSOR_TEST); +// gl.enable(gl.SCISSOR_TEST); gl.scissor( this.destinationFrame.x | 0, this.destinationFrame.y | 0, @@ -238,7 +238,7 @@ } else { - gl.disable(gl.SCISSOR_TEST); + // gl.disable(gl.SCISSOR_TEST); } // TODO - does not need to be updated all the time?? diff --git a/src/core/shader/generateUniformsSync.js b/src/core/shader/generateUniformsSync.js index a14086f..5885d7d 100644 --- a/src/core/shader/generateUniformsSync.js +++ b/src/core/shader/generateUniformsSync.js @@ -37,6 +37,7 @@ mat4: 'gl.uniformMatrix4fv(location, false, value)', sampler2D: 'uniform1i(location, value)', + samplerCube: 'uniform1i(location, value)' }; const GLSL_TO_ARRAY_SETTERS = { @@ -58,6 +59,7 @@ bvec4: 'gl.uniform4iv(location, value)', sampler2D: 'uniform1i(location, value)', + samplerCube: 'uniform1i(location, value)' }; export default function generateUniformsSync(uniformData) { diff --git a/src/core/index.js b/src/core/index.js index 9e4f1f1..f282dd9 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -32,6 +32,9 @@ export { default as CanvasGraphicsRenderer } from './graphics/canvas/CanvasGraphicsRenderer'; export { default as Spritesheet } from './textures/Spritesheet'; export { default as Texture } from './textures/Texture'; +export { default as NewTexture } from './textures/new/Texture'; +export { default as NewFrameBuffer } from './textures/new/FrameBuffer'; +export { default as NewCubeTexture } from './textures/new/CubeTexture'; export { default as BaseTexture } from './textures/BaseTexture'; export { default as RenderTexture } from './textures/RenderTexture'; export { default as BaseRenderTexture } from './textures/BaseRenderTexture'; diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 830b382..3a70cf2 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -2,6 +2,8 @@ import MaskManager from './managers/MaskManager'; import StencilManager from './managers/StencilManager'; import FilterManager from './managers/FilterManager'; +import FramebufferManager from './managers/FramebufferManager'; +import NewTextureManager from './managers/NewTextureManager'; import RenderTarget from './utils/RenderTarget'; import ObjectRenderer from './utils/ObjectRenderer'; import TextureManager from './TextureManager'; @@ -115,6 +117,9 @@ */ this.emptyRenderer = new ObjectRenderer(this); + this.framebufferManager = new FramebufferManager(this); + this.newTextureManager = new NewTextureManager(this); + /** * The currently active ObjectRenderer. * @@ -559,7 +564,16 @@ } const gl = this.gl; - const glTexture = texture._glTextures[this.CONTEXT_UID]; + let glTexture = texture._glTextures[this.CONTEXT_UID]; + + if(texture._newTexture) + { + this.newTextureManager.bindTexture(texture._newTexture, location); + glTexture = texture._newTexture.glTextures[this.CONTEXT_UID]; + console.log("!!!") + + return; + } if (!glTexture) { diff --git a/src/core/renderers/webgl/managers/FramebufferManager.js b/src/core/renderers/webgl/managers/FramebufferManager.js new file mode 100644 index 0000000..308e959 --- /dev/null +++ b/src/core/renderers/webgl/managers/FramebufferManager.js @@ -0,0 +1,121 @@ +import WebGLManager from './WebGLManager'; +import { GLFramebuffer, GLTexture } from 'pixi-gl-core'; + +/** + * @class + * @extends PIXI.WebGLManager + * @memberof PIXI + */ +export default class FramebufferManager extends WebGLManager +{ + /** + * @param {PIXI.WebGLRenderer} renderer - The renderer this manager works for. + */ + constructor(renderer) + { + super(renderer); + } + + /** + * Sets up the renderer context and necessary buffers. + * + * @private + */ + onContextChange() + { + this.gl = this.renderer.gl; + this.CONTEXT_UID = this.renderer.CONTEXT_UID; + + this.drawBufferExtension = this.gl.getExtension('WEBGL_draw_buffers'); + } + + bindFramebuffer(framebuffer) + { + const gl = this.gl; + + if(framebuffer) + { + // TODO cacheing layer! + const fbo = framebuffer.glFrameBuffers[this.CONTEXT_UID] || this.initFramebuffer(framebuffer); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo.framebuffer); + // makesure all textures are unbound.. + + // now check for updates... + if(fbo.dirtyId !== framebuffer.dirtyId) + { + fbo.dirtyId = framebuffer.dirtyId; + + this.updateFramebuffer(framebuffer); + } + + this.renderer.newTextureManager.unbindTexture(framebuffer.colorTextures[0].glTextures[this.CONTEXT_UID]._bound) + } + else + { + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + } + } + + clearFramebuffer(r, g, b, a) + { + var gl = this.gl; + + // TODO clear color can be set only one right? + gl.clearColor(r, g, b, a); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + } + + initFramebuffer(framebuffer) + { + var fbo = GLFramebuffer.createRGBA(this.gl, framebuffer.width, framebuffer.height); + + framebuffer.glFrameBuffers[this.CONTEXT_UID] = fbo; + + console.log('framebuffer created!', fbo) + + return fbo; + } + + updateFramebuffer(framebuffer) + { + const gl = this.gl; + + const fbo = framebuffer.glFrameBuffers[this.CONTEXT_UID]; + + // bind the color texture + const colorTextures = framebuffer.colorTextures; + + let count = colorTextures.length; + + if(!this.drawBufferExtension) + { + count = Math.min(count, 1); + } + + const activeTextures = []; + + for (var i = 0; i < count; i++) + { + const texture = framebuffer.colorTextures[i]; + + this.renderer.newTextureManager.bindTexture(texture, 0); + + const glTexture = texture.glTextures[this.CONTEXT_UID]; + + activeTextures.push(gl.COLOR_ATTACHMENT0 + i); + + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i, gl.TEXTURE_2D, glTexture.texture, 0); + } + + if(this.drawBufferExtension && activeTextures.length > 1) + { + this.drawBufferExtension.drawBuffersWEBGL(activeTextures); + } + + if(framebuffer.stencil || framebuffer.depth) + { + fbo.enableStencil(); + } + } + +} \ No newline at end of file diff --git a/src/core/renderers/webgl/managers/NewTextureManager.js b/src/core/renderers/webgl/managers/NewTextureManager.js new file mode 100644 index 0000000..0b9e282 --- /dev/null +++ b/src/core/renderers/webgl/managers/NewTextureManager.js @@ -0,0 +1,132 @@ +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() + { + this.gl = this.renderer.gl; + this.CONTEXT_UID = this.renderer.CONTEXT_UID; + } + + bindTexture(texture, location) + { + const gl = this.gl; + + location = location || 0; + + gl.activeTexture(gl.TEXTURE0 + location); + + if(texture) + { + const glTexture = texture.glTextures[this.CONTEXT_UID] || this.initTexture(texture); + + if(texture.isCube) + { + gl.bindTexture(gl.TEXTURE_CUBE_MAP, glTexture.texture); + } + else + { + gl.bindTexture(gl.TEXTURE_2D, glTexture.texture); + } + + this.boundTextures[location] = texture; + } + else + { + gl.bindTexture(gl.TEXTURE_2D, null); + this.boundTextures[location] = null; + } + } + + unbindTexture(texture) + { + for (var i = 0; i < this.boundTextures.length; i++) { + + if(this.boundTextures[i] === texture) + { + gl.activeTexture(gl.TEXTURE0 + location); + gl.bindTexture(gl.TEXTURE_2D, null); + this.boundTextures[i] = null; + } + } + } + + initTexture(texture) + { + const gl = this.gl; + + var glTexture = new GLTexture(this.gl); + + if(texture.isCube) + { + gl.bindTexture(gl.TEXTURE_CUBE_MAP, glTexture.texture); + + glTexture.width = texture.width; + glTexture.height = texture.height; + + // upload the 6 faces.. + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, glTexture.format, glTexture.format, glTexture.type, window.tex1); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, glTexture.format, glTexture.format, glTexture.type, window.tex2); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, glTexture.format, glTexture.format, glTexture.type, window.tex3); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, glTexture.format, glTexture.format, glTexture.type, window.tex4); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, glTexture.format, glTexture.format, glTexture.type, window.tex5); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, glTexture.format, glTexture.format, glTexture.type, window.tex6); + + + gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + } + else + { + glTexture.uploadData(null, texture.width, texture.height); + + // settings.. + glTexture.enableNearestScaling(); + glTexture.enableWrapClamp(); + } + + + + texture.glTextures[this.CONTEXT_UID] = glTexture; + + return glTexture; + } +} \ No newline at end of file diff --git a/src/core/renderers/webgl/utils/RenderTarget.js b/src/core/renderers/webgl/utils/RenderTarget.js index 6d2467f..6c165f2 100644 --- a/src/core/renderers/webgl/utils/RenderTarget.js +++ b/src/core/renderers/webgl/utils/RenderTarget.js @@ -228,7 +228,7 @@ // TODO add a check as them may be the same! if (this.destinationFrame !== this.sourceFrame) { - gl.enable(gl.SCISSOR_TEST); +// gl.enable(gl.SCISSOR_TEST); gl.scissor( this.destinationFrame.x | 0, this.destinationFrame.y | 0, @@ -238,7 +238,7 @@ } else { - gl.disable(gl.SCISSOR_TEST); + // gl.disable(gl.SCISSOR_TEST); } // TODO - does not need to be updated all the time?? diff --git a/src/core/shader/generateUniformsSync.js b/src/core/shader/generateUniformsSync.js index a14086f..5885d7d 100644 --- a/src/core/shader/generateUniformsSync.js +++ b/src/core/shader/generateUniformsSync.js @@ -37,6 +37,7 @@ mat4: 'gl.uniformMatrix4fv(location, false, value)', sampler2D: 'uniform1i(location, value)', + samplerCube: 'uniform1i(location, value)' }; const GLSL_TO_ARRAY_SETTERS = { @@ -58,6 +59,7 @@ bvec4: 'gl.uniform4iv(location, value)', sampler2D: 'uniform1i(location, value)', + samplerCube: 'uniform1i(location, value)' }; export default function generateUniformsSync(uniformData) { diff --git a/src/core/shader/generateUniformsSync2.js b/src/core/shader/generateUniformsSync2.js index 5a1da3b..f3e46c5 100644 --- a/src/core/shader/generateUniformsSync2.js +++ b/src/core/shader/generateUniformsSync2.js @@ -37,6 +37,7 @@ mat4: 'gl.uniformMatrix4fv(location, false, value)', sampler2D: 'uniform1i(location, value)', + samplerCube: 'uniform1i(location, value)', }; const GLSL_TO_ARRAY_SETTERS = { @@ -58,11 +59,12 @@ bvec4: 'gl.uniform4iv(location, value)', sampler2D: 'uniform1i(location, value)', + samplerCube: 'uniform1i(location, value)', }; export default function generateUniformsSync2(group, uniformData) { - let textureCount = 1; + let textureCount = 0; let func = `var value = null; var cacheValue = null var gl = renderer.gl`; @@ -72,7 +74,7 @@ { const data = uniformData[i]; //group.uniforms[i]; - // console.log(i, data); + console.log(i, data); if(!data) { if(group.uniforms[i].group) @@ -94,11 +96,11 @@ gl.uniform1f(uniformData.${i}.location, uniformValues.${i}) }\n`; } - else if (data.type === 'sampler2D' && data.size === 1) + else if ( (data.type === 'sampler2D' || data.type === 'samplerCube') && data.size === 1) { func += `\nif (uniformValues.${i}.baseTexture) { - var location = renderer.bindTexture(uniformValues.${i}.baseTexture, ${textureCount++}, false); + var location = renderer.bindTexture(uniformValues.${i}.baseTexture, ${textureCount}, false); if(uniformData.${i}.value !== location) { @@ -106,14 +108,23 @@ gl.uniform1i(uniformData.${i}.location, location);\n; // eslint-disable-line max-len } } +else if(uniformValues.${i}._new) +{ + uniformData.${i}.value = ${textureCount}; + renderer.newTextureManager.bindTexture(uniformValues.${i}, ${textureCount}) + + gl.uniform1i(uniformData.${i}.location, ${textureCount});\n; // eslint-disable-line max-len + +} else { uniformData.${i}.value = ${textureCount}; renderer.boundTextures[${textureCount}] = renderer.emptyTextures[${textureCount}]; - gl.activeTexture(gl.TEXTURE0 + ${textureCount++}); + gl.activeTexture(gl.TEXTURE0 + ${textureCount}); uniformValues.${i}.bind(); }`; + textureCount++; } else if (data.type === 'mat3' && data.size === 1) { diff --git a/src/core/index.js b/src/core/index.js index 9e4f1f1..f282dd9 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -32,6 +32,9 @@ export { default as CanvasGraphicsRenderer } from './graphics/canvas/CanvasGraphicsRenderer'; export { default as Spritesheet } from './textures/Spritesheet'; export { default as Texture } from './textures/Texture'; +export { default as NewTexture } from './textures/new/Texture'; +export { default as NewFrameBuffer } from './textures/new/FrameBuffer'; +export { default as NewCubeTexture } from './textures/new/CubeTexture'; export { default as BaseTexture } from './textures/BaseTexture'; export { default as RenderTexture } from './textures/RenderTexture'; export { default as BaseRenderTexture } from './textures/BaseRenderTexture'; diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 830b382..3a70cf2 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -2,6 +2,8 @@ import MaskManager from './managers/MaskManager'; import StencilManager from './managers/StencilManager'; import FilterManager from './managers/FilterManager'; +import FramebufferManager from './managers/FramebufferManager'; +import NewTextureManager from './managers/NewTextureManager'; import RenderTarget from './utils/RenderTarget'; import ObjectRenderer from './utils/ObjectRenderer'; import TextureManager from './TextureManager'; @@ -115,6 +117,9 @@ */ this.emptyRenderer = new ObjectRenderer(this); + this.framebufferManager = new FramebufferManager(this); + this.newTextureManager = new NewTextureManager(this); + /** * The currently active ObjectRenderer. * @@ -559,7 +564,16 @@ } const gl = this.gl; - const glTexture = texture._glTextures[this.CONTEXT_UID]; + let glTexture = texture._glTextures[this.CONTEXT_UID]; + + if(texture._newTexture) + { + this.newTextureManager.bindTexture(texture._newTexture, location); + glTexture = texture._newTexture.glTextures[this.CONTEXT_UID]; + console.log("!!!") + + return; + } if (!glTexture) { diff --git a/src/core/renderers/webgl/managers/FramebufferManager.js b/src/core/renderers/webgl/managers/FramebufferManager.js new file mode 100644 index 0000000..308e959 --- /dev/null +++ b/src/core/renderers/webgl/managers/FramebufferManager.js @@ -0,0 +1,121 @@ +import WebGLManager from './WebGLManager'; +import { GLFramebuffer, GLTexture } from 'pixi-gl-core'; + +/** + * @class + * @extends PIXI.WebGLManager + * @memberof PIXI + */ +export default class FramebufferManager extends WebGLManager +{ + /** + * @param {PIXI.WebGLRenderer} renderer - The renderer this manager works for. + */ + constructor(renderer) + { + super(renderer); + } + + /** + * Sets up the renderer context and necessary buffers. + * + * @private + */ + onContextChange() + { + this.gl = this.renderer.gl; + this.CONTEXT_UID = this.renderer.CONTEXT_UID; + + this.drawBufferExtension = this.gl.getExtension('WEBGL_draw_buffers'); + } + + bindFramebuffer(framebuffer) + { + const gl = this.gl; + + if(framebuffer) + { + // TODO cacheing layer! + const fbo = framebuffer.glFrameBuffers[this.CONTEXT_UID] || this.initFramebuffer(framebuffer); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo.framebuffer); + // makesure all textures are unbound.. + + // now check for updates... + if(fbo.dirtyId !== framebuffer.dirtyId) + { + fbo.dirtyId = framebuffer.dirtyId; + + this.updateFramebuffer(framebuffer); + } + + this.renderer.newTextureManager.unbindTexture(framebuffer.colorTextures[0].glTextures[this.CONTEXT_UID]._bound) + } + else + { + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + } + } + + clearFramebuffer(r, g, b, a) + { + var gl = this.gl; + + // TODO clear color can be set only one right? + gl.clearColor(r, g, b, a); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + } + + initFramebuffer(framebuffer) + { + var fbo = GLFramebuffer.createRGBA(this.gl, framebuffer.width, framebuffer.height); + + framebuffer.glFrameBuffers[this.CONTEXT_UID] = fbo; + + console.log('framebuffer created!', fbo) + + return fbo; + } + + updateFramebuffer(framebuffer) + { + const gl = this.gl; + + const fbo = framebuffer.glFrameBuffers[this.CONTEXT_UID]; + + // bind the color texture + const colorTextures = framebuffer.colorTextures; + + let count = colorTextures.length; + + if(!this.drawBufferExtension) + { + count = Math.min(count, 1); + } + + const activeTextures = []; + + for (var i = 0; i < count; i++) + { + const texture = framebuffer.colorTextures[i]; + + this.renderer.newTextureManager.bindTexture(texture, 0); + + const glTexture = texture.glTextures[this.CONTEXT_UID]; + + activeTextures.push(gl.COLOR_ATTACHMENT0 + i); + + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i, gl.TEXTURE_2D, glTexture.texture, 0); + } + + if(this.drawBufferExtension && activeTextures.length > 1) + { + this.drawBufferExtension.drawBuffersWEBGL(activeTextures); + } + + if(framebuffer.stencil || framebuffer.depth) + { + fbo.enableStencil(); + } + } + +} \ No newline at end of file diff --git a/src/core/renderers/webgl/managers/NewTextureManager.js b/src/core/renderers/webgl/managers/NewTextureManager.js new file mode 100644 index 0000000..0b9e282 --- /dev/null +++ b/src/core/renderers/webgl/managers/NewTextureManager.js @@ -0,0 +1,132 @@ +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() + { + this.gl = this.renderer.gl; + this.CONTEXT_UID = this.renderer.CONTEXT_UID; + } + + bindTexture(texture, location) + { + const gl = this.gl; + + location = location || 0; + + gl.activeTexture(gl.TEXTURE0 + location); + + if(texture) + { + const glTexture = texture.glTextures[this.CONTEXT_UID] || this.initTexture(texture); + + if(texture.isCube) + { + gl.bindTexture(gl.TEXTURE_CUBE_MAP, glTexture.texture); + } + else + { + gl.bindTexture(gl.TEXTURE_2D, glTexture.texture); + } + + this.boundTextures[location] = texture; + } + else + { + gl.bindTexture(gl.TEXTURE_2D, null); + this.boundTextures[location] = null; + } + } + + unbindTexture(texture) + { + for (var i = 0; i < this.boundTextures.length; i++) { + + if(this.boundTextures[i] === texture) + { + gl.activeTexture(gl.TEXTURE0 + location); + gl.bindTexture(gl.TEXTURE_2D, null); + this.boundTextures[i] = null; + } + } + } + + initTexture(texture) + { + const gl = this.gl; + + var glTexture = new GLTexture(this.gl); + + if(texture.isCube) + { + gl.bindTexture(gl.TEXTURE_CUBE_MAP, glTexture.texture); + + glTexture.width = texture.width; + glTexture.height = texture.height; + + // upload the 6 faces.. + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, glTexture.format, glTexture.format, glTexture.type, window.tex1); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, glTexture.format, glTexture.format, glTexture.type, window.tex2); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, glTexture.format, glTexture.format, glTexture.type, window.tex3); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, glTexture.format, glTexture.format, glTexture.type, window.tex4); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, glTexture.format, glTexture.format, glTexture.type, window.tex5); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, glTexture.format, glTexture.format, glTexture.type, window.tex6); + + + gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + } + else + { + glTexture.uploadData(null, texture.width, texture.height); + + // settings.. + glTexture.enableNearestScaling(); + glTexture.enableWrapClamp(); + } + + + + texture.glTextures[this.CONTEXT_UID] = glTexture; + + return glTexture; + } +} \ No newline at end of file diff --git a/src/core/renderers/webgl/utils/RenderTarget.js b/src/core/renderers/webgl/utils/RenderTarget.js index 6d2467f..6c165f2 100644 --- a/src/core/renderers/webgl/utils/RenderTarget.js +++ b/src/core/renderers/webgl/utils/RenderTarget.js @@ -228,7 +228,7 @@ // TODO add a check as them may be the same! if (this.destinationFrame !== this.sourceFrame) { - gl.enable(gl.SCISSOR_TEST); +// gl.enable(gl.SCISSOR_TEST); gl.scissor( this.destinationFrame.x | 0, this.destinationFrame.y | 0, @@ -238,7 +238,7 @@ } else { - gl.disable(gl.SCISSOR_TEST); + // gl.disable(gl.SCISSOR_TEST); } // TODO - does not need to be updated all the time?? diff --git a/src/core/shader/generateUniformsSync.js b/src/core/shader/generateUniformsSync.js index a14086f..5885d7d 100644 --- a/src/core/shader/generateUniformsSync.js +++ b/src/core/shader/generateUniformsSync.js @@ -37,6 +37,7 @@ mat4: 'gl.uniformMatrix4fv(location, false, value)', sampler2D: 'uniform1i(location, value)', + samplerCube: 'uniform1i(location, value)' }; const GLSL_TO_ARRAY_SETTERS = { @@ -58,6 +59,7 @@ bvec4: 'gl.uniform4iv(location, value)', sampler2D: 'uniform1i(location, value)', + samplerCube: 'uniform1i(location, value)' }; export default function generateUniformsSync(uniformData) { diff --git a/src/core/shader/generateUniformsSync2.js b/src/core/shader/generateUniformsSync2.js index 5a1da3b..f3e46c5 100644 --- a/src/core/shader/generateUniformsSync2.js +++ b/src/core/shader/generateUniformsSync2.js @@ -37,6 +37,7 @@ mat4: 'gl.uniformMatrix4fv(location, false, value)', sampler2D: 'uniform1i(location, value)', + samplerCube: 'uniform1i(location, value)', }; const GLSL_TO_ARRAY_SETTERS = { @@ -58,11 +59,12 @@ bvec4: 'gl.uniform4iv(location, value)', sampler2D: 'uniform1i(location, value)', + samplerCube: 'uniform1i(location, value)', }; export default function generateUniformsSync2(group, uniformData) { - let textureCount = 1; + let textureCount = 0; let func = `var value = null; var cacheValue = null var gl = renderer.gl`; @@ -72,7 +74,7 @@ { const data = uniformData[i]; //group.uniforms[i]; - // console.log(i, data); + console.log(i, data); if(!data) { if(group.uniforms[i].group) @@ -94,11 +96,11 @@ gl.uniform1f(uniformData.${i}.location, uniformValues.${i}) }\n`; } - else if (data.type === 'sampler2D' && data.size === 1) + else if ( (data.type === 'sampler2D' || data.type === 'samplerCube') && data.size === 1) { func += `\nif (uniformValues.${i}.baseTexture) { - var location = renderer.bindTexture(uniformValues.${i}.baseTexture, ${textureCount++}, false); + var location = renderer.bindTexture(uniformValues.${i}.baseTexture, ${textureCount}, false); if(uniformData.${i}.value !== location) { @@ -106,14 +108,23 @@ gl.uniform1i(uniformData.${i}.location, location);\n; // eslint-disable-line max-len } } +else if(uniformValues.${i}._new) +{ + uniformData.${i}.value = ${textureCount}; + renderer.newTextureManager.bindTexture(uniformValues.${i}, ${textureCount}) + + gl.uniform1i(uniformData.${i}.location, ${textureCount});\n; // eslint-disable-line max-len + +} else { uniformData.${i}.value = ${textureCount}; renderer.boundTextures[${textureCount}] = renderer.emptyTextures[${textureCount}]; - gl.activeTexture(gl.TEXTURE0 + ${textureCount++}); + gl.activeTexture(gl.TEXTURE0 + ${textureCount}); uniformValues.${i}.bind(); }`; + textureCount++; } else if (data.type === 'mat3' && data.size === 1) { diff --git a/src/core/textures/BaseTexture.js b/src/core/textures/BaseTexture.js index aeccf39..b4b5539 100644 --- a/src/core/textures/BaseTexture.js +++ b/src/core/textures/BaseTexture.js @@ -193,9 +193,15 @@ */ this._glTextures = {}; + // 0 = color : 1 = depth : 2 = cube; + + this.type = 0; + + this._enabled = 0; this._virtalBoundId = -1; + // if no source passed don't try to load if (source) { @@ -217,6 +223,10 @@ * @event error * @memberof PIXI.BaseTexture# */ + + + // temp hacky API + this._newTexture = null; } /** diff --git a/src/core/index.js b/src/core/index.js index 9e4f1f1..f282dd9 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -32,6 +32,9 @@ export { default as CanvasGraphicsRenderer } from './graphics/canvas/CanvasGraphicsRenderer'; export { default as Spritesheet } from './textures/Spritesheet'; export { default as Texture } from './textures/Texture'; +export { default as NewTexture } from './textures/new/Texture'; +export { default as NewFrameBuffer } from './textures/new/FrameBuffer'; +export { default as NewCubeTexture } from './textures/new/CubeTexture'; export { default as BaseTexture } from './textures/BaseTexture'; export { default as RenderTexture } from './textures/RenderTexture'; export { default as BaseRenderTexture } from './textures/BaseRenderTexture'; diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 830b382..3a70cf2 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -2,6 +2,8 @@ import MaskManager from './managers/MaskManager'; import StencilManager from './managers/StencilManager'; import FilterManager from './managers/FilterManager'; +import FramebufferManager from './managers/FramebufferManager'; +import NewTextureManager from './managers/NewTextureManager'; import RenderTarget from './utils/RenderTarget'; import ObjectRenderer from './utils/ObjectRenderer'; import TextureManager from './TextureManager'; @@ -115,6 +117,9 @@ */ this.emptyRenderer = new ObjectRenderer(this); + this.framebufferManager = new FramebufferManager(this); + this.newTextureManager = new NewTextureManager(this); + /** * The currently active ObjectRenderer. * @@ -559,7 +564,16 @@ } const gl = this.gl; - const glTexture = texture._glTextures[this.CONTEXT_UID]; + let glTexture = texture._glTextures[this.CONTEXT_UID]; + + if(texture._newTexture) + { + this.newTextureManager.bindTexture(texture._newTexture, location); + glTexture = texture._newTexture.glTextures[this.CONTEXT_UID]; + console.log("!!!") + + return; + } if (!glTexture) { diff --git a/src/core/renderers/webgl/managers/FramebufferManager.js b/src/core/renderers/webgl/managers/FramebufferManager.js new file mode 100644 index 0000000..308e959 --- /dev/null +++ b/src/core/renderers/webgl/managers/FramebufferManager.js @@ -0,0 +1,121 @@ +import WebGLManager from './WebGLManager'; +import { GLFramebuffer, GLTexture } from 'pixi-gl-core'; + +/** + * @class + * @extends PIXI.WebGLManager + * @memberof PIXI + */ +export default class FramebufferManager extends WebGLManager +{ + /** + * @param {PIXI.WebGLRenderer} renderer - The renderer this manager works for. + */ + constructor(renderer) + { + super(renderer); + } + + /** + * Sets up the renderer context and necessary buffers. + * + * @private + */ + onContextChange() + { + this.gl = this.renderer.gl; + this.CONTEXT_UID = this.renderer.CONTEXT_UID; + + this.drawBufferExtension = this.gl.getExtension('WEBGL_draw_buffers'); + } + + bindFramebuffer(framebuffer) + { + const gl = this.gl; + + if(framebuffer) + { + // TODO cacheing layer! + const fbo = framebuffer.glFrameBuffers[this.CONTEXT_UID] || this.initFramebuffer(framebuffer); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo.framebuffer); + // makesure all textures are unbound.. + + // now check for updates... + if(fbo.dirtyId !== framebuffer.dirtyId) + { + fbo.dirtyId = framebuffer.dirtyId; + + this.updateFramebuffer(framebuffer); + } + + this.renderer.newTextureManager.unbindTexture(framebuffer.colorTextures[0].glTextures[this.CONTEXT_UID]._bound) + } + else + { + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + } + } + + clearFramebuffer(r, g, b, a) + { + var gl = this.gl; + + // TODO clear color can be set only one right? + gl.clearColor(r, g, b, a); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + } + + initFramebuffer(framebuffer) + { + var fbo = GLFramebuffer.createRGBA(this.gl, framebuffer.width, framebuffer.height); + + framebuffer.glFrameBuffers[this.CONTEXT_UID] = fbo; + + console.log('framebuffer created!', fbo) + + return fbo; + } + + updateFramebuffer(framebuffer) + { + const gl = this.gl; + + const fbo = framebuffer.glFrameBuffers[this.CONTEXT_UID]; + + // bind the color texture + const colorTextures = framebuffer.colorTextures; + + let count = colorTextures.length; + + if(!this.drawBufferExtension) + { + count = Math.min(count, 1); + } + + const activeTextures = []; + + for (var i = 0; i < count; i++) + { + const texture = framebuffer.colorTextures[i]; + + this.renderer.newTextureManager.bindTexture(texture, 0); + + const glTexture = texture.glTextures[this.CONTEXT_UID]; + + activeTextures.push(gl.COLOR_ATTACHMENT0 + i); + + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i, gl.TEXTURE_2D, glTexture.texture, 0); + } + + if(this.drawBufferExtension && activeTextures.length > 1) + { + this.drawBufferExtension.drawBuffersWEBGL(activeTextures); + } + + if(framebuffer.stencil || framebuffer.depth) + { + fbo.enableStencil(); + } + } + +} \ No newline at end of file diff --git a/src/core/renderers/webgl/managers/NewTextureManager.js b/src/core/renderers/webgl/managers/NewTextureManager.js new file mode 100644 index 0000000..0b9e282 --- /dev/null +++ b/src/core/renderers/webgl/managers/NewTextureManager.js @@ -0,0 +1,132 @@ +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() + { + this.gl = this.renderer.gl; + this.CONTEXT_UID = this.renderer.CONTEXT_UID; + } + + bindTexture(texture, location) + { + const gl = this.gl; + + location = location || 0; + + gl.activeTexture(gl.TEXTURE0 + location); + + if(texture) + { + const glTexture = texture.glTextures[this.CONTEXT_UID] || this.initTexture(texture); + + if(texture.isCube) + { + gl.bindTexture(gl.TEXTURE_CUBE_MAP, glTexture.texture); + } + else + { + gl.bindTexture(gl.TEXTURE_2D, glTexture.texture); + } + + this.boundTextures[location] = texture; + } + else + { + gl.bindTexture(gl.TEXTURE_2D, null); + this.boundTextures[location] = null; + } + } + + unbindTexture(texture) + { + for (var i = 0; i < this.boundTextures.length; i++) { + + if(this.boundTextures[i] === texture) + { + gl.activeTexture(gl.TEXTURE0 + location); + gl.bindTexture(gl.TEXTURE_2D, null); + this.boundTextures[i] = null; + } + } + } + + initTexture(texture) + { + const gl = this.gl; + + var glTexture = new GLTexture(this.gl); + + if(texture.isCube) + { + gl.bindTexture(gl.TEXTURE_CUBE_MAP, glTexture.texture); + + glTexture.width = texture.width; + glTexture.height = texture.height; + + // upload the 6 faces.. + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, glTexture.format, glTexture.format, glTexture.type, window.tex1); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, glTexture.format, glTexture.format, glTexture.type, window.tex2); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, glTexture.format, glTexture.format, glTexture.type, window.tex3); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, glTexture.format, glTexture.format, glTexture.type, window.tex4); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, glTexture.format, glTexture.format, glTexture.type, window.tex5); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, glTexture.format, glTexture.format, glTexture.type, window.tex6); + + + gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + } + else + { + glTexture.uploadData(null, texture.width, texture.height); + + // settings.. + glTexture.enableNearestScaling(); + glTexture.enableWrapClamp(); + } + + + + texture.glTextures[this.CONTEXT_UID] = glTexture; + + return glTexture; + } +} \ No newline at end of file diff --git a/src/core/renderers/webgl/utils/RenderTarget.js b/src/core/renderers/webgl/utils/RenderTarget.js index 6d2467f..6c165f2 100644 --- a/src/core/renderers/webgl/utils/RenderTarget.js +++ b/src/core/renderers/webgl/utils/RenderTarget.js @@ -228,7 +228,7 @@ // TODO add a check as them may be the same! if (this.destinationFrame !== this.sourceFrame) { - gl.enable(gl.SCISSOR_TEST); +// gl.enable(gl.SCISSOR_TEST); gl.scissor( this.destinationFrame.x | 0, this.destinationFrame.y | 0, @@ -238,7 +238,7 @@ } else { - gl.disable(gl.SCISSOR_TEST); + // gl.disable(gl.SCISSOR_TEST); } // TODO - does not need to be updated all the time?? diff --git a/src/core/shader/generateUniformsSync.js b/src/core/shader/generateUniformsSync.js index a14086f..5885d7d 100644 --- a/src/core/shader/generateUniformsSync.js +++ b/src/core/shader/generateUniformsSync.js @@ -37,6 +37,7 @@ mat4: 'gl.uniformMatrix4fv(location, false, value)', sampler2D: 'uniform1i(location, value)', + samplerCube: 'uniform1i(location, value)' }; const GLSL_TO_ARRAY_SETTERS = { @@ -58,6 +59,7 @@ bvec4: 'gl.uniform4iv(location, value)', sampler2D: 'uniform1i(location, value)', + samplerCube: 'uniform1i(location, value)' }; export default function generateUniformsSync(uniformData) { diff --git a/src/core/shader/generateUniformsSync2.js b/src/core/shader/generateUniformsSync2.js index 5a1da3b..f3e46c5 100644 --- a/src/core/shader/generateUniformsSync2.js +++ b/src/core/shader/generateUniformsSync2.js @@ -37,6 +37,7 @@ mat4: 'gl.uniformMatrix4fv(location, false, value)', sampler2D: 'uniform1i(location, value)', + samplerCube: 'uniform1i(location, value)', }; const GLSL_TO_ARRAY_SETTERS = { @@ -58,11 +59,12 @@ bvec4: 'gl.uniform4iv(location, value)', sampler2D: 'uniform1i(location, value)', + samplerCube: 'uniform1i(location, value)', }; export default function generateUniformsSync2(group, uniformData) { - let textureCount = 1; + let textureCount = 0; let func = `var value = null; var cacheValue = null var gl = renderer.gl`; @@ -72,7 +74,7 @@ { const data = uniformData[i]; //group.uniforms[i]; - // console.log(i, data); + console.log(i, data); if(!data) { if(group.uniforms[i].group) @@ -94,11 +96,11 @@ gl.uniform1f(uniformData.${i}.location, uniformValues.${i}) }\n`; } - else if (data.type === 'sampler2D' && data.size === 1) + else if ( (data.type === 'sampler2D' || data.type === 'samplerCube') && data.size === 1) { func += `\nif (uniformValues.${i}.baseTexture) { - var location = renderer.bindTexture(uniformValues.${i}.baseTexture, ${textureCount++}, false); + var location = renderer.bindTexture(uniformValues.${i}.baseTexture, ${textureCount}, false); if(uniformData.${i}.value !== location) { @@ -106,14 +108,23 @@ gl.uniform1i(uniformData.${i}.location, location);\n; // eslint-disable-line max-len } } +else if(uniformValues.${i}._new) +{ + uniformData.${i}.value = ${textureCount}; + renderer.newTextureManager.bindTexture(uniformValues.${i}, ${textureCount}) + + gl.uniform1i(uniformData.${i}.location, ${textureCount});\n; // eslint-disable-line max-len + +} else { uniformData.${i}.value = ${textureCount}; renderer.boundTextures[${textureCount}] = renderer.emptyTextures[${textureCount}]; - gl.activeTexture(gl.TEXTURE0 + ${textureCount++}); + gl.activeTexture(gl.TEXTURE0 + ${textureCount}); uniformValues.${i}.bind(); }`; + textureCount++; } else if (data.type === 'mat3' && data.size === 1) { diff --git a/src/core/textures/BaseTexture.js b/src/core/textures/BaseTexture.js index aeccf39..b4b5539 100644 --- a/src/core/textures/BaseTexture.js +++ b/src/core/textures/BaseTexture.js @@ -193,9 +193,15 @@ */ this._glTextures = {}; + // 0 = color : 1 = depth : 2 = cube; + + this.type = 0; + + this._enabled = 0; this._virtalBoundId = -1; + // if no source passed don't try to load if (source) { @@ -217,6 +223,10 @@ * @event error * @memberof PIXI.BaseTexture# */ + + + // temp hacky API + this._newTexture = null; } /** diff --git a/src/core/textures/new/CubeTexture.js b/src/core/textures/new/CubeTexture.js new file mode 100644 index 0000000..eea3526 --- /dev/null +++ b/src/core/textures/new/CubeTexture.js @@ -0,0 +1,18 @@ +import Texture from './Texture'; + +export default class CubeTexture extends Texture +{ + constructor(width, height, format) + { + super(width, height, format); + + this.isCube = true; + + //this.side1 = {_glTextures:this.glTextures, id:1}; + //this.side2 = {_glTextures:this.glTextures, id:2}; + //this.side3 = {_glTextures:this.glTextures, id:3}; + //this.side4 = {_glTextures:this.glTextures, id:4}; + //this.side5 = {_glTextures:this.glTextures, id:5}; + //this.side6 = {_glTextures:this.glTextures, id:6}; + } +} \ No newline at end of file diff --git a/src/core/index.js b/src/core/index.js index 9e4f1f1..f282dd9 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -32,6 +32,9 @@ export { default as CanvasGraphicsRenderer } from './graphics/canvas/CanvasGraphicsRenderer'; export { default as Spritesheet } from './textures/Spritesheet'; export { default as Texture } from './textures/Texture'; +export { default as NewTexture } from './textures/new/Texture'; +export { default as NewFrameBuffer } from './textures/new/FrameBuffer'; +export { default as NewCubeTexture } from './textures/new/CubeTexture'; export { default as BaseTexture } from './textures/BaseTexture'; export { default as RenderTexture } from './textures/RenderTexture'; export { default as BaseRenderTexture } from './textures/BaseRenderTexture'; diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 830b382..3a70cf2 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -2,6 +2,8 @@ import MaskManager from './managers/MaskManager'; import StencilManager from './managers/StencilManager'; import FilterManager from './managers/FilterManager'; +import FramebufferManager from './managers/FramebufferManager'; +import NewTextureManager from './managers/NewTextureManager'; import RenderTarget from './utils/RenderTarget'; import ObjectRenderer from './utils/ObjectRenderer'; import TextureManager from './TextureManager'; @@ -115,6 +117,9 @@ */ this.emptyRenderer = new ObjectRenderer(this); + this.framebufferManager = new FramebufferManager(this); + this.newTextureManager = new NewTextureManager(this); + /** * The currently active ObjectRenderer. * @@ -559,7 +564,16 @@ } const gl = this.gl; - const glTexture = texture._glTextures[this.CONTEXT_UID]; + let glTexture = texture._glTextures[this.CONTEXT_UID]; + + if(texture._newTexture) + { + this.newTextureManager.bindTexture(texture._newTexture, location); + glTexture = texture._newTexture.glTextures[this.CONTEXT_UID]; + console.log("!!!") + + return; + } if (!glTexture) { diff --git a/src/core/renderers/webgl/managers/FramebufferManager.js b/src/core/renderers/webgl/managers/FramebufferManager.js new file mode 100644 index 0000000..308e959 --- /dev/null +++ b/src/core/renderers/webgl/managers/FramebufferManager.js @@ -0,0 +1,121 @@ +import WebGLManager from './WebGLManager'; +import { GLFramebuffer, GLTexture } from 'pixi-gl-core'; + +/** + * @class + * @extends PIXI.WebGLManager + * @memberof PIXI + */ +export default class FramebufferManager extends WebGLManager +{ + /** + * @param {PIXI.WebGLRenderer} renderer - The renderer this manager works for. + */ + constructor(renderer) + { + super(renderer); + } + + /** + * Sets up the renderer context and necessary buffers. + * + * @private + */ + onContextChange() + { + this.gl = this.renderer.gl; + this.CONTEXT_UID = this.renderer.CONTEXT_UID; + + this.drawBufferExtension = this.gl.getExtension('WEBGL_draw_buffers'); + } + + bindFramebuffer(framebuffer) + { + const gl = this.gl; + + if(framebuffer) + { + // TODO cacheing layer! + const fbo = framebuffer.glFrameBuffers[this.CONTEXT_UID] || this.initFramebuffer(framebuffer); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo.framebuffer); + // makesure all textures are unbound.. + + // now check for updates... + if(fbo.dirtyId !== framebuffer.dirtyId) + { + fbo.dirtyId = framebuffer.dirtyId; + + this.updateFramebuffer(framebuffer); + } + + this.renderer.newTextureManager.unbindTexture(framebuffer.colorTextures[0].glTextures[this.CONTEXT_UID]._bound) + } + else + { + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + } + } + + clearFramebuffer(r, g, b, a) + { + var gl = this.gl; + + // TODO clear color can be set only one right? + gl.clearColor(r, g, b, a); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + } + + initFramebuffer(framebuffer) + { + var fbo = GLFramebuffer.createRGBA(this.gl, framebuffer.width, framebuffer.height); + + framebuffer.glFrameBuffers[this.CONTEXT_UID] = fbo; + + console.log('framebuffer created!', fbo) + + return fbo; + } + + updateFramebuffer(framebuffer) + { + const gl = this.gl; + + const fbo = framebuffer.glFrameBuffers[this.CONTEXT_UID]; + + // bind the color texture + const colorTextures = framebuffer.colorTextures; + + let count = colorTextures.length; + + if(!this.drawBufferExtension) + { + count = Math.min(count, 1); + } + + const activeTextures = []; + + for (var i = 0; i < count; i++) + { + const texture = framebuffer.colorTextures[i]; + + this.renderer.newTextureManager.bindTexture(texture, 0); + + const glTexture = texture.glTextures[this.CONTEXT_UID]; + + activeTextures.push(gl.COLOR_ATTACHMENT0 + i); + + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i, gl.TEXTURE_2D, glTexture.texture, 0); + } + + if(this.drawBufferExtension && activeTextures.length > 1) + { + this.drawBufferExtension.drawBuffersWEBGL(activeTextures); + } + + if(framebuffer.stencil || framebuffer.depth) + { + fbo.enableStencil(); + } + } + +} \ No newline at end of file diff --git a/src/core/renderers/webgl/managers/NewTextureManager.js b/src/core/renderers/webgl/managers/NewTextureManager.js new file mode 100644 index 0000000..0b9e282 --- /dev/null +++ b/src/core/renderers/webgl/managers/NewTextureManager.js @@ -0,0 +1,132 @@ +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() + { + this.gl = this.renderer.gl; + this.CONTEXT_UID = this.renderer.CONTEXT_UID; + } + + bindTexture(texture, location) + { + const gl = this.gl; + + location = location || 0; + + gl.activeTexture(gl.TEXTURE0 + location); + + if(texture) + { + const glTexture = texture.glTextures[this.CONTEXT_UID] || this.initTexture(texture); + + if(texture.isCube) + { + gl.bindTexture(gl.TEXTURE_CUBE_MAP, glTexture.texture); + } + else + { + gl.bindTexture(gl.TEXTURE_2D, glTexture.texture); + } + + this.boundTextures[location] = texture; + } + else + { + gl.bindTexture(gl.TEXTURE_2D, null); + this.boundTextures[location] = null; + } + } + + unbindTexture(texture) + { + for (var i = 0; i < this.boundTextures.length; i++) { + + if(this.boundTextures[i] === texture) + { + gl.activeTexture(gl.TEXTURE0 + location); + gl.bindTexture(gl.TEXTURE_2D, null); + this.boundTextures[i] = null; + } + } + } + + initTexture(texture) + { + const gl = this.gl; + + var glTexture = new GLTexture(this.gl); + + if(texture.isCube) + { + gl.bindTexture(gl.TEXTURE_CUBE_MAP, glTexture.texture); + + glTexture.width = texture.width; + glTexture.height = texture.height; + + // upload the 6 faces.. + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, glTexture.format, glTexture.format, glTexture.type, window.tex1); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, glTexture.format, glTexture.format, glTexture.type, window.tex2); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, glTexture.format, glTexture.format, glTexture.type, window.tex3); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, glTexture.format, glTexture.format, glTexture.type, window.tex4); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, glTexture.format, glTexture.format, glTexture.type, window.tex5); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, glTexture.format, glTexture.format, glTexture.type, window.tex6); + + + gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + } + else + { + glTexture.uploadData(null, texture.width, texture.height); + + // settings.. + glTexture.enableNearestScaling(); + glTexture.enableWrapClamp(); + } + + + + texture.glTextures[this.CONTEXT_UID] = glTexture; + + return glTexture; + } +} \ No newline at end of file diff --git a/src/core/renderers/webgl/utils/RenderTarget.js b/src/core/renderers/webgl/utils/RenderTarget.js index 6d2467f..6c165f2 100644 --- a/src/core/renderers/webgl/utils/RenderTarget.js +++ b/src/core/renderers/webgl/utils/RenderTarget.js @@ -228,7 +228,7 @@ // TODO add a check as them may be the same! if (this.destinationFrame !== this.sourceFrame) { - gl.enable(gl.SCISSOR_TEST); +// gl.enable(gl.SCISSOR_TEST); gl.scissor( this.destinationFrame.x | 0, this.destinationFrame.y | 0, @@ -238,7 +238,7 @@ } else { - gl.disable(gl.SCISSOR_TEST); + // gl.disable(gl.SCISSOR_TEST); } // TODO - does not need to be updated all the time?? diff --git a/src/core/shader/generateUniformsSync.js b/src/core/shader/generateUniformsSync.js index a14086f..5885d7d 100644 --- a/src/core/shader/generateUniformsSync.js +++ b/src/core/shader/generateUniformsSync.js @@ -37,6 +37,7 @@ mat4: 'gl.uniformMatrix4fv(location, false, value)', sampler2D: 'uniform1i(location, value)', + samplerCube: 'uniform1i(location, value)' }; const GLSL_TO_ARRAY_SETTERS = { @@ -58,6 +59,7 @@ bvec4: 'gl.uniform4iv(location, value)', sampler2D: 'uniform1i(location, value)', + samplerCube: 'uniform1i(location, value)' }; export default function generateUniformsSync(uniformData) { diff --git a/src/core/shader/generateUniformsSync2.js b/src/core/shader/generateUniformsSync2.js index 5a1da3b..f3e46c5 100644 --- a/src/core/shader/generateUniformsSync2.js +++ b/src/core/shader/generateUniformsSync2.js @@ -37,6 +37,7 @@ mat4: 'gl.uniformMatrix4fv(location, false, value)', sampler2D: 'uniform1i(location, value)', + samplerCube: 'uniform1i(location, value)', }; const GLSL_TO_ARRAY_SETTERS = { @@ -58,11 +59,12 @@ bvec4: 'gl.uniform4iv(location, value)', sampler2D: 'uniform1i(location, value)', + samplerCube: 'uniform1i(location, value)', }; export default function generateUniformsSync2(group, uniformData) { - let textureCount = 1; + let textureCount = 0; let func = `var value = null; var cacheValue = null var gl = renderer.gl`; @@ -72,7 +74,7 @@ { const data = uniformData[i]; //group.uniforms[i]; - // console.log(i, data); + console.log(i, data); if(!data) { if(group.uniforms[i].group) @@ -94,11 +96,11 @@ gl.uniform1f(uniformData.${i}.location, uniformValues.${i}) }\n`; } - else if (data.type === 'sampler2D' && data.size === 1) + else if ( (data.type === 'sampler2D' || data.type === 'samplerCube') && data.size === 1) { func += `\nif (uniformValues.${i}.baseTexture) { - var location = renderer.bindTexture(uniformValues.${i}.baseTexture, ${textureCount++}, false); + var location = renderer.bindTexture(uniformValues.${i}.baseTexture, ${textureCount}, false); if(uniformData.${i}.value !== location) { @@ -106,14 +108,23 @@ gl.uniform1i(uniformData.${i}.location, location);\n; // eslint-disable-line max-len } } +else if(uniformValues.${i}._new) +{ + uniformData.${i}.value = ${textureCount}; + renderer.newTextureManager.bindTexture(uniformValues.${i}, ${textureCount}) + + gl.uniform1i(uniformData.${i}.location, ${textureCount});\n; // eslint-disable-line max-len + +} else { uniformData.${i}.value = ${textureCount}; renderer.boundTextures[${textureCount}] = renderer.emptyTextures[${textureCount}]; - gl.activeTexture(gl.TEXTURE0 + ${textureCount++}); + gl.activeTexture(gl.TEXTURE0 + ${textureCount}); uniformValues.${i}.bind(); }`; + textureCount++; } else if (data.type === 'mat3' && data.size === 1) { diff --git a/src/core/textures/BaseTexture.js b/src/core/textures/BaseTexture.js index aeccf39..b4b5539 100644 --- a/src/core/textures/BaseTexture.js +++ b/src/core/textures/BaseTexture.js @@ -193,9 +193,15 @@ */ this._glTextures = {}; + // 0 = color : 1 = depth : 2 = cube; + + this.type = 0; + + this._enabled = 0; this._virtalBoundId = -1; + // if no source passed don't try to load if (source) { @@ -217,6 +223,10 @@ * @event error * @memberof PIXI.BaseTexture# */ + + + // temp hacky API + this._newTexture = null; } /** diff --git a/src/core/textures/new/CubeTexture.js b/src/core/textures/new/CubeTexture.js new file mode 100644 index 0000000..eea3526 --- /dev/null +++ b/src/core/textures/new/CubeTexture.js @@ -0,0 +1,18 @@ +import Texture from './Texture'; + +export default class CubeTexture extends Texture +{ + constructor(width, height, format) + { + super(width, height, format); + + this.isCube = true; + + //this.side1 = {_glTextures:this.glTextures, id:1}; + //this.side2 = {_glTextures:this.glTextures, id:2}; + //this.side3 = {_glTextures:this.glTextures, id:3}; + //this.side4 = {_glTextures:this.glTextures, id:4}; + //this.side5 = {_glTextures:this.glTextures, id:5}; + //this.side6 = {_glTextures:this.glTextures, id:6}; + } +} \ No newline at end of file diff --git a/src/core/textures/new/FrameBuffer.js b/src/core/textures/new/FrameBuffer.js new file mode 100644 index 0000000..004c84f --- /dev/null +++ b/src/core/textures/new/FrameBuffer.js @@ -0,0 +1,71 @@ +import Texture from './Texture' + + +export default class FrameBuffer +{ + constructor(width, height) + { + this.width = width || 100; + this.height = height || 100; + + this.stencil = false; + this.depth = false; + + this.dirtyId = 0; + + this.depthTexture = null; + this.colorTextures = []; + + this.glFrameBuffers = {}; + } + + get colorTexture() + { + return this.colorTextures[0]; + } + + addColorTexture(index, texture) + { + // TODO add some validation to the texture - same width / height etc? + this.colorTextures[index || 0] = texture || new Texture(this.width, this.height, 'rgba');// || new Texture(); + + this.dirtyId++; + + return this; + } + + addDepthTexture() + { + this.depthTexture[0] = new Texture(this.width, this.height, 'depth');// || new Texture(); + this.dirtyId++; + return this; + } + + enableDepth() + { + this.depth = true; + + this.dirtyId++; + + return this; + } + + enableStencil() + { + this.stencil = true; + + this.dirtyId++; + + return this; + } + + resize(width, height) + { + this.width = width; + this.height = height; + + this.dirtyId++; + } + + +} \ No newline at end of file diff --git a/src/core/index.js b/src/core/index.js index 9e4f1f1..f282dd9 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -32,6 +32,9 @@ export { default as CanvasGraphicsRenderer } from './graphics/canvas/CanvasGraphicsRenderer'; export { default as Spritesheet } from './textures/Spritesheet'; export { default as Texture } from './textures/Texture'; +export { default as NewTexture } from './textures/new/Texture'; +export { default as NewFrameBuffer } from './textures/new/FrameBuffer'; +export { default as NewCubeTexture } from './textures/new/CubeTexture'; export { default as BaseTexture } from './textures/BaseTexture'; export { default as RenderTexture } from './textures/RenderTexture'; export { default as BaseRenderTexture } from './textures/BaseRenderTexture'; diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 830b382..3a70cf2 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -2,6 +2,8 @@ import MaskManager from './managers/MaskManager'; import StencilManager from './managers/StencilManager'; import FilterManager from './managers/FilterManager'; +import FramebufferManager from './managers/FramebufferManager'; +import NewTextureManager from './managers/NewTextureManager'; import RenderTarget from './utils/RenderTarget'; import ObjectRenderer from './utils/ObjectRenderer'; import TextureManager from './TextureManager'; @@ -115,6 +117,9 @@ */ this.emptyRenderer = new ObjectRenderer(this); + this.framebufferManager = new FramebufferManager(this); + this.newTextureManager = new NewTextureManager(this); + /** * The currently active ObjectRenderer. * @@ -559,7 +564,16 @@ } const gl = this.gl; - const glTexture = texture._glTextures[this.CONTEXT_UID]; + let glTexture = texture._glTextures[this.CONTEXT_UID]; + + if(texture._newTexture) + { + this.newTextureManager.bindTexture(texture._newTexture, location); + glTexture = texture._newTexture.glTextures[this.CONTEXT_UID]; + console.log("!!!") + + return; + } if (!glTexture) { diff --git a/src/core/renderers/webgl/managers/FramebufferManager.js b/src/core/renderers/webgl/managers/FramebufferManager.js new file mode 100644 index 0000000..308e959 --- /dev/null +++ b/src/core/renderers/webgl/managers/FramebufferManager.js @@ -0,0 +1,121 @@ +import WebGLManager from './WebGLManager'; +import { GLFramebuffer, GLTexture } from 'pixi-gl-core'; + +/** + * @class + * @extends PIXI.WebGLManager + * @memberof PIXI + */ +export default class FramebufferManager extends WebGLManager +{ + /** + * @param {PIXI.WebGLRenderer} renderer - The renderer this manager works for. + */ + constructor(renderer) + { + super(renderer); + } + + /** + * Sets up the renderer context and necessary buffers. + * + * @private + */ + onContextChange() + { + this.gl = this.renderer.gl; + this.CONTEXT_UID = this.renderer.CONTEXT_UID; + + this.drawBufferExtension = this.gl.getExtension('WEBGL_draw_buffers'); + } + + bindFramebuffer(framebuffer) + { + const gl = this.gl; + + if(framebuffer) + { + // TODO cacheing layer! + const fbo = framebuffer.glFrameBuffers[this.CONTEXT_UID] || this.initFramebuffer(framebuffer); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo.framebuffer); + // makesure all textures are unbound.. + + // now check for updates... + if(fbo.dirtyId !== framebuffer.dirtyId) + { + fbo.dirtyId = framebuffer.dirtyId; + + this.updateFramebuffer(framebuffer); + } + + this.renderer.newTextureManager.unbindTexture(framebuffer.colorTextures[0].glTextures[this.CONTEXT_UID]._bound) + } + else + { + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + } + } + + clearFramebuffer(r, g, b, a) + { + var gl = this.gl; + + // TODO clear color can be set only one right? + gl.clearColor(r, g, b, a); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + } + + initFramebuffer(framebuffer) + { + var fbo = GLFramebuffer.createRGBA(this.gl, framebuffer.width, framebuffer.height); + + framebuffer.glFrameBuffers[this.CONTEXT_UID] = fbo; + + console.log('framebuffer created!', fbo) + + return fbo; + } + + updateFramebuffer(framebuffer) + { + const gl = this.gl; + + const fbo = framebuffer.glFrameBuffers[this.CONTEXT_UID]; + + // bind the color texture + const colorTextures = framebuffer.colorTextures; + + let count = colorTextures.length; + + if(!this.drawBufferExtension) + { + count = Math.min(count, 1); + } + + const activeTextures = []; + + for (var i = 0; i < count; i++) + { + const texture = framebuffer.colorTextures[i]; + + this.renderer.newTextureManager.bindTexture(texture, 0); + + const glTexture = texture.glTextures[this.CONTEXT_UID]; + + activeTextures.push(gl.COLOR_ATTACHMENT0 + i); + + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i, gl.TEXTURE_2D, glTexture.texture, 0); + } + + if(this.drawBufferExtension && activeTextures.length > 1) + { + this.drawBufferExtension.drawBuffersWEBGL(activeTextures); + } + + if(framebuffer.stencil || framebuffer.depth) + { + fbo.enableStencil(); + } + } + +} \ No newline at end of file diff --git a/src/core/renderers/webgl/managers/NewTextureManager.js b/src/core/renderers/webgl/managers/NewTextureManager.js new file mode 100644 index 0000000..0b9e282 --- /dev/null +++ b/src/core/renderers/webgl/managers/NewTextureManager.js @@ -0,0 +1,132 @@ +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() + { + this.gl = this.renderer.gl; + this.CONTEXT_UID = this.renderer.CONTEXT_UID; + } + + bindTexture(texture, location) + { + const gl = this.gl; + + location = location || 0; + + gl.activeTexture(gl.TEXTURE0 + location); + + if(texture) + { + const glTexture = texture.glTextures[this.CONTEXT_UID] || this.initTexture(texture); + + if(texture.isCube) + { + gl.bindTexture(gl.TEXTURE_CUBE_MAP, glTexture.texture); + } + else + { + gl.bindTexture(gl.TEXTURE_2D, glTexture.texture); + } + + this.boundTextures[location] = texture; + } + else + { + gl.bindTexture(gl.TEXTURE_2D, null); + this.boundTextures[location] = null; + } + } + + unbindTexture(texture) + { + for (var i = 0; i < this.boundTextures.length; i++) { + + if(this.boundTextures[i] === texture) + { + gl.activeTexture(gl.TEXTURE0 + location); + gl.bindTexture(gl.TEXTURE_2D, null); + this.boundTextures[i] = null; + } + } + } + + initTexture(texture) + { + const gl = this.gl; + + var glTexture = new GLTexture(this.gl); + + if(texture.isCube) + { + gl.bindTexture(gl.TEXTURE_CUBE_MAP, glTexture.texture); + + glTexture.width = texture.width; + glTexture.height = texture.height; + + // upload the 6 faces.. + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, glTexture.format, glTexture.format, glTexture.type, window.tex1); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, glTexture.format, glTexture.format, glTexture.type, window.tex2); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, glTexture.format, glTexture.format, glTexture.type, window.tex3); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, glTexture.format, glTexture.format, glTexture.type, window.tex4); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, glTexture.format, glTexture.format, glTexture.type, window.tex5); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, glTexture.format, glTexture.format, glTexture.type, window.tex6); + + + gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + } + else + { + glTexture.uploadData(null, texture.width, texture.height); + + // settings.. + glTexture.enableNearestScaling(); + glTexture.enableWrapClamp(); + } + + + + texture.glTextures[this.CONTEXT_UID] = glTexture; + + return glTexture; + } +} \ No newline at end of file diff --git a/src/core/renderers/webgl/utils/RenderTarget.js b/src/core/renderers/webgl/utils/RenderTarget.js index 6d2467f..6c165f2 100644 --- a/src/core/renderers/webgl/utils/RenderTarget.js +++ b/src/core/renderers/webgl/utils/RenderTarget.js @@ -228,7 +228,7 @@ // TODO add a check as them may be the same! if (this.destinationFrame !== this.sourceFrame) { - gl.enable(gl.SCISSOR_TEST); +// gl.enable(gl.SCISSOR_TEST); gl.scissor( this.destinationFrame.x | 0, this.destinationFrame.y | 0, @@ -238,7 +238,7 @@ } else { - gl.disable(gl.SCISSOR_TEST); + // gl.disable(gl.SCISSOR_TEST); } // TODO - does not need to be updated all the time?? diff --git a/src/core/shader/generateUniformsSync.js b/src/core/shader/generateUniformsSync.js index a14086f..5885d7d 100644 --- a/src/core/shader/generateUniformsSync.js +++ b/src/core/shader/generateUniformsSync.js @@ -37,6 +37,7 @@ mat4: 'gl.uniformMatrix4fv(location, false, value)', sampler2D: 'uniform1i(location, value)', + samplerCube: 'uniform1i(location, value)' }; const GLSL_TO_ARRAY_SETTERS = { @@ -58,6 +59,7 @@ bvec4: 'gl.uniform4iv(location, value)', sampler2D: 'uniform1i(location, value)', + samplerCube: 'uniform1i(location, value)' }; export default function generateUniformsSync(uniformData) { diff --git a/src/core/shader/generateUniformsSync2.js b/src/core/shader/generateUniformsSync2.js index 5a1da3b..f3e46c5 100644 --- a/src/core/shader/generateUniformsSync2.js +++ b/src/core/shader/generateUniformsSync2.js @@ -37,6 +37,7 @@ mat4: 'gl.uniformMatrix4fv(location, false, value)', sampler2D: 'uniform1i(location, value)', + samplerCube: 'uniform1i(location, value)', }; const GLSL_TO_ARRAY_SETTERS = { @@ -58,11 +59,12 @@ bvec4: 'gl.uniform4iv(location, value)', sampler2D: 'uniform1i(location, value)', + samplerCube: 'uniform1i(location, value)', }; export default function generateUniformsSync2(group, uniformData) { - let textureCount = 1; + let textureCount = 0; let func = `var value = null; var cacheValue = null var gl = renderer.gl`; @@ -72,7 +74,7 @@ { const data = uniformData[i]; //group.uniforms[i]; - // console.log(i, data); + console.log(i, data); if(!data) { if(group.uniforms[i].group) @@ -94,11 +96,11 @@ gl.uniform1f(uniformData.${i}.location, uniformValues.${i}) }\n`; } - else if (data.type === 'sampler2D' && data.size === 1) + else if ( (data.type === 'sampler2D' || data.type === 'samplerCube') && data.size === 1) { func += `\nif (uniformValues.${i}.baseTexture) { - var location = renderer.bindTexture(uniformValues.${i}.baseTexture, ${textureCount++}, false); + var location = renderer.bindTexture(uniformValues.${i}.baseTexture, ${textureCount}, false); if(uniformData.${i}.value !== location) { @@ -106,14 +108,23 @@ gl.uniform1i(uniformData.${i}.location, location);\n; // eslint-disable-line max-len } } +else if(uniformValues.${i}._new) +{ + uniformData.${i}.value = ${textureCount}; + renderer.newTextureManager.bindTexture(uniformValues.${i}, ${textureCount}) + + gl.uniform1i(uniformData.${i}.location, ${textureCount});\n; // eslint-disable-line max-len + +} else { uniformData.${i}.value = ${textureCount}; renderer.boundTextures[${textureCount}] = renderer.emptyTextures[${textureCount}]; - gl.activeTexture(gl.TEXTURE0 + ${textureCount++}); + gl.activeTexture(gl.TEXTURE0 + ${textureCount}); uniformValues.${i}.bind(); }`; + textureCount++; } else if (data.type === 'mat3' && data.size === 1) { diff --git a/src/core/textures/BaseTexture.js b/src/core/textures/BaseTexture.js index aeccf39..b4b5539 100644 --- a/src/core/textures/BaseTexture.js +++ b/src/core/textures/BaseTexture.js @@ -193,9 +193,15 @@ */ this._glTextures = {}; + // 0 = color : 1 = depth : 2 = cube; + + this.type = 0; + + this._enabled = 0; this._virtalBoundId = -1; + // if no source passed don't try to load if (source) { @@ -217,6 +223,10 @@ * @event error * @memberof PIXI.BaseTexture# */ + + + // temp hacky API + this._newTexture = null; } /** diff --git a/src/core/textures/new/CubeTexture.js b/src/core/textures/new/CubeTexture.js new file mode 100644 index 0000000..eea3526 --- /dev/null +++ b/src/core/textures/new/CubeTexture.js @@ -0,0 +1,18 @@ +import Texture from './Texture'; + +export default class CubeTexture extends Texture +{ + constructor(width, height, format) + { + super(width, height, format); + + this.isCube = true; + + //this.side1 = {_glTextures:this.glTextures, id:1}; + //this.side2 = {_glTextures:this.glTextures, id:2}; + //this.side3 = {_glTextures:this.glTextures, id:3}; + //this.side4 = {_glTextures:this.glTextures, id:4}; + //this.side5 = {_glTextures:this.glTextures, id:5}; + //this.side6 = {_glTextures:this.glTextures, id:6}; + } +} \ No newline at end of file diff --git a/src/core/textures/new/FrameBuffer.js b/src/core/textures/new/FrameBuffer.js new file mode 100644 index 0000000..004c84f --- /dev/null +++ b/src/core/textures/new/FrameBuffer.js @@ -0,0 +1,71 @@ +import Texture from './Texture' + + +export default class FrameBuffer +{ + constructor(width, height) + { + this.width = width || 100; + this.height = height || 100; + + this.stencil = false; + this.depth = false; + + this.dirtyId = 0; + + this.depthTexture = null; + this.colorTextures = []; + + this.glFrameBuffers = {}; + } + + get colorTexture() + { + return this.colorTextures[0]; + } + + addColorTexture(index, texture) + { + // TODO add some validation to the texture - same width / height etc? + this.colorTextures[index || 0] = texture || new Texture(this.width, this.height, 'rgba');// || new Texture(); + + this.dirtyId++; + + return this; + } + + addDepthTexture() + { + this.depthTexture[0] = new Texture(this.width, this.height, 'depth');// || new Texture(); + this.dirtyId++; + return this; + } + + enableDepth() + { + this.depth = true; + + this.dirtyId++; + + return this; + } + + enableStencil() + { + this.stencil = true; + + this.dirtyId++; + + return this; + } + + resize(width, height) + { + this.width = width; + this.height = height; + + this.dirtyId++; + } + + +} \ No newline at end of file diff --git a/src/core/textures/new/Texture.js b/src/core/textures/new/Texture.js new file mode 100644 index 0000000..ae8db17 --- /dev/null +++ b/src/core/textures/new/Texture.js @@ -0,0 +1,36 @@ +import TextureStyle from './TextureStyle'; + +export default class Texture +{ + constructor(width, height, format) + { + + this.style = new TextureStyle(); + + /** + * The width of texture + * + * @member {Number} + */ + this.width = width || -1; + /** + * The height of texture + * + * @member {Number} + */ + this.height = height || -1; + + /** + * The pixel format of the texture. defaults to gl.RGBA + * + * @member {Number} + */ + this.format = format;//format || gl.RGBA; + + this.data = null; + + this.glTextures = {}; + this.isCube = false; + this._new = true; + } +} \ No newline at end of file diff --git a/src/core/index.js b/src/core/index.js index 9e4f1f1..f282dd9 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -32,6 +32,9 @@ export { default as CanvasGraphicsRenderer } from './graphics/canvas/CanvasGraphicsRenderer'; export { default as Spritesheet } from './textures/Spritesheet'; export { default as Texture } from './textures/Texture'; +export { default as NewTexture } from './textures/new/Texture'; +export { default as NewFrameBuffer } from './textures/new/FrameBuffer'; +export { default as NewCubeTexture } from './textures/new/CubeTexture'; export { default as BaseTexture } from './textures/BaseTexture'; export { default as RenderTexture } from './textures/RenderTexture'; export { default as BaseRenderTexture } from './textures/BaseRenderTexture'; diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 830b382..3a70cf2 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -2,6 +2,8 @@ import MaskManager from './managers/MaskManager'; import StencilManager from './managers/StencilManager'; import FilterManager from './managers/FilterManager'; +import FramebufferManager from './managers/FramebufferManager'; +import NewTextureManager from './managers/NewTextureManager'; import RenderTarget from './utils/RenderTarget'; import ObjectRenderer from './utils/ObjectRenderer'; import TextureManager from './TextureManager'; @@ -115,6 +117,9 @@ */ this.emptyRenderer = new ObjectRenderer(this); + this.framebufferManager = new FramebufferManager(this); + this.newTextureManager = new NewTextureManager(this); + /** * The currently active ObjectRenderer. * @@ -559,7 +564,16 @@ } const gl = this.gl; - const glTexture = texture._glTextures[this.CONTEXT_UID]; + let glTexture = texture._glTextures[this.CONTEXT_UID]; + + if(texture._newTexture) + { + this.newTextureManager.bindTexture(texture._newTexture, location); + glTexture = texture._newTexture.glTextures[this.CONTEXT_UID]; + console.log("!!!") + + return; + } if (!glTexture) { diff --git a/src/core/renderers/webgl/managers/FramebufferManager.js b/src/core/renderers/webgl/managers/FramebufferManager.js new file mode 100644 index 0000000..308e959 --- /dev/null +++ b/src/core/renderers/webgl/managers/FramebufferManager.js @@ -0,0 +1,121 @@ +import WebGLManager from './WebGLManager'; +import { GLFramebuffer, GLTexture } from 'pixi-gl-core'; + +/** + * @class + * @extends PIXI.WebGLManager + * @memberof PIXI + */ +export default class FramebufferManager extends WebGLManager +{ + /** + * @param {PIXI.WebGLRenderer} renderer - The renderer this manager works for. + */ + constructor(renderer) + { + super(renderer); + } + + /** + * Sets up the renderer context and necessary buffers. + * + * @private + */ + onContextChange() + { + this.gl = this.renderer.gl; + this.CONTEXT_UID = this.renderer.CONTEXT_UID; + + this.drawBufferExtension = this.gl.getExtension('WEBGL_draw_buffers'); + } + + bindFramebuffer(framebuffer) + { + const gl = this.gl; + + if(framebuffer) + { + // TODO cacheing layer! + const fbo = framebuffer.glFrameBuffers[this.CONTEXT_UID] || this.initFramebuffer(framebuffer); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo.framebuffer); + // makesure all textures are unbound.. + + // now check for updates... + if(fbo.dirtyId !== framebuffer.dirtyId) + { + fbo.dirtyId = framebuffer.dirtyId; + + this.updateFramebuffer(framebuffer); + } + + this.renderer.newTextureManager.unbindTexture(framebuffer.colorTextures[0].glTextures[this.CONTEXT_UID]._bound) + } + else + { + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + } + } + + clearFramebuffer(r, g, b, a) + { + var gl = this.gl; + + // TODO clear color can be set only one right? + gl.clearColor(r, g, b, a); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + } + + initFramebuffer(framebuffer) + { + var fbo = GLFramebuffer.createRGBA(this.gl, framebuffer.width, framebuffer.height); + + framebuffer.glFrameBuffers[this.CONTEXT_UID] = fbo; + + console.log('framebuffer created!', fbo) + + return fbo; + } + + updateFramebuffer(framebuffer) + { + const gl = this.gl; + + const fbo = framebuffer.glFrameBuffers[this.CONTEXT_UID]; + + // bind the color texture + const colorTextures = framebuffer.colorTextures; + + let count = colorTextures.length; + + if(!this.drawBufferExtension) + { + count = Math.min(count, 1); + } + + const activeTextures = []; + + for (var i = 0; i < count; i++) + { + const texture = framebuffer.colorTextures[i]; + + this.renderer.newTextureManager.bindTexture(texture, 0); + + const glTexture = texture.glTextures[this.CONTEXT_UID]; + + activeTextures.push(gl.COLOR_ATTACHMENT0 + i); + + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i, gl.TEXTURE_2D, glTexture.texture, 0); + } + + if(this.drawBufferExtension && activeTextures.length > 1) + { + this.drawBufferExtension.drawBuffersWEBGL(activeTextures); + } + + if(framebuffer.stencil || framebuffer.depth) + { + fbo.enableStencil(); + } + } + +} \ No newline at end of file diff --git a/src/core/renderers/webgl/managers/NewTextureManager.js b/src/core/renderers/webgl/managers/NewTextureManager.js new file mode 100644 index 0000000..0b9e282 --- /dev/null +++ b/src/core/renderers/webgl/managers/NewTextureManager.js @@ -0,0 +1,132 @@ +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() + { + this.gl = this.renderer.gl; + this.CONTEXT_UID = this.renderer.CONTEXT_UID; + } + + bindTexture(texture, location) + { + const gl = this.gl; + + location = location || 0; + + gl.activeTexture(gl.TEXTURE0 + location); + + if(texture) + { + const glTexture = texture.glTextures[this.CONTEXT_UID] || this.initTexture(texture); + + if(texture.isCube) + { + gl.bindTexture(gl.TEXTURE_CUBE_MAP, glTexture.texture); + } + else + { + gl.bindTexture(gl.TEXTURE_2D, glTexture.texture); + } + + this.boundTextures[location] = texture; + } + else + { + gl.bindTexture(gl.TEXTURE_2D, null); + this.boundTextures[location] = null; + } + } + + unbindTexture(texture) + { + for (var i = 0; i < this.boundTextures.length; i++) { + + if(this.boundTextures[i] === texture) + { + gl.activeTexture(gl.TEXTURE0 + location); + gl.bindTexture(gl.TEXTURE_2D, null); + this.boundTextures[i] = null; + } + } + } + + initTexture(texture) + { + const gl = this.gl; + + var glTexture = new GLTexture(this.gl); + + if(texture.isCube) + { + gl.bindTexture(gl.TEXTURE_CUBE_MAP, glTexture.texture); + + glTexture.width = texture.width; + glTexture.height = texture.height; + + // upload the 6 faces.. + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, glTexture.format, glTexture.width, glTexture.height, 0, glTexture.format, glTexture.type, null); + + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, glTexture.format, glTexture.format, glTexture.type, window.tex1); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, glTexture.format, glTexture.format, glTexture.type, window.tex2); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, glTexture.format, glTexture.format, glTexture.type, window.tex3); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, glTexture.format, glTexture.format, glTexture.type, window.tex4); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, glTexture.format, glTexture.format, glTexture.type, window.tex5); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, glTexture.format, glTexture.format, glTexture.type, window.tex6); + + + gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + } + else + { + glTexture.uploadData(null, texture.width, texture.height); + + // settings.. + glTexture.enableNearestScaling(); + glTexture.enableWrapClamp(); + } + + + + texture.glTextures[this.CONTEXT_UID] = glTexture; + + return glTexture; + } +} \ No newline at end of file diff --git a/src/core/renderers/webgl/utils/RenderTarget.js b/src/core/renderers/webgl/utils/RenderTarget.js index 6d2467f..6c165f2 100644 --- a/src/core/renderers/webgl/utils/RenderTarget.js +++ b/src/core/renderers/webgl/utils/RenderTarget.js @@ -228,7 +228,7 @@ // TODO add a check as them may be the same! if (this.destinationFrame !== this.sourceFrame) { - gl.enable(gl.SCISSOR_TEST); +// gl.enable(gl.SCISSOR_TEST); gl.scissor( this.destinationFrame.x | 0, this.destinationFrame.y | 0, @@ -238,7 +238,7 @@ } else { - gl.disable(gl.SCISSOR_TEST); + // gl.disable(gl.SCISSOR_TEST); } // TODO - does not need to be updated all the time?? diff --git a/src/core/shader/generateUniformsSync.js b/src/core/shader/generateUniformsSync.js index a14086f..5885d7d 100644 --- a/src/core/shader/generateUniformsSync.js +++ b/src/core/shader/generateUniformsSync.js @@ -37,6 +37,7 @@ mat4: 'gl.uniformMatrix4fv(location, false, value)', sampler2D: 'uniform1i(location, value)', + samplerCube: 'uniform1i(location, value)' }; const GLSL_TO_ARRAY_SETTERS = { @@ -58,6 +59,7 @@ bvec4: 'gl.uniform4iv(location, value)', sampler2D: 'uniform1i(location, value)', + samplerCube: 'uniform1i(location, value)' }; export default function generateUniformsSync(uniformData) { diff --git a/src/core/shader/generateUniformsSync2.js b/src/core/shader/generateUniformsSync2.js index 5a1da3b..f3e46c5 100644 --- a/src/core/shader/generateUniformsSync2.js +++ b/src/core/shader/generateUniformsSync2.js @@ -37,6 +37,7 @@ mat4: 'gl.uniformMatrix4fv(location, false, value)', sampler2D: 'uniform1i(location, value)', + samplerCube: 'uniform1i(location, value)', }; const GLSL_TO_ARRAY_SETTERS = { @@ -58,11 +59,12 @@ bvec4: 'gl.uniform4iv(location, value)', sampler2D: 'uniform1i(location, value)', + samplerCube: 'uniform1i(location, value)', }; export default function generateUniformsSync2(group, uniformData) { - let textureCount = 1; + let textureCount = 0; let func = `var value = null; var cacheValue = null var gl = renderer.gl`; @@ -72,7 +74,7 @@ { const data = uniformData[i]; //group.uniforms[i]; - // console.log(i, data); + console.log(i, data); if(!data) { if(group.uniforms[i].group) @@ -94,11 +96,11 @@ gl.uniform1f(uniformData.${i}.location, uniformValues.${i}) }\n`; } - else if (data.type === 'sampler2D' && data.size === 1) + else if ( (data.type === 'sampler2D' || data.type === 'samplerCube') && data.size === 1) { func += `\nif (uniformValues.${i}.baseTexture) { - var location = renderer.bindTexture(uniformValues.${i}.baseTexture, ${textureCount++}, false); + var location = renderer.bindTexture(uniformValues.${i}.baseTexture, ${textureCount}, false); if(uniformData.${i}.value !== location) { @@ -106,14 +108,23 @@ gl.uniform1i(uniformData.${i}.location, location);\n; // eslint-disable-line max-len } } +else if(uniformValues.${i}._new) +{ + uniformData.${i}.value = ${textureCount}; + renderer.newTextureManager.bindTexture(uniformValues.${i}, ${textureCount}) + + gl.uniform1i(uniformData.${i}.location, ${textureCount});\n; // eslint-disable-line max-len + +} else { uniformData.${i}.value = ${textureCount}; renderer.boundTextures[${textureCount}] = renderer.emptyTextures[${textureCount}]; - gl.activeTexture(gl.TEXTURE0 + ${textureCount++}); + gl.activeTexture(gl.TEXTURE0 + ${textureCount}); uniformValues.${i}.bind(); }`; + textureCount++; } else if (data.type === 'mat3' && data.size === 1) { diff --git a/src/core/textures/BaseTexture.js b/src/core/textures/BaseTexture.js index aeccf39..b4b5539 100644 --- a/src/core/textures/BaseTexture.js +++ b/src/core/textures/BaseTexture.js @@ -193,9 +193,15 @@ */ this._glTextures = {}; + // 0 = color : 1 = depth : 2 = cube; + + this.type = 0; + + this._enabled = 0; this._virtalBoundId = -1; + // if no source passed don't try to load if (source) { @@ -217,6 +223,10 @@ * @event error * @memberof PIXI.BaseTexture# */ + + + // temp hacky API + this._newTexture = null; } /** diff --git a/src/core/textures/new/CubeTexture.js b/src/core/textures/new/CubeTexture.js new file mode 100644 index 0000000..eea3526 --- /dev/null +++ b/src/core/textures/new/CubeTexture.js @@ -0,0 +1,18 @@ +import Texture from './Texture'; + +export default class CubeTexture extends Texture +{ + constructor(width, height, format) + { + super(width, height, format); + + this.isCube = true; + + //this.side1 = {_glTextures:this.glTextures, id:1}; + //this.side2 = {_glTextures:this.glTextures, id:2}; + //this.side3 = {_glTextures:this.glTextures, id:3}; + //this.side4 = {_glTextures:this.glTextures, id:4}; + //this.side5 = {_glTextures:this.glTextures, id:5}; + //this.side6 = {_glTextures:this.glTextures, id:6}; + } +} \ No newline at end of file diff --git a/src/core/textures/new/FrameBuffer.js b/src/core/textures/new/FrameBuffer.js new file mode 100644 index 0000000..004c84f --- /dev/null +++ b/src/core/textures/new/FrameBuffer.js @@ -0,0 +1,71 @@ +import Texture from './Texture' + + +export default class FrameBuffer +{ + constructor(width, height) + { + this.width = width || 100; + this.height = height || 100; + + this.stencil = false; + this.depth = false; + + this.dirtyId = 0; + + this.depthTexture = null; + this.colorTextures = []; + + this.glFrameBuffers = {}; + } + + get colorTexture() + { + return this.colorTextures[0]; + } + + addColorTexture(index, texture) + { + // TODO add some validation to the texture - same width / height etc? + this.colorTextures[index || 0] = texture || new Texture(this.width, this.height, 'rgba');// || new Texture(); + + this.dirtyId++; + + return this; + } + + addDepthTexture() + { + this.depthTexture[0] = new Texture(this.width, this.height, 'depth');// || new Texture(); + this.dirtyId++; + return this; + } + + enableDepth() + { + this.depth = true; + + this.dirtyId++; + + return this; + } + + enableStencil() + { + this.stencil = true; + + this.dirtyId++; + + return this; + } + + resize(width, height) + { + this.width = width; + this.height = height; + + this.dirtyId++; + } + + +} \ No newline at end of file diff --git a/src/core/textures/new/Texture.js b/src/core/textures/new/Texture.js new file mode 100644 index 0000000..ae8db17 --- /dev/null +++ b/src/core/textures/new/Texture.js @@ -0,0 +1,36 @@ +import TextureStyle from './TextureStyle'; + +export default class Texture +{ + constructor(width, height, format) + { + + this.style = new TextureStyle(); + + /** + * The width of texture + * + * @member {Number} + */ + this.width = width || -1; + /** + * The height of texture + * + * @member {Number} + */ + this.height = height || -1; + + /** + * The pixel format of the texture. defaults to gl.RGBA + * + * @member {Number} + */ + this.format = format;//format || gl.RGBA; + + this.data = null; + + this.glTextures = {}; + this.isCube = false; + this._new = true; + } +} \ No newline at end of file diff --git a/src/core/textures/new/TextureStyle.js b/src/core/textures/new/TextureStyle.js new file mode 100644 index 0000000..9cf0567 --- /dev/null +++ b/src/core/textures/new/TextureStyle.js @@ -0,0 +1,38 @@ +import settings from '../../settings'; + + +export default class TextureStyle +{ + constructor() + { + /** + * If mipmapping was used for this texture, enable and disable with enableMipmap() + * + * @member {Boolean} + */ + this.mipmap = settings.MIPMAP_TEXTURES; + + + /** + * Set to true to enable pre-multiplied alpha + * + * @member {Boolean} + */ + this.premultiplyAlpha = false; + + /** + * [wrapMode description] + * @type {[type]} + */ + this.wrapMode = settings.WRAP_MODE; + + /** + * The scale mode to apply when scaling this texture + * + * @member {number} + * @default PIXI.settings.SCALE_MODE + * @see PIXI.SCALE_MODES + */ + this.scaleMode = settings.SCALE_MODE; + } +} \ No newline at end of file