發表文章

目前顯示的是有「Shader」標籤的文章

Unity:餵魚小遊戲

圖片
    最近終於製作好了一個餵魚的小遊戲,是四景山水圖秋景-URP重製版這個專案裡的一部分,內容很簡單只有餵魚的互動功能而已,主要會做這個的動機還是添增趣味。 在傳統園林裏面水是很重要的,雖然這個專案目前看大概不會太著重在怎麼理水這方面,因為一些素材都沒有(石材駁岸和植栽的模型之類),所以也沒有辦法做太多處理,但是水的部分只有湖面就很無聊,所以加一點可互動的功能。之後肯定還會在水裡加上其他細節像是植栽之類的,讓水體這個部分變得豐富一些。   這個餵魚小遊戲分成兩個部分,魚的模型和渲染以及互動的部分 魚的模型和渲染 魚隻的渲染是利用Shader來處理魚的變形動畫和花色的變化。   魚的互動 互動包括游動、吃飼料和如何灑飼料。魚隻游動吃飼料都是依靠插件完成,插件使用的是 FlockBox ,基本上魚類游動與吃飼料可以簡單的做到,但是有個問題是與地形的碰撞,目前為止然有些障礙,有些魚會穿過地形。除此之外魚類游動的時候還會計算角度的差值傳給Shader做魚隻模型的變形。 灑飼料和水花這些都是依靠粒子系統搭配腳本控制,灑出來的飼料一開始是一般的粒子,等到碰到水面後才變成可以被魚隻辨別並吃掉的物件(在插件裡稱做Agent),飼料的物件用物件池管理,等要生成時才依照對應的參數召喚。    

Unity:嘗試製作可相交的視差遮蔽貼圖 Shader (Trying to Create an Parallax Occlusion Mapping Shader with Pixel Depth Offset)

圖片
  警告,本文只是分享摸索的過程,並不是完善的技術文。 此文在計算深度位移有錯誤,後續有所更新,詳見 此文     視差貼圖(Parallax Mapping)是一種改進後的凹凸貼圖的技術,可以用極少的面數模擬複雜模型的表面凹凸,因為介紹視差貼圖這個技術的文章很多了此處就不詳細介紹,本文只大概說明使用視差貼圖要怎麼讓模型與一般的物件產生正確的陰影投射和相交的效果。  一般的視差貼圖的做法是依照切線空間的視線相量位移貼圖採樣的 UV 座標而產生立體感,物件本身的幾何形狀並未更改,因此各個像素的深度也是原有形狀的位置,因此相交時無論畫面上的物體因為視差貼圖產生凹凸的樣貌為何,相交還是依照原有的幾何形狀,而接收物件陰影投射亦有相同狀況。(如下圖) Unity 中的 HDRP 中內建的 Lit Shader 提供的像素深度位移(Pixel Depth Offset)的功能,可以讓各個像素的深度位置依照視差貼圖位移的量產生位移,進而讓視差貼圖凹凸的效果也能對應到物件的相交上。(如下圖) 需要提到的是 Unreal 引擎的 Shader 也有同個功能,但無論是 Unity 和 Unreal 引擎的做法我都無法取得夠詳細的資料,雖然 Unity 的 Lit Shader 可以找到原始碼,但是太複雜了,目前暫時還是沒有辦法理清做法。 (゚∀。) 為了產生正確的物件相交與陰影投射勢必要計算出正確的深度,那麼怎麼計算正確的深度呢?我的做法就是直接將像素的世界空間座標依照凹凸的位移量計算出位移後的世界座標,然後再計算剪裁空間的座標,然後就得出深度了。 需要說的是我採用的視差貼圖技術是視差遮蔽貼圖(Parallax Occlusion Mapping,POM) ,原先是在 Shader Graph 中用 Custom Function 節點製作的,結果如下方的影片。   參考了 Unity 的做法,使用的是高度圖而非深度圖,因此高度(深度)最低為0,最高為1,需要特別注意。 取得視差位移後的深度首先第一步是求出視差位移後的高度(深度)。這個很簡單,回傳位移後的 UV 時一並回傳目前的高度(深度),如下圖可以看到高度最低至最高由 0 到 1 灰階漸層。 一旦取得高度後便可以取得世界空間的...

Unity:URP的獲取光照節點

圖片
  最近想要在URP用Shader Graph的Unlit節點上使用自定義的光照,所以要取得場景的光照資訊,Unity官方是有提供獲取方向光以及多重光源的光照資訊的 方式 。 問題就來了,新版的URP似乎沒有辦法照上面官方文章裡提到的方式獲取陰影,這個問題是出在獲取陰影的功能實際上要定義特定的指示詞才能計算陰影,如果沒有定義會變成不計算陰影。 翻了網路上的文章已經有人對此問題做出詳細說明, 可見此 。要獲取光照的陰影就需要把原先計算陰影的程式碼複製過來,直接在自定義的節點裡執行計算,在文章裡其實已經有完成品了,不過只有主光源,那麼如果要處理多重光源(這邊指的是除了主光源以外的Additional Lights)怎麼辦呢?  其實Unity官方的文章已經有說明了獲取多重光源的光照資訊,有一點問題就是沒告訴你怎麼取得陰影,如果照舊版URP,應該是跟獲取主光源陰影一樣的方法,陰影的值應該封裝在燈光的struct裡,同樣的在新版的URP也無法作用。 所以如果要在新版的URP獲取多重光源的陰影的做法與取得主光源的陰影是相近的,差異在多重光源獲取陰影要在獲取光照資訊裡的迴圈執行。同樣的,需要將世界座標轉換到陰影空間的座標,取得陰影的相關參數,並在ShadowMap採樣陰影。計算各個光源的光照強度與顏色( attenuatedLightColor )會變成如下: half4 shadowCoord = mul(_AdditionalLightsWorldToShadow[i], float4(WorldPosition, 1.0f)); half4 shadowParams = GetAdditionalLightShadowParams(i); ShadowSamplingData shadowSamplingData = GetAdditionalLightShadowSamplingData(); float shadowAtten = SampleShadowmap(TEXTURE2D_ARGS(_AdditionalLightsShadowmapTexture, sampler_AdditionalLightsShadowmapTexture), shadowCoord, shadowSamplingData, shadowParams, tru...