軟件:Unity?2022.3.51f1c1、vscode、Meta XR All in One SDK V72
硬件:Meta Quest3
僅針對urp管線
參考了YY老師這篇,可以先看他的再看這個可能更好理解一些:Unity Meta Quest MR 開發(七):使用 Stencil Test 模板測試制作可以在虛擬與現實之間穿梭的 MR 傳送門_unitymr-CSDN博客
他這篇只講了怎么在現實開虛擬世界的門,我的游戲需要有透視“裂縫”,所以研究了一下怎么在虛擬世界打開能被虛擬物體遮擋的透視窗口(building block里面已有的surface projected passthrough并沒有遮擋關系)
我的大概思路就是把他的邏輯不完全地反過來吧,要在虛擬世界開透視世界的洞,又不能像surface projected passthrough一樣讓它浮在最前方,那么只能讓透視世界作為最底層的背景層,只讓指定物體(下文稱為crack)可以顯示出最底層,并讓指定物體正常參與深度測試。
博主對渲染完全不熟,胡亂嘗試中摸出了想要的結果,我盡可能去理解解釋原理,可能有誤,不要完全相信我講的,希望渲染大佬指正。
一、使用BuildingBlock配置全局透視
刪除原有場景的mainCamera將以下兩個模塊拖入場景
原理解釋:打開passthrough物體找到下面這個組件,可以看到設置的placement是underlay,表明該透視圖層會放置在虛擬下方
那么這種情況下,如果場景中還有天空盒的話,透視圖層則無法顯示(因為透視圖層在最下層)
而meta在自動配置中給出的辦法則是讓攝像機忽略天空盒
點開BackGround可以看到它將背景顏色設為了透明
二、設置虛擬世界天空盒
要知道,我們現在可是想在虛擬世界開一個透視世界的洞,虛擬世界怎么能沒有天空呢
建一個巨大球體給上需要的天空盒材質即可
將該球體的Layer設置為Background層級(很關鍵)
三、新建一個模板Shader和材質并將其賦給需要透視的物體crack
先解釋一下模板測試
每個像素都有一個“模板值”(存在Stencil Buffer模板緩沖區里,默認保存的值是 0)。
你設置一個測試條件(比如:只有模板值 != 1 的地方才畫)。
Unity 會檢查每個像素的模板值是否滿足這個條件。
滿足 → 可以渲染。
不滿足 → 這個像素就被“擋住”,不渲染。
而下面這個shader的作用是更新它自身的模板值為我們手動設定的StencilID
Shader "Examples/Stencil"
{Properties{[IntRange] _StencilID ("Stencil ID", Range(0, 255)) = 0}SubShader{Tags { "RenderType" = "Opaque"//告訴Unity這個是“不透明”物體"Queue" = "Geometry"//設置渲染隊列(在透明物體之前渲染)"RenderPipeline" = "UniversalPipeline"//指定這個 Shader 適用于 URP}Pass{Blend Zero One//不畫任何東西(顏色乘以0),因為只想用這個 Pass 來設置模板值,不是真的畫圖。//ZWrite Off //不寫入深度,不參與深度測試,一定要畫上去Stencil{Ref [_StencilID]// 要寫入的模板值Comp Always// 總是通過測試Pass Replace// 測試通過時把模板值替換為 _StencilIDFail Keep//如果測試失敗 → 保持原值(雖然這里總是通過)}}}
}
這就是YY老師給的Shader代碼,我唯一改的是注釋掉了不寫入深度,因為我們需要讓掛有此材質的crack物體與背景以外的其他物體有正常的遮擋關系。
創建一個材質,shader選擇為Stencil,模板值設置為1,將材質賦給需要透視的物體
給上去以后發現是這種不可見的效果
因為我們還沒有在管線里打開模板測試,現在這個shader所做的只是更改了自身的模板值,然后什么也不畫。
四、配置URP管線
1.在quality里找到自己正在使用的渲染管線
2.找到Render Pipeline Asset里正在使用的Renderer,復制一份后修改名字替換給它(也可以不復制直接改,我這里為了備份一下才復制了個新的)
3.配置Renderer Data
Unity - Manual: Universal Renderer asset reference for URP
Filtering里移除天空盒所在的Background層級,即在主渲染流程中不渲染該層
在此Renderer Data中添加一個RendererFeature(渲染器功能),配置如下
Unity - Manual: Render Objects Renderer Feature reference for URP
Unity - Manual: Stencil command in ShaderLab reference
各個配置的意思大家翻unity文檔吧,這里只解釋作用還有一個比較容易誤會的點
作用:它相當于為此渲染器添加了一個功能,在渲染完不透明物體以后,再渲染Background層級的物體,并針對該層級開啟模板測試,只讓該層級下模板值!=1的物體通過模板測試,也就是說,有crack在的屏幕像素點都無法通過模板測試就會形成下面的效果。
易錯點:pass keep和fail keep的意思是有沒有通過模板測試都會保留該位置模板值,不是保留像素點顏色
這時候應該會有同學和我有一樣的疑惑吧,為什么在crack前面的物體就正常渲染出來了,而天空盒就這樣被摳了一個洞呢?
因為crack的層級不是Background,所以,它自身并沒有參與模板測試,它所做的只是為需要模板測試的Background層級提供了一個模板值。它自己是位于正常的層級關系里,當然會和其他物體一樣具有遮擋關系
好了這就完成啦,串流上頭盔就能看見透視場景咯。
我不知道沒學過渲染的同學是不是覺得我說得很有道理。希望大家可以照著步驟做但是不要全信我講的原理,因為我是根據現象推的結論,而這一切結論都被我將管線設置為對所有層級進行模板測試,只讓不等于1的模板值通過測試后出現的效果推翻了哈哈哈。按理來說應該會和之前的效果一致啊,怎么會無效呢,到底為什么呢,是順序出錯了嗎,有沒有大佬跟我講一下為什么
2025.4.17
測試發現這種配置方法和Lit材質里開了alpha clipping的材質不兼容,會出現詭異的透視效果,目前沒找到解決辦法,直接解決問題的來源了哈(不用alpha clipping)