参考
may佬《技术美术百人计划》
Grass Shader
草地交互
图形3.3 曲面细分与几何着色器
Tessellation Shader(TESS)曲面细分着色器
应用
细分直线逼近曲线,细分几何体进行平滑,制作海浪、雪地等地形,与置换贴图结合来改变物体的形状,增加表面细节
- 单独使用置换贴图的问题在于,如果模型的面数不够多,边缘就会非常锐利,效果不好;使用曲面细分着色器使模型面数变多之后,细节的表达会更精确、更平滑
- 使用曲面细分着色器可以根据一定的规则(如距离)来动态地调整模型的复杂度,比起直接使用高模能带来更好的性能
着色器执行顺序(渲染管线)
- Hull Shader:用于定义细分的参数
- Domian Shader:曲面细分之后的点位于重心空间,在Domain Shader中将其转换到我们需要用的空间中
TESS的输入与输出
- 输入:Patch,可以看成是多个顶点的集合,包含每个顶点的属性,可以指定一个Patch包含的顶点数以及自己的属性
- 功能:将图元细分(可以是三角形,矩形等,不同的图元输入参数也不同)
- 输出:细分后的顶点
TESS流程
Hull Shader
- 决定细分数量(设定Tessellation factor 以及Inside Tessellation factor)
- 对输入的Patch参数进行改变
Tessellation Primitive Generation
- 进行细分操作
Domain Shader
- 对细分后的点进行处理,从重心空间(Barycentric coordinate system)转换到屏幕空间
Hull Shader参数解析
Tessellation Factor:决定将一条边分成几部分
-
equal_spacing:向上取整,然后均分成该份数(默认)
-
fractional_even_spacing:向下取偶数整数,然后大部分均分成该份数,剩下的小部分分两半
-
fractional_odd_spacing:向下取奇数整数,然后大部分均分成该份数,剩下的小部分分两半
-
后两种的细分会更加平滑
Inner Tessellation Factor:决定内部的三角形如何生成
- 将边等分之后向内部做垂线,取交点继续细分,直到没有交点或交于重心一点
TESS demo演示
Quad细分
Shader "TA100/TESS/Tess"
{
Properties
{
_TessellationUniform ("Tessellation Uniform", Range(1,64)) = 1
}
SubShader
{
Tags {
"RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
//定义Hull Shader
#pragma hull hullProgram
//定义Domain Shader
#pragma domain ds
#pragma vertex tessvert
#pragma fragment frag
#pragma target 5.0
#include "UnityCG.cginc"
//曲面细分的头文件,其中包含很多有用的辅助函数
#include "Tessellation.cginc"
struct VertexInput
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 tangent : TANGENT;
float2 uv : TEXCOORD0;
};
struct VertexOutput
{
float2 uv : TEXCOORD0;
float3 normal : NORMAL;
float4 tangent : TANGENT;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
VertexOutput vert (VertexInput v) //应用在domain函数中,用来进行空间转换
{
VertexOutput o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.normal = v.normal;
o.tangent = v.tangent;
return o;
}
//TESS并不是所有平台都支持,定义一个宏来保证在不支持的硬件上面不会报错
#ifdef UNITY_CAN_COMPILE_TESSELLATION
struct TessVertex {
float4 vertex : INTERNALTESSPOS;
float3 normal : NORMAL;
float4 tangent : TANGENT;
float2 uv : TEXCOORD0;
};
struct OutputPatchConstant {
//定义path用于Hull Shader
float edge[3] : SV_TESSFACTOR; //不同的图元结构体也会不同,此处为三角形 //mesh中有一个topology属性可以修改图元
float inside : SV_INSIDETESSFACTOR;
};
TessVertex tessvert (VertexInput v) {
//此处没有进行空间转换,只是把信息传到曲面细分着色器中
TessVertex o;
o.vertex = v.vertex;
o.normal =</