Weavermount
Weavermount

Reputation: 746

THREE.js transparency and EffectComposer

I'm trying to combine texture passes in someway that preserves the alpha channel. I've tried or assured that.

  1. Renderer has alpha set to true
  2. Renderer with many different setClearColor setting.
  3. The material on the full-screen quad used by the effect passes have transparency set to true
  4. The textures are in fact transparent
  5. The shaders I'm using for combining use the alpha channel

The textures/pass all draw properly if you comment out the others, I just can't get PNG1.png to blend over gits.jpg.

var width = window.innerWidth;
var height = window.innerHeight;
var updateFcts    = [];

var masterRenderer = new THREE.WebGLRenderer({
    alpha: true,
    autoClear: false
});
masterRenderer.setSize( window.innerWidth, window.innerHeight );
masterRenderer.setClearColor ( 0xFFFFFF, 1.0);
document.body.insertBefore( masterRenderer.domElement, document.body.firstChild);

var parameters = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat, stencilBuffer: false };
var renderTarget = new THREE.WebGLRenderTarget( width, height, parameters );
var masterComposer = new THREE.EffectComposer(masterRenderer, renderTarget);

var gitsTexture = THREE.ImageUtils.loadTexture( "images/gits.jpg" );
var pngTexture = THREE.ImageUtils.loadTexture( "images/PNG1.png" );

// declare passes
var passes = {};
passes.toScreen = new THREE.ShaderPass(THREE.CopyShader); passes.toScreen.renderToScreen = true;
passes.gitsTexturePass = new THREE.TexturePass(gitsTexture);
passes.gitsTexturePass.material.transparent = true;
passes.pngTexturePass = new THREE.TexturePass(pngTexture);
passes.pngTexturePass.material.transparent = true;

//add passes
masterComposer.addPass(passes.gitsTexturePass);
masterComposer.addPass(passes.pngTexturePass);
masterComposer.addPass(passes.toScreen);

// render the webgl

updateFcts.push(function(delta,now){
    masterComposer.render();
})


//////////////////////////////////////////////////////////////////////////////////
//      handle resize                           //
//////////////////////////////////////////////////////////////////////////////////

function onResize(){
    width = window.innerWidth;
    height = window.innerHeight;
    // notify the renderer of the size change
    masterRenderer.setSize( window.innerWidth, window.innerHeight );
    // update the camera
    camera.aspect   = window.innerWidth / window.innerHeight
    camera.updateProjectionMatrix();
    resizeFcts.forEach(function(resizeFn){resizeFn()})
}

window.addEventListener('resize', onResize, false)

//////////////////////////////////////////////////////////////////////////////////
//      loop runner                         //
//////////////////////////////////////////////////////////////////////////////////
var lastTimeMsec= null
requestAnimationFrame(function animate(nowMsec){
    // keep looping
    requestAnimationFrame( animate );
    // measure time
    lastTimeMsec    = lastTimeMsec || nowMsec-1000/60
    var deltaMsec   = Math.min(200, nowMsec - lastTimeMsec)
    lastTimeMsec    = nowMsec
    // call each update function
    updateFcts.forEach(function(updateFn){
        updateFn(deltaMsec/1000, nowMsec/1000)
    })
})

Upvotes: 1

Views: 3088

Answers (1)

Weavermount
Weavermount

Reputation: 746

Solution:

You could try { premultipliedAlpha: false } in the renderer constructor, but you will need to be careful about blending modes if you do so.

This comment handled my original issue.


I couldn't figure out exactly where my issue was. My Best guess is that when using the CopyShader, your textures get "pre-multiplied". I found a workaround to achieve the effect I was after by writing a shader that takes the multiplies the alpha back in.

    fragmentShader: [


    "uniform sampler2D tBase;",
    "uniform sampler2D tAdd;",
    "uniform float amount;",

    "varying vec2 vUv;",

    "void main() {",

        "vec4 t1 = texture2D( tBase, vUv );",
        "vec4 t2 = texture2D( tAdd, vUv );",
        "gl_FragColor = (t1 * (1.0 - t2.a))+(t2 * t2.a);",

    "}"

].join("\n")

Upvotes: 0

Related Questions