Esfog_UnityShader教程_遮擋描邊(原理篇)


  咳咳,有段時間沒有更新了,最近有點懶!把不少精力都放在C++身上了。閑言少敘,今天要講的可和之前的幾篇有所不同了,這次是一個次綜合應用.這篇內容中與之前不同主要體現在下面幾點上.

  1.之前我們寫的都是只用一個Shader來實現某些效果,而這次我們要使用多個Shader結合起來發揮作用。

  2.之前我們只是寫的都是純Shader代碼,沒有涉及到客戶端的C#腳本(你愛用JS也可).而這次也要使用到。

  3.這篇教程涉及到的代碼量也是之前是之前的幾倍了.

  4.總的來說之前的都是比較簡單的,而這篇就有了些難度了。

  不過不要怕,我們先講解實現的原理,因為這個教程內容比較多,所以只能抽出一篇來單獨講原理了,建議看這篇教程的同學,最好能有基本的UnityShader基礎,不妨去看看我的前幾篇教程,在后面講解代碼中我不會事無巨細的都講到,直跳比較重點的地方進行說明。

  好了進入正題,什么是遮擋描邊呢?直接上圖吧。

    

  如上圖, 在很多游戲中,特別是3D游戲中,當我們的角色被一些牆體或者其它物體擋着的時候,為了讓玩家清楚的看到角色當前身處的位置,就需要把角色被遮擋部分的外輪廓描出來(上圖中的綠色邊框)。這就是我們要實現的"遮擋描邊"。大家可以聯想一下自己玩過的游戲看看有沒有這種情況。


重要概念


   在講解具體原理之前,我們要先了解幾個比較重要的概念:

  1.后期處理:有點類似於影音方面后期處理的意思,在這里指的就是,當攝像機把當前幀渲染完畢之后,我們不是直接把圖像映射到屏幕上,而是利用我們的代碼來對原圖像進行處理,把處理后的顯示在屏幕上。游戲中非常多的效果都通過后期處理實現的,比如Bloom效果,運動模糊效果等等。我們這篇說的"遮擋描邊"也算作是后期處理。

  2.深度緩沖:對於一款3D游戲,要將三維世界里攝像機看到的部分展示到二維的屏幕上,除了要展示物體本身的顏色,還要處理物體的前后關系。而在我們的顯存里有兩個緩沖區(和具體顯卡架構有關,這里只是舉個例子)來分別用來保存游戲的畫面和物體的前后關系。我們把它們分別稱作顏色緩沖區和深度緩沖區。顏色緩沖區你可以理解為他是一個二維數組,里面的一個元素對應着屏幕的一個像素點的顏色(還會附帶一些其他信息)。深度緩沖區也可以理解為一個二維數組,里面存放着屏幕像素上每一個點所對應場景中物體上的點距離相機的距離。在渲染流程中深度緩沖非常重要的,如果沒有它,也就沒有了物體間的前后關系,我們在屏幕上看到的可能是雜亂的圖像了。

  3.深度圖:深度圖適合深度緩沖相關聯的一個概念,深度緩沖是由操作系統通過顯卡API來控制的,而我們使用引擎的時候也只能通過引擎提供的有限的API來讀寫利用深度緩沖來實現一些效果。那當我們需要利用深度緩沖來做一些特殊效果的時候就要抓狂了,別急我們可以通過制定一個相機,讓它把渲染的圖像不是顯示到屏幕上,而是顯示到一張我們設定好的二維圖片上,我們在通過我們寫的Shader來讓它把這個相機所拍攝到物體的深度信息保存到這個二維圖片(它現在就是深度圖了)上,而不是顏色信息。這樣在接下來的處理用我們就可以利用這個深度圖來做一下事情了。


原理


   有了上面的一些概念我們就來了解一下實現的原理(當然了,實現遮擋描邊的方法很多,而每一款游戲需要的效果也不盡相同,這里的方法僅供參考):

  大體上可以分四個大步驟:(下面的兩張圖片,在游戲中玩家是看不到的,開發人員也是看不到的,全部都是在代碼中處理的,這里顯示出來只是為了讓大家能更好的理解一下)

  1.獲得一共只包含我們要進行遮擋描邊處理的物體(在我們的例子中,就是上圖的那個士兵)深度信息的深度圖。對於我們的例子,這一步的結果如下圖,粗看起來是一片紅,但是大家細看右邊你會看到那個士兵的.至於為什么圖像這么偏紅,大家可以想想,我在下篇中會說明。

  

  2.通過比較判斷主攝像機(就是你在Game窗口看到的圖像所用到的攝像機)的深度信息和我們第一步中獲得到的深度圖信息,來界定出我們要處理的物體的哪些部分被擋住了。並對被遮擋全部塗上描邊顏色。如下圖

  

  3.把被遮擋部分分別進行一次左右,上下方向的拉伸一像素.這個就不用圖了基本和上面的圖一樣,只是上下左右都多了一個像素,所以看起來不明顯。

  4.最后把除了我們在第三步中額外繪制的一像素外輪廓以外,對角色的被遮擋部分還使用原來的顏色(就是牆本身的顏色)。效果就是本文一開始放的那個圖片了。


涉及到的一些API


  這樣我們就實現了遮擋描邊,不過上面只是比較籠統的概括,有很多細節需要注意。具體的代碼實現我會在下次的教程中進行具體講解,這里我先把需要設計到的一些Unity知識列出來,很多內容都可以通過Unity的官方API文檔查到,大家可以自己先了解一下然后試着實現一下遮擋描邊。這樣看下一次教程的時候會效果更好:

  1.在Unity進行后處理需要涉及到的一些API,有 OnRenderImage(...),RenderTexture.GetTemporary,RenderTexture.ReleaseTemporary,Graphics.Blit,RenderWithShader.

  2.在C#腳本中對Shader進行傳值設計到的一些API,如Shader.SetGlobalXXX(),Shader.Find,Material.SetXXX().

  3.相機的深度模式,和Unity提供給我們的一個默認深度圖.Camera.depthTextureMode,_CameraDepthTexture等.

 

  好了關於遮擋描邊的原理篇基本就講完了,怎么樣是不是和之前幾篇的內容有很多不同,這篇內容也只是做了一個拋磚引玉,只是希望大家能了解一下渲染中的幾個重要概念,然后自己去做一些擴展,比如說深度緩沖和深度圖,他們兩個能夠實現的效果遠遠不只是"遮擋描邊"。更多神奇的功能還等待大家自己一起去探索。另外我會在近期完成"實現篇"的,這段時間大家不妨自己動手試着寫寫看,沒准在我發下一篇之前,聰明的你啊已經搞定了呢!!!

 

  尊重他人智慧成果,歡迎轉載,請注明作者esfog,原文地址 http://www.cnblogs.com/Esfog/p/CoverOutline_Shader.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM