Article
Realistic Real Time Grass Rendering With Unity
Updated 2 years ago
1.3 K
2
Realistic Real Time Grass Rendering With Unity

## 0x01 一个简单的星型

• 从不同的角度观察，草都必须显得密集
• 草的排布不能过于规则，否则会不自然

``````if (o.uv.y > 0.5)
{
float4 translationPos =
float4(sin(_Time.x * _TimeFactor * Pi ), 0, sin(_Time.y * _TimeFactor * Pi ), 0);
v.vertex += translationPos * _StrengthFactor;
}``````

（图片来自：九州天空城3D）
（图片来自：剑网3）

## 0x02 更真实的草叶

（图片来自：Edward Lee）

ok，接下来就在GPU上通过一个根位置来制作草的叶子。
``````[maxvertexcount(30)]
void geom(point v2g points[1], inout TriangleStream<g2f> triStream)
{

float4 root = points[0].pos;``````

`````` float random = sin(UNITY_HALF_PI * frac(root.x) + UNITY_HALF_PI * frac(root.z));
_Width = _Width + (random / 50);
_Height = _Height +(random / 5``````

`````` for (uint i = 0; i < vertexCount; i++)
{
v[i].norm = float3(0, 0, 1);

if (fmod(i , 2) == 0)
{
v[i].pos = float4(root.x - _Width , root.y + currentVertexHeight, root.z, 1);
v[i].uv = float2(0, currentV);
}
else
{
v[i].pos = float4(root.x + _Width , root.y + currentVertexHeight, root.z, 1);
v[i].uv = float2(1, currentV);

currentV += offsetV;
currentVertexHeight = currentV * _Height;
}

v[i].pos = UnityObjectToClipPos(v[i].pos);

}``````

`````` SubShader
Tags{ "Queue" = "AlphaTest" "RenderType" = "TransparentCutout" "IgnoreProjector" = "True" }

Pass

``````half4 frag(g2f IN) : COLOR
{
fixed4 color = tex2D(_MainTex, IN.uv);
fixed4 alpha = tex2D(_AlphaTex, (IN.uv));

return float4(color.rgb, alpha.g);
}``````

## 0x03 生成覆盖地面的无尽草地

``````for (int i = 0; i < 250; i++)
{
for (int j = 0; j < 250; j++)
{
verts.Add(new Vector3(i, heightMap.GetPixel(i, j).grayscale * 5 , j));
if (i == 0 || j == 0) continue;
tris.Add(250 * i + j - 1);
tris.Add(250 * (i - 1) + j - 1);
tris.Add(250 * (i - 1) + j - 1);
tris.Add(250 * (i - 1) + j);
}
}
...
Mesh m = new Mesh();
m.vertices = verts.ToArray();
m.uv = uvs;
m.triangles = tris.ToArray();``````

`````` m.vertices = verts.ToArray();
m.SetIndices(indices，MeshTopology.Points, 0);

grassLayer = new GameObject("grassLayer");

wow，我们的草地出现了。

## 0x03 风的模拟

`````` ...伪代码
wind.x += sin(_Time.x + root.x);
wind *= random;
...``````

chenjd/Realistic-Real-Time-Grass-Rendering-With-Unity

## ref：

【1】《Chapter 7. Rendering Countless Blades of Waving Grass》
【2】《Rendering Grass Terrains inReal-Time with Dynamic Lighting》
【3】《REALISTIC REAL-TIME GRASS RENDERING》
【4】《Programming Guide for Direct3D 11》