激情六月丁香婷婷|亚洲色图AV二区|丝袜AV日韩AV|久草视频在线分类|伊人九九精品视频|国产精品一级电影|久草视频在线99|在线看的av网址|伊人99精品无码|午夜无码视频在线

高校合作1:010-59833514 ?咨詢電話:400-810-1418 服務(wù)與監(jiān)督電話:400-810-1418轉(zhuǎn)接2

「游戲開發(fā)」游戲后期特效 2:相交高亮(掃描效果)

發(fā)布時間:2024-01-16 14:02:24 瀏覽量:168次

關(guān)注“indienova”,挖掘獨立游戲的更多樂趣

1介紹

大萌喵現(xiàn)在還只是學(xué)生黨一枚, 對圖形學(xué)和渲染技術(shù)的理解依然比較膚淺, 如果文章中有不明確甚至出錯的地方, 煩請前輩們斧正啦~

OK, 我們進入Warming Up環(huán)節(jié)。

2相交高亮(Intersection Highlight)是個啥

相交高亮, 是一種附加在Mesh上的著色器特效, 其功能是將所有其他穿過該Mesh表面的截面輪廓繪制出來, 產(chǎn)生一種類似于掃描一樣的效果。 多用于科幻類游戲中。

在這里大萌喵要檢討下 ... 這種相交高亮的特效出現(xiàn)的頻次真心不低, 我能確切想起來的實際應(yīng)用游戲便有殺戮地帶系列,質(zhì)量效應(yīng)系列,泰坦隕落系列和死亡空間系列. 不過大萌喵在youtube上找了好幾圈也沒有找到一個包含了這個效果的視頻 ... 所以說只能貼上這張圖啦.。(喵, 下次玩游戲要邊玩邊截圖了哈哈哈哈)

3所以說我們要干啥?

根據(jù)攝像機的CameraDepthTexture(深度紋理? 不知道這么翻譯對不對)繪制相交區(qū)域的高亮顏色。

4想看懂這篇文章, 我得知道啥?

對著色器的混合模式, 深度測試, 點元著色器和片元著色器有一定了解. 寫作過程中我也會貼上一些可供查閱的資料。

我順帶著也打算講解下一個坐標轉(zhuǎn)換的原理, 如果想要看懂的話需要一定的線性代數(shù)基礎(chǔ)。

5看完了這篇文章, 我能得到啥?

你會知道一種優(yōu)雅地使用DepthBuffer的方法。

以及, 說好的源代碼。

大萌喵.不正常模式.SetStatus(false);

大萌喵.SetFace (Face.嚴肅臉);

6相交高亮著色器工作原理

獲取當前攝像機渲染的場景的DepthBuffer, 在渲染當前模型的時候判斷每一個經(jīng)過坐標變換的片元的世界坐標Z是否和DepthBuffer的對應(yīng)點深度足夠接近. 如果足夠接近, 則將其渲染成另一種顏色.

7首先, 假設(shè)我們什么都不知道

還是那個熟悉的水壺, 只不過加上了一臺優(yōu)雅的Macbook(不過為毛那個桌面長得有點像OpenSUSE)和一個凌空飛舞放蕩不羈的鍵盤。當然了這不關(guān)鍵, 關(guān)鍵的是后面的那個黃色的正方體

我們要實現(xiàn)的就是那個正方體的材質(zhì). 從圖中我們清楚的看到, 水壺, 電腦和鍵盤在正方體外面的部分是非常正常的, 在正方體內(nèi)部的部分蒙上了一層黃色。 但是和正方體的相交截面的外輪廓被繪制成了藍顏色。

到此, 我們能夠推斷出來的事實有:

  1. Blend Mode為: Blend SrcAlpha OneMinusSrcAlpha 原因很簡單, 因為我們能夠通過正方體看到其后面的物體, 這說明正方體本身的顏色和原本的ColorBuffer的Alpha值被"平分秋色"后進行了混合。 依然看不懂的童鞋請參見Unity官方文檔(http://link.zhihu.com/?target=
    https%3A//docs.unity3d.com/Manual/SL-Blend.html).

  2. RenderQueue為Transparent 很明顯, 我們當然是希望這個正方體在Geometry后渲染出來, 這樣才能透過它看到優(yōu)先渲染的Opaque Materials. 關(guān)于Render Order的詳細描述可以看Unity官方文檔(http://link.zhihu.com/?target=
    https%3A//docs.unity3d.com/462/Documentation/Manual/SL-SubshaderTags.html)。

  3. 正因為我們的正方體是被后渲染出來的, 所以我們可以通過當前的ColorBuffer或者是DepthBuffer等資源來以某種方式處理相交截面。


但是不管截面到底是怎么被處理出來的, 我們必須得知道屏幕上某點的世界坐標相對于正方體某個片元的世界坐標的相對關(guān)系。

很明顯, 我們要做的就是優(yōu)雅地解決第四個問題。

8如何優(yōu)雅地比較坐標

可以通過DepthBuffer, 攝像機Near Clip Plane, Far Clip Plane, Field of View來計算出屏幕上每一個點的世界坐標, 但是傳統(tǒng)的在片元著色器中計算世界坐標的方式是處理后依次乘以世界-視圖矩陣的逆, 效率堪憂。 就算利用點元著色器預(yù)先計算視椎體射線, 效率有了些許提升, 也遠遠達不到"優(yōu)雅"的水準。

(PS: 我會在后面的文章中詳細介紹Global Fog后期處理特效, 其中會對在片元著色器中通過DepthBuffer計算世界坐標的方法展開討論。 )

說了這么多, 我們發(fā)現(xiàn)直接求世界坐標這種套路最直接, 最好理解, 但似乎并不太可取. 那么我們就要思考一個問題: 我們真的必須得知道具體的世界坐標嘛?

通過觀察上面的那張圖, 我們發(fā)現(xiàn)為了確定如何渲染并混合顏色, 我們只需要知道相對于攝像機來講, 正方體的片元和原本場景中對應(yīng)位置的像素誰離得更遠就行了。 也就是說, 我們只需要知道兩個三維向量的長度, 也就是兩個實數(shù), 而并不需要知道這兩個三維向量的xyz都分別是什么。

所以說, 求世界坐標的話有點兒殺雞用牛刀了。

8如何獲取一個片元所在屏幕位置的DepthBuffer

如果你不知道DepthBuffer, 或者是Unity的CameraDepthTexture, 那么強烈建議你谷歌下, 要不然接下來的東東就都GG了。

我們是如何知道一個片元的投影坐標的呢? 恐怕下面這段代碼你都看爛了:

o.pos = mul ( UNITY_MATRIX_MVP, v.vertex );

我甚至不用說出o和v的變量聲明以及這段代碼出自何處, 你就知道我在說什么了。 (語氣頗像 ... 額, 專欄還是要辦下去的, 打住)

所以說我們要怎么通過世界坐標來將其xy映射到[0, 1]區(qū)間呢? 畢竟只有這樣我們才能采樣DepthBuffer啊! 不用擔心, Unity都替我們做好了: 在UnityCG.cginc中, 有這么個函數(shù):

當然了并不是要調(diào)用它, 而是要使用ComputeScreenPos函數(shù):

吶, 帶著編譯器指令原封不動地搬過來, 大家看起來肯定有點方. 其實大多數(shù)情況下, ComputeScreenPos函數(shù)可以重寫成以下形式:

傳入Clip Space坐標pos, 最終輸出xy在[0, 1]之間, z值為Camera Space深度的結(jié)果。

不過 ... 這個函數(shù)什么鬼 ... 拿到了Clip Space坐標先乘個0.5 ... 然后 ... 還要加上w分量的二分之一?

大萌喵接下來打算稍微介紹下這個函數(shù)的原理. 如果你之前對坐標轉(zhuǎn)換不是很了解, 大萌喵提供了幾個鏈接, 可供參考:

learnOpenGL(神啟蒙教程):

http://link.zhihu.com/?target=http%3A//learnopengl.com/%23%21Getting-started/Coordinate-Systems

scratchapixel.com :

http://link.zhihu.com/?target=http%3A//www.scratchapixel.com/lessons/3d-basic-rendering/perspective-and-orthographic-projection-matrix/projection-matrix-GPU-rendering-pipeline-clipping

神書:

http://link.zhihu.com/?target=https%3A//books.google.co.uk/books%3Fid%3DmNw_CQAAQBAJ%26pg%3DPA14%26dq%3Dhomogeneous%2Bcoordinate%2Bin%2Bthe%2Bfixed-function%2Bpipeline%26hl%3Den%26sa%3DX%26ved%3D0ahUKEwiE7-rk8crJAhUDPhQKHSzSCJQQ6AEIIzAA%23v%3Donepage%26q%3Dhomogeneous%2520coordinate%2520in%2520the%2520fixed-function%2520pipeline%26f%3Dfalse

如果你覺得Math = Mental Abuse To Human(對人類的精神侮辱), 那暫時略過也無所謂。 ComputeScreenPos當成黑盒子使用也沒什么問題。

10如無需要可略過

首先上一張圖:

在Unity中,mul ( UNITY_MATRIX_MVP, v.vertex )和UnityObjectToClipPos(float4 ( v.vertex.xyz, 1.0 ) )干的差不多都是一回事兒, 就是將模型坐標轉(zhuǎn)換到攝像機的Homogeneous Clip Space. 詳情參加官方文檔(http://link.zhihu.com/?target=
https%3A//docs.unity3d.com/Manual/SL-BuiltinFunctions.html)。

但是, 一般渲染管線不會立刻將Clip后的坐標標準化(也就是除以w分量. 不知道w分量代表什么的童鞋 ... 請先補課), 而是在點元著色函數(shù)結(jié)束以后將其標準化. 這個地方有點坑.

(原文摘錄如下: Once all the vertices are transformed to clip space a final operation called perspective division is performed where we divide the x, y and z components of the position vectors by the vector's homogeneous w component; perspective division is what transforms the 4D clip space coordinates to 3D normalized device coordinates. This step is performed automatically at the end of each vertex shader run.)

所以, 可以認為我們現(xiàn)在得到的是已經(jīng)經(jīng)過Clipping, 但是還沒有標準化的投影坐標. 我們的目的是要將這個坐標轉(zhuǎn)化為xy在[0, 1]之間, 而z反映深度的屏幕坐標.

既然是[0, 1]之間, 那么我們自然就不用向上圖一樣乘以ViewPort寬高了. 同時要注意ViewPort坐標原點的問題: Unity中是左下角, 而上圖采用的是左上角. 所以具體到我們的情況下y和x的處理方式應(yīng)該是相同的.

為了將[-1, 1]映射到[0, 1]上, 將原坐標加1然后除2是顯而易見的. 但是要注意我們的x和y都比人家多乘著一個w分量. 因為運算到這個時候我們依然在點元著色器函數(shù)中, 因此最終的標準化過程還沒有執(zhí)行.

所以, 我們就得到了下面這段代碼(其實也是上面那段)

float4 o = pos * 0.5;

o.xy = float2(o.x, o.y*_ProjectionParams.x) + o.w;

如果沒想清楚是怎么轉(zhuǎn)過這個彎來的 ... 對比上圖倒數(shù)第二個框框和上面的文字就OK了.

11千呼萬喚始出來的點元著色器函數(shù)

(如果我不是手賤翻了下ComputeScreenPos的源代碼, 也就沒這么多麻煩事兒了哈哈哈)

12實際上非常簡單的片元著色器函數(shù)

在片元著色器中, 我們只需要提取出對應(yīng)屏幕位置的深度信息, 然后和點元著色器的輸出深度信息作比較, 根據(jù)相差結(jié)果進行插值即可.

不知道那個插值是怎么回事兒的童鞋, 請動用C語言的思考模式, 寫個if出來, 然后想辦法消除掉這個if.

雖然話說回來就算這有個if也不算動態(tài)分支, 對性能的影響不太大 ... 但還是養(yǎng)成良好的習慣吧.

13最終成果(其實一般再加上個Texture糊到Quad上實現(xiàn)掃描的特效)

14后記

其實這個特效的原理真心一點也不復(fù)雜, 只是用到了DepthTexture來獲取屏幕中每個像素的深度信息來進行比對以決定模型最終的顏色. 但是UnityCG.cginc里面的ComputeScreenPos函數(shù)那個奇怪的外觀引發(fā)了我極大的好奇心.

15FIN

大萌喵是個學(xué)生黨, 非常熱切地希望能和諸位前輩們交流! 如果文章中存在任何疏漏, 不足, 或錯誤之處, 希望您能批評指正! 謝謝!

Preview: 大萌喵最近對DepthTexture有點著迷呀, 下幾次打算講講Global Fog, Volumetric Light Scattering和Edge Detection. 不過中間也會夾雜一些小的好玩兒的著色器效果 ~

想了解更多?請點擊下方

閱讀原文

熱門課程推薦

熱門資訊

請綁定手機號

x

同學(xué)您好!

您已成功報名0元試學(xué)活動,老師會在第一時間與您取得聯(lián)系,請保持電話暢通!
確定