使用three.js,我想对单个场景应用单独的后处理效果,然后将所有这些场景组合成最终渲染.为了做到这一点,我使用的是3.js Effects Composer.
const radialBlurShader = { uniforms: { "tDiffuse": { value: null },},vertexShader: ` varying vec2 vUv; void main() { vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0); } `,fragmentShader: ` uniform sampler2D tDiffuse; varying vec2 vUv; const float strength = 0.7; const int samples = 50; void main() { vec4 col = vec4(0); vec2 dir = vec2(0.5) - vUv; for (int i = 0; i < samples; i++) { float amount = strength * float(i) / float(samples); vec4 sample = texture2D(tDiffuse,vUv + dir * amount) + texture2D(tDiffuse,vUv - dir * amount); col += sample; } gl_FragColor = 0.5 * col / float(samples); } ` }; const renderWidth = window.innerWidth; const renderHeight = window.innerHeight; const renderer = new THREE.WebGLRenderer({ antialias: true,}); renderer.setSize(renderWidth,renderHeight); document.body.appendChild(renderer.domElement); const camera = new THREE.PerspectiveCamera(45,renderWidth / renderHeight,0.1,1000); camera.position.z = 10; var geometry = new THREE.PlaneGeometry(1,1); var material = new THREE.MeshBasicMaterial({ color: 0x0000ff,transparent: true }); function makeEC(scene) { const ec = new THREE.EffectComposer(renderer); const rp = new THREE.RenderPass(scene,camera); const sp = new THREE.ShaderPass(radialBlurShader); rp.clearColor = 0xffffff; rp.clearAlpha = 0; sp.renderToScreen = true; sp.material.transparent = true; sp.material.blending = THREE.CustomBlending; ec.addPass(rp); ec.addPass(sp); return ec; } const scene1 = new THREE.Scene(); const mesh1 = new THREE.Mesh(geometry,material); mesh1.position.x = 2; scene1.add(mesh1); ec1 = makeEC(scene1); const scene2 = new THREE.Scene(); const mesh2 = new THREE.Mesh(geometry,material); mesh2.position.x = -2; scene2.add(mesh2); ec2 = makeEC(scene2); renderer.setClearColor(0xffffaa,1); renderer.autoClear = false; renderer.clear(); ec1.render(); ec2.render();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r82/three.js"></script> <script src="https://rawgit.com/mrdoob/three.js/r82/examples/js/shaders/CopyShader.js"></script> <script src="https://rawgit.com/mrdoob/three.js/r82/examples/js/postprocessing/EffectComposer.js"></script> <script src="https://rawgit.com/mrdoob/three.js/r82/examples/js/postprocessing/RenderPass.js"></script> <script src="https://rawgit.com/mrdoob/three.js/r82/examples/js/postprocessing/ShaderPass.js"></script>
我为每一个后处理着色器我想申请一个独立的影响作曲家实例. (在本例中,我使用相同的径向模糊着色两次为简单起见).
function makeEC(scene) { const ec = new THREE.EffectComposer(renderer); const rp = new THREE.RenderPass(scene,camera); const sp = new THREE.ShaderPass(radialBlurShader); rp.clearColor = 0xffffff; rp.clearAlpha = 0; sp.renderToScreen = true; sp.material.transparent = true; // defaults to SRC_ALPHA,ONE_MINUS_SRC_ALPHA sp.material.blending = THREE.CustomBlending; ec.addPass(rp); ec.addPass(sp); return ec; } const ec1 = makeEC(scene1); const ec2 = makeEC(scene2);
如你所见,我将渲染通知清除为透明背景.然后,着色器传递将使用典型的SRC_ALPHA,ONE_MINUS_SRC_ALPHA混合来绘制到renderbuffer.
我的渲染代码看起来像这样
renderer.setClearColor(0xffffaa,1); renderer.autoClear = false; renderer.clear(); ec1.render(); ec2.render();
然而,这个过程并不能正确地混合这些层
这是我得到的
混合前首先(正确)
混合前二次(正确)
两个通过混合如所述(不正确)
太暗了
prefultipliedAlpha disabled(不正确)
太透明了
当两层混合在一起时,为什么方格太暗?
为什么平方太透明了的时候premultipliedAlpha被禁用?
如何将两层混合在一起,使它们看起来与混合前相同?