2018年7月11日 星期三

DOF with alpha blend depth map

一般DOF的做法大多是參考Depth Map,然後依照遠近再來決使用Blur Map或Color Buffer。
但是因為Alpha Blend通常沒有輸出深度,所以會發生因為錯誤的深度導致Alpha物件會顯示
錯誤的模糊效果。

目前自己的解決方法是為Alpha Blend物件單獨輸出一張Alpha Test的Depth Map,之後再跟深度貼圖取最近的深度即可。

在還沒使用Alpha Blend Map時,畫面如下(其中藍色的部份因為不透明物件的關係,顯示比較正確的結果):

2018年7月7日 星期六

使用Unity Command buffer調整SSAO後置效果的繪圖流程

SSAO如果擺在最後的後置繪圖流程,會造成因為Alpha Blending的物件沒有深度的問題,
而造成不正確的視覺效果。
為了解決這個問題,最好是將其放在整個Render完所有的非透明物件時再將其畫出,雖然
應該可以用一個full screen face quad物件,調整其render queue來畫應該也可以解決,但是
Unity有更好用的東西(Command Buffer)可以讓我們在特定的繪圖流程時機來畫後置特效。

這個是在畫完所有物件時機畫的結果:

2018年6月28日 星期四

在Unity下模擬水接收陰影從淺灘到深海的過渡

基本上設計思路很簡單,就是先讓水可以接收陰影,之後再依照水平面深度逐漸將陰影顯現出來,在深度最深的時候完全接收百分百的光源衰減值。

在折射處理方面,因為是使用GrabPass,所以並沒有針對折射另外進行拍射陰影,不會增加額外的DrawCall,但有花了拷貝背景圖的成本。
重點如下:
  1. UNITY_LIGHT_ATTENUATION(LightAttenuation, Input, Input.WorldPosition)
  2. LightAttenuation = lerp(1.0, LightAttenuation, pow(DepthRatio, 5));
之後在打光的地方使用這個光源衰減值即可,相關影片如下(記得要住意岸邊與深海接收影子的過渡)。

2018年6月2日 星期六

優化unity post processing stack SSAO on紅米Note3 fps 57

之前其實也自行整合其他的SSAO到Unity裡,但覺得效果不好,後來花一間時間研究post processing stack,發現它的Distance-based SSAO相對穩定,但在手機上效能很差,於是踏上了整合優化之旅。

優化重點:

  1. 降低RenderTexture分辦率
  2. 減少Sample次數
  3. 用Multi Render Target來降低Draw call
  4. 設計自己的Post rendering架構來避免Unity OnRenderImage產生多餘的Graphic blt renderTexture的處理。

優化後:
 

與Bloom及除錯資訊的影片:


Dream continues in...

2018年4月17日 星期二

Define base shader architecture

使用Define架構的方式來實作Shader。
好處:
1.Reused(代碼可以重複利用)
2.彈性(可以輕易地組合出不同的shader)
3.效能調效(可以輕易利用define來開關功能)
4.方便除錯(同上)
5.使用者容易理解(看define就知道做了那些事)
缺點:
1.代碼比較複雜(define的地方太多,建議先把代碼寫好測完,之後再考慮怎麼切…)

比較適合應用的例子有Lighting的計算,水系統…等。
以下用目前實作的水系統當作例子:
//========================================================
//一般平面水
Shader "CustomShader/PlaneWater"
{
Properties
{
...
}
SubShader
{
...
LOD 500 //在高階硬體以上的時候使用
Pass
{
...
CGPROGRAM
#pragma vertex WaterSimulateVertexProgram
#pragma fragment WaterSimulateFragmentProgram
#pragma multi_compile_fog
#define PROCESS_FOG //霧氣功能
#define PROCESS_SMALL_NORMAL //小波Normal
#define PROCESS_MEDIUM_NORMAL //中波Normal
#define PROCESS_LARGE_NORMAL //大波Normal
#define PROCESS_DEPTH //深度處理
#define PROCESS_REFRACTION //折射處理
#define PROCESS_REFLECTION //反射處理
#define PROCESS_EDGE_FOAM //水邊緣處理
#define PROCESS_WAVE_FOAM //浪泡沫處理
#include "WaterSimulation.cginc"
ENDCG
}
}
SubShader
{
...
LOD 100 //在低階硬體以上的時候使用
Pass
{
...
CGPROGRAM
#pragma vertex WaterSimulateVertexProgram
#pragma fragment WaterSimulateFragmentProgram
#pragma multi_compile_fog
#define PROCESS_FOG //霧氣功能
#define PROCESS_SMALL_NORMAL //小波Normal
#define PROCESS_LARGE_NORMAL //大波Normal
#include "WaterSimulation.cginc"
ENDCG
}
}
}
//========================================================
//無限大點位移水
Shader "CustomShader/ProjectedGridWater"
{
SubShader
{
...
LOD 500 //在高階硬體以上的時候使用
Pass
{
...
CGPROGRAM
#pragma vertex WaterSimulateVertexProgram
#pragma fragment WaterSimulateFragmentProgram
#pragma multi_compile_fog
#define PROCESS_FOG //霧氣功能
#define PROCESS_SMALL_NORMAL //小波Normal
#define PROCESS_MEDIUM_NORMAL //中波Normal
#define PROCESS_LARGE_NORMAL //大波Normal
#define PROCESS_DEPTH //深度處理
#define PROCESS_REFRACTION //折射處理
#define PROCESS_REFLECTION //反射處理
#define PROCESS_EDGE_FOAM //水邊緣處理
#define PROCESS_WAVE_FOAM //浪泡沫處理
#define PROCESS_PROJECTEDGRID //GPU點位移(高低)處理
#define PROCESS_DECAL //平貼水面特效處理
#include "WaterSimulation.cginc"
ENDCG
}
}
}
//========================================================
//簡單湖泊
Shader "CustomShader/Lake"
{
SubShader
{
...
LOD 100 //在低階硬體以上的時候使用
Pass
{
...
Blend SrcAlpha OneMinusSrcAlpha
ZWrite Off
CGPROGRAM
#pragma vertex WaterSimulateVertexProgram
#pragma fragment WaterSimulateFragmentProgram
#pragma multi_compile_fog
#define PROCESS_FOG //霧氣功能
#define PROCESS_SMALL_NORMAL //小波Normal
#define PROCESS_LARGE_NORMAL //大波Normal
#define PROCESS_CUBEMAP_REFLECTION //Cubeamp反射
#define PROCESS_WITH_VERTEXCOLOR //整合Vertex color
#include "WaterSimulation.cginc"
ENDCG
}
}
}

2018年3月27日 星期二

Interactive ripple + refraction + reflection + wave decal in Unity.

這是完全基於GUP的pixel shader及normal的運作,算是一種高明的騙術
,視角要是平貼於水面就破功了,不過對俯視類型的遊戲來說,還算
堪用,尤其是當美術需要為符合模型外型,模擬真實的水波佈了很多
的particle Emitter是較有效率的做法。

但這並不是通解,它是基於一個投射於整個水平大小的平行視角的鏡
頭來進行水波物件的拍射,所以沒辦法做很大的場景(一張RTT要去
貼在整個水面,而且沒辦法tile)。

其中類似Compute shader的應用蠻有意思的,這開擴了我對Shader運算的觀念…

相關影片:

2018年3月15日 星期四

Screen space interactive grass

在mobile的效能的考量下,做全場景的physic interactive grass可能太浪費,有沒有其他的方式可以簡單地表現interactive grass的效果呢?
我自己自行設計一個以Screen space的方式來處理這部份,這樣可以省下相關物理處理(做場景的screen query蠻傷的),流程大概如下:
  1. 在畫草之前,先針對要互動的物件拍射一個interactive depth map。
  2. 在畫草的vertex shader地方,使用這張貼圖來進行互動處理,當然免不了要處理depth to world space position。

相關影片如下: