2017年12月11日 星期一

My new infinity GPU vertex animated ocean on mobile average fps 60 (Samsung 7)

其實這個系統做一半,因為專案趕進度的關係,就停下來了,最近比較有時間把它給順好。 總結一下Implement的過程:

Vertex program:
1.計算 projected(目的是為了無限大:參考了Habib's Water ShaderCeto Ocean System
2.計算 projected position
3.計算 Perlin noise on GPU(目的是為了加速計算大量的點位移-高度)
4.計算 Vertex Normal (之後會拿來當normal map的world space)
5.Animated UV(normal and foam map)

Fragment(Pixel)Program:
1.計算深度(高度及透視深度的混合,參考Ceto Ocean System,有點類似霧氣擴散的效果)
2.將Normal map轉換成World Space
3.計算diffuse
4.計算specular
5.計算distortion(refraction或reflection參數分開)
6.計算泡沫效果,並將其與refraction混合(只有岸邊淺水的地方才有邊緣泡沫)
7.計算水顏色,淺水、深水與refractoin依照深度及折射率進行混色,之後再依照反射率跟reflection進行混色,完成了所謂的SeaColor。
8.簡單模擬Fersnel Terms(依照一張Fersnel map,混合沒有考慮Diffuse及有考慮Diffuse的狀況,進行混色):
fixed3 SpecAndDiffuse = SeaColor * Diffuse + Specular;
fixed3 SpecNoDiffuse = SeaColor + Specular;
fixed4 OutColor = fixed4(lerp(SpecAndDiffuse, SpecNoDiffuse, FresnelRatio), 1.0);
9.再加上海浪模擬(依照Normal與Up軸的dot值,決定海浪貼圖顯示的強弱)
10.最後再加上fog的顏色,便大功告成
成果如下:

2017年11月29日 星期三

Dynamic clouds shadow with screen space projector

一般我們在模擬動態雲陰影或AE選擇範圍時,最常用的就是projector(通常會用multi pass technique)。在Unity架構下Projector也是用multi pass實現(可想而知Draw call Batch會多一倍),但它卻會打斷Unity的合批(Batching)處理,對於好不容易規劃好的優化架構相當嚴重。

有沒有好的其他解決方案呢?其實有,那就是screen space projector,它和一般的projector一樣會多畫一次,主要是要把深度資料繪製出來(其實如果可以access native buffer,就可以省掉),但卻不會打斷合批處理,算是一個效能與效果兼顧的折衷方案。

以下的Demo影片會分別顯示WithoutAnyProjector、OriginalProjector、ScreenSpaceProjector三種模式,可以從中看到Batching數量的變化。





Dream continues in...

2017年11月11日 星期六

模擬海平面以下的無水效果

這個部份主要是應用了DepthMask的機制,目前我的深度貼是採用ObliqueMatrix的方式,所以深度是只有儲存高度,而不是一般的深度貼圖,至於Render Ocean Depth的Shader則分三種,利用Unity的Replace Shader的機制來處理Opaque、Transparent、Depth Mask三種不同的類型物件,程式碼的概念如下:
Shader "RenderOceanDepth"
{
Properties
{
[HideInInspector]_MainTex("MainTex", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
//負責繪製一般的Opaque深度資料…
}
}
SubShader
{
Tags{
"Queue" = "Transparent"
"RenderType" = "Transparent"
}
LOD 100
Pass
{
Blend SrcAlpha OneMinusSrcAlpha
//負責繪製帶有Alpha物件深度資料…
}
}
SubShader
{
Tags{
"RenderType" = "FilterDepth"
}
LOD 100
Pass
{
//負責繪製深度遮閉物件,深度傳回值皆為零…
}
}
}
視頻除了展示可以繪製水平下以下的地表(不含水),還展示了類似摩西分紅海的模擬,但由於Screen base的Depth資料,在不同的視角還是有破綻…




Dream continues in...

2017年10月21日 星期六

詳解火炬之光穿透剪影的效果(Silhouette or X Ray)

其實這個效果跟Shader沒什麼關係,基本上就是畫兩次,一次是畫剪影(Behind Pass),第二次是畫原本的模型(Original Pass),重點是Render State的設置…
以下是以Untiy Shader Lib為例:

Behind Pass的ZBuffer相關屬性設為:
ZTest Greater:意思是畫的時候,深度要大於目前畫面的深度值才畫,也就是被擋住的時候才
畫。
ZWrite Off:指的是不要寫入深度值,因為這個只是簡影,他跟目前畫面深度值是一樣
的。
基本上,這樣就差不多了,剩下的OgrinalPass就不多說了,因為這就是你原來的Shader Pass
啊!相關的範例Source Code如下:

Shader "Unlit/XRayExample"
{
Properties
{
_XrayColor("RimColor", Color) = (1.0, 0.0, 0.0, 1.0)
_MainTex("MainTex", 2D) = "white" {}
}
SubShader
{
LOD 200
Pass //behind pass
{
//render after opacity with alphaTest
Tags{ "RenderType" = "Transparent" "Queue" = "Transparent-20" }
ZWrite Off
ZTest Greater
Cull Back
Blend SrcAlpha One
CGPROGRAM
#include "UnityCG.cginc"
#pragma vertex VertexProgram
#pragma fragment FragmentProgram
struct VertexInput
{
float4 Vertex : POSITION;
};

struct VertexOutput
{
float4 Vertex : SV_POSITION;
};
uniform fixed4 _XrayColor;

VertexOutput VertexProgram(VertexInput Input)
{
VertexOutput Output;
Output.Vertex = mul(UNITY_MATRIX_MVP, Input.Vertex);;
return Output;
}
fixed4 FragmentProgram(VertexOutput Input) : SV_Target
{
return _XrayColor;
}
ENDCG
}
Pass //original pass
{
CGPROGRAM
#pragma vertex VertexProgram
#pragma fragment FragmentProgram
#include "UnityCG.cginc"

struct VertexInput
{
float4 Vertex : POSITION;
float2 UV : TEXCOORD0;
};

struct VertexOutput
{
float4 Vertex : SV_POSITION;
float2 UV : TEXCOORD0;
};
uniform sampler2D _MainTex;
half4 _MainTex_ST;

VertexOutput VertexProgram(VertexInput Input)
{
VertexOutput Output;
Output.Vertex = mul(UNITY_MATRIX_MVP, Input.Vertex);
Output.UV = TRANSFORM_TEX(Input.UV, _MainTex);
return Output;
}
fixed4 FragmentProgram(VertexOutput Input) : SV_Target
{
return tex2D(_MainTex, Input.UV);
}
ENDCG
}
}
}

相關的影片如下:



如果想模擬XRay顯示效果的話,在BehindPass加入Rim處理即可,相關的範例影片如下:



後記:其實在沒有Shader的時代,就可以利用multi pass及Render State來實作許多效果,好好利用SceneBlend、MultiPass及RenderState吧。

2017年9月28日 星期四

Sailing simulation with Recastnavigation

For sailing purpose and path finding, I append smooth rotate and speed limit process.
but it's cause unsafe path problem, so i reduce max speed when happen hit wall and agent obstacle.
The final result is here:




Dream continues in...

2017年9月22日 星期五

Append smooth rotate process to Recastnavigation DetourCrowd system

Recastnavigation Detour Crowd is a best path find solution, but for vehicle is not, maybe open steer is better.
I try append smooth process to DetourCrowd, it looks better(smooth rotate).

What did I do?

  1. Append float currentDir[3] and float roateSpeed to dtCrowdAgent.
  2. Append Smooth process to calcSmoothSteerDirection function
  3. Store finial velocity to currentDir[3]
the result is here:




Dream continues in...

2017年6月27日 星期二

AI-RecastNavgation and Crowd avoidance system

在RTS遊戲開發的領域,Path find及local avoidance
一直是很重要的相關技術,而這兩個部份的位移處理
整合,也是令人頭痛的問題。

RecastNavgation是一套相當成熟的路徑搜尋函式庫,
作者Mikko Mononen曾在Crysis擔任lead AI programmer,
且這套函式庫廣泛被商業遊戲引擎中使用(Unreal及Unity)
,也支持動態計算導航網格。

一般的做法大部份都是使用RVO+RecastNavgation但這樣
會造成整合相當困難(RVO說要去這裡,Recast說要去這裡
,倒底聽誰的)。

另外RVO本身也支援靜態阻檔物(obstacle),但它是用一
直撞過去的方式,沒有路徑搜尋。筆者之前曾嘗試著利用
其相關資訊,動態計算出導航點,但在比較複雜的場景效
果不佳,所以就放棄了。

後來去抓最新的RecastNavgation,發現他早就支援了crowd
local avoidance的功能,而且也找到許多Unreal的開發者
早就從RVO移轉到Recast crowd system。

Unity的Path find system雖然也是以RecastNavgation為基
礎開發的,但目前卻還沒有支援Crowd,人家Unreal全部都是
C++,可能比較好支援…

話說回來,目前的專案需求是Server及Client要共用路徑搜尋
的功能,所以不能跟Unity有任何的關係,於是如果要支援
RecastNavgation及其Crowd系統,比較好的解決方案可能就是
自行設計RecastNavgation native c++ plugin

以下是初步整合的成果,此畫面目前是用Ogre來Render(之後
再整合到Unity),在走道可以通過的時候,Agent Sphere會
在那邊排隊等通過,但沒辦法走的時候就各自從旁邊繞過去了

Dream continues in...