diff --git a/packages/core/src/framebuffer/FramebufferSystem.js b/packages/core/src/framebuffer/FramebufferSystem.js index f062025..5fa0152 100644 --- a/packages/core/src/framebuffer/FramebufferSystem.js +++ b/packages/core/src/framebuffer/FramebufferSystem.js @@ -371,7 +371,6 @@ { // you can't have both, so one should take priority if enabled gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, fbo.stencil); } - // fbo.enableStencil(); } } @@ -428,6 +427,44 @@ } /** + * Forcing creation of stencil buffer for current framebuffer, if it wasn't done before. + * Used by MaskSystem, when its time to use stencil mask for Graphics element. + * + * Its an alternative for public lazy `framebuffer.enableStencil`, in case we need stencil without rebind. + * + * @private + */ + forceStencil() + { + const framebuffer = this.current; + + if (!framebuffer) + { + return; + } + + const fbo = framebuffer.glFramebuffers[this.CONTEXT_UID]; + + if (!fbo || fbo.stencil) + { + return; + } + framebuffer.enableStencil(); + + const w = framebuffer.width; + const h = framebuffer.height; + const gl = this.gl; + const stencil = gl.createRenderbuffer(); + + gl.bindRenderbuffer(gl.RENDERBUFFER, stencil); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, w, h); + + fbo.stencil = stencil; + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, stencil); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo.framebuffer); + } + + /** * resets framebuffer stored state, binds screen framebuffer * * should be called before renderTexture reset() diff --git a/packages/core/src/framebuffer/FramebufferSystem.js b/packages/core/src/framebuffer/FramebufferSystem.js index f062025..5fa0152 100644 --- a/packages/core/src/framebuffer/FramebufferSystem.js +++ b/packages/core/src/framebuffer/FramebufferSystem.js @@ -371,7 +371,6 @@ { // you can't have both, so one should take priority if enabled gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, fbo.stencil); } - // fbo.enableStencil(); } } @@ -428,6 +427,44 @@ } /** + * Forcing creation of stencil buffer for current framebuffer, if it wasn't done before. + * Used by MaskSystem, when its time to use stencil mask for Graphics element. + * + * Its an alternative for public lazy `framebuffer.enableStencil`, in case we need stencil without rebind. + * + * @private + */ + forceStencil() + { + const framebuffer = this.current; + + if (!framebuffer) + { + return; + } + + const fbo = framebuffer.glFramebuffers[this.CONTEXT_UID]; + + if (!fbo || fbo.stencil) + { + return; + } + framebuffer.enableStencil(); + + const w = framebuffer.width; + const h = framebuffer.height; + const gl = this.gl; + const stencil = gl.createRenderbuffer(); + + gl.bindRenderbuffer(gl.RENDERBUFFER, stencil); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, w, h); + + fbo.stencil = stencil; + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, stencil); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo.framebuffer); + } + + /** * resets framebuffer stored state, binds screen framebuffer * * should be called before renderTexture reset() diff --git a/packages/core/src/mask/StencilSystem.js b/packages/core/src/mask/StencilSystem.js index 0452e31..0353c4a 100644 --- a/packages/core/src/mask/StencilSystem.js +++ b/packages/core/src/mask/StencilSystem.js @@ -60,6 +60,8 @@ if (prevMaskCount === 0) { + // force use stencil texture in current framebuffer + this.renderer.framebuffer.forceStencil(); gl.enable(gl.STENCIL_TEST); } diff --git a/packages/core/src/framebuffer/FramebufferSystem.js b/packages/core/src/framebuffer/FramebufferSystem.js index f062025..5fa0152 100644 --- a/packages/core/src/framebuffer/FramebufferSystem.js +++ b/packages/core/src/framebuffer/FramebufferSystem.js @@ -371,7 +371,6 @@ { // you can't have both, so one should take priority if enabled gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, fbo.stencil); } - // fbo.enableStencil(); } } @@ -428,6 +427,44 @@ } /** + * Forcing creation of stencil buffer for current framebuffer, if it wasn't done before. + * Used by MaskSystem, when its time to use stencil mask for Graphics element. + * + * Its an alternative for public lazy `framebuffer.enableStencil`, in case we need stencil without rebind. + * + * @private + */ + forceStencil() + { + const framebuffer = this.current; + + if (!framebuffer) + { + return; + } + + const fbo = framebuffer.glFramebuffers[this.CONTEXT_UID]; + + if (!fbo || fbo.stencil) + { + return; + } + framebuffer.enableStencil(); + + const w = framebuffer.width; + const h = framebuffer.height; + const gl = this.gl; + const stencil = gl.createRenderbuffer(); + + gl.bindRenderbuffer(gl.RENDERBUFFER, stencil); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, w, h); + + fbo.stencil = stencil; + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, stencil); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo.framebuffer); + } + + /** * resets framebuffer stored state, binds screen framebuffer * * should be called before renderTexture reset() diff --git a/packages/core/src/mask/StencilSystem.js b/packages/core/src/mask/StencilSystem.js index 0452e31..0353c4a 100644 --- a/packages/core/src/mask/StencilSystem.js +++ b/packages/core/src/mask/StencilSystem.js @@ -60,6 +60,8 @@ if (prevMaskCount === 0) { + // force use stencil texture in current framebuffer + this.renderer.framebuffer.forceStencil(); gl.enable(gl.STENCIL_TEST); } diff --git a/packages/core/src/renderTexture/BaseRenderTexture.js b/packages/core/src/renderTexture/BaseRenderTexture.js index 17666f9..23fbe55 100644 --- a/packages/core/src/renderTexture/BaseRenderTexture.js +++ b/packages/core/src/renderTexture/BaseRenderTexture.js @@ -86,8 +86,7 @@ this.clearColor = [0, 0, 0, 0]; this.framebuffer = new Framebuffer(this.width * this.resolution, this.height * this.resolution) - .addColorTexture(0, this) - .enableStencil(); + .addColorTexture(0, this); // TODO - could this be added the systems?