用three.js構建自己的後處理渲染器第三篇---架構設計

上一篇主要討論性能問題,這一篇我們開始設計後處理渲染器架構

effectComposer ---(默認生成 sourceTarget(原場景), readBuffer(後續每一個pass的最終結果),writeBuffer(負責與readBuffer進行交換))
			---renderPass (負責渲染一遍原場景,最終渲染到sourceTarget)
			---pass1 (針對物體的後處理)
			---pass2
			...
			---screenPass1(針對屏幕的後處理)
			---screenPass2
			...

1.系統架構大概是這樣,由於我們考慮使用MSAA和FXAA兩種方式,首先需要封裝一個createRenderTarget的方法,用於動態切換WebGLRenderTarget和WebGLMultisampleRenderTarge。然後封裝setDepth方法來爲它們創建深度貼圖和深度緩衝對象。
2.爲了照顧到顯存,如果使用MSAA,我們最多隻給原圖使用WebGLMultisampleRenderTarge以及每一張scheme圖(針對物體的後處理效果中渲染物體的那張圖稱爲scheme圖)使用WebGLMultisampleRenderTarget, 其餘renderTarget儘量使用WebGLRenderTarget。同時我們要注意儘量少使用額外的renderTarget,以便減少內存多消耗。
3.renderTarget處理完後我們開始着手設計物體級的Pass
物體級的Pass的第一步是要生成一張scheme圖,如下:

 			var strategy = SchemeStrategyPool.getStrategy( this.name, schemeName);//設計一個schemeStrategy策略用於修改scheme物體的材質
            strategy.getRenderStrategy();
            renderer.materialManager.setMode(schemeName);//設置當前渲染策略
            renderer.setRenderTarget( this.schemeTargetBuffer );//綁定schemeBuffer
           renderer.clear(true, false, true);//清除顏色和模版,不清除深度。如果不考慮深度可以將深度清除
            renderer.initRenderList = false;//禁止渲染列表更新
            renderer.render(this.renderScene, this.renderCamera);
            renderer.initRenderList = true;//重新開啓渲染列表更新
            renderer.materialManager.setMode(0);//重置爲three.js默認渲染策略

strategy是當前的渲染策略,比如在渲染scheme圖的時候很多時候都需要替換成一個自定義的材質等等。
現在scheme圖到手了,但是如果設置後處理的物體過多,這一步的開銷還是比較大的,因此需要設計一個靜幀策略(如果有MRT則可以一次性把所有scheme圖和原圖渲染出來就不需要靜幀了),如

if (this._dirty) {
            this._updateSchemeBuffer(renderer, readBuffer);
            this._dirty = false;
 }

非常簡單,設計一個dirty,只有需要更新時將dirty設置爲true就行,靜止的時候我們不需要更新。
接下來就是你需要後期的代碼了,不過最後一定要切換到readBuffer,然後把結果更新過去。如果要渲染到屏幕,則拿readBuffer的結果渲染到屏幕即可。這樣每一個pass就可以串起來了。

---後期相關代碼,如outLine
renderer.setRenderTarget(this.readBuffer);
  renderer.clear();
 renderer.render(this.scene, this.camera);
  if (this.renderToScreen) {
                     this.quad.material = this.materialCopy;
                     this.copyUniforms['tDiffuse'].value = this.readBuffer.texture;
                     renderer.setRenderTarget(null);
                     renderer.clear();
                     renderer.render(this.scene, this.camera);
             }

這樣pass就設計完了。如果是全屏級的,直接跳過scheme圖的步驟,拿readBuffer的結果開始處理即可。
4.設計好最核心的pass,基本上一個簡單版的後處理渲染器就設計好了。
5.當然某些情況下你可以設計一些策略來實現高性能的多glow效果(比如在渲染的時候通過某些參數一般是顏色或者透明度來決定發光的顏色和強度等等,但是一次渲染也有它的一些小問題,總之看需求吧)。很多情況,多個不同glow效果還是需要創建多個glowpass的。下面是一些高性能一次渲染不同glow的一些例子,理論上一次渲染和創建多個glowpass的方式都要實現,這樣可以給用戶更多的選擇。
截幾個圖吧:
一次渲染多個不同內發光效果:
在這裏插入圖片描述一次渲染多種不同強度glow效果
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章