【Unity】Multipass Rendering

帽捲
Maochinn
Published in
Sep 21, 2023

首先,這邊要做的事情非常簡單,就是將相機畫面render到一個Texture上,然後再render到遊戲畫面(Display)上,這件事情就是Multipass Rendering,也就是render兩次(Two Pass),值得注意的是這邊的Pass是圖學意義上的Pass,並非Unity中Shader的Pass,意義不太一樣。

事實上,這種作法類似於Postprocess,許多都會透過RenderTexture加上Fragment Shader來後處理畫面,但是這邊想用更加直覺,或是更加「遊戲引擎」的方式來做。

Setting the Scene

首先先設置一個簡單的Scene,裡面只有個平面

並且增加UI,這邊是增加一個Text,因為我們想要連UI一起後處理。

畫面大致設置成這樣

這是我們最終期望的畫面,類似魚眼效果的畫面

Render UI on the display

那麼,因為我們希望UI的部分也要能被後處理,所以這邊需要先將Canvas的Render Mode設定換成Camera,因為Overlay是等所有東西都畫完之後,最後將Canvas中的所有東西畫到遊戲畫面上。

然後Render Camera要選擇Main Camera,也就是會將UI畫在Main Camera的Render完的畫面上。

這時候可以先把解析度固定下來比較好解釋,這邊我設成1920x1080

Render to Texture

接下來要將畫面上的內容不直接畫到遊戲畫面(Display 1)上,而是畫到一張Texture,這種Texture叫做Render Texture,在Asset中上新增(asset/create/render texture)。

新增出來可以看到是一張全黑的Texture,這是因為目前沒有任何東西畫到它上面。

也就是說,我們要將Main Camera的Target Texture從None換成RenderTexture,也就是將Main Camera的不再輸出到Target Display,而是輸出到Render Texture

可以發現,Main Camera還是有畫面,但是遊戲畫面已經沒有東西了。

這個時候可以注意到Main Camera的畫面變成正方形,而且Text變得很大,這是因為此時Main Camera的長寬比不再是依據Display,而是依據Render Texture,Render Texture預設是256x256,我們可以把長寬設成192x108,這樣長寬比就是相同的

然後是看起來Text變大是因為,我們的Canvas因為Render Camera設成Main Camera,且Main Camera的Target Texture的長寬是192x108,所以Canvas的大小會變成192x108,但是Text的大小不受影響,因此Canvas從1920x1080變成192x108造成Text看起來變大,這邊我們先不理它。

Render a Quad

接下來,要將這張Render Texture重新畫到Display 1上,我們先創一個Quad,設一個遠一點的地方。

然後,在場景中新增一個Camera,把它放到Quad中。

接著將Camera的位置設成0,然後Clear Flag換成Solid Color,最後將Perspective Projection換成Orthographic Projection。

將將,沒有畫面!

因為我們的Quad正好在Camera的位置上,我們要將Quad放到Camera前面才看的到,或者說把Camera往後退。

退到-3就夠了,可以看到畫面上有看到Quad了。

可是Quad太小,我們希望它剛好占滿整個畫面,所以我們調整大小成192x108。

然後Camera的Size調成108/2=54,也就是從中心往上的高54,往下的高54,也就是Camera的高是108。

此時可以看到Quad剛好占滿畫面。

Render “Render Texture”

接下來,我們要將Render Texture貼到Quad上,新增一個Material,Shader選擇Unlit/Texture

然後將Base設成Render Texture

將將,我們辛苦的把Main Camera的畫面render到Display 1了。

這邊可以發現有點鋸齒是因為Render Texture的解析度太低,我們改成1920x1080。

可以發現比較沒有鋸齒了,Text既然也恢復了,因為畫Text的Canvas長寬也變回了1920x1080

Final

最後,終於可以做魚眼效果,就是把Mesh換成Sphere。

可以發現球變成很扁的樣子,因為球的長寬高是192x108x1

但是在畫面上看起來OK,只是發現Texture有點歪掉,這是因為球的正面會照到畫面中間的1/2,所以我們可以往左移0.25

看起來正常多了,但是如果你想要正常一點的效果不調整Offset,而是將Tiling.X調成2,那就不會有放大的效果,這個就不放圖了。

事實上,做這些事情大可以用寫Code的方式解決,但是我認為既然都用遊戲引擎了,了解它的設計邏輯比起直接衝下去爆改裡面的東西還更重要,另外,上述的做法還有一個優點是,我們的魚眼是透過Mesh產生,而非數學公式或是Map,這可以讓我們有可能用Mesh的變形來產生任何我們想要的後處理變形效果,這是Shader較難做到的。

最後,這是我事後重做一次的影片。

--

--