【Unity Shader】半透明特效在RenderTexture上的顯示問題

0x00現象

下圖可見,模型的翅膀部分有黑色的矩形。

遊戲項目中,需要模型顯示在UI上,這裏採用了RenderTexture的方案,可以參考使用RenderTexture實現3D模型與UI的組合顯示

RenderCamera Background(0,0,0,0)

 

0x01尋找原因

首先查看RenderTexture的繪製是否正常

由於粒子特效常常會對alpha進行處理,加之模型不透明部分顯示沒有問題,於是查看alpha通道,有驚喜:

可以看到,翅膀的外圍還有一大一小兩個矩形,從alpha通道的情況來看,應該是介於[0, 1]之間。

最終與UI混合的圖片

我們期望的效果是翅膀的外圍(特效部分)並不需要顯示矩形。翻譯一下, 我們只想要特效alpha通道爲1的部分,並不想要特效alpha通道介於[0, 1]之間的部分。

Unity對半透明物體的渲染,依賴於Alpha Blend。

爲什麼一個物體會看起來是“半透明”的。在OpenGL中,這是通過Blending技術實現的。我們都知道一個叫“Color Buffer”的東西,這個可以理解成我們會在屏幕上看到的各種顏色。

對於不透明物體來說,經過Fragment Shader處理後的fragment會和當前在Color Buffer中的fragment進行深度比較,結果要麼覆蓋它要麼就被捨棄。

但對於半透明物體,由於它關閉了深度緩存,因此不會進行深度比較,而是通過混合係數和當前Color Buffer中的顏色進行混合,使物體看起來好像透過它看到了其他物體。

參見:【Unity Shaders】Alpha Test和Alpha Blending

問題出現在顯示的部分,顯示的問題無非就是顏色的問題,即RGBA。那麼來分析一下,從渲染特效,渲染模型,渲染到RenderTexture,其中有兩次Alpha Blend:

第一次Alpha Blend

Particle & Background ==> RenderTexture       

        Cull Off
        Lighting Off
        ZWrite Off
        Blend SrcAlpha One    // Blend 1
        ColorMask RGBA   

第二次Alpha Blend

RenderTexture & UI      ==> FinalColor

        Cull Off
        Lighting Off
        ZWrite Off
        Blend One OneMinusSrcAlpha      //Blend 2
        ColorMask RGBA

0x02 解決方案

如果想去除翅膀周圍的黑色方塊,可以在第一次Alpha Blend的時候ColorMask不輸出Alpha通道的方式。

ColorMask RGBA

修改爲

ColorMask RGB

ColorMask是什麼?

ColorMask

ColorMask RGB | A | 0 | any combination of R, G, B, A

Set color channel writing mask. Writing ColorMask 0 turns off rendering to all color channels. Default mode is writing to all channels (RGBA), but for some special effects you might want to leave certain channels unmodified, or disable color writes completely.

When using multiple render target (MRT) rendering, it is possible to set up different color masks for each render target, by adding index (0–7) at the end. For example, ColorMask RGB 3 would make render target #3 write only to RGB channels.

參見:ShaderLab: Pass

爲什麼這樣修改可以?

由於Blend One OneMinusSrcAlpha的計算方式,當輸出的alpha = 1時(ColorMask RGBA),DstColor就消失了。而當輸出的alpha = 0時(ColorMask RGB),沒有寫入alpha通道,所以alpha從camera background處獲得,取得0,會保留DstColor。

 

爲什麼ColorMask不會影響Blend?

可以看到ColorMask(Writing Masking)是在Blend之後,而寫入Framebuffer之前執行

https://www.khronos.org/opengl/wiki/Write_Mask

 

還有一種方案:

在特效後面增加一層背景,宣雨松有一篇文章介紹這種方案UGUI研究院之在UI上使用RenderTexture顯示模型+AlphaBlend特效(二十五)

 

0x03 最終效果

如圖,可見特效顯示正常,後面的背景也顯示正常。

 

參考資料

https://www.cnblogs.com/jietian331/p/10675265.html

https://blog.uwa4d.com/archives/Severe_MOBA.html

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