初次嘗試GPU Driver —— 大范圍植被渲染之着色


初次嘗試GPU Driver —— 大范圍植被渲染之着色

《初次嘗試GPU Driven —— 大范圍植被渲染》中實現了草地分布,本文實現草的着色。

本文分四個部分:

  • 生成網格
  • 隨機調整
  • 着色
  • 風場

生成草網格

網格形狀通常有矩形和三角形,本文使用三角形的網格。

草網格

上圖從左到右依次提高細節。

隨機調整

用上一步生成的網格渲染,會看到這樣的畫面。

整齊

很顯然,分布的太整齊了,草叢不是整齊排列的,所以每顆草不能都用一樣的方向和大小渲染,在這一步將草隨機一下。思路是通過草的世界坐標得出隨機值,用該隨機數去旋轉&縮放頂點,因為每顆草的世界坐標是固定的,所以隨機數也是固定的,又因為每顆草的坐標都不一樣,所以隨機數也可能會不一樣(這不是病句)。

隨機數的計算方法有很多,只要讓其盡可能亂就行了,計算出縮放和旋轉后,再加上之前算出來的世界坐標,就可以構建變換矩陣了。

float3 wcoord = _GrassCoords[instanceID];

...

float random(float2 pos)
{
    return frac(sin(dot(pos, float2(12.9898, 78.2330))) * 1.9);
}

...

//  平移/縮放/旋轉
float  rand  = random(wcoord.xz);
//  隨機縮放
float2 scale = lerp(float2(0.2, 0.5),
                    float2(0.3, 1.0), rand);
//  隨機旋轉
float2 rotate = float2(cos(rand * UNITY_PI * 2),
                       sin(rand * UNITY_PI * 2));

float4x4 transform = float4x4(float4(scale.x * rotate.x,       0, -rotate.y, wcoord.x),
                              float4(                 0, scale.y,         0, wcoord.y),
                              float4(         -rotate.y,       0,  rotate.x, wcoord.z),
                              float4(0, 0, 0, 1));

...

o.wcoord = mul(transform, v.vertex);
o.vertex = UnityWorldToClipPos(o.wcoord);

隨機

草已經被打亂了,但每顆草太直了,接下來壓彎每顆草,思路是將草往前傾斜,同時降低Y軸值,Y軸值越大,則傾斜越大,下壓力越大。

float2 forward = float2(0, 1);
float2 offset = forward * scale.y * _Bend
              * v.vertex.y * v.vertex.y;
v.vertex.xz += offset;
v.vertex.y  -= length(offset);

壓彎

把數量翻10倍后,畫面如下:

10倍

着色

着色這部分簡單處理,給定兩個基礎顏色,分別表示草的頂部和底部色,隨后用Lambert光照着色。

float3 worldCoord = i.wcoord;
float3 worldNormal = normalize(i.normal);
float3 lightNormal = UnityWorldSpaceLightDir(worldCoord);
float4 color = lerp(_BottomColor, _TopColor, i.vcoord.y);

fixed3 ambient = color * UNITY_LIGHTMODEL_AMBIENT.rgb;
fixed  wDotL = max(0.2, dot(worldNormal,lightNormal));
fixed3 diffuse = color * wDotL * _LightColor0.rgb;
color.rgb += ambient;
color.rgb += diffuse;
return color;

着色

風場

這一步加入風的影響,通過風向,風速,風力三個因素定義風,隨時間挪動影響范圍。

本文的風區分微風和強風,微風持續影響,強風按頻率影響,可以抖動一下頻率效果更佳。

本文強風用下圖頻率:

波浪

//  基礎風
float3 wind      = _WindDirect * _WindPower * v.vertex.y * v.vertex.y;
float  windValue = tex2Dlod(_WindMask, float4(wcoord.xz / 64, 0, 0)).r;
//  微風
wcoord.xyz += wind * sin(_Time.y * _WindSpeed + dot(wcoord, _WindDirect)) * 0.3;
//  強風
wcoord.xyz += wind * saturate(sin(_Time.y * _WindSpeed + dot(wcoord, _WindDirect))) * windValue;
wcoord.xyz += wind * saturate(sin(0.75 * _Time.y * _WindSpeed + dot(wcoord, _WindDirect))) * windValue;
wcoord.xyz += wind * saturate(sin(0.25 * _Time.y * _WindSpeed + dot(wcoord, _WindDirect))) * windValue;

到此,渲染部分就結束了,下面展示一段加入高度圖后的最終表現:

最終渲染
最終渲染


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM