当前位置: 首页 > article >正文

前部分知识复习01

一、关于变体

1.#pragma multi_compile  A

2.#pragma shader_feature  A

Unity提供了两个关键字来定义宏 multi_compile 和 shader_feature,Unity 会根据宏定义来生成不同种类的shader,这些不同种类的shader就是所谓的变体。

multi_compile的特点如下:
1、会组合爆炸
#pragma multi_compile A B
#pragma multi_compile C D

这样就会生成4种变体 (A,C) (A,D) (B,C) (B,D)
如果multi_compile定义的越多,生成的变体组合数就会非常非常多,特别恐怖。

2、不论是否动态启用(代码中调用EnableKeyword),变体都会打进包中

所以这样带来的问题就是,multi_compile 控制不好会导致打包慢,还生成很多没用的shader。

两种变体的适用范围:

  两种定义方式可以使用在任何shader中,只是各自有一些建议使用情况。

  multi_compile定义的宏,如#pragma multi_compile_fog,#pragma multi_compile_fwdbase等,基本上适用于大部分shader,与shader自身所带的属性无关。

  shader_feature定义的宏多用于针对shader自身的属性。比如shader中有_NormalMap这个属性(Property),便可通过#pragma shader_feature _NormalMap来定义宏,用来实现这个shader在material有无_NormalMap时可进行不同的处理。


以上内容引用自:

Shader变体收集与打包 - 金城寺的文章 - 知乎
https://zhuanlan.zhihu.com/p/68888831

Unity 之唠叨下 Shader 变体 - 阿文的文章 - 知乎
https://zhuanlan.zhihu.com/p/645102924

变体的两种使用方法

1. #pragam shader_feature MASKENABLE

Properties{

//定义与变体有关的开关   //括号内为变体名 可以没有ON 也可以没有下划线 

[MaterialToggle( MASKENABLE )] _MaskEnable("MaskEnable",int)=0 

}

#if MASKENABLE

        ......

#endif

2. #pragma shader_feature _DISTORTENABLE_ON

Properties

{

[Toggle]_DistortEnable("DistortEnable",int)=0

}

#if _DISTORTENABLE_ON

        .......

#endif

二、lerp(a,b,x)函数

lerp(a,b,x)

x的范围为(0,1);当x=0时,函数值取a;当x=1时,函数值取b;当x为0-1之间的值时,函数取a,b之间的插值

三、特效通用的材质Shader

Shader"unity/Effects2"
{
	Properties
	{
		[Header(RenderingMode)]
		[Space(5)]

		//Blend混合枚举属性
		[Enum(UnityEngine.Rendering.BlendMode)]_SrcBlend("SrcBlend",int)=0
		[Enum(UnityEngine.Rendering.BlendMode)]_DstBlend("DstBlend",int)=0

		//剔除属性
		[Enum(UnityEngine.Rendering.CullMode)]_Cull("Cull",int)=0

		[Header(Base)]
		[Space(5)]

		//主贴图
		_MainTex("MainTex",2D)="white"{}

		//主贴图UV流动
		_MainUVSpeedX("MainUVSpeed X",float)=0
		_MainUVSpeedY("MainUVSpeed Y",float)=0

		//颜色属性
		_Color("Color",Color)=(1,1,1,1)

		//颜色增加滑杆
		_Intensity("Intensity",Range(-3,3))=1
		
		[Header(Mask)]
		[Space(5)]

		//遮罩开关
		// [Toggle]_MaskEnabled("MaskEnable",int)=0
		[MaterialToggle(MASKENABLED)]_MaskEnable("MaskEnable",int)=0  //括号内为变体名 可以没有ON 也可以没有下划线 

		//遮罩贴图
		_MaskTex("MaskTex",2D)="white"{}

		//遮罩贴图UV流动
		_MaskUVSpeedX("MaskUVSpeed X",float)=0
		_MaskUVSpeedY("MaskUVSpeed Y",float)=0


		[Header(Distort)]
		[Space(5)]

		//扭曲开关
		[Toggle]_DistortEnabled("DistortEnabled",int)=0

		//UV扭曲贴图
		_DistortTex("DistortTex",2D)="white"{}

		//扭曲贴图UV流动属性
		_DistortUVSpeedX("DistortUVSpeed X",float)=0
		_DistortUVSpeedY("DistortUVSpeed Y",float)=0

		//扭曲滑杆调节
		_Distort("Distort",Range(0,1))=0

	 }
	
	SubShader
	{
		Tags{"Queue"="Transparent"}   //半透明队列

		Blend [_SrcBlend][_DstBlend]  //混合

		Cull [_Cull]                  //剔除

		Pass
		{
			CGPROGRAM
			#pragma vertex vert;
			#pragma fragment frag;
			#pragma shader_feature MASKENABLED   //变体的声明  _MASKENABLED_ON 为变体名
			#pragma shader_feature _DISTORTENABLED_ON
			#include "UnityCG.cginc"

			sampler2D _MainTex;
			float4 _MainTex_ST;
			fixed4 _Color;
			float _MainUVSpeedX;
			float _MainUVSpeedY;
			sampler2D _MaskTex;
			float4 _MaskTex_ST;
			float _MaskUVSpeedX;
			float _MaskUVSpeedY;
			half _Intensity;   //注意使用half定义

			//扭曲属性的声明
			sampler2D _DistortTex;       //扭曲贴图
			float4 _DistortTex_ST;
			float _DistortUVSpeedX;      //UV流动
			float _DistortUVSpeedY;         
			float _Distort;              //滑杆

			struct appdate
			{
				float4 vertex :POSITION;
				float4 uv:TEXCOORD;
				float2 uv1:TEXCOORD1;   //重新定义一张UV 用来存放扭曲贴图
			 };

			struct v2f
			{
				float4 pos:SV_POSITION;
				float4 uv:TEXCOORD;
				float2 uv1:TEXCOORD1;   //重新定义一张UV 用来存放扭曲贴图
			 };

			v2f vert(appdate v)
			{
				v2f o;
				o.pos=UnityObjectToClipPos(v.vertex);
				o.uv.xy=TRANSFORM_TEX(v.uv,_MainTex)+float2(_MainUVSpeedX,_MainUVSpeedY)*_Time.y;
				#if MASKENABLED
					o.uv.zw=TRANSFORM_TEX(v.uv,_MaskTex)+float2(_MaskUVSpeedX,_MaskUVSpeedY)*_Time.y;
				#endif
				#if _DISTORTENABLED_ON
					o.uv1.xy=TRANSFORM_TEX(v.uv,_DistortTex)+float2(_DistortUVSpeedX,_DistortUVSpeedY)*_Time.y;  //扭曲贴图中使Tilling和Offset有效 并实现UV自流动
				#endif
				return o;
			 }

			float4 frag(v2f i):SV_TARGET
			{
				float4 c;
				float2 distort=i.uv.xy;   //默认值为主贴图的UV坐标

				#if _DISTORTENABLED_ON
					float4 distortTex=tex2D(_DistortTex,i.uv1.xy);   //扭曲贴图UV采样  须写在主贴图采样前 因为主贴图中采样的UV值需用到扭曲贴图UV采样后的结果
					distort=lerp(i.uv.xy,distortTex,_Distort);       //这里distort所得的结果用作主贴图的纹理采样UV
				#endif
				
				float4 tex=tex2D(_MainTex,distort);  //使用lerp()函数和_Distort滑杆值来更改扭曲值
				c=tex;
				c*=_Color*_Intensity;

				#if MASKENABLED
					float4 maskTex=tex2D(_MaskTex,i.uv.zw);
					c*=maskTex;
				#endif

				return c;
			 }
			ENDCG
		 }
	 }
 }

四、模版测试

stencil

{

        Ref [_Stencil]
        ReadMask [_StencilReadMask]
        WriteMask [_StencilWriteMask]
        Comp [_StencilComp] ((UnityEngine.Rendering.CompareFunction))
        Pass [_StencilOp] (UnityEngine.Rendering.StencilOp)

        Fail [_Fail]
        ZFail [_ZFail]

}

模版测试公式:

(Ref & ReadMask)  Comp  (StencilBufferValue & ReadMask)

读取掩码ReadMask默认值为255 二进制位(11111111)

StencilBufferValue为模版缓冲区内的存储值  Ref为当前模版测试值

所以(StencilBufferValue & ReadMask) &(与) 后的结果仍为StencilBufferValue(模版缓冲区内的存储值)

之后再用当前的模版测试值Ref与模版缓冲中的存储值StencilBufferValue进行Comp操作


Stencil
{
Ref [_Stencil]
ReadMask [_StencilReadMask]
WriteMask [_StencilWriteMask]
Comp [_StencilComp] ((UnityEngine.Rendering.CompareFunction))
Pass [_StencilOp] (UnityEngine.Rendering.StencilOp)
Fail [_Fail]
ZFail [_ZFail]
}

Ref: 设定的参考值,这个值将用来与模板缓冲中的值进行比较.取值范围位为0-255的整数.
ReadMask: ReadMask的值将和Ref的值以及模板缓冲中的值进行按位与(&)操作,取值范围也是0-255的整数,默认值为255(二进制位11111111),即读取的时候不对Ref的值和模板缓冲中的值产生修改,读取的还是原始值.
WriteMask: WriteMask的值是当写入模板缓冲时进行的按位与操作,取值范围是0-255的整数,默认值也是255,即不做任何修改.
Comp: 定义Ref与模板缓冲中的值比较的操作函数,默认值为always.
Pass: 当模板测试(和深度测试)通过时,则根据(stencilOperation值)对模板缓冲值进行处理,默认值为keep.
Fail: 当模板测试(和深度测试)失败时,则根据(stencilOperation值)对模板缓冲值进行处理,默认值为keep.
ZFail: 当模板测试通过而深度测试失败时,则根据(stencilOperation值)对模板缓冲值进行处理,默认值为keep
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
                        
原文链接:https://blog.csdn.net/2401_83878847/article/details/143590005

Comp 比较操作符

Less: 相当于“<”操作,即仅当左边<右边,模板测试通过,渲染像素.
Greater: 相当于“>”操作,即仅当左边>右边,模板测试通过,渲染像素.
Equal: 相当于“=”操作,即仅当左边=右边,模板测试通过,渲染像素.
NotEqual: 相当于“!=”操作,即仅当左边!=右边,模板测试通过,渲染像素.
Always: 不管公式两边为何值,模板测试总是通过,渲染像素.
Never: 不管公式两边为何值,模板测试总是失败 ,像素被抛弃.

Pass 更新模版缓冲区内的值

Keep: 保留当前缓冲中的内容,即stencilBufferValue不变.
Zero: 将0写入缓冲,即stencilBufferValue值变为0.
Replace: 将参考值写入缓冲,即将referenceValue赋值给stencilBufferValue.
IncrSat: 将当前模板缓冲值加1,如果stencilBufferValue超过255了,那么保留为255,即不大于255.
DecrSat: 将当前模板缓冲值减1,如果stencilBufferValue超过为0,那么保留为0,即不小于0.
Invert: 将当前模板缓冲值(stencilBufferValue)按位取反.
IncrWrap: 当前缓冲的值加1,如果缓冲值超过255了,那么变成0,(然后继续自增).
DecrWrap: 当前缓冲的值减1,如果缓冲值已经为0,那么变成255,(然后继续自减)

五、半透明混合模式

SrcAlphaOneMinusSrcAlpha  半透明混合模式

六、使image中的颜色变灰

方法一: c.rgb=c.rrr;   

方法二:c.rgb=c.r*0.22+c.g*0.787+c.b*0.071; 

方法三:c.rgb=Luminance(c.rgb);

Shader"unity/UIMask04"
{
	Properties
	{
		_MainTex("MainTex",2D)="white"{}
		[Enum(UnityEngine.Rendering.BlendMode)]_SrcBlend("SrcBlend",int)=0
		[Enum(UnityEngine.Rendering.BlendMode)]_DstBlend("DstBlend",int)=0
		_Ref("Ref",float)=0
		[Enum(UnityEngine.Rendering.CompareFunction)]_Comp("Comp",int)=0
		[Enum(UnityEngine.Rendering.StencilOp)]_Pass("Pass",int)=0

		[Toggle]_GrayEnable("GrayEnable",int)=0
	 }

	SubShader
	{
		Tags{"Queue"="Transparent"}

		//SrcAlpha 和 OneMinusSrcAlpha  半透明混合模式
		Blend [_SrcBlend] [_DstBlend]  

		//模版测试 (在透明度测试之后,深度测试之前)
		Stencil
		{
			Ref [_Ref]
			Comp [_Comp]
			Pass [_Pass]
		 }

		Pass
		{
			CGPROGRAM

			#pragma vertex vert
			#pragma fragment frag 

			#pragma shader_feature _GRAYENABLE_ON

			#include "UnityCG.cginc"

			sampler2D _MainTex;
			int _GrayEnable;

			struct appdate
			{
				float4 vertex : POSITION;
				float4 uv : TEXCOORD;
				float4 Color:COLOR;  //引用image中的颜色
			 };

			struct v2f
			{
				float4 pos : SV_POSITION;
				float4 uv : TEXCOORD;
				float4 Color:COLOR;
			 };

			v2f vert(appdate v)
			{
				v2f o;
				o.pos=UnityObjectToClipPos(v.vertex);
				o.uv=v.uv;
				o.Color=v.Color;
				return o;
			 }

			float4 frag(v2f i):SV_Target
			{
				float4 c;
				float4 mainTex=tex2D(_MainTex,i.uv);
				c=mainTex;
				c*=i.Color;

				#if _GRAYENABLE_ON
				//使颜色变灰
				c.rgb=Luminance(c.rgb);
				#endif

				return c;
			 }
			ENDCG
		 }
	 }
 }


http://www.kler.cn/a/521015.html

相关文章:

  • Canny 边缘检测
  • 汽车网络信息安全-ISO/SAE 21434解析(中)
  • 递归搜索回溯综合练习(十五题)
  • MacOS安装Docker battery-historian
  • Sora学习
  • 算法【有依赖的背包】
  • SpringBoot使用 easy-captcha 实现验证码登录功能
  • spring spring-boot spring-cloud发布以及适配
  • SAP MM 记录一次SAP外协采购收货提示 这种物料的特殊库存 O 0100003359 14019002不存在的问题
  • PTMD2.0-疾病相关的翻译后修饰数据库
  • 数字图像处理:实验七
  • 【ProtoBuf 安装】ProtoBuf在window/Linux下的安装 创建/删除swap分区
  • HarmonyOS简介:应用开发的机遇、挑战和趋势
  • DDD实战课 笔记
  • sendto丢包
  • 基于C++的DPU医疗领域编程初探
  • 二级C语言题解:统计奇偶个数以及和与差、拼接字符串中数字并计算差值、提取字符串数组中单词尾部字母
  • Flutter TextPainter 计算文本高度和行数
  • 01-02 三元组与七元组
  • K8S极简教程(4小时快速学会)
  • OAuth1和OAuth2授权协议
  • Kotlin开发(六):Kotlin 数据类,密封类与枚举类
  • Linux-day10
  • 代码随想录——二叉树(二)
  • location的使用规则
  • C语言学习强化