曲面细分着色器总结

先看unity下 Plane的曲面细分效果: 顶点数 由少到多的变化效果。
在这里插入图片描述

  1. 在这里插入图片描述重点: 数据传输和处理 a2v, v2t, v2f 明白这三个数据的存储和赋值, 是理解曲面细分着色器的关键

  2. 代码中注释(最后会附上代码)
    在这里插入图片描述
    在这里插入图片描述
    (1)domain: patch 类型或者叫做模型图元的拓扑结构有效参数为tri,quad,isoline。tri表示三角面

(2)partitioning:指定曲面细分的拆分模式

integer:新的顶点只在细分因子为整数时进行添加或删除,细分因子的小数部分被忽略,这种情况下对于动态曲面细分因子,会出现在某个点(整数点)模型精度突然提高或减低,会有肉眼可见的精度突变
fraction:新的顶点依然在位于整数细分因子时(1.0,2.0,3.0等)进行添加或删除,但是根据细分因子的小数部分进行平滑过度。fraction模式,包括fractional_even和fractional_odd

(3)outputtopology:输出的三角面正面的环绕方式

triangle_cw:顶点顺时针排列代表正面
triangle_ccw:顶点逆时针排列代表正面
line:只针对line的细分

(4)outputcontrolpoints:输出的control point 的数目,同时也是control point hull shader的执行次数,因为每输出一个control point ,都执行一次hull shader.SV_OutputControlPointID语义指定的索引值的总数,对应于这里的control point数目

(5)patchconstantfunc:一个字符串指定的constant hull shader 函数的名字,既前面的constant hull shader

(6)maxtessfactor:告诉硬件最大的细分因子,有了此上限值,硬件可以执行某些优化,例如可以预先知道需要多少资源来执行曲面细分。Direct3D 11支持的最大值为64.其他硬件支持的最大值可能为16,因此unity中使用通常使用16作为最大值上限。

在这里插入图片描述

Shader "Unlit/SnowShader"
{
    Properties
    {
		_Color("Color", Color) = (1,1,1,1)
        _BaceTex ("BaceTex", 2D) = "white" {}
	_SnowColor("SnowColor", Color) = (1,1,1,1)
		_SnowTex("SnowTex", 2D) = "white" {}

	_MaskTex("mask tex",2D) = "white"{}
	_aaaa("TesselationNum",Range(0.1,100)) = 0.145299

		_Displacement("_Displacement",Range(0.1,100)) = 0.5
	}
		SubShader
	{
		Tags { "RenderType" = "Opaque" }
		LOD 100

		Pass
		{
			CGPROGRAM

        #pragma hull hull
        #pragma domain domain

			#pragma vertex tessvert
			#pragma fragment frag

			#include "UnityCG.cginc"
#include "Tessellation.cginc"
#pragma multi_compile_fwdbase_fullshadows
#pragma only_renderers d3d9 d3d11 glcore gles
#pragma target 4.6

		sampler2D _BaceTex,_SnowTex,_MaskTex;
	float4 _MaskTex_ST ;
	float _aaaa;
	float4 _Color, _SnowColor;
	float _Displacement;
            struct VertexInput
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
				float3 normal : NORMAL;
				float4 tangent : TANGENT;

            };

            struct VertexOutput
            {
                float2 uv : TEXCOORD0;
                
                float4 pos : SV_POSITION;
				float3 normal_dir : TEXCOORD1;
				float2 uv_bace : TEXCOORD2;
				float2 uv_snow : TEXCOORD3;
            };
			VertexOutput vert(VertexInput v)
			{
				VertexOutput o = (VertexInput)0;
				o.uv = v.uv;
				o.normal_dir = UnityObjectToWorldNormal(v.normal);

				float4 _MaskTex_var = tex2Dlod(_MaskTex, float4(o.uv, 0, 0));
				float4 _BaceTex_var = tex2Dlod(_BaceTex, float4(o.uv, 0, 0));

				v.vertex.xyz -= v.normal * (_BaceTex_var.r - 0.7 + _MaskTex_var.r) * _Displacement;
				o.pos = UnityObjectToClipPos(v.vertex);
				return o;
			}

#ifdef UNITY_CAN_COMPILE_TESSELLATION
			struct TessVertex {
				float4 vertex : INTERNALTESSPOS;
				float3 normal : NORMAL;
				float4 tangent : TANGENT;
				float2 uv : TEXCOORD0;
			};
			struct OutputPatchConstant {
				float edge[3] : SV_TessFactor;
				float inside : SV_InsideTessFactor;
				float3 vTangent[4] : TANGENT;
				float2 vUV[4] : TEXCOORD;
				float3 vTanUCorner[4] : TANUCORNER;
				float3 vTanVCorner[4] : TANVCORNER;
				float3 vCWts :TANWELIGHTS;
			};
			//将顶点里的处理 传入到曲面细分中
			TessVertex tessvert(VertexInput v) {
				TessVertex o;
				o.vertex = v.vertex;
				o.normal = v.normal;
				o.tangent = v.tangent;
				o.uv = v.uv;
				return o;
			}
			// 曲面细分的  远近控制(近处细分,远处不细分)
			float4 Tessellation(TessVertex v, TessVertex v1, TessVertex v2) {
				float minDist = 1.0;
				float maxDist = 25.0;
				return UnityDistanceBasedTess(v.vertex, v1.vertex, v2.vertex, minDist, maxDist, _aaaa);
			}
			// 曲面细分的强度控制
			float Tessellation(TessVertex v)
			{
				return _aaaa;
			}

			// InputPatch<TessVertex, 3> 表示输入的 patch 为3个 TessVertex 数据,对应三角形 patch 的3个顶点
			OutputPatchConstant hullconst(InputPatch<TessVertex, 3> v) {
				OutputPatchConstant o = (OutputPatchConstant)0;
				float4 ts = Tessellation(v[0], v[1], v[2]);
				// 每个边分成几段	
				o.edge[0] = ts.x;
				o.edge[1] = ts.y;
				o.edge[2] = ts.z;
				// 意味着在三角形内部加入三个新的顶点,但是这个函数并不会创建任何新的顶点,只是会计算出所有新的顶点的重心坐标。
				o.inside = ts.w;
				return o;
			}

			
			[domain("tri")] // 定义特性  输入进hull shader的图元是三角形
			[partitioning("fractional_odd")]// 决定分割方式
			[outputtopology("triangle_cw")]//决定图元的朝向
			[patchconstantfunc("hullconst")]// 补丁常量缓存函数名
			[outputcontrolpoints(3)]//决定三个控制点
			TessVertex hull(InputPatch<TessVertex, 3> v, uint id : SV_OutputControlPointID) {
				return v[id];
			}

			[domain("tri")]
			VertexOutput domain(OutputPatchConstant tessFactors, const OutputPatch<TessVertex, 3> vi, float3 bary : SV_DomainLocation)
			{
				VertexInput v = (VertexInput)0;
				v.vertex = vi[0].vertex * bary.x + vi[1].vertex * bary.y + vi[2].vertex * bary.z;
				v.normal = vi[0].normal * bary.x + vi[1].normal * bary.y + vi[2].normal * bary.z;

				v.tangent = vi[0].tangent * bary.x + vi[1].tangent * bary.y + vi[2].tangent * bary.z;
				v.uv = vi[0].uv * bary.x + vi[1].uv * bary.y + vi[2].uv * bary.z;
				VertexOutput o = vert(v);
				return o;
			}
#endif

            fixed4 frag (VertexOutput i) : SV_Target
            {               
				float4 _MaskTex_var = tex2D(_MaskTex, TRANSFORM_TEX(i.uv,_MaskTex));
			float4 BaceTex_var = tex2D(_BaceTex, i.uv) * _Color;
			float4 SnowTex_var = tex2D(_SnowTex, i.uv) * _SnowColor;
                
			float4 c = lerp(BaceTex_var, SnowTex_var, _MaskTex_var.r);
				float3 finalColor = c.xyz;
                return fixed4(finalColor,1);
            }
            ENDCG
        }
    }
}

曲面细分参数意义
曲面代码详解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值