在three.js中的后期效果和透明背景

时间:2018-05-21 08:21:45

标签: javascript three.js webgl rendering

尝试使用带有一些后期效果的透明背景,例如示例中提供的Unreal Bloom,SMAA和Tonemapping,但它似乎打破了渲染的透明度。

renderer = new THREE.WebGLRenderer({ canvas, alpha: true });
renderer.setClearColor(0xFF0000, 0);

composer = new EffectComposer(renderer);
composer.addPass(new RenderPass(scene, camera));

// Bloom pass
canvasSize = new THREE.Vector2(canvas.width, canvas.height);
pass = new UnrealBloomPass(canvasSize, strength, radius, threshhold);
composer.addPass(pass);

// SMAA pass
size = canvasSize.multiplyScalar(this.renderer.getPixelRatio());
pass = new SMAAPass(size.x, size.y);
pass.renderToScreen = true
composer.addPass(pass);

// Tonemapping
renderer.toneMappingExposure = exposure;
renderer.toneMappingWhitePoint = whitePoint;
renderer.toneMapping = type;

composer.render();

如果我停用了布鲁斯传球,我会得到正确的透明背景,但在激活时,我会获得黑色背景。我查看了源代码,看起来它应该正确处理alpha纹理通道,因为格式设置正确THREE.RGBAFormat

编辑:经过一番研究,我发现了它的来源。它来自 js \ postprocessing \ UnrealBloomPass.js中的getSeperableBlurMaterial

片段的alpha通道始终设置为1.0,这样可以在最后进行添加混合时完全删除先前的alpha值。

很酷的是找到一种在高斯模糊中应用alpha的正确方法。知道怎么样?

1 个答案:

答案 0 :(得分:0)

我找到了一个解决方案,可以这样排序: https://github.com/mrdoob/three.js/issues/14104

void main()
{
    vec2 invSize = 1.0 / texSize;
    float fSigma = float(SIGMA);
    float weightSum = gaussianPdf(0.0, fSigma);
    float alphaSum = 0.0;
    vec3 diffuseSum = texture2D(colorTexture, vUv).rgb * weightSum;
    for( int i = 1; i < KERNEL_RADIUS; i ++ )
    {
        float x = float(i);
        float weight = gaussianPdf(x, fSigma);
        vec2 uvOffset = direction * invSize * x;

        vec4 sample1 = texture2D( colorTexture, vUv + uvOffset);
        float weightAlpha = sample1.a * weight;
        diffuseSum += sample1.rgb * weightAlpha;
        alphaSum += weightAlpha;
        weightSum += weight;

        vec4 sample2 = texture2D( colorTexture, vUv - uvOffset);
        weightAlpha = sample2.a * weight;
        diffuseSum += sample2.rgb * weightAlpha;
        alphaSum += weightAlpha;
        weightSum += weight;

    }
    alphaSum /= weightSum;
    diffuseSum /= alphaSum; // Should apply discard here if alphaSum is 0
    gl_FragColor = vec4(diffuseSum.rgb, alphaSum);
}