使用深度圖重構(gòu)世界空間坐標(biāo)

如果我們知道世界空間相機(jī)的坐標(biāo)庄涡,并且使用cam.depthTextureMode = DepthTextureMode.Depth;讓相機(jī)能夠得到屏幕深度圖的話胰柑,那么我們實(shí)際上就能夠用這個(gè)兩個(gè)要素在后處理中重構(gòu)出(已寫入深度緩存的)片元在世界空間中的坐標(biāo)。

不影響透明物體

動(dòng)態(tài)效果

用這樣的方法,我們可以做一個(gè)類似Projector在地表投影的效果踏堡,但是只用到了一個(gè)腳本和一個(gè)Shader醋旦。

重構(gòu)世界空間坐標(biāo)

看網(wǎng)上的教程學(xué)了一招恒水,那就是我們可以自己寫一個(gè)自定義的Blit方法,給要?jiǎng)?chuàng)建的Quad送入額外的TexCoord饲齐。我們剛才提到可以用世界空間相機(jī)坐標(biāo)和深度圖重構(gòu)片元坐標(biāo)寇窑,但是我們還需要一個(gè)方向向量:從相機(jī)原點(diǎn)到Blit中創(chuàng)建的Quad上的點(diǎn)的方向。因此箩张,我們需要在自定義的Blit方法中為要?jiǎng)?chuàng)建的Quad的頂點(diǎn)添加上方向的數(shù)據(jù)甩骏,具體計(jì)算用到cam.transform的幾個(gè)和方向有關(guān)的成員,以及相機(jī)FOV和屏幕長(zhǎng)寬比例先慷。

計(jì)算好四個(gè)頂點(diǎn)的方向向量后饮笛,使用GL.Begin(GL.QUADS)在屏幕上畫一個(gè)Quad并傳入U(xiǎn)V和方向數(shù)據(jù),經(jīng)過(guò)插值后论熙,我們便能在fragment shader中獲取每個(gè)片元正確的方向向量(注意這里不能對(duì)方向向量normalization福青,否則計(jì)算世界坐標(biāo)會(huì)出一定偏差)。以下是自定義Blit的腳本:

void CustomBlit(RenderTexture source, RenderTexture dest, Material mat)
    {
        float camFov = cam.fieldOfView;
        float camAspect = cam.aspect;
        float fovWHalf = camFov * 0.5f;

        Vector3 toRight = cam.transform.right * Mathf.Tan(fovWHalf * Mathf.Deg2Rad) * camAspect;
        Vector3 toTop = cam.transform.up * Mathf.Tan(fovWHalf * Mathf.Deg2Rad);
        Vector3 topLeft = (cam.transform.forward - toRight + toTop);
        Vector3 topRight = (cam.transform.forward + toRight + toTop);
        Vector3 bottomRight = (cam.transform.forward + toRight - toTop);
        Vector3 bottomLeft = (cam.transform.forward - toRight - toTop);

        RenderTexture.active = dest;
        mat.SetTexture("_MainTex", source);

        GL.PushMatrix();
        GL.LoadOrtho();

        mat.SetPass(0);

        GL.Begin(GL.QUADS);

        GL.MultiTexCoord2(0, 0.0f, 0.0f);
        GL.MultiTexCoord(1, bottomLeft);
        GL.Vertex3(0.0f, 0.0f, 0.0f);

        GL.MultiTexCoord2(0, 1.0f, 0.0f);
        GL.MultiTexCoord(1, bottomRight);
        GL.Vertex3(1.0f, 0.0f, 0.0f);

        GL.MultiTexCoord2(0, 1.0f, 1.0f);
        GL.MultiTexCoord(1, topRight);
        GL.Vertex3(1.0f, 1.0f, 0.0f);

        GL.MultiTexCoord2(0, 0.0f, 1.0f);
        GL.MultiTexCoord(1, topLeft);
        GL.Vertex3(0.0f, 1.0f, 0.0f);

        GL.End();
        GL.PopMatrix();
    }
}

紋理處理和Shader

紋理是網(wǎng)上隨便找了一張jpeg魔法陣脓诡,Photoshop中顏色反相后復(fù)制背景圖層到圖層2无午,用選擇顏色選擇黑色刪除留下透明部分,然后對(duì)圖層2進(jìn)行高斯模糊模擬發(fā)光效果祝谚。因?yàn)榘l(fā)光效果對(duì)圖像有一定外擴(kuò)宪迟,在開(kāi)始時(shí)要把畫布大小設(shè)置為110%。

處理前后

Shader 很簡(jiǎn)單交惯,計(jì)算得到世界空間坐標(biāo)后取xz分量和傳入的效果中心xz做計(jì)算即可得到對(duì)紋理采樣的UV次泽,我還加入了一個(gè)旋轉(zhuǎn)效果。采樣到的值用于把顏色lerp到輸入的_TintColor到白色席爽,同時(shí)也代表加性發(fā)光強(qiáng)度意荤。以下是fragment shader的代碼:

half4 frag (v2f i) : SV_Target
{
    half4 col = tex2D(_MainTex, i.uv);
    float rawDepth = tex2D(_CameraDepthTexture, i.uv_depth);
    float linearDepth = LinearEyeDepth(rawDepth);
    float3 surfacePos = _WorldSpaceCameraPos + (linearDepth * i.interpolatedRay).xyz;
    half4 effectCol = half4(0, 0, 0, 0);
    float dist = distance(surfacePos.xz, _WorldSpaceEffectPos.xz);
    float s = 0; float c = 0;
    float angle = atan2((surfacePos.x - _WorldSpaceEffectPos.x),(surfacePos.z - _WorldSpaceEffectPos.z));
    angle += _Time.x * _SpinningSpeed;
    sincos(angle, s ,c);
    float2 surfaceUV = (float2(s * dist  , c * dist) / _Radius + 1) * 0.5;
    float effectFactor = tex2D(_DetailTex, float2(surfaceUV));
    if (dist < _Radius ) effectCol = lerp(_TintColor, float4(1,1,1,1) ,effectFactor) * effectFactor;
    return col + effectCol;
}

不影響透明物體

OnRenderImage前加入[ImageEffectOpaque]屬性即可,這會(huì)讓這個(gè)后處理效果在透明物體隊(duì)列渲染開(kāi)始之前其作用只锻。

其他

類似的我們可以用這種方法做爆炸范圍指示器之類的需要改變場(chǎng)景可視物體表面的效果玖像。這里距離計(jì)算直接取的重構(gòu)坐標(biāo)的距離和爆炸中心的距離,因此實(shí)際上會(huì)有種球的效果齐饮。


不過(guò)作為爆炸指示器的話捐寥,站在掩體后應(yīng)該是不能被炸到的,如果這時(shí)候想更精確的指示爆炸沈矿,那么應(yīng)該要把掩體后的效果消除上真,而直接計(jì)算距離是達(dá)不到這種效果的咬腋。


這個(gè)暫時(shí)沒(méi)想到太好的辦法羹膳,覺(jué)得比較可行的是在中心放一個(gè)點(diǎn)光源然后讀取其陰影圖(待完成)。


Github: https://github.com/techizgit/UnityPlayground

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末根竿,一起剝皮案震驚了整個(gè)濱河市陵像,隨后出現(xiàn)的幾起案子就珠,更是在濱河造成了極大的恐慌,老刑警劉巖醒颖,帶你破解...
    沈念sama閱讀 212,454評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件妻怎,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡泞歉,警方通過(guò)查閱死者的電腦和手機(jī)逼侦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)腰耙,“玉大人榛丢,你說(shuō)我怎么就攤上這事⊥ε樱” “怎么了晰赞?”我有些...
    開(kāi)封第一講書人閱讀 157,921評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)选侨。 經(jīng)常有香客問(wèn)我掖鱼,道長(zhǎng),這世上最難降的妖魔是什么援制? 我笑而不...
    開(kāi)封第一講書人閱讀 56,648評(píng)論 1 284
  • 正文 為了忘掉前任戏挡,我火速辦了婚禮,結(jié)果婚禮上晨仑,老公的妹妹穿的比我還像新娘增拥。我一直安慰自己,他們只是感情好寻歧,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布掌栅。 她就那樣靜靜地躺著,像睡著了一般码泛。 火紅的嫁衣襯著肌膚如雪猾封。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 49,950評(píng)論 1 291
  • 那天噪珊,我揣著相機(jī)與錄音晌缘,去河邊找鬼。 笑死痢站,一個(gè)胖子當(dāng)著我的面吹牛磷箕,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播阵难,決...
    沈念sama閱讀 39,090評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼岳枷,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起空繁,我...
    開(kāi)封第一講書人閱讀 37,817評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤殿衰,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后盛泡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體闷祥,經(jīng)...
    沈念sama閱讀 44,275評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評(píng)論 2 327
  • 正文 我和宋清朗相戀三年傲诵,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了凯砍。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,724評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡拴竹,死狀恐怖果覆,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情殖熟,我是刑警寧澤局待,帶...
    沈念sama閱讀 34,409評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站菱属,受9級(jí)特大地震影響钳榨,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜纽门,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評(píng)論 3 316
  • 文/蒙蒙 一薛耻、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧赏陵,春花似錦饼齿、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,815評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至吃型,卻和暖如春证鸥,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背勤晚。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,043評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工枉层, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人赐写。 一個(gè)月前我還...
    沈念sama閱讀 46,503評(píng)論 2 361
  • 正文 我出身青樓鸟蜡,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親挺邀。 傳聞我的和親對(duì)象是個(gè)殘疾皇子揉忘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容