From b7eef5a000b415dd4609d1349383dcda365cb50f Mon Sep 17 00:00:00 2001 From: Mun Wai Kong Date: Mon, 14 Jan 2019 19:30:26 +0000 Subject: [PATCH] improvements for blending functions such that bleeding with background clearColor is avoided --- src/DestinationNode/destinationnode.js | 11 +++++++++-- src/ProcessingNodes/compositingnode.js | 19 ++++++++++++++++++- src/ProcessingNodes/effectnode.js | 4 ++++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/DestinationNode/destinationnode.js b/src/DestinationNode/destinationnode.js index 01ac4fc9..4cc19e09 100644 --- a/src/DestinationNode/destinationnode.js +++ b/src/DestinationNode/destinationnode.js @@ -29,11 +29,14 @@ class DestinationNode extends ProcessingNode { let gl = this._gl; gl.bindFramebuffer(gl.FRAMEBUFFER, null); - gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); - gl.enable(gl.BLEND); gl.clearColor(0, 0, 0, 0.0); // green; gl.clear(gl.COLOR_BUFFER_BIT); + // Set the initial blend function to 'proiritize' the SRC so that the background + // clearColor doesn't bleed / blend into output + gl.enable(gl.BLEND); + gl.blendFunc(gl.ONE, gl.ZERO); + this.inputs.forEach(node => { super._render(); //map the input textures input the node @@ -46,6 +49,10 @@ class DestinationNode extends ProcessingNode { } gl.drawArrays(gl.TRIANGLES, 0, 6); + + // Update the blend function to allow for 'default' blend of transparency + // of the next inputs of the node + gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); }); } } diff --git a/src/ProcessingNodes/compositingnode.js b/src/ProcessingNodes/compositingnode.js index 11692b00..0d8d3522 100644 --- a/src/ProcessingNodes/compositingnode.js +++ b/src/ProcessingNodes/compositingnode.js @@ -38,7 +38,11 @@ class CompositingNode extends ProcessingNode { ); gl.clearColor(0, 0, 0, 0); // green; gl.clear(gl.COLOR_BUFFER_BIT); - gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA); + + // Set the initial blend function to 'proiritize' the SRC so that the background + // clearColor doesn't bleed / blend into output + gl.enable(gl.BLEND); + gl.blendFunc(gl.ONE, gl.ZERO); this.inputs.forEach(node => { if (node === undefined) return; @@ -54,6 +58,19 @@ class CompositingNode extends ProcessingNode { } gl.drawArrays(gl.TRIANGLES, 0, 6); + + // Update the blend function to allow for 'default' blend of transparency + // of the next inputs of the node + gl.blendFuncSeparate( + gl.SRC_ALPHA, + gl.ONE_MINUS_SRC_ALPHA, + gl.ONE, + gl.ONE_MINUS_SRC_ALPHA + ); + // We blend RGB and Alpha separately because as you stack layers in a CompositionNode, we don’t want to interpolate alpha + // (i.e. we don’t want a mid-point or a weighted average of the alpha channels) + // Transparent things in real life don’t blend. The colors blend, but the opacity gets monotonically more opaque as things pile up + // (i.e. stack two transparent gels and the result is more opaque than either one individually) }); gl.bindFramebuffer(gl.FRAMEBUFFER, null); diff --git a/src/ProcessingNodes/effectnode.js b/src/ProcessingNodes/effectnode.js index 429bd18f..e7b2b925 100644 --- a/src/ProcessingNodes/effectnode.js +++ b/src/ProcessingNodes/effectnode.js @@ -40,6 +40,10 @@ class EffectNode extends ProcessingNode { ); gl.clearColor(0, 0, 0, 0); // green; gl.clear(gl.COLOR_BUFFER_BIT); + + // Set the initial blend function to 'proiritize' the SRC so that the background + // clearColor doesn't bleed / blend into output + gl.enable(gl.BLEND); gl.blendFunc(gl.ONE, gl.ZERO); super._render();