Unity Shader基於視差對映的雲海效果
雲海效果的實現
這裡的雲海shader有RPM和POM兩個版本,最終使用的是RPM。
在迭代次數足夠的情況下,兩種差別不大。
躁波圖的rgb是顏色,a是高度
VS方法
v2f vert (appdata_full v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.texcoord,_MainTex) + frac(_Time.y*_HeightTileSpeed.zw);
o.uv2 = v.texcoord * _HeightTileSpeed.xy;
o.posWorld = mul(unity_ObjectToWorld, v.vertex);
o.normalDir = UnityObjectToWorldNormal(v.normal);
TANGENT_SPACE_ROTATION;
o.viewDir = mul(rotation, ObjSpaceViewDir(v.vertex));
o.color = v.color;
#if USING_FOG
HeightFog(o.posWorld.xyz,o.fog);
#endif
UNITY_TRANSFER_FOG(o,o.pos);
return o;
}
shader計算了兩套uv,uv是高度和顏色貼圖的uv,uv2是做擾動用的uv
viewDir是切線空間下的視線向量,透明度寫在頂點色裡
FS方法裡初始化
float3 viewRay = normalize(-i.viewDir);
viewRay.z = abs(viewRay.z)+0.42;
viewRay.xy *= _Height;
float3 shadeP = float3(i.uv,0);
float3 shadeP2 = float3(i.uv2,0);
0.42的一個hack的值,是為了防止攝像機向量V和法向量N夾角過大。本身精度足夠是不需要這個值的,但是為了減少迭代次數必須加上這個值。
_Height控制雲的凹凸程度。
shadeP、shadeP2 用於記錄迭代的狀態。
shadeP的xy是取樣uv,z是當前深度。
shadeP2的xy是擾動uv,z沒有用到。
視差計算
RPM版
const int linearStep = 2;
const int binaryStep = 5;
float4 T = tex2D(_MainTex, shadeP2.xy);
float h2 = T.a * _HeightAmount;
// linear search
float3 lioffset = viewRay / (viewRay.z * (linearStep+1));
for(int k=0; k<linearStep; k++)
{
float d = 1.0 - tex2Dlod(_MainTex, float4(shadeP.xy,0,0)).a * h2;
shadeP += lioffset * step(shadeP.z, d);
}
// binary search
float3 biOffset = lioffset;
for(int j=0; j<binaryStep; j++)
{
biOffset = biOffset * 0.5;
float d = 1.0 - tex2Dlod(_MainTex, float4(shadeP.xy,0,0)).a * h2;
shadeP += biOffset * sign(d - shadeP.z);
}
先線性查詢,再用二分法查詢。
取樣過程中乘上擾動的高度值。
注:專案用的深度圖其實是高度圖,所以取樣和上文有點區別,取的是一個反向的值。
迭代次數越多,效果越好,過少會出現顏色分層。
POM版
float linearStep = 7;
float4 T = tex2D(_MainTex, shadeP2.xy);
float h2 = T.a * _HeightAmount;
float3 lioffset = viewRay / (viewRay.z * linearStep);
float d = 1.0 - tex2Dlod(_MainTex, float4(shadeP.xy,0,0)).a * h2;
float3 prev_d = d;
float3 prev_shadeP = shadeP;
while(d > shadeP.z)
{
prev_shadeP = shadeP;
shadeP += lioffset;
prev_d = d;
d = 1.0 - tex2Dlod(_MainTex, float4(shadeP.xy,0,0)).a * h2;
}
float d1 = d - shadeP.z;
float d2 = prev_d - prev_shadeP.z;
float w = d1 / (d1 - d2);
shadeP = lerp(shadeP, prev_shadeP, w);
先線性查詢,最後直接對最後兩次查詢做線性插值。
迭代的次數過少會丟失細節。
光照計算
half4 c = tex2D(_MainTex,shadeP.xy) * T * _Color;
half Alpha = i.color.r;
float3 normal = normalize(i.normalDir);
half3 lightDir = UnityWorldSpaceLightDir(i.posWorld);
float NdotL = max(0,dot(normal,lightDir));
#if USING_FOG
fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.posWorld));
float sunFog = saturate( dot(-viewDir,lightDir));
half3 sunFogColor = lerp(_HeightFogColor,_sunFogColor,pow(sunFog,2));
fixed3 finalColor = c.rgb * (NdotL * lightColor + unity_AmbientEquator.rgb * sunFogColor * _LightIntensity);
unity_FogColor.rgb = lerp(sunFogColor, unity_FogColor.rgb, i.fog.y*i.fog.y);
finalColor.rgb = lerp(finalColor.rgb,unity_FogColor.rgb, i.fog.x);
#else
fixed3 finalColor = c.rgb*(NdotL*lightColor + unity_AmbientEquator.rgb);
#endif
UNITY_APPLY_FOG(i.fogCoord, finalColor);
return ColorOutput(fixed4(finalColor.rgb,Alpha));
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70016819/viewspace-2895935/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Unity Shader 實現雨天的水面漣漪效果Unity
- Unity Shader 00 - 梳理 Unity Shader 的基本結構Unity
- Unity Shader 基於光照圖的簡易晝夜變化Unity
- Unity Shader之磨砂玻璃與水霧玻璃效果Unity
- Unity 的 Surface Shader有關記錄Unity
- unity 統一替換shaderUnity
- Unity2D橫板遊戲之背景視差與無限滾動效果Unity遊戲
- 什麼是視差滾動?如何實現視差滾動的效果?
- 用css實現視差效果CSS
- CSS完成視差滾動效果CSS
- 自定義實現MIUI的拖動視差效果(阻尼效果)UI
- unity shader 溶解,上下左右,cutoffUnity
- Spring MVC 基於URL的攔截和對映規則SpringMVC
- [非專業翻譯] Mapster - 基於規則的對映
- 《Unity Shader入門精要》自學筆記(五)第八章 透明效果Unity筆記
- Unity3D學習筆記3——Unity Shader的初步使用Unity3D筆記
- Unity&Shader常用函式的使用方法Unity函式
- 視覺差緩動效果的輪播--React版視覺React
- Unity Shader 入門精要 筆記(1)Unity筆記
- Unity3D 透明物體ShaderUnity3D
- Mybatis 基礎xml對映MyBatisXML
- ElasticSearch - 基礎概念和對映Elasticsearch
- 基於雲端的視訊剪輯工具
- 基於JDBC寫一個和mybatis類似的對映框架—DBUtilsJDBCMyBatis框架
- Unity Shader-後處理:Bloom全屏泛光UnityOOM
- 基於canvas生成海報Canvas
- 揭祕《Sherman》:使用Unity製作影視級光照效果Unity
- 基於螢石雲實現的九宮格影片監控效果
- 基於 HTML5 Canvas 的 3D 熱力雲圖效果HTMLCanvas3D
- Unity Shader之雙面材質和多Pass渲染Unity
- SAP Spartacus B2B OrgUnit 和 OrgUser 的路由對映差異比較路由
- unity 劉海屏問題Unity
- OpenGL shader 程式基礎
- 基於Unity的A星尋路演算法(絕對簡單完整版本)Unity演算法
- Shader 函式視覺化函式視覺化
- 基於AbstractProcessor擴充套件MapStruct自動生成實體對映工具類套件Struct
- 對映
- 使用Holer服務端軟體搭建基於自己伺服器的埠對映功能服務端伺服器