235 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
		
		
			
		
	
	
			235 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| 
								 | 
							
								## 纯Shader
							 | 
						|||
| 
								 | 
							
								- Uniform代表该变量在顶点与片元着色器中值都是相同的。
							 | 
						|||
| 
								 | 
							
								- fixed:低精度数字,它们以精度来换取移动设备上的速度。在台式机上,fixed只是float的别名。
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								## 内置库
							 | 
						|||
| 
								 | 
							
								- UnityShaderVariables.cginc定义了渲染所需的一堆着色器变量,例如变换,相机和光照数据。这些都在需要时由Unity设置。
							 | 
						|||
| 
								 | 
							
								- HLSLSupport.cginc进行了设置,因此无论代码针对的是哪个平台,都可以使用相同的代码进行编写。无需担心使用特定于平台的数据类型等。
							 | 
						|||
| 
								 | 
							
								- UnityInstancing.cginc专门用于实例化支持,这是一种减少绘制调用的特定渲染技术。尽管它不直接包含文件,但依赖于UnityShaderVariables。
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								## 关键字
							 | 
						|||
| 
								 | 
							
								### PropertyType
							 | 
						|||
| 
								 | 
							
								- Int
							 | 
						|||
| 
								 | 
							
								- Float
							 | 
						|||
| 
								 | 
							
								- Range
							 | 
						|||
| 
								 | 
							
								- Color
							 | 
						|||
| 
								 | 
							
								- Vector
							 | 
						|||
| 
								 | 
							
								- 2D      texture
							 | 
						|||
| 
								 | 
							
								- Cube    texture
							 | 
						|||
| 
								 | 
							
								- 3D      texture
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								### SubShader
							 | 
						|||
| 
								 | 
							
								针对不同性能的显卡适配不同的Shader。
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								SubShader{
							 | 
						|||
| 
								 | 
							
								    [Tags]
							 | 
						|||
| 
								 | 
							
								    
							 | 
						|||
| 
								 | 
							
								    [RenderSetup]
							 | 
						|||
| 
								 | 
							
								    
							 | 
						|||
| 
								 | 
							
								    Pass{
							 | 
						|||
| 
								 | 
							
								        
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								### Fallback关键字
							 | 
						|||
| 
								 | 
							
								Fallback关键词用于处理匹配失败的情况,指定一个用于处理这个情况的Pass或者直接跳过。
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								>FallBack Off
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								### CGPROGRAM与ENDCG
							 | 
						|||
| 
								 | 
							
								里面编写这里编写HLSL/CG,对于VertexShader与PixelShader则写在SubShader的Pass关键字的{}中。
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								## 内置变量
							 | 
						|||
| 
								 | 
							
								### 矩阵
							 | 
						|||
| 
								 | 
							
								- UNITY_MATRIX_MVP
							 | 
						|||
| 
								 | 
							
								- UNITY_MATRIX_MV
							 | 
						|||
| 
								 | 
							
								- UNITY_MATRIX_P
							 | 
						|||
| 
								 | 
							
								- UNITY_MATRIX_VP
							 | 
						|||
| 
								 | 
							
								- UNITY_MATRIX_T_MV
							 | 
						|||
| 
								 | 
							
								- UNITY_MATRIX_IT_MV
							 | 
						|||
| 
								 | 
							
								- _Object2World
							 | 
						|||
| 
								 | 
							
								- _World2Object
							 | 
						|||
| 
								 | 
							
								- unity_WorldToObject
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								### 摄像机
							 | 
						|||
| 
								 | 
							
								- WorldSpaceCameraPos
							 | 
						|||
| 
								 | 
							
								- ProjectionParams
							 | 
						|||
| 
								 | 
							
								- ScreenParams
							 | 
						|||
| 
								 | 
							
								- ZBufferParams
							 | 
						|||
| 
								 | 
							
								- unity_OrthoParams
							 | 
						|||
| 
								 | 
							
								- unity_CameraProjection
							 | 
						|||
| 
								 | 
							
								- unity_CameraInvProjection
							 | 
						|||
| 
								 | 
							
								- unity_CameraWorldClipPlanes[6]
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								### 灯光
							 | 
						|||
| 
								 | 
							
								- UNITY_LIGHTMODEL_AMBIENT
							 | 
						|||
| 
								 | 
							
								- _WorldSpaceLightPos0
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								## 定义VS与PS名称
							 | 
						|||
| 
								 | 
							
								```c++
							 | 
						|||
| 
								 | 
							
								#pragma vertex vert
							 | 
						|||
| 
								 | 
							
								#pragma fragment frag
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								## UnityCG.cginc
							 | 
						|||
| 
								 | 
							
								### 常用结构体
							 | 
						|||
| 
								 | 
							
								- appdata_base float4 vertex : POSITION; float3 normal : NORMAL; float4 texcoord: TEXCOORD0;
							 | 
						|||
| 
								 | 
							
								- appdata_tan float4 vertex : POSITION; float4 tangent : TANGENT; float3 normal : NORMAL; float4 texcoord : TEXCOORD0;	
							 | 
						|||
| 
								 | 
							
								- appdata_full float4 vertex : POSITION; float4 tangent : TANGENT; float3 normal : NORMAL; float4 texcoord : TEXCOORD0; float4 texcoord1 : TEXCOORD1; float4 texcoord2 : TEXCOORD2; float4 texcoord3 : TEXCOORD3; # if defined(SHADER_API_XBOX360) half4 texcoord4 : TEXCOORD4; half4 texcoord5 : TEXCOORD5; # endif fixed4 color : COLOR;
							 | 
						|||
| 
								 | 
							
								- appdata_img float4 vertex : POSITION; half2 texcoord : TEXCOORD0;
							 | 
						|||
| 
								 | 
							
								- v2f_img 裁剪空间中的位置、纹理坐标
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								### 常用函数
							 | 
						|||
| 
								 | 
							
								- float4 WorldSpaceViewDir(float4 v)输入一个模型空间中的顶点位置,返回世界空间中从该点到摄像机的观察方向
							 | 
						|||
| 
								 | 
							
								- float4 UnityWorldSpaceViewDir(float4 v)输入一个世界空间中的顶点位置,返回世界空间中从该点到摄像机的观察方向
							 | 
						|||
| 
								 | 
							
								- float4 ObjSpaceViewDir(float4 v)输入一个模型空间中的顶点位置,返回模型空间中从该店到摄像机的观察方向
							 | 
						|||
| 
								 | 
							
								- float4 WorldSpaceLightDir(flaot4 v)仅用于向前渲染。 输入一个模型空间中的顶点位置,返回世界空间中从该点到光源的光照方向。没有被归一化
							 | 
						|||
| 
								 | 
							
								- float4 ObjectSpaceLightDir(float4 v)仅用于向前渲染中,输入一个模型空间中的顶点位置, 返回模型空间中从该点到光源的光照方向。没有被归一化
							 | 
						|||
| 
								 | 
							
								- float4 UnityWorldSpaceLightDir(float4 v)仅用于向前渲染中,输入一个世界空间中的顶点位置, 返回世界空间中从该点到光源的光照方向。没有被归一化
							 | 
						|||
| 
								 | 
							
								- float3 UnityObjectToWorldNormal(float3 norm)把法线方向从模型空间中转换到世界空间中
							 | 
						|||
| 
								 | 
							
								- float3 UnityObjectToWorldDir(float3 dir)把方向矢量从模型空间中变换到世界空间中
							 | 
						|||
| 
								 | 
							
								- float3 Unity WorldToObjectDir(float3 dir)把方向矢量从世界空间变换到模型空间中
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								## 浮点格式
							 | 
						|||
| 
								 | 
							
								float:32位
							 | 
						|||
| 
								 | 
							
								half:16位 -60000~+60000
							 | 
						|||
| 
								 | 
							
								fixed:11位 -2.0~+2.0
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								## 贴图
							 | 
						|||
| 
								 | 
							
								`Sampler2D _MainTex`使用类似`float4 _MainTex_ST`作为缩放与位移。
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								## 管线LightMode
							 | 
						|||
| 
								 | 
							
								定义在Pass内的Tag{}中。
							 | 
						|||
| 
								 | 
							
								- Always:总是渲染,但不计算任何光照。
							 | 
						|||
| 
								 | 
							
								- ForwardBase:用于前向渲染,该Pass会计算环境光、平行光、逐顶点SH与LightMap。
							 | 
						|||
| 
								 | 
							
								- ForwardAdd:用于前向渲染,该Pass会计算额外的逐像素光源,每个Pass对应一个光源。
							 | 
						|||
| 
								 | 
							
								- Deferred:用于延迟渲染,该Pass会计算GBuffer。
							 | 
						|||
| 
								 | 
							
								- ShadowCaster:把物体的深度信息渲染ShadowMap或是一张深度纹理中。
							 | 
						|||
| 
								 | 
							
								- PrepassBase:用于遗留的延迟渲染,该Pass会渲染法线和高光反射的指数部分。
							 | 
						|||
| 
								 | 
							
								- PrepassFinal:用于遗留的延迟渲染,该Pass通过合并纹理、光照和自发光来渲染得到最终的颜色。
							 | 
						|||
| 
								 | 
							
								- Vertex、VertexLMRGBM、VertexLM:用于遗留的顶点光照渲染。
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								## 不透明物体的渲染顺序
							 | 
						|||
| 
								 | 
							
								1. 先渲染所有不透明物体,并开启深度测试与深度写入
							 | 
						|||
| 
								 | 
							
								2. 把半透明物体按它距离摄像机的远近进行排序 ,然后按照从后往前的顺序渲染这些半透明物体,并开启它们的深度测试,但关闭深度写入。
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								### Unity3d的解决方案
							 | 
						|||
| 
								 | 
							
								定义了5个渲染队列
							 | 
						|||
| 
								 | 
							
								- Backgrouond
							 | 
						|||
| 
								 | 
							
								- Geometry
							 | 
						|||
| 
								 | 
							
								- AlphaTest
							 | 
						|||
| 
								 | 
							
								- Transparent
							 | 
						|||
| 
								 | 
							
								- Overlay
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								可以在Tags定义队列:
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								SubShader{
							 | 
						|||
| 
								 | 
							
								    Tags{"Queue"="AlphaTest"}
							 | 
						|||
| 
								 | 
							
								    Pass{
							 | 
						|||
| 
								 | 
							
								        ZWrite Off
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								### Blend相关命令
							 | 
						|||
| 
								 | 
							
								BlendOff
							 | 
						|||
| 
								 | 
							
								BlendSrcFactorDstFactor
							 | 
						|||
| 
								 | 
							
								BlendSrcFactorDstFactor,SrcFactorA DstFactorA
							 | 
						|||
| 
								 | 
							
								BlendOp BlendOperation
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								### 混合操作
							 | 
						|||
| 
								 | 
							
								1. Add
							 | 
						|||
| 
								 | 
							
								2. Sub
							 | 
						|||
| 
								 | 
							
								3. RevSub
							 | 
						|||
| 
								 | 
							
								4. Min
							 | 
						|||
| 
								 | 
							
								5. Max
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								### 常见的混合类型
							 | 
						|||
| 
								 | 
							
								1. Blend SrcAlpha OneMinusSrcAlpha      正常
							 | 
						|||
| 
								 | 
							
								2. Blend OneMinusDstColor One           柔和相加
							 | 
						|||
| 
								 | 
							
								3. Blend DstColor Zero                  正片叠底
							 | 
						|||
| 
								 | 
							
								4. Blend DstColor SrcColor              两倍相乘
							 | 
						|||
| 
								 | 
							
								5. BlendOp Min Blend One One            变暗
							 | 
						|||
| 
								 | 
							
								6. BlendOp Max Blend One One            变亮
							 | 
						|||
| 
								 | 
							
								7. Blend One One                        线性减淡
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								### 解决半透明乱序问题
							 | 
						|||
| 
								 | 
							
								1. 使用两个Pass来渲染模型,第一个Pass开启深度写入,但不输出颜色。第二个Pass进行正常的透明度混合。
							 | 
						|||
| 
								 | 
							
								2. 双面渲染的透明效果
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								## 剔除命令
							 | 
						|||
| 
								 | 
							
								Cull Back | Front | Off
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								## 内置时间变量
							 | 
						|||
| 
								 | 
							
								- _Time:场景加载开始到现在的时间,4个分量为:t/20,t,2t,3t
							 | 
						|||
| 
								 | 
							
								- _SinTime:时间的正弦值,4个分量为:t/8,t/4,t/2,t
							 | 
						|||
| 
								 | 
							
								- _CosTime:时间的余弦值,4个分量为:t/8,t/4,t/2,t
							 | 
						|||
| 
								 | 
							
								- untiy_DeltaTime:dt为时间的增量,4个分量为:dt,1/dt,SmoothDt,1/SmoothDt
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								## 预处理命令
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								### multi_compile
							 | 
						|||
| 
								 | 
							
								`multi_compile`定义的宏,如`#pragma multi_compile_fog`,`#pragma multi_compile_fwdbase`等,基本上适用于大部分shader,与shader自身所带的属性无关。
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								### shader_feature
							 | 
						|||
| 
								 | 
							
								`shader_feature`定义的宏多用于针对shader自身的属性。比如shader中有`_NormalMap`这个属性(Property),便可通`过#pragma shader_feature _NormalMap`来定义宏,用来实现这个shader在material有无`_NormalMap`时可进行不同的处理。
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								## 优化
							 | 
						|||
| 
								 | 
							
								减少Draw Call的方式有动态合批与静态合批。Unity中支持两种批处理方式:一种是动态批处理,一种是静态批处理。对于动态批处理来说,有点是一切处理都是Unity自动完成的,不需要我们自己做任何操作,而且物体是可以移动的,但缺点是,限制很多,可能一不小心就会破坏了这种机制,导致Unity无法动态批处理一些使用了相同材质的物体。
							 | 
						|||
| 
								 | 
							
								而对于静态批处理来说,它的优点是自由度很高,限制很少;但缺点是可能会占用更多的内存,而且经过静态批出里的所有物体都不可以再移动了。
							 | 
						|||
| 
								 | 
							
								动态批处理的原理是,每一帧把可以进行批处理的模型网格进行合并,再把合并后模型数据传递给GPU,然后使用同一个材质对其渲染。处理实现方便,动态批处理的另一个好处是,经过批处理的物体仍然可以移动,这是由于在处理每帧时Unity都会重新合并一次网格。
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								### 共享材质
							 | 
						|||
| 
								 | 
							
								将多张纹理合并到一起,并且制作成材质。
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								### 动态合批
							 | 
						|||
| 
								 | 
							
								在使用同一个材质的情况下,满足的条件后就会被动态处理,每帧都会合并一次。条件:
							 | 
						|||
| 
								 | 
							
								- 能够进行动态批处理的网格顶点属性规模要小于900.例如,如果Shader中需要使用顶点位置、法线和纹理坐标这3个顶点属性,那么想要让模型能够被动态批处理,它的顶点数目不能超过300。需要注意的是,这个数字未来有可能会发生变化,因此不要依赖这个数据。
							 | 
						|||
| 
								 | 
							
								- 一般来说,所有对象都需要使用同一个缩放尺度。一个例外的情况是,如果所有的物体都使用了不同的非统一缩放,那么它们也是可以被动态批处理的。但在Unity 5 中,这种对模型缩放的限制已经不存在了。
							 | 
						|||
| 
								 | 
							
								- 使用光照纹理的物体需要格外小心处理。这些物体需要额外的渲染参数,例如,在光照纹理上的索引、偏移量和缩放信息等。因此,为了让这些物体可以被动态批处理,我们需要保证它们指向光照纹理中的同一个位置。
							 | 
						|||
| 
								 | 
							
								- 多Pass的Shader会中断批处理。在前向渲染中,我们有时需要使用额外的Pass来为模型添加更多的光照效果,但这样一来模型就会被动态批处理了。
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								### 静态合批
							 | 
						|||
| 
								 | 
							
								在运行开始阶段,把需要进行静态批处理的模型合并到一个新的网格结构中。
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								## GeometryShader
							 | 
						|||
| 
								 | 
							
								>ShaderModel必须4.0以上`#program target 4.0`,如果低于这个目标,u3d会自定提升至该级别。
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								- maxvertexcount定义输出顶点数,如果只是处理三角形只需要设置为3即可。
							 | 
						|||
| 
								 | 
							
								- triangle为输入类型关键字。
							 | 
						|||
| 
								 | 
							
								- TriangleStream为输出流类型。
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								[maxvertexcount(3)]
							 | 
						|||
| 
								 | 
							
								void MyGeometryProgram (
							 | 
						|||
| 
								 | 
							
									triangle InterpolatorsVertex i[3],
							 | 
						|||
| 
								 | 
							
									inout TriangleStream<InterpolatorsGeometry> stream
							 | 
						|||
| 
								 | 
							
								)
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								### Flat线框效果(CatLikeCoding中的案例)
							 | 
						|||
| 
								 | 
							
								向三角形添加重心坐标的一种方法是使用网格的顶点颜色存储它们。每个三角形的第一个顶点变为红色,第二个顶点变为绿色,第三个顶点变为蓝色。但是,这将需要具有以此方式分配的顶点颜色的网格,并且无法共享顶点。我们想要一种适用于任何网格的解决方案。幸运的是,我们可以使用我们的几何程序添加所需的坐标。
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								由于网格不提供重心坐标,因此顶点程序不了解它们。所以,它们不属于InterpolatorsVertex结构。要使几何程序输出它们,我们必须定义一个新结构。首先在MyGeometryProgram上方定义InterpolatorsGeometry。它应包含与InterpolatorsVertex相同的数据,因此使用它作为其内容
							 | 
						|||
| 
								 | 
							
								```hlsl
							 | 
						|||
| 
								 | 
							
								struct InterpolatorsGeometry {
							 | 
						|||
| 
								 | 
							
									InterpolatorsVertex data;
							 | 
						|||
| 
								 | 
							
									CUSTOM_GEOMETRY_INTERPOLATORS
							 | 
						|||
| 
								 | 
							
								};
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								- MyGeometryProgram的作用为调整按照面法线调整顶点法线;在调整barycentricCoordinates值,最后塞入inout TriangleStream<InterpolatorsGeometry>中。
							 | 
						|||
| 
								 | 
							
								- GetAlbedoWithWireframe为线控效果控制,最终会在My Lighting.cginc中以宏替换的方式整合至渲染流程中。
							 | 
						|||
| 
								 | 
							
								```hlsl
							 | 
						|||
| 
								 | 
							
								float3 GetAlbedoWithWireframe (Interpolators i) {
							 | 
						|||
| 
								 | 
							
									float3 albedo = GetAlbedo(i);
							 | 
						|||
| 
								 | 
							
									float3 barys;
							 | 
						|||
| 
								 | 
							
									barys.xy = i.barycentricCoordinates;
							 | 
						|||
| 
								 | 
							
									barys.z = 1 - barys.x - barys.y;
							 | 
						|||
| 
								 | 
							
									float3 deltas = fwidth(barys);
							 | 
						|||
| 
								 | 
							
									float3 smoothing = deltas * _WireframeSmoothing;
							 | 
						|||
| 
								 | 
							
									float3 thickness = deltas * _WireframeThickness;
							 | 
						|||
| 
								 | 
							
									barys = smoothstep(thickness, thickness + smoothing, barys);
							 | 
						|||
| 
								 | 
							
									float minBary = min(barys.x, min(barys.y, barys.z));
							 | 
						|||
| 
								 | 
							
									return lerp(_WireframeColor, albedo, minBary);
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								```
							 |