(本文章纯原创,转载请标注)
先上效果图
这里用的是three的后效EffectComposer,材质用的是UnrealBloomPass。
正常使用后效的代码如下:
var renderPass = new RenderPass( scene, camera );
var bloomPass = new UnrealBloomPass( new THREE.Vector2( window.innerWidth, window.innerHeight), 1.5, 0.4, 0.85 );
var composer = new EffectComposer( renderer);
composer.addPass( renderPass );
composer.addPass( bloomPass );
然后每帧调用composer.render();
这时候会整个场景都发光,效果图如下:
如果想要做到部分发光怎么办呢?
我搜了网上其他人的代码,比如我想让鞋带单独发光
代码如下:
model_.traverse(function(obj)
{
if(obj.isMesh)
obj.layers.set(1);
});
xiedai.layers.set(0);
其实就是把鞋带的层级设为0, 其他都设为1
render()中在composer.render();前后添加:
renderer.clear();
camera.layers.set(0);
composer.render();
render.clearDepth();
camera.layers.set(1);
renderer.render(scene, camera);
效果图如下
我们发现鞋带没了。。。。
真的没了吗?
我换了个角度看
鞋带其实是在的,而且正常发光,只不过three后效的layer被原场景挡住了
而且还有个很坑的问题,就是three的后效只有layer为0的时候才会生效,其他层都不会显示。
那该怎么办呢?
于是我想了个办法,让后效按照我的顺序渲染,所以就把UnrealBloomPass.js的render改了一下
具体做法如下:
先注掉外部render()中的这三行代码
// renderer.clearDepth();
// camera.layers.set(1);
//renderer.render(scene, camera);
首先解决只有layer为0才有后效的问题,只要改一行代码即可
找到fsQuad的定义,也就是this.fsQuad = new FullScreenQuad( null );这行代码
在下面加上this.fsQuad._mesh.layers.enableAll();
其实就是后效没有在所有层级上生效导致的
我们再解决后效渲染问题
首先改一下UnrealBloomPass的构造函数,添加两个参数 scene和camera
再添加到this属性中,这个后面要用到
class UnrealBloomPass extends Pass {
constructor( resolution, strength, radius, threshold, scene, camera ) {
super();
this.renderScene = scene;
this.renderCamera = camera;
this.strength = ( strength !== undefined ) ? strength : 1;
定义UnrealBloomPass的时候要做相应的修改,把scene和camera传入
var bloomPass = new UnrealBloomPass( new THREE.Vector2( window.innerWidth, window.innerHeight), 1.5, 0.4, 0.85, scene, camera );
然后到UnrealBloomPass.js中的render()中
有两个if ( this.renderToScreen )这样的判断
我们就修改这两个地方
第一个判断中注释掉这行
//this.fsQuad.render( renderer );
在下面添加代码
renderer.render( this.renderScene, this.renderCamera );
第二个判断
if和else中都注释掉
//this.fsQuad.render( renderer );
然后在判断外部添加
this.renderCamera.layers.set(1);
renderer.render( this.renderScene, this.renderCamera );
this.fsQuad.render( renderer );
这样就改好了 效果图如下
这样就实现了局部发光,但是随即我有发现了个问题
就是透明材质会和背景混合
比如我的字体的背景就是透明的 跟黑色的背景混合了,如下图:
字体虽然发光了,但是黑色背景挡住了模型,我能想到的办法就是专门用一个层级去跟透明材质混合,所以我又进行了如下处理:
把字体背景挡住的材质放到一个新的层级
houpian.layers.set(2);
回到UnrealBloomPass的render(),在第一个上述renderToScreen的判断中添加代码:
this.renderCamera.layers.set(2);
就可以得到开头的效果图了
不过以上所有的做法都没有封装性,希望three官方能考虑到多个层级需要单独后效的问题
完事
cslg.panda
2021.6.22