Unity3D Shader系列之几何着色器基础


1.什么是几何着色器

最近一直在练习写Shader,发现用几何着色器可以写出特别酷炫的效果。于是去学习了一下,这里做个总结以备查阅。
几何着色器位于渲染流水线的几何阶段,在顶点着色器与片元着色器之间。
GPU流水线
备注:图片来源于冯乐乐的《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 stream) { }
几何着色器方法,返回类型为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 几何着色器实现的效果

4 参考文章

UnityShader中的几何着色器Geometry Shader)是一个可选的着色器阶段,它位于顶点着色器(Vertex Shader)之后,片元着色器(Fragment Shader)之前。几何着色器的主要作用是对输入的图元进行操作,比如产生新的图元,这可以用于实现例如粒子系统、毛发效果等复杂的渲染效果。 在几何着色器中,`triangleadj`是一种图元类型,表示带有相邻顶点的三角形带。这是DirectX 10及以上版本中引入的一种图元类型,与普通的三角形带(`trianglestrip`)不同,`triangleadj`允许每个三角形都访问其相邻的三角形的顶点,这样的相邻信息可以用于生成复杂的几何结构,比如几何体细分或者自定义的轮廓线效果。 在Unity中使用`triangleadj`图元类型,你需要在几何着色器的输入中声明相邻顶点的信息,然后在代码中通过访问这些相邻顶点来进行操作。下面是一个简单的示例代码: ```hlsl [maxvertexcount(6)] void geo(triangleadj VertexInput IN[6], inout TriangleStream<VertexOutput> triStream) { // 假设我们有一个顶点结构体叫做VertexInput,以及输出结构体叫做VertexOutput // 这里是处理每个顶点的代码 // 可以通过IN[0]到IN[5]访问相邻的顶点信息 // 例如,我们可以创建一个新的三角形带,或者对顶点进行其他处理 // ... // 最后将处理后的顶点输出到triStream // ... } ``` 需要注意的是,在Unity中使用几何着色器有一些限制,比如它不支持所有平台,并且在使用时可能需要配置特定的渲染管线。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值