http://demo.bkcore.com/threejs/webgl_tron_glow.html
glowcomposer = new THREE.EffectComposer( renderer, renderTarget );
glowcomposer.addPass( renderModelGlow ); // RenderPass
glowcomposer.addPass( hblur ); // ShaderPass
glowcomposer.addPass( vblur ); // ShaderPass
glowcomposer.addPass( effectSave ); // SavePass
glowcomposer.addPass( renderModel ); // RenderPass
glowcomposer.addPass( finalPass ); // ShaderPass
我有两个场景使用相同的对象/相机/灯光。 一种具有漫反射纹理(http://demo.bkcore.com/threejs/webgl_tron.html),一种具有发光纹理(发光区域为黑色白色)。
我的渲染管道如下:
我首先渲染发光场景并对其进行H / V模糊处理,然后使用SavePass将输出存储到frameBuffer中。
然后我要渲染漫反射场景。
最后,将其与发光帧缓冲区混合。
我的辉光采样器2D可以很好地传递给我的finalPass着色器,但是正如您在演示中所看到的那样,漫反射场景的第二个RenderPass调用效果不佳。 它仅输出黑色。
我试图在单个“渲染”通道中渲染漫反射场景,并且可以正常工作。 当我将其用作第二个RenderPass时,它不起作用。
有任何想法吗 ?
谢谢。
蒂博特D.
我认为这是因为深度缓冲区被破坏,请参阅#1017。
对于您的用例,可以使用两个作曲器(因此使用两个完全独立的渲染目标,每个目标都有自己的深度缓冲区)来代替。
像这样:
glowComposer = new THREE.EffectComposer( renderer, renderTargetGlow );
glowComposer.addPass( renderModelGlow ); // RenderPass
glowComposer.addPass( hblur ); // ShaderPass
glowComposer.addPass( vblur ); // ShaderPass
finalComposer = new THREE.EffectComposer( renderer, renderTargetFinal );
finalComposer.addPass( renderModel ); // RenderPass
finalComposer.addPass( finalPass ); // ShaderPass
现在,漫反射层将在finalComposer
作为常规的tDiffuse
纹理采样器提供,而发光层将从glowComposer
。
根据通行证的特定数量以及通行证是否切换前后缓冲区,将是glowComposer.renderTarget1
或glowComposer.renderTarget2
,最简单的方法是同时尝试这两种方法,然后看看哪个可行。
finalshader.uniforms[ 'tGlow' ].texture = glowComposer.renderTarget1;
我尝试过,但是得到了非常意外的结果。
这是您建议的代码:
http://demo.bkcore.com/threejs/webgl_tron_glow_swap.html
renderModel的tDiffuse仍为黑色。
这是完全相同的代码,只交换了两个渲染通道(漫反射场景在glow编写器中,glow场景在最终编写器中):
http://demo.bkcore.com/threejs/webgl_tron_glow_swap2.html
因为漫反射模糊而不是发光,所以这当然不是我要查找的效果,但是如您所见,tGlow和tDiffuse采样器都在工作...
我所做的就是交换(第130和175行):
新的THREE.RenderPass(场景,相机);
与
新的THREE.RenderPass(glowscene,glowcamera);
真是令人吃惊。
如果使用透明度,则需要使用RGBA
格式作为渲染目标。
好吧,我同意,但是我没有使用任何透明度,因为我的辉光通道在黑色上呈现白色,而漫反射通道在黑色上呈现良好。 然后,我将它们添加起来,因此不需要透明度。
不过,可以肯定的是,我将RT的格式更改为RGBA,但这没有任何改变。
这里的一个奇怪问题是,在我的glowscene / glowcamera RenderPass之后执行我的场景/相机RenderPass不起作用,而在我的glowscene / glowcamera RenderPass之前执行我的场景/相机RenderPass。
嗯,似乎是不同材质的几何共享问题(请参阅#1211)。
尝试这个:
function createScene( geometry, x, y, z, b ) {
zmesh = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial() );
// ...
var geometryClone = THREE.GeometryUtils.clone( geometry );
var gmat = new THREE.MeshBasicMaterial( { map: gtex } );
var gmesh = new THREE.Mesh( geometryClone, gmat );
// ...
}
是的! 就是这样
现在,我的两个采样器已正确填充。 谢谢 :)
嗯...还有另一种奇怪的行为,当我这样做时,我的两个采样器都很好
gl_FragColor = texel;
我正确地获得了扩散(http://demo.bkcore.com/threejs/webgl_tron_glow_swap2.html)
当我做
gl_FragColor = glow;
我得到正确的光芒。
但是当我尝试对两者进行简单的添加剂混合时
gl_FragColor =纹素+发光;
我只得到光晕(http://demo.bkcore.com/threejs/webgl_tron_glow_swap.html)。
很抱歉问了这么多问题,我一直在努力使它起作用,但无济于事。
实际上似乎在做
gl_FragColor = texel + glow;
关于渲染输出,看起来更像这样:
gl_FragColor = glow + glow;
就像texel vec4被发光vec4莫名其妙地取代了。 听起来很疯狂。
您需要以不同的纹理单位放置纹理:
uniforms: {
tDiffuse: { type: "t", value: 0, texture: null },
tGlow: { type: "t", value: 1, texture: null }
},
夏季!
万一有人对Three.js进行选择性发光渲染感到困惑,我刚刚发表了一篇关于它的小文章: http ://bkcore.com/blog/3d/webgl-three-js-animated-selective-glow.html
希望能帮助到你。
不错;)
另外,代替几何克隆,另一个更便宜的选择是使用更多相似的材料(这样,两次通过中的几何都需要相同的缓冲区)。
在这种情况下,您可以尝试使用零散射光(仅使用环境光)替代Lambert材料,而不是使用Basic材料进行辉光传递。
像这样:
glowScene.add( new THREE.AmbientLight( 0xffffff ) );
// ...
var gmat = new THREE.MeshLambertMaterial( { map: gtex, ambient: 0xffffff, color: 0x000000 } );
var gmesh = new THREE.Mesh( geometry, gmat );
我正在将此代码移植到r60,并奇怪地通过链接效果作曲家遇到了同一问题。 如果将其渲染到屏幕上,我可以使用Godray通行证。 但是最后一遍只输出模型。 当我不使用单独的Effect Composer时,向“ tadd”纹理通道输出的oclcomposer似乎还可以! 我已经尝试过renderer.PreserveDrawingBuffer = true,但这也不起作用。 我试过将autoclear设置为false,但这不是。
如果我在最终的作曲家之后渲染oclcomposer,并使godray通过输出到屏幕上,则可以看到Godray,但是没有模型。
如果我不将oclcomposer输出引导到最后一遍的tadd通道,而是将其通过管道传递到MeshBasicMaterial并创建带纹理的四边形并将其添加到主场景,现在我可以看到模型和Godray(在平面上),而不是我想要的效果,但它告诉我纹理管道正在工作。
// COMPOSERS
//-------------------
var renderTargetParameters = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat, stencilBufer: false };
renderTargetOcl = new THREE.WebGLRenderTarget( SCREEN_WIDTH/2, SCREEN_HEIGHT/2, renderTargetParameters );
hblur = new THREE.ShaderPass( THREE.ShaderExtras[ "horizontalBlur" ] );
vblur = new THREE.ShaderPass( THREE.ShaderExtras[ "verticalBlur" ] );
var bluriness = 2;
hblur.uniforms[ 'h' ].value = bluriness / SCREEN_WIDTH*2;
vblur.uniforms[ 'v' ].value = bluriness / SCREEN_HEIGHT*2;
var renderModel = new THREE.RenderPass( scene, camera );
var renderModelOcl = new THREE.RenderPass( oclscene, oclcamera );
grPass = new THREE.ShaderPass( THREE.Extras.Shaders.Godrays );
grPass.needsSwap = true;
grPass.renderToScreen = false;
oclcomposer = new THREE.EffectComposer( renderer, renderTargetOcl );
oclcomposer.addPass( renderModelOcl );
oclcomposer.addPass( hblur );
oclcomposer.addPass( vblur );
oclcomposer.addPass( grPass );
var finalPass = new THREE.ShaderPass( THREE.Extras.Shaders.Additive );
finalPass.needsSwap = true;
finalPass.renderToScreen = true;
finalPass.uniforms[ 'tAdd' ].texture = oclcomposer.renderTarget1;
renderTarget = new THREE.WebGLRenderTarget( SCREEN_WIDTH, SCREEN_HEIGHT, renderTargetParameters );
finalcomposer = new THREE.EffectComposer( renderer, renderTarget );
finalcomposer.addPass( renderModel );
finalcomposer.addPass( finalPass );
//RENDER
//-----------
oclcomposer.render(0.1);
finalcomposer.render( 0.1 );
@bbis是最新版本的相同问题。 你发现什么了吗
是的,我确实可以正常工作-这是代码
var renderTargetOcl = new THREE.WebGLRenderTarget( webGL_window_width/4, webGL_window_height/4, renderTargetParameters );
hblur = new THREE.ShaderPass( THREE.ShaderExtras[ "horizontalBlur" ] );
vblur = new THREE.ShaderPass( THREE.ShaderExtras[ "verticalBlur" ] );
var bluriness = 3;
hblur.uniforms[ 'h' ].value = bluriness / webGL_window_width*2;
vblur.uniforms[ 'v' ].value = bluriness / webGL_window_height*2;
var renderModel = new THREE.RenderPass( scene, camera );
var renderModelOcl = new THREE.RenderPass( g_occlusion_buffer, g_occlusion_camera );
grPass = new THREE.ShaderPass( THREE.Extras.Shaders.Godrays );
grPass.needsSwap = true;
grPass.renderToScreen = false;
g_volumetric_light_composer = new THREE.EffectComposer( webGLRenderer, renderTargetOcl );
g_volumetric_light_composer.addPass( renderModelOcl );
g_volumetric_light_composer.addPass( hblur );
g_volumetric_light_composer.addPass( vblur );
g_volumetric_light_composer.addPass( hblur );
g_volumetric_light_composer.addPass( vblur );
g_volumetric_light_composer.addPass( grPass );
var finalPass = new THREE.ShaderPass( THREE.Extras.Shaders.Additive );
finalPass.needsSwap = true;
finalPass.renderToScreen = true;
finalPass.uniforms[ 'tAdd' ].value = g_volumetric_light_composer.renderTarget1;
finalcomposer.addPass( renderModel );
finalcomposer.addPass( finalPass );
//in Render Loop
g_occlusion_camera.position = camera.position;
g_occlusion_camera.lookAt( new THREE.Vector3(0,0,0) );
camera.lookAt( new THREE.Vector3(0,0,0) );
vlight.position = pointLight1.position;
vlight.updateMatrixWorld();
var lPos = THREE.Extras.Utils.projectOnScreen(pointLight1, camera);
grPass.uniforms["fX"].value = lPos.x;
grPass.uniforms["fY"].value = lPos.y;
g_volumetric_light_composer.render(0.1);
finalcomposer.render( 0.1 );
非常感谢!
这是finalPass.uniforms[ 'tAdd' ].value
。 我之前有finalPass.uniforms[ 'tAdd' ].texture
。
嗨,bbiswas,可以在此部分添加创建g_occlusion_buffer的位置:
var renderModelOcl = new THREE.RenderPass(g_occlusion_buffer,g_occlusion_camera);
最有用的评论
似乎原始演示不再起作用:
FWIW我做了一个简化的演示,该演示选择性地应用FX并通过Additive Blend(使用Three.js v79)在此处进行合成: https ://www.airtightinteractive.com/demos/selective-fx/