若是你還不知道如何在three.js中添加後期渲染通道,請先看一下官方的一個最簡單的demo : github。html
正如demo中所示的那樣,咱們的掃光效果,也是一個自定義的ShaderPass。git
因此,咱們得寫一個shader來實現想要的效果,這裏介紹一下實現的思路。github
1.在自定義通道上,先獲取場景本來的uv,而後原樣輸出;web
2.在fs裏,下降gl_FragColor的亮度(乘以小於1.0的數,這裏取0.3),這樣,畫面立馬暗了下來;composer
3.畫一條直線 y = -x;在這條直線上的部分顏色亮度爲1.0,實際上光束是有寬度的,因此咱們取一下abs(dy) < 0.1的時候亮度爲1.0,那麼光束的寬度爲0.2 * 根號2;函數
4.光束內的abs(dy),範圍是0~0.1,那麼能夠用smoothstep函數來作一個平滑插值處理,使得光束的亮度由中間向兩邊平滑過渡;post
5.添加uniform參數time實現動畫,此時直線函數變爲y = -x + time,隨着time值的變化,天然y值也會變化,最終的效果就是光束左右移動,如動圖所示;動畫
下面上shader代碼:webgl
/** * author:桔子桑 * time:2019.10.13 */ THREE.SweepingLightShader = { uniforms: { "tDiffuse": {type: "t", value: null}, "time":{type: "f", value: -1.0} }, vertexShader:` varying vec2 vUv; varying vec3 iPosition; void main(){ vUv = uv; iPosition = position; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); } `, fragmentShader:` uniform float time; uniform sampler2D tDiffuse; varying vec2 vUv; varying vec3 iPosition; void main(){ vec4 texel = texture2D(tDiffuse, vUv); float x = iPosition.x; float lighty = -x*1.2 + time; float alpha = abs(iPosition.y - lighty); if(alpha < 0.1){ float a = 1.0 - alpha / 0.1; float enda = smoothstep(0.0,1.0,a) + 0.3; gl_FragColor = texel * enda; }else{ gl_FragColor = texel * 0.3; } } ` };
爲了實現動畫,咱們須要在每次animate的時候,適當地增減這個time參數的值:spa
//掃光效果 SweepingLightShader = new THREE.ShaderPass( THREE.SweepingLightShader ); composer.addPass(SweepingLightShader);
var type = 'add'; function animate() { requestAnimationFrame( animate ); var time = SweepingLightShader.uniforms[ 'time' ].value; if(time > 1.0){ type = 'reduce' }else if(time < -1.0){ type = 'add'; } if(type =='add'){ SweepingLightShader.uniforms[ 'time' ].value += 0.01; }else{ SweepingLightShader.uniforms[ 'time' ].value -= 0.01; } composer.render(); }