
Unity3D Shader系列之几何着色器基础
1.什么是几何着色器
最近一直在练习写Shader,发现用几何着色器可以写出特别酷炫的效果。于是去学习了一下,这里做个总结以备查阅。
几何着色器位于渲染流水线的几何阶段,在顶点着色器与片元着色器之间。
备注:图片来源于冯乐乐的《Unity Shader入门精要》p9
其在Shader中是可选的,完全可编程的。
顶点着色器是以顶点数据(局部坐标、法线方向、纹理坐标等)做为输入,然后输出齐次裁剪空间下的顶点坐标、顶点颜色以及其他阶段需要的信息。每个顶点都会调用一次顶点着色器。顶点着色器不能够创建和销毁任何顶点,也不知道此顶点与其他顶点的关系(比如这个顶点与其他顶点是否在同一个三角形里面)。
而几何着色器以完整的图元(Primitive)作为输入数据,输出经过我们处理后的图元。我们可以在几何着色器里面去创建或销毁顶点,完全控制输出的图元个数与类型。几何着色器的输入图元和输出图元都可以为点、线、面任一种。
2 语法
几何着色器的语法还是挺简单的,这里以一个Demo为例。
Shader "Custom/Geometry/Wireframe3"
{
Properties
{
_WireFrameColor ("Wireframe Color", color) = (1.0, 1.0, 1.0, 1.0)
}
SubShader
{
Pass
{
Tags { "RenderType" = "Opaque" "RenderQueue" = "Geometry"}
CGPROGRAM
// 1.设置着色器编译目标等级
#pragma target 4.0
#pragma vertex vert
// 2.声明几何着色器方法
#pragma geometry geo
#pragma fragment frag
#include "UnityCG.cginc"
struct v2g {
float4 pos : SV_POSITION;
};
struct g2f {
float4 pos : SV_POSITION;
};
fixed4 _WireFrameColor;
v2g vert(appdata_base v)
{
v2g o;
o.pos = UnityObjectToClipPos(v.vertex);
return o;
}
// 输入: point line triangle
// 输出: PointStream LineStream TriangleStream
// Append
// triStream.RestartStrip
// 3.指定几何着色器方法内添加的顶点数
[maxvertexcount(3)]
void geo(triangle v2g p[3], inout LineStream<g2f> stream)
{
g2f o;
o.pos = p[0].pos;
stream.Append(o);
o.pos = p[1].pos;
stream.Append(o);
o.pos = p[2].pos;
stream.Append(o);
}
fixed4 frag(g2f i) : SV_Target
{
return _WireFrameColor;
}
ENDCG
}
}
}
#pragma target 4.0
#pragma target 4.0
#pragma target
用来指定着色器的编译目标等级。
几何着色器在Shader Model 4.0及以上才支持。比如OpenGL ES2.0是不支持的,也就是说几何着色器目前基本只能在PC端使用。具体哪些平台支持Shader Model 4.0呢?可通过查看Unity官方文档,https://docs.unity3d.com/Manual/SL-ShaderCompileTargets.html。
#pragma geometry geo
指定几何着色器的方法名,这没什么可说的,与顶点着色器和片元着色器一样。
[maxvertexcount(num)]
几何着色器方法名上必须添加。其用来定义几何着色器中输出顶点的最大数量,输出顶点可以每次都不同,但是不能超过这个值。
[NVIDIA08]指出,当GS输出在1到20个标量之间时,可以实现GS的性能峰值,如果GS输出在27-40个标量之间,则性能下降50%。
void geo(triangle v2g p[3], inout LineStream
几何着色器方法,返回类型为void。triangle v2g p[3]
为输入图元,triangle表示输入图元类型为三角形。输入图元类型如下。
| 输入类型 | 描述 | 顶点数量 |
| :————: | :————: | :————: |
| point | 输入图元为点 | 1 |
| line | 输入图元为线 | 2 |
| triangle | 输入图元为三角形 | 3 |
| lineadj | 输入图元为带有邻接信息的直线,由4个顶点构成3条线 | 4 |
| triangleadj | 输入图元为带有邻接信息的三角形,由6个顶点构成 | 6 |v2g
为我们自定义的顶点着色器到几何着色器的结构体。
inout LineStream<g2f> stream
为输出图元。inout为关键词,LineStream表示输出图元类型为线,g2f为我们自定义的几何着色器到片元着色器的结构体。
输出类型 | 描述 |
---|---|
PointStream | 输出图元为点 |
LineStream | 输出图元为线 |
TriangleStream | 输出图元为三角形 |
需要注意的是
每个输出的顶点都要Append到输出流中。
对于TriangleStream,Append足够的顶点数(3个)后,还需要调用一次RestartStrip,然后再继续构成下一图元。
3 几何着色器实现的效果
- k神的瞬移效果
https://lab.uwa4d.com/lab/5bc54e8404617c5805d4e89b - 模型爆炸、沙化
https://blog.csdn.net/xdedzl/article/details/89644365 - 法线可视化
https://blog.csdn.net/qq_31804159/article/details/80372596 - 网格线
https://blog.csdn.net/sinat_25415095/article/details/110846743 - 溶解扩散
https://blog.csdn.net/qq_37925032/article/details/82936769
博主个人博客本文链接。
哇,(鼓掌)竟然说到这个。