百人计划(图形)3.3曲面细分与几何着色器

一、曲面细分着色器(Tessellation Shader)

曲面细分(TESS)是利用镶嵌化处理技术对网格中三角形进行细分,以此来增加物体表面上三角形数量,表现出更多的细节。

曲面细分着色器的应用

(1)海浪、雪地等

(2)与置换贴图 

TESS的输入与输出

  • 输入:Patch,可以看成是多个顶点的集合,包含每个顶点的属性;可以指定一个Patch包含的顶点数以及自己的属性​

  • 功能:将图元细分(可以是三角形,矩形等)

  • 输出:细分后的顶点

TESS流程

  • Hull Shader(细分控制着色器):决定细分的数量(设定Tessellation factor以及Inside Tessellation factor)、对输入的Patch参数进行改变(如果需要)

  • Tessellation Primitive Generation:将图元细分(可以是三角形,矩形等)

  • Domain Shader:对细分后的点进行处理,从重心空间(Barycentric coordinate system)转换到屏幕空间

Hull Shader

TessellationFactors patchConstantFunction (InputPatch<vertexInput, 3> patch)
{
	TessellationFactors f;
	f.edge[0] = _TessellationUniform;
	f.edge[1] = _TessellationUniform;
	f.edge[2] = _TessellationUniform;
	f.inside = _TessellationUniform;
	return f;
}

[UNITY_domain("tri")]
[UNITY_outputcontrolpoints(3)]
[UNITY_outputtopology("triangle_cw")]
[UNITY_partitioning("integer")]
[UNITY_patchconstantfunc("patchConstantFunction")]
vertexInput hull (InputPatch<vertexInput, 3> patch, uint id : SV_OutputControlPointID)
{
	return patch[id];
}

 重要特性解析:

  • [UNITY_domain("tri")]:指明输入进hull shader的图元是三角形

  • [UNITY_outputcontrolpoints(3)]:为hull shader输出的outputpatch中的顶点数量

  • [UNITY_outputtopology("triangle_cw")]:决定图元的朝向,由组成三角形的三个顶点的顺序所产生的方向决定,cw为clockwise顺时针,ccw为counter clockwise逆时针

  • [UNITY_partitioning("integer")]:决定舍入规则

integer:细分层将被截断在[1,max]范围内,然后取整到下一个整数值。

 

fractional_odd:数值将被截断在[1,max]范围内,然后取整到下一个奇数整数值n,然后将边界划分为n-2个等长的部分以及2个位于两端的部分。

fractional_oven:数值将被截断在[1,max]范围内,然后取整到下一个偶数整数值n,然后将边界划分为n-2个等长的部分以及2个位于两端的部分。

  • [UNITY_patchconstantfunc("hsconst")]:指明计算factor的方法,然后在方法hsconst中计算每个边的Tessellation factor和内部的Inside Tessellation factor。

Domain Shader

[UNITY_domain("tri")]
vertexOutput domain(TessellationFactors factors, OutputPatch<vertexInput, 3> patch, float3 barycentricCoordinates : SV_DomainLocation)
{
	vertexInput v;

	#define MY_DOMAIN_PROGRAM_INTERPOLATE(fieldName) v.fieldName = \
		patch[0].fieldName * barycentricCoordinates.x + \
		patch[1].fieldName * barycentricCoordinates.y + \
		patch[2].fieldName * barycentricCoordinates.z;

	MY_DOMAIN_PROGRAM_INTERPOLATE(vertex)
	MY_DOMAIN_PROGRAM_INTERPOLATE(normal)
	MY_DOMAIN_PROGRAM_INTERPOLATE(tangent)

	return tessVert(v);
}

  重要特性解析:

  • [UNITY_domain(“tri”)]:决定了输入数据SV_DomainLocation的类型,不同类型图元使用不同长度的向量

二、几何着色器(Geometry Shader)

几何着色器的应用

(1)几何动画

(2)草地等(与曲面细分着色器结合)

GS的输入与输出

  • 输入:图元(三角形、矩形、线等);根据图元的不同,shader中会出现对应不同数量的顶点

  • 输出:图元,一个或多个;需要自己从顶点构建,顺序很重要,同时需要定义最大输出的顶点数

Geo Shader

[maxcertexcount(N)]
void ShaderName (PrimitiveType InputVertexType InputName[NumElements],
                inout StreamOutputObjectVertexType) OutputName){
    // 几何着色器具体实现
    StreamOutputObjectVertexType gout;
    OutputName.Append(gout);
    OutputName.RestartStrip();
    OutputName.Append(gout);
}

解释说明: 

1.[maxcertexcount(N)]:用来指定几何着色器单次调用所输出的最大顶点数量

2.PrimitiveType:输入图元的类型,必须对应输入装配阶段的图元拓扑类型

  • point:输入图元拓扑类型为点列表

  • line:输入图元拓扑类型为线列表或线条带

  • triangle:输入的图元拓扑类型为三角形列表或三角形带

  • lineadj:输入的图元拓扑类型为线条列表/带及其邻接图元

  • triangleadj:输入的图元为三角形列表/带及其邻接图元

3.StreamOutputObjectVertexType:流类型(stream type) ,存有一系列顶点,它们定义了几何着色器输出的几何图形

  • PointStream<OutputVertexType>:一系列顶点所定义的点列表

  • LineStream<OutputVertexType>:一系列顶点所定义的线条带

  • TriangleStream<OutputVertexType>:一系列顶点所定义的三角形带

4.Append函数:用来将几何着色器的输出数据追加到一个现有的流中

5.RestartStrip函数:用来结束当前的基元条带,开始一个新的条带;如果当前的条带没有足够的顶点被追加出来以填满基元拓扑结构,那么末端的不完整基元将被丢弃

三、草地应用案例

 具体参考:Unity Grass Shader Tutorial (roystan.net)

增加了与草地的互动:

geometryOutput VertexOutput(float3 pos, float2 uv, float3 normal)
{
    geometryOutput o;

	float3 worldPos = mul(unity_ObjectToWorld, pos);
	float dis = distance(worldPos, _PlayerPos);
	float forceStrength = saturate((_InteractRadius - dis) * _InteractStrength);
	float3 forceDir = normalize(worldPos - _PlayerPos);
	float3 force = forceStrength * forceDir;
	worldPos.xyz += force;

	o.pos = UnityWorldToClipPos(worldPos);
	o.uv = uv;
	o._ShadowCoord = ComputeScreenPos(o.pos);
	o.normal = UnityObjectToWorldNormal(normal);

	#if UNITY_PASS_SHADOWCASTER
		// Applying the bias prevents artifacts from appearing on the surface.
		o.pos = UnityApplyLinearShadowBias(o.pos);
	#endif		
	return o;
}	

思路很简单,通过草的顶点位置减去需要交互物体的位置得到草受力的方向,让其顶点在此方向上偏移即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值