从Geometry Shader到Compute Shader:Realistic-Real-Time-Grass-Rendering-With-Unity的性能演进路线图与Unity草地渲染未来
【免费下载链接】Realistic-Real-Time-Grass-Rendering-With-UnityRealistic Real Time Grass Rendering With Unity. Using the Geometry Shader to generate millions of grass on GPU. ref:Edward Lee项目地址: https://gitcode.com/gh_mirrors/re/Realistic-Real-Time-Grass-Rendering-With-Unity
Realistic-Real-Time-Grass-Rendering-With-Unity 是一个 Unity 草地渲染开源项目,它利用Geometry Shader 在 GPU 上实时生成并渲染海量随风摇曳的草叶,让开发者无需手动摆放每一根草,即可在大场景中实现"无尽草地"效果。本文将从它的 Geometry Shader 实现出发,梳理一条从 GPU 顶点扩展到 Compute Shader 的性能演进路线图,并展望 Unity 草地渲染的未来方向。
🌱 项目概览:GPU 生成的实时草地
这个项目的设计思路非常清晰:CPU 只负责撒下"草点",GPU 负责把每个点展开成一根完整的草叶。
- CPU 端:
Assets/Script/GrassSpanner.cs读取灰度高度图,生成起伏地形,并在每个草片区随机撒点,把所有草点打包成 Points 拓扑的网格传给 GPU; - GPU 端:
Assets/Shader/GrassGeometryShader.shader的 Geometry Shader 将每个点扩展成 12 个顶点、10 个三角形的草叶,并实时计算风场摆动; - 光照与抠图:片元着色器采样草叶颜色与 Alpha 纹理,通过
AlphaToMask实现边缘透明。
下面是项目自带素材中的草地与枯叶混合纹理预览,可以直观感受草地渲染所需的细节层次:

这套素材(含 diffuse、normal 贴图与两套材质)位于Assets/Grass & dead leafs 01/,可直接用于地形表面细节渲染,与 GPU 草叶配合使用。
📐 Unity 草地渲染原理:CPU 撒点 + GPU 顶点扩展
以项目自带的Assets/Scene/demo.unity场景为例(terrainSize=64、terrainHeight=10),渲染管线分为三步:
- 高度图驱动地形:
Assets/Texture/Heightmap.png是一张 1024x1024 的灰度图,像素亮度直接映射为地形高度,这也是撒草点的位置依据。
- CPU 撒点云:
GrassSpanner.cs将地形划分为 30×30 个草片区、每区随机 50 个点,共约 45,000 个草点;由于索引缓冲限制,代码会把超过 65,000 点的网格自动拆分成多个grassLayer对象分批提交。 - GPU 顶点扩展:Geometry Shader 声明
#pragma target 4.0与[maxvertexcount(30)],对每个点输入生成 12 个顶点。草叶的宽度、高度由坐标推导的伪随机数扰动,风场则基于_Time叠加多组正弦波,让每根草的摆动相位都不同——45,000 个点在 GPU 上最终扩展为约 54 万个顶点、18 万个三角形。
草叶外观由两张小纹理决定:Assets/Texture/grassBlade.png(草叶颜色渐变)与Assets/Texture/grassBladeAlpha.png(Alpha 轮廓),参数在Assets/Mat/GrassMat.mat中可调(_Height=3、_Width=0.05)。
📉 Geometry Shader 的性能天花板
Geometry Shader 方案优雅,但存在公认的瓶颈,这也是演进路线图的起点:
- 顶点扩展吞吐受限:VS→GS 阶段的顶点放大是 GPU 管线中的传统性能瓶颈,中低端与移动端 GPU 上尤其明显,草量超过一定规模后帧率下降明显;
maxvertexcount硬性上限:单点可输出的顶点数有固定上限,无法自由调整草叶细分精度;- 移动端兼容性差:着色器要求图形 API 4.0 级别(DirectX 11 / OpenGL 4.0+),在移动端常用 API 上往往不可用;
- 逻辑表达受限:LOD、视锥剔除、按密度淡出等逻辑难以在 Geometry Shader 中高效实现。
🚀 演进路线图:从 Geometry Shader 到 Compute Shader
结合项目现有结构,一条平滑的性能升级路线如下:
| 阶段 | 技术路线 | 核心改动 | 预期收益 |
|---|---|---|---|
| 1️⃣ 现状 | Geometry Shader 顶点扩展 | 点输入 → GPU 上展开草叶 | 零额外内存,实时渲染数万~数百万草 |
| 2️⃣ 过渡 | GPU Instancing | 复用撒点逻辑,用实例化绘制草叶 | 摆脱 GS 依赖,大幅提升移动端兼容性 |
| 3️⃣ 目标 | Compute Shader | 并行计算草叶顶点与风场,写入顶点缓冲 | 更高的顶点吞吐,风场/LOD 逻辑灵活 |
| 4️⃣ 进阶 | 3D 噪声高度图 + LOD 混合 | 远景草叶淡入地形纹理 | 支持大世界无缝草地 |
第 2 阶段改动最小:GrassSpanner.cs的撒点输出可以原封不动复用,只需把几何 Pass 替换为 Instancing 草叶绘制(每张草叶作为一个实例),即可在移动端获得可用的性能。
第 3 阶段是核心跃迁:用 Compute Shader 替代 Geometry Shader,将"点 → 草叶"的扩展逻辑与风场计算全部搬到并行线程中,输出写入顶点缓冲后再绘制。风场算法可直接从GrassGeometryShader.shader中现有的正弦叠加逻辑迁移,几乎零学习成本。这一方向也是业界共识,经典参考是 GPU Gems 第 7 章与 Kevin Boulanger 的草地渲染论文(项目 README 中列有文献出处)。
第 4 阶段面向大世界:用 3D 噪声替代 2D 高度图实现平滑采样,配合距离 LOD 将远景草叶淡入地表混合纹理,从而把 GPU 预算集中在近景高密度区域。
⚡ 快速上手:Unity 草地渲染 Demo 运行步骤
- 克隆仓库:
git clone https://gitcode.com/gh_mirrors/re/Realistic-Real-Time-Grass-Rendering-With-Unity - 用 Unity 5.6+(推荐 2017.3+,支持 32 位索引缓冲)打开工程;
- 进入
Assets/Scene/demo.unity,确保图形 API 支持 Geometry Shader(DirectX 11 / OpenGL 4.0+); - 在 Inspector 中调整 GrassSpanner 组件的
terrainSize、terrainHeight即可改变地形规模与起伏。
🗂️ 核心文件路径索引
- 撒点与地形生成脚本:
Assets/Script/GrassSpanner.cs - 草地 Geometry Shader:
Assets/Shader/GrassGeometryShader.shader - 草叶材质(高度/宽度参数):
Assets/Mat/GrassMat.mat - 高度图与草叶纹理:
Assets/Texture/Heightmap.png、Assets/Texture/grassBlade.png - 草地枯叶纹理素材包:
Assets/Grass & dead leafs 01/ - Demo 场景:
Assets/Scene/demo.unity
🔭 Unity 草地渲染的未来方向
从 Geometry Shader 到 Compute Shader 的演进,本质是把"顶点扩展"从管线中的受限阶段解放到完全可编程的并行计算中。对新手而言,这个项目的价值在于:它用不到千行代码完整呈现了"CPU 撒点 + GPU 扩展"的经典 GPU 草地范式,你既可以先跑通 Demo 建立直觉,也可以沿着上面的路线图,把它改造成面向 URP/HDRP、支持移动端与开放世界的现代草地渲染系统。🌿
【免费下载链接】Realistic-Real-Time-Grass-Rendering-With-UnityRealistic Real Time Grass Rendering With Unity. Using the Geometry Shader to generate millions of grass on GPU. ref:Edward Lee项目地址: https://gitcode.com/gh_mirrors/re/Realistic-Real-Time-Grass-Rendering-With-Unity
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考