Unity移動端動態陰影總結
以此國際象棋屋為例,屋子中間放置一個Reflect probe來拍攝周圍環境,只用了Cubemap的RGB通道,而周圍環境的Alpha其實也代表了光是穿透了窗戶還是被牆壁遮擋,那就可以利用Cubemap剩餘的Alpha通道就可以來存儲光和周圍環境的遮擋情況,Alpha通道圖如下:
V – 頂點坐標
L – vertex-to-light向量,已normalized 輸出參數:Lp – 校準後的vertex-to-light向量,作為UV去採樣Cubemap校準過程:先利用線和包圍盒求交點,從包圍盒位置到交點的向量就是Lp,然後利用Lp去採樣Cubemap用於著色。
另外背面要特殊處理下,防止陰影穿透問題。
2.軟陰影:
陰影平滑的過程比較有趣,首先Cubemap過濾方式選擇tri-linear filtering,然後計算vertex-to-intersection-point(頂點到交點)向量的長度,然後乘以外部傳入係數:
為了平滑陰影,我們用texCUBElod 去採樣Cubemap,其中UV的XYZ來自Lp,W來自vertex-to-intersection-point(頂點到交點)的距離。
下圖也可以看到離窗戶越遠處的陰影越模糊。
這種做陰影方法的限制是比較適合室內環境、點光源位置不變、內部有移動物體的情況。
二、地面雲陰影對於地面上雲陰影,用實時燈光照射出陰影顯然是不划算,可以直接在地面shader中混合一個運動的雲圖就能達到類似效果。對於樹、草、旗子這類位置不變但有搖曳動畫的物體,可以預先把陰影烘焙到貼圖中,然後把陰影圖作為單獨貼圖、或地面貼圖Alpha通道傳送到地面shader中,然後只需要添加陰影晃動的特性的就可以,隨植物晃動而晃動,會有一種真實陰影的感覺。另外注意陰影的方向、和植物晃動的同步登細節。
1.Standard Shadow Mapping:的基本思想是在光源位置放置一個相機(Light space Camera),畫一遍深度得到深度圖,在渲染場景時將pixel坐標轉換Light Space計算深度,然後比較它深度和深度圖中的深度,如果比深度圖中深度大就意味著在陰影中,否則在被照亮。
陰影的鋸齒有兩類:透視導致的鋸齒(Perspective alias)和投影導致的鋸齒(Project alias)。2.PCF:投影導致的鋸齒是因為燈光投射方向和物體表面夾角過小時多pixel對應陰影圖的一個texel,這可以通過提高陰影圖的大小來解決,也可以通過Percentage Closer Filtering來柔化邊緣。PCF就是在繪製時,除了繪製當前點還會對周圍像素進行多次採樣、混合來柔化鋸齒,常用PCF有:使用隨機採樣實現soft shadow、泊松採樣等。4.LISPSM:在PSM的基礎上又有了新的陰影技術Light Space Perspective Shadow Maps,它是在和燈光方向垂直的方向構建View Frustrum,然後將燈光、場景都轉到這個View Frustrum的Perspective space,然後再計算Shadow Map,這樣無論是點光、聚光、平行光就都轉為平行光。
// Build a matrix for cropping light"s projection // Given vectors are in light"s clip spaceMatrix Light::CalculateCropMatrix(Frustum splitFrustum){ Matrix lightViewProjMatrix = viewMatrix * projMatrix; // Find boundaries in light"s clip space BoundingBox cropBB = CreateAABB(splitFrustum.AABB, lightViewProjMatrix); // Use default near-plane value cropBB.min.z = 0.0f; // Create the crop matrix float scaleX, scaleY, scaleZ; float offsetX, offsetY, offsetZ; scaleX = 2.0f / (cropBB.max.x - cropBB.min.x); scaleY = 2.0f / (cropBB.max.y - cropBB.min.y); offsetX = -0.5f * (cropBB.max.x + cropBB.min.x) * scaleX; offsetY = -0.5f * (cropBB.max.y + cropBB.min.y) * scaleY; scaleZ = 1.0f / (cropBB.max.z - cropBB.min.z); offsetZ = -cropBB.min.z * scaleZ; return Matrix( scaleX, 0.0f, 0.0f, 0.0f, 0.0f, scaleY, 0.0f, 0.0f, 0.0f, 0.0f, scaleZ, 0.0f, offsetX, offsetY, offsetZ, 1.0f);}
c)針對切分的每一塊渲染陰影圖,一般陰影圖大小一樣的,比如都是1024*1024,而近處包含的場景範圍比遠處小,所以近處陰影圖的精度會更高。
d)渲染場景陰影推薦閱讀:
※《Splatoon 2》繪製效果的簡單實現
※Instagram濾鏡,影視級調色演算法實現
※2D遊戲開發時有那些驚艷的效果是一定要學會著色器(shader)編程?
※編寫Unity Shader的時候,語義POSITION和SV_POSITION的區別?
※Shader model 5.0 的片段著色器能不能得到該片段所在的三角圖元實際光柵化後有多少像素?