Unity Shader中各部分定义内容详解

Unity Shader中各部分定义内容详解

样板

Shader "Practice/Unlit/SimpleUnlit"
{
	Properties
	{
		_MainTex ("Texture", 2D) = "white" {}
		_Num ("Float", float) = 0
		_RangeNum ("Range Number", Range(0, 1)) = 0
	}
	SubShader
	{
		Tags { "RenderType"="Opaque" }
		LOD 100

		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			// make fog work
			#pragma multi_compile_fog
			
			#include "UnityCG.cginc"

			struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
			};

			struct v2f
			{
				float2 uv : TEXCOORD0;
				UNITY_FOG_COORDS(1)
				float4 vertex : SV_POSITION;
			};

			sampler2D _MainTex;
			float4 _MainTex_ST;
			
			v2f vert (appdata v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.uv = TRANSFORM_TEX(v.uv, _MainTex);
				UNITY_TRANSFER_FOG(o,o.vertex);
				return o;
			}
			
			fixed4 frag (v2f i) : SV_Target
			{
				// sample the texture
				fixed4 col = tex2D(_MainTex, i.uv);
				// apply fog
				UNITY_APPLY_FOG(i.fogCoord, col);
				return col;
			}
			ENDCG
		}
	}
  FallBack "Diffuse"
}

Shader “Practice/Unlit/SimpleUnlit”

Shader "Practice/Unlit/SimpleUnlit"

定义shader及其在材质中的指定路径
Unity Shader中各部分定义内容详解

Properties

	Properties
	{
		_MainTex ("Texture", 2D) = "white" {}
		_Num ("Float", float) = 0
		_RangeNum ("Range Number", Range(0, 1)) = 0
	}

定义了显示在材质面板上的属性
Unity Shader中各部分定义内容详解

数据定义

变量名 (“变量表现名”, 变量类型) = 变量默认值

变量类型 默认值
Float float
Vector (x, y, z, w) //float
Range(min, max) float
Color (float, float, float, float) //0~1
2D “”{option}
Cube “”{option}
Rect “”{option}

Color: 范围是0~1

2D、Cube、Rect: 默认值可以为一个代表默认tint颜色的字符串 “white”,“black”,“gray”,“bump” 或 “”

​ {option}字段中,option可取:

​ option: ObjectLinear, EyeLinear, SphereMap, CubeReflect, CubeNormal

SubShader

	SubShader
	{
		...
	}

一个Shader中可以有多个SubShader,以便适配不同的硬件配置

Shader在执行过程中会依次检测SubShader,直到找到一个可以执行的SubShader,或在最后通过FullBack字段执行默认SubShader

SubShader Tags

//Tags { "TagName1" = "Value1" "TagName2" = "Value2" }
Tags { "RenderType"="Opaque" }
定义

Tags { “TagName1” = “Value1” “TagName2” = “Value2” }

SubShader中定义的Tags会应用于当前SubShader的所有Pass

  • Rendering Order - Queue tag

设置渲染队列顺序

Option 描述
Background 最先被调用的渲染,通常用来渲染背景
Geometry**(default)** 默认值,大多数物体使用此队列,用来渲染不透明的物体
AlphaTest 透明度测试模式,在绘制Geometry之后,进行透明度测试,透明物体会被直接放弃渲染
Transparent 这个渲染队列是在Geometry和AlphaTest之后,以从后往前的顺序渲染的。 任何alpha混合(alpha-blended )(即不写入深度缓冲区depth buffer的Shader)应该在这里。例如玻璃,粒子效果。
Overlay 此渲染队列用于叠加效果。 任何最后呈现的东西都应该在这里(例如镜头光晕)

示例:

Tags { "Queue"="Transparent" }

实际上Queue的每个Option在内部被解释成固定的数值索引:

Background=1000,Geometry=2000,AlphaTest=2450,Transparent=3000和Overlay=4000.

就是渲染队列的索引

例如

Tags { "Queue"="Geometry+1" }

代表该SubShader在所有不透明物体之后,透明物体之前渲染,渲染队列的索引是2001

对于“透明物体”考虑较高的渲染队列,并按距离对物体进行排序,从最远的一个开始渲染,并以最近的一个结束。 天空盒在所有不透明和所有透明对象之间绘制。

注意:

渲染队列只是指定渲染顺序,和透明与否无关

  • RenderType tag
Option 说明
Opaque 用于大多数着色器(法线着色器、自发光着色器、反射着色器以及地形的着色器),告 诉了系统应该在渲染非透明物体时调用我们
Transparent 用于半透明着色器(透明着色器、粒子着色器、字体着色器、地形额外通道的着色器)
TransparentCutout 蒙皮透明着色器(Transparent Cutout,两个通道的植被着色器)
Background Skybox shaders. 天空盒着色器
Overlay 光晕着色器、闪光着色器
TreeOpaque 地形引擎中的树皮
TreeTransparentCutout 地形引擎中的树叶
TreeBillboard 地形引擎中的广告牌树
Grass 地形引擎中的草
GrassBillboard 地形引擎何中的广告牌草

这些RenderType的类型名称实际上是一种约定,用来区别这个Shader要渲染的对象,当然你也可以改成自定义的名称,只不过需要自己区别场景中不同渲染对象使用的Shader的RenderType的类型名称不同,也就是说RenderType类型名称使用自定义的名称并不会对该Shader的使用和着色效果产生影响。

指定RenderType的名称,主要是为了配合使用替代渲染的方法:

Camera.SetReplacementShader("shader","RenderType")  

在使用替代渲染方法时,相机会使用指定的 shader 来代替场景中的其他 shader 对场景进行渲染.

SetReplacementShader(A ,""; 					//将场景中所有用到的材质的shader类型改成A
SetReplacementShader(A ,"RanderType";	//场景中Shader的RenderType的值和A的值相等,则Shader替换为A渲染,否则不渲染

示例:

1.将所有不透明物体shader替换为一种subShader进行渲染,同时将所有透明物体shader替换为另一种shader进行渲染:

写一个shaderA,让其中一个subShader包含一个带“RenderType”=“Opaque"标签,再写一个带"RenderType”="Transparent"标签的subShader

然后调用

GetComponent<Camera>().RenderWithShader(Shader.Find("shaderA"), "RenderType");

总结:

RenderType tag不使用替换渲染的话,就没有任何意义

  • DisableBatching tag
Option 说明
true 关闭Batching
false 开启Batching(默认)

批处理技术

很多着色器中,如果使用的Batching技术,物体的模型空间中的位置信息都没了。如果要设计的模型空间坐标系的操作的shader,就得禁用 Batching,保存模型空间的信息。 我们可以使用 "DisableBatching "=“True”,默认都是“False”

  • ForceNoShadowCasting tag
Option 说明
true 表示不受其它物体投掷阴影影响
false 表示接受其他物体投掷阴影影响(默认)

一般用于渲染半透明物体时,不接受其他物体阴影,则设置为true

  • IgnoreProjector tag
Option 说明
true 表示不受其贴图投影影响
false 表示接受贴图投影的影响(默认)

unity有种贴图投影方式,类似古老的2d游戏中,人物脚下的贴图投影(非光照造成的)

  • CanUseSpriteAtlas tag
Option 说明
true 启用图集
false 不启用图集

如果该着色器片段仅用于处理图片(sprite)时,请设置【CanUseSpriteAtlas】的值为False,当想把图片打包成图集时,这个命令不会其作用。

  • PreviewType tag
Option 说明
Plane 材质展示为平面
Cube 材质展示为正方体
Sphere 材质展示为球体(默认)
Cylinder 材质展示为圆柱体

指明材质面板将如何预览该材质。默认情况下,材质将显示为一个球型,我们可以通过把该标签的值设为“Plane” “SkyBox” 来改变预览类型

Pass

		Pass
		{
			...
		}

定义在SubShader中,一个SubShader中可以有多个Pass,执行具体的渲染步骤

Shader在执行当前SubShader时,会依次执行其中的Pass

注:一些材质效果可能由多个渲染步骤组合而成,例如双面材质,可以在两个Pass中分别渲染正面和反面

命名Pass
Name "PassName"

为当前Pass命名, 在SubShader中, 可以用UsePass来使用当前Pass

#####Pass Tags

  • LightMode tag
Option 说明
Always 始终渲染;没有光照
ForwardBase 用于正向渲染,应用环境光,主平行光,顶点/ SH光和光照贴图
ForwardAdd 用于正向渲染,应用逐像素添加的光照,每个光照都会通过pass一次
Deferred 用于延时着色,渲染g-buffer
ShadowCaster 将对象深度渲染到阴影贴图或深度纹理中
MotionVectors 用于计算每个对象的运动矢量
PrepassBase 用于旧的延时光照,渲染法线和镜面反射指数
PrepassFinal 用于旧的延时光照,通过组合纹理,光照和自发光来渲染最终颜色
Vertex 当对象未进行光照贴图时,用于旧的顶点光照渲染 ; 应用所有顶点光照
VertexLMRGBM 在对象进行光照贴图时用于旧的Vertex光照渲染;在lightmap是RGBM编码的平台上(PC和控制台)
VertexLM 在对象进行光照贴图时用于旧的Vertex光照渲染;在光照贴图采用双LDR编码的平台上(移动平台)

LightMode tag定义了pass在光照流水线中的角色。这些tag很少手动调用,大多数需要与光照交互的shader都会被写成表面shader,并且所有这些细节都会被考虑到。

  • PassFlags tag

pass可以用这个标志来改变渲染流水线传递数据给它的方式。

目前被Unity支持的是:

OnlyDirectional:当pass使用ForwardBase类型时,这个标志使只有主平行光和环境光/lightprobe数据可以传递到shader。这意味着不重要的光照数据不会被传递到顶点光照或是spherical harmonics shader变量中。查看正向渲染部分获取更多信息。

  • RequireOptions tag

pass通过使用RequireOptions tag声明它只在一些额外的条件被满足的情况下被渲染。

目前被Unity支持的选项是:

SoftVegetation:只有当在Quality Settings选项中Soft Vegetation被开启时才渲染此通道。

混合(Blend)
  • Blend

Blend混合操作是作用于在所有计算之后,是Shader渲染的最后一步,进行Blend操作后就可以显示在屏幕上。

Blend Off //不混合 
Blend SrcFactor DstFactor //SrcFactor是源系数,DstFactor是目标系数 

默认最终颜色计算公式:
=Shader+ 最终颜色 = (Shader计算出的点颜色值 * 源系数)+(点累积颜色 * 目标系数)

系数(SrcFactor,DstFactor) 说明
One 1
Zero 0
SrcColor 源的RGB值
SrcAlpha 源的A值
DstColor 混合目标的RGB值
DstAlpha 混合目标的A值
OneMinusSrcColor (1,1,1) - SrcColor
OneMinusSrcAlpha 1 - SrcAlpha
OneMinusDstColor (1,1,1) - DstColor
OneMinusDstAlpha 1 - DstAlpha

计算公式:
r,g,ba=(ra,ga,ba) (r,g,b) * a = (r*a , g*a , b*a)

r,g,b(x,y,z)=(rx,gy,bz) (r,g,b) * (x,y,z) = (r*x , g*y , b*z)

r,g,b+(x,y,z)=(r+x,g+y,b+z) (r,g,b) + (x,y,z) = (r+x , g+y , b+z)

r,g,b(x,y,z)=(rx,gy,bz) (r,g,b) - (x,y,z) = (r-x , g-y , b-z)

以下为示例:

// 假设 当前颜色 (a,b,c,d) 背景颜色(x,y,z,w)

Blend One One		
// 最终颜色 = (a,b,c)*1 + (x,y,z)*1
// 背景色和当前颜色相加, 不计算透明通道

Blend One Zero
// 最终颜色 = (a,b,c)*1 + (x,y,z)*0
// 仅当前颜色, 不计算透明通道

Blend SrcColor Zero
// 最终颜色 = (a,b,c)*(a,b,c) + (x,y,z)*0
// 仅当前颜色, 变黑(两个小数相乘数值变小), 不计算透明通道

Blend SrcAlpha Zero
// 最终颜色 = (a,b,c)*d + (x,y,z)*0
// (当前色 * 透明度)和背景色叠加, 变黑(乘以小数数值变小)

Blend SrcAlpha OneMinusSrcAlpha
// 最终颜色 = (a,b,c)*d + (x,y,z)*(1-d)
// 常用的透明度模式 当前颜色*自身透明度 + 背景色 * (1-自身透明度)
// 使用贴图时,完全透明的贴图部分建议其他通道也为0,否则易出错
// 例如: 当前颜色 (a, 0, 0, 0)  	背景色(0,y,0,0)
// 此时 最终颜色 = (a,0,0)*0 + (0,y,0)*(1-0) = (0,y,0)
// 显然是错误的
  • BlendOp

在Blend中,默认混合操作是加法,即:
FinalColor=SrcFactorSrcColor+DstFactorDstColor FinalColor = SrcFactor* SrcColor + DstFactor* DstColor
实际我们也可以用BlendOp定义其他混合操作

Option 说明
Add FinalColor = SrcFactor* SrcColor + DstFactor* DstColor(默认)
Sub FinalColor = SrcFactor* SrcColor - DstFactor* DstColor
RevSub FinalColor = DstFactor* DstColor - SrcFactor* SrcColor
Min 取各通道二者最小值
Max 取各通道二者最大值

常用混合模式:

  BlendOp Min ,Blend One One		//变暗
  BlendOp Max ,Blend One One		//变亮
  Blend SrcAlpha OneMinusAlpha 	 //传统混合
  Blend OneMinusDstColor One			//柔和相加(soft Additive)
  Blend DstColor Zero						//正片叠底(Multiply)
  Blend DstColor SrcColor				//2*Multiply
  Blend OneMinusDstColor One		//滤色
  Blend One One									//线性变淡
剔除和深度测试(Culling & Depth Testing)
  • Cull
Option 说明
Back 设置剔除模式,剔除背面
Front 剔除正面
Off 关闭剔除(默认)

例如在双面渲染中,我们希望第一个Pass剔除正面渲染背面,第二个Pass剔除背面渲染正面,可以在Pass中单独设置

  • ZTest
Option 说明
Greater >
GEqual >=
Less <
LEqual <=(默认)
Equal ==
NotEqual !=
Always 直接写入颜色缓冲
Never 从不写入颜色缓冲
Off 关闭深度测试(=直接写入颜色缓冲)

深度测试代表如何更新颜色缓存和深度缓存,例如当取默认值的情况下,如果将要绘制的新像素的z值小于等于深度缓存中的值,则将用新像素的颜色值更新深度缓存中对应像素的颜色值。

注意:

1.深度测试比较的是对应像素的深度值,写的是对应像素颜色缓存的颜色,同时开启深度写入的话,也会更新对应像素深度缓存中的深度

2.当ZTest取值为Off时,表示的是关闭深度测试,等价于取值为Always,而不是Never!Always指的是直接将当前像素颜色(不是深度)写进颜色缓冲区中;而Never指的是不要将当前像素颜色写进颜色缓冲区中,相当于消失。

  • ZWrite
Option 说明
On 开启深度写入(默认)
Off 关闭深度写入

深度写入代表是否要将像素的深度写入深度缓存中,结合ZTest使用

1.当ZWrite为On时,ZTest通过时,该像素的深度才能成功写入深度缓存,同时因为ZTest通过了,该像素的颜色值也会写入颜色缓存。

2.当ZWrite为On时,ZTest不通过时,该像素的深度不能成功写入深度缓存,同时因为ZTest不通过,该像素的颜色值不会写入颜色缓存。

3.当ZWrite为Off时,ZTest通过时,该像素的深度不能成功写入深度缓存,同时因为ZTest通过了,该像素的颜色值会写入颜色缓存。

4.当ZWrite为Off时,ZTest不通过时,该像素的深度不能成功写入深度缓存,同时因为ZTest不通过,该像素的颜色值不会写入颜色缓存。

  • Offset
Offset Factor, Units

Offset给了两个参数:factor和units,通过这两个参数可以强行改变深度测试的结果, 将当前多边形绘制在另一个多边形之上

Unity官方文档解释的很抽象, 百度搜到了以下结果:

offset = (m * factor) + (r * units)

m是多边形的深度的斜率(在光栅化阶段计算得出)中的最大值。这句话难以理解,你只需知道,一个多边形越是与近裁剪面(near clipping plan)平行,m就越接近0。

r是能产生在窗口坐标系的深度值中可分辨的差异的最小值,r是由具体实现OpenGL的平台指定的一个常量。

一个大于0的offset 会把模型推到离你(摄像机)更远一点的位置,相应地,一个小于0的offset 会把模型拉近。

#####模板测试(Stencil Testing)

模板缓冲区可以将每个像素同模板一一对照,并决定保留或丢弃像素

模板缓冲区通常是每像素8位整数。该值可以写入,递增或递减。后续绘制调用可以测试该值,以确定在运行像素着色器之前是否应丢弃像素。

Stencil 
{
	Ref 2
  	Comp equal
 	Pass keep 
  	ZFail decrWrap
}

模板测试一共有以下可以设置的项:

  • Ref

    Ref 是一个0~255之间的参考值, 用于模板测试进行比较

  • ReadMask

    ReadMask 对当前参考值和已有值进行mask操作,默认值255,一般不用

  • WriteMask

    写入Mask操作,默认值255,一般不用

  • Comp

    用于将参考值和缓冲区内容进行比较的函数

    函数 说明
    Greater (参考值) > (缓冲区)时通过,以下类似
    GEqual >=
    Less <
    LEqual <=
    Equal ==
    NotEqual !=
    Always 始终通过测试
    Never 始终不通过测试
  • Pass

    如果模板测试通过,如何处理缓冲区内容

    处理方式 说明
    Keep 保持当前缓冲区(即不把参考值赋值缓冲区)(默认)
    Zero 归零
    Replace 替换(用参考值替换缓冲区原值)
    IncrSat 值+1,达到255就不再加
    DecrSat 值-1, 达到0就不再减
    Invert 反转(例如1变254)
    IncrWrap 值+1,超过255时溢出1变为0
    DecrWrap 值-1, 小于0时溢出1后变为255
  • Fail

    如果模板测试没有通过, 如何处理缓冲区内容

  • ZFail

    如果模板测试通过, 而深度测试没有通过, 如何处理缓冲区内容

雾化(Fog)

雾化效果是随着摄像机的距离和雾效部分的设置来改变颜色, 不会改变混合像素的Alpha值, 只会改变RGB的值。

//格式
Fog 
{
	Fog Commands
}		
//举例
Fog 
{ 
	Mode Linear 
	Color[_Color] 
	Range [_From],[_To] 
	Density [_Density]}
}
命令 参数 说明
Mode Off | Global | Linear | Exp | Exp2 定义雾模式, 默认为Global, 根据“Render Settings”中是否启用了雾,将其转换为“关闭”或“Exp2”。
Color ColorValue 设置雾的颜色
Density FloatValue 设置雾的浓度,影响Exp/Exp2
Range FloatValue, FloatValue 雾的开始和结束距离,影响Linear

默认雾设置基于照明窗口中的设置:雾模式为Exp2或Off;密度和颜色也取自设置。

Note:如果使用片元着色器程序,则着色器的雾设置 仍将适用。在没有固定功能雾功能的平台上,Unity将在运行时修补着色器以支持所请求的雾模式。

透明度测试(Alpha Testing)

Note:使用片段程序时,AlphaTest命令无效;在大多数平台上,alpha测试是在着色器中完成的
使用HLSL clip()函数。建议最近使用可编程着色器而不是SetTexture命令。

AlphaTest Off											//关闭透明度测试
AlphaTest comparison AlphaValue		//用 comparison 比较 当前像素 和 AlphaValue 的值

comparison的可选项

comparison 说明
Greater (当前像素) > (AlphaValue) 通过
GEqual >=
Less <
LEqual <=
Equal ==
NotEqual !=
Always 直接写入颜色缓冲
Never 总是不通过测试

AlphaValue

一个参考值, 介于0和1之间的浮点数。这也可以是对float或range属性的变量引用,在这种情况下,应使用标准方括号表示法([VariableName])来编写。

注意:

使用透明度测试后, 如果像素无法通过透明度测试, 那么即使启用透明度混合, 也一样不会显示

通道绑定(BindChannels)

命令允许你定义顶点数据如何映射到显卡

默认情况,Unity 会处理 bingdings,但是在某些情况你希望自定义一个。

Note: 当使用 vertex programs 时, _BindChannels 不会生效, 在这种情况下 bindings 被 vertex shader 输入控制。如今使用可编程 shader 代替固定管线过程是明智的。

BindChannels { Bind "source", target }

Source可用的类型:

Source 说明
Vertex 顶点坐标
Normal 顶点法线
Tangent 顶点切线
Texcoord 主要UV坐标
Texcoord1 第二套UV坐标
Color 顶点颜色

Target可用类型

Target 说明
Vertex 顶点坐标
Normal 顶点法线
Tangent 顶点切线
Texcoord0,Texcoord1,… 相应纹理Stage的纹理坐标
Texcoord 所有纹理Stages的纹理坐标
Color 顶点颜色

注:Unity对哪些资源可以映射到哪些目标进行了一些限制。Source 和 target 必须匹配 Vertex, Normal, TangentColor。来自 mesh 的 Texture 坐标 (Texcoord and Texcoord1) 可以被映射进纹理坐标 target (Texcoord for all texture stages, or TexcoordN for a specific stage).

UsePass

//格式
UsePass "Shader/Name"
  
//示例
UsePass "VertexLit/SHADOWCASTER"

在当前Shader 指定的名称的 Shader插入所有给定名称的Pass

Shader/Name 指定了Shader名称和Pass名称

Note:

1.只会取第一个被支持的SubShader中的Pass

2.内部所有传递名称都是大写的,因此UsePass必须以大写形式引用名称。

GrabPass

截屏,截屏后把纹理传给后续的Pass使用

//格式
GrabPass {}
GrabPass {"纹理名称"}

//示例
GrabPass
{
    "_BackgroundTexture"
}
  • GrabPass{} 抓取当前屏幕内容,每次使用的开销都非常昂贵。 texture用_GrabTexture获取
  • GrabPass{“TextureName”}将抓取屏幕内容并保存至一张texture里, 通过定义simple2D TextureName使用, 每帧只为第一次使用这张纹理的物体做一次,这种更高效

FallBack

当所有的SubShader都不能处理时, 使用默认值

Fallback "name"		//使用指定的shader进行处理
Fallback Off			//明确说明不进行处理, 并不会打出警告, 即没有SubShader可以在此硬件上运行

CustomEditor

可以为着色器定义CustomEditor。

当你这样做时,Unity将寻找一个使用此名称扩展ShaderGUI的类。 如果找到一个使用此着色器的材料将使用此ShaderGUI。

//格式
CustomEditor "name"
  
//示例
Shader "example" 
{
    // properties and subshaders here...
    CustomEditor "MyCustomEditor"
}

###Shader中的预编译指令

  Pass {
      // ... tags 和 render setup ...
      
      CGPROGRAM
      // 预编译指令:
      #pragma vertex vert
      #pragma fragment frag
      
      // Cg/HLSL 代码
      
      ENDCG
      // ... the rest of pass setup ...
  }

在代码片段的开头,编译指令可以作为#pragma语句给出。

指示哪个着色器函数要编译的指令

指令 说明
#pragma vertex name 编译name函数为顶点着色器
#pragma fragment name 编译name函数为片段着色器
#pragma geometry name 编译name函数为DX10的几何着色器,会自动开启#pragma target 4.0
#pragma hull name 编译name函数为DX10的壳着色器,会自动开启#pragma target 5.0
#pragma domain name 编译name函数为DX10的域着色器,会自动开启#pragma target 5.0

其他编译指令:

指令 说明
#pragma target 表明编译目标,参考Shader Compilation Targets
#pragma require 着色器需要GPU的精细控制, 参考Shader Compilation Targets
#pragma only_renderers 仅为给定的渲染器编译着色器。默认情况下,为所有渲染器编译着色器。
#pragma exclude_renderers 不为给定的渲染器编译着色器。默认情况下,为所有渲染器编译着色器。
#pragma multi_compile for working with multiple shader variants.
#pragma enable_d3d11_debug_symbols 为为DirectX 11编译的着色器生成调试信息,这将允许您通过Visual Studio 2012(或更高版本)图形调试器调试着色器。
#pragma hardware_tier_variants 对于可以运行选定的渲染每个硬件层, 生成每个编译着色器的多个着色器硬件的变体。
#pragma hlslcc_bytecode_disassembly 将反汇编的HLSLcc字节码嵌入到已翻译的着色器中。
#pragma disable_fastmath 实现精确的IEEE 754规则,主要涉及NaN处理(目前仅影响Metal平台)。
#pragma glsl_es2 在GLSL着色器中设置时,即使着色器目标是OpenGL ES 3,也会生成GLSL ES 1.0(OpenGL ES 2.0)。

Unity支持的渲染器平台:

名称 渲染器
d3d11 Direct3D 11/12
glcore OpenGL 3.x/4.x
gles OpenGL ES 2.0
gles3 OpenGL ES 3.x
metal iOS/Mac Metal
vulkan Vulkan
d3d11_9x Direct3D 11 9.x 级别的功能, 同WSA平台一样
xboxone Xbox One
ps4 PlayStation 4
n3ds Nintendo 3DS
wiiu Nintendo Wii U

Note: API(例如Direct3D 11和OpenGL),默认情况下,所有着色器程序都编译到所有支持的渲染器中。 您可以使用#pragma only_renderers或#pragma exclude_renderers指令指示要编译的渲染器。 这在您明确使用某些您知道在某些平台上无法实现的着色器语言功能的情况下非常有用。