說到實時陰影的實現(xiàn)烟阐,一般比較容易想到使用ShadowMap,通過投射燈光空間的深度圖掷贾,并在投射物體上進行深度比較,判斷是否處于陰影的范圍荣茫,以此來渲染陰影想帅。深度圖投射到接受陰影的物體上的效果如圖所示:
你所需要做的就是在燈光空間渲染一張深度紋理,并投射到接受陰影的物體上啡莉,并和接受陰影的物體上對應像素位置的深度(燈光空間)進行比較港准,來確定當前像素是否處于陰影即可旨剥,此外還要考慮深度圖的精度以及以此會造成的ZFighting等,當然這并不是本文討論的重點浅缸。
本文主要介紹一種直接投射燈光空間攝像機的Rendertexture來實現(xiàn)陰影的方法轨帜,并將在稍后將其和projector結合。當然同時熟悉這兩項技術的開發(fā)者應該已經清楚衩椒,使用projector實現(xiàn)陰影意味著你將會消耗額外的drawcall蚌父,實際上被投射projector并且未在shader中使用"IgnoreProjector"="true"的物體都會在自身shader渲染完(也可能是渲染前,具體看自身渲染隊列和projector的shader的渲染隊列的先后順序)后再次使用projector的shader渲染一次毛萌。
首先比較一下這種技術和shadowmap技術苟弛,實際上個人感覺很大程度上兩者的技術其實差不多,都需要用到屏幕投影阁将,只不過shadowmap投射的是深度圖(深度緩沖)膏秫,而本文介紹的是直接投射屏幕紋理(幀緩沖),因此投射的紋理是帶Alpha通道的做盅,
和shadowmap不同的是,燈光空間的攝像機應該只看到投射陰影的物體:
此時投射后的效果大致如圖所示:
當然使用這種方式投射rendertexture必然造成的一個問題是言蛇,由于沒有投射接受陰影的平面僻他,導致一旦投射陰影的物體穿透接受陰影的物體時會造成陰影的穿幫:
接受陰影物體Shader主要實現(xiàn)代碼:
其中viewMatrix為燈光空間攝像機的worldToCameraMatrix,projMatrix為燈光空間攝像機的投影矩陣腊尚。
當然使用這種方式實現(xiàn)陰影的不足之處在于需要明確的知道投射陰影的物體和接受陰影的物體吨拗。
接下來將嘗試將其與Projector結合,注意之前已經討論過婿斥,使用projector意味著額外的drawcall劝篷,尤其是場景中物件很多且全部都是分離的物體時,不建議使用這種方式民宿。當然如果場景中只有極少部分物體需要接受陰影娇妓,比如只有主要地形,則不妨可以嘗試使用這種方式活鹰,因為使用projector哈恰,你可以很方便的在shader中加入IgnoreProjector標簽來忽略投影機的作用,或者直接在projector上修改projector影響的層志群。
從unity標準資源包中的projector shader我們大致可以了解着绷,projector shader中需要兩個4階矩陣,分別為_Projector和_ProjectorClip锌云,其中后者主要用于近遠裁面的淡入淡出荠医,并不是必須的。而前者的_Projector,注意這個矩陣應該區(qū)別于攝像機的projection矩陣(盡管攝像機和projector在很多參數(shù)上很相似)彬向,原因是官方的projector shader中直接通過:o.uvShadow = mul (_Projector, vertex);計算得到投影紋理坐標兼贡,這意味著_Projector矩陣應該同時實現(xiàn)將vertex轉換到世界空間,再轉換到projector的局部空間娃胆,最后轉換到projector的投影空間的功能遍希,所以其性質應該類似UNITY_MATRIX_MVP矩陣,所以使用projector實現(xiàn)投射rendertexture的效果缕棵,只需要添加一個腳本孵班,其會創(chuàng)建一個攝像機涉兽,并使用projector的參數(shù)招驴,并將這個攝像機的rendertexture傳遞給projector的material,具體實現(xiàn)如下:
其中_FadeTex是一張表示陰影衰減的貼圖枷畏,其r别厘、g通道效果如下:
這是實現(xiàn)后的陰影效果:
另外由于投射的是帶Alpha通道的Rendertexture,意味著可以方便的對其使用模糊shader完成模糊效果拥诡,這里是我自己編寫的模糊腳本效果圖: