Unity三种物体溶解方法

这篇具有很好参考价值的文章主要介绍了Unity三种物体溶解方法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

效果展示

Dissolve1-3

1. 利用Noise纹理进行溶解

该方法的效果好坏在于噪声纹理的分布。本例利用SD的Blend节点,将Noise贴图和渐变贴图进行正片叠底操作,并简单调整边缘边缘大小,得到如下所示的噪声贴图。
Unity三种物体溶解方法

制作的遮罩为四周较暗,且对角线轴向向内亮度递增,使得最终的溶解效果从四周向内部溶解。

shader要点

  1. 通过一个噪声权重因子来控制Noise贴图的整体亮度;
  2. 利用saturate将其截断在0,1之间。通过改变噪声权重因子的大小影响Noise贴图的亮度,
  3. 将加权过的噪声图作为输出图片的alpha值,从而改变物体的透明度,结合Blend最终达到消融的目的。
  4. 通过判断透明度的值生成包边效果,通过改变透明度的阈值范围控制包边的宽度。
  5. 结合之前的Bloom后处理方法,通过包边所在的透明度范围对包边进行提取,达到局部bloom的效果。

shader代码

Shader "Custom/DissolveShader" {
	Properties {
		_MainTex ("Main Texture", 2D) = "white" { }
		_DissolveMap ("Noise Map", 2D) = "white" { }
		_DissolveFactor ("Dissolve Factor", Range(0, 18)) = 0.5
		_Diffuse ("Diffuse Color", Color) = (1, 1, 1, 1)
		_DissolveColor ("Dissolve Color", Color) = (1, 0, 0, 1)
		_DissolveBoundaryBegin ("Dissolve Boundary Begin", Range(0.3, 1)) = 0.4
		_DissolveBoundaryEnd ("Dissolve Boundary End", Range(0.3, 0.4)) = 0.3

		_DissolveBoundaryAlpha ("Dissolve Boundary Alpha", Range(0, 1)) = 0.5
	}
	SubShader {
		Tags { "Queue" = "Geometry+1" "RenderType" = "Opaque" }

		pass {
			Blend SrcAlpha OneMinusSrcAlpha
			
			Tags { "LightMode" = "ForwardBase" }

			CGPROGRAM
			#include "UnityCG.cginc"
			#include "Lighting.cginc"

			#pragma vertex vert
			#pragma fragment frag

			fixed4 _Diffuse;
			sampler2D _MainTex;
			float4 _MainTex_ST;

			sampler2D _DissolveMap;
			float4 _DissoveMap_ST;
			float _DissolveFactor;

			fixed4 _DissolveColor;
			float _DissolveBoundaryBegin;
			float _DissolveBoundaryEnd;
			float _DissolveBoundaryAlpha;

			struct v2f {
				float4 pos : SV_POSITION;
				float3 worldNormal : TEXCOORD2;
				float2 uv : TEXCOORD0;
				float4 screenPos : TEXCOORD1;
			};

			v2f vert(appdata_base v) {
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				o.uv = v.texcoord;
				o.worldNormal = UnityObjectToWorldNormal(v.normal);
				o.screenPos = ComputeGrabScreenPos(o.pos);
				return o;
			}

			fixed4 frag(v2f i) : SV_Target {
				// 采样噪声贴图的值
				fixed dissolveTex = tex2D(_DissolveMap, i.uv).r;

				// 计算光照
				fixed3 worldNormal = normalize(i.worldNormal);
				fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
				fixed3 lambert = saturate(dot(worldNormal, worldLightDir));

				fixed3 albedo = lambert * _Diffuse.xyz * _LightColor0.xyz + UNITY_LIGHTMODEL_AMBIENT.xyz;
				fixed3 color = albedo * tex2D(_MainTex, i.uv).rgb;

				// 利用时间实现一个简单的动态效果
				fixed dissolveFactor = _DissolveFactor * abs(lerp(-1, 1, frac(_Time.y * 0.1)));
				// 利用消融因子为消融贴图赋值,使其整体灰度值随着消融因子的变化而变化
				fixed alpha = saturate(dissolveTex * dissolveFactor * dissolveFactor);

				// 判断当前的透明度 若在设定范围内则更改颜色 并同时更改透明度方便后续bloom效果实现
				if (alpha < _DissolveBoundaryBegin && alpha > _DissolveBoundaryEnd) {
					return fixed4(_DissolveColor.rgb, _DissolveBoundaryAlpha);
				} else if (alpha < _DissolveBoundaryEnd) {
					alpha = 0;
				}
				return fixed4(color, alpha);
			}
			ENDCG
		}
	}
	FallBack "Diffuse"
}

2. 屏幕空间棋盘格

利用cllip方法强制中止当前渲染过程,达到透视效果。由于clip方法的使用,导致无法进行early-z等操作,在手机端会有较大的性能开销。

shader要点

  1. 该方法在屏幕空间进行操作,所以要得到屏幕空间中的具体坐标;
  2. 利用floor方法将x,y值乘以棋盘格控制因子的结果限制为整数;
  3. 通过乘以0.5再相加的方式使得结果带小数部分或者不带小鼠部分;
  4. 最后利用frac函数对小数部分进行提取,从而得到一系列值为0和0.5的数;
  5. 对这些值取负值并利用clip函数进行判断,当对应的值为-0.5时,渲染中断,当为0时,渲染继续;从而实现棋盘格效果。

shader代码

Shader "Custom/Dissolve2Shader" {
	Properties {
		_MainTex ("Albedo (RGB)", 2D) = "white" { }
		_Diffuse ("Diffuse Color", Color) = (1, 1, 1, 1)
		_Range ("Range", Range(0, 1)) = 0.1
	}
	SubShader {
		Tags { "RenderType" = "Opaque" }

		pass {
			CGPROGRAM

			#pragma vertex vert
			#pragma fragment frag
			#pragma target 3.0

			#include "UnityCG.cginc"
			#include "Lighting.cginc"

			float _Range;
			sampler2D _MainTex;
			float4 _Diffuse;

			struct v2f {
				float4 pos : SV_POSITION;
				float3 worldNormal : TEXCOORD2;
				float2 uv : TEXCOORD0;
				float4 screenPos : TEXCOORD1;
			};

			v2f vert(appdata_base v) {
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				o.uv = v.texcoord;
				o.worldNormal = UnityObjectToWorldNormal(v.normal);
				o.screenPos = ComputeScreenPos(o.pos);
				return o;
			}

			fixed4 frag(v2f i) : SV_Target {
				float2 wcoord = (i.screenPos.xy / i.screenPos.w);
				// 记得再乘以屏幕的像素个数,才能最终得到屏幕位置
				wcoord *= _ScreenParams.xy;

				// 随时间变化 * _Time.y * 3
				float changeRange = _Range;

				// screenPos *0.5 是为了方便当两数相加时有奇偶的区分,
				// 若和为奇数,则乘以0.5再取小数部分则小数部分必为0.5,若为偶数,再乘0.5则小数部分为0
				float2 screenPos = floor(wcoord.xy * changeRange) * 0.5;
				// 棋盘图案中 4x4 像素块的 checker 值为负
				float checker = -frac(screenPos.r + screenPos.g);
				// 如果clip函数中的值为负数,则停止渲染
				clip(checker);

				// 计算光照
				fixed3 worldNormal = normalize(i.worldNormal);
				fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
				fixed3 lambert = saturate(dot(worldNormal, worldLightDir));

				fixed3 albedo = lambert * _Diffuse.xyz * _LightColor0.xyz + UNITY_LIGHTMODEL_AMBIENT.xyz;

				// 对于保留的像素,读取纹理并将其输出
				fixed3 color = albedo * tex2D(_MainTex, i.uv).rgb;
				return fixed4(color, 1);
			}
			ENDCG
		}
	}
	FallBack "Diffuse"
}

3. 判断顶点距离摄像头的距离进行clip

该方法同样利用clip方法达到消融的目的,距离的运算在世界空间中完成,消融的实现在屏幕空间中完成。

这里最后一句话有点没看懂 再琢磨琢磨。文章来源地址https://www.toymoban.com/news/detail-405729.html

shader 代码

Shader "Custom/Dissolve3Shader" {
	Properties {
		_MainTex ("Albedo (RGB)", 2D) = "white" { }
		_Diffuse ("Diffuse Color", Color) = (1, 1, 1, 1)
		_FogNear ("Fog Near", float) = 1.0
		_FogFar ("Fog Far", float) = 1.0
		_Test ("Test", float) = 1.0
	}
	SubShader {
		Tags { "RenderType" = "Opaque" }

		pass {
			Blend SrcAlpha OneMinusSrcAlpha
			CGPROGRAM

			#pragma vertex vert
			#pragma fragment frag
			#pragma target 3.0

			#include "UnityCG.cginc"
			#include "Lighting.cginc"

			sampler2D _MainTex;
			float4 _Diffuse;
			float _FogFar;
			float _FogNear;
			float _Test;

			struct appdata {
				float4 vertex : POSITION;
				float2 uv1 : TEXCOORD0;
				float2 uv2 : TEXCOORD1;
				float3 normal : NORMAL;
			};

			struct v2f {
				float4 uv : TEXCOORD0;
				float4 vertex : SV_POSITION;
				float3 worldPos : TEXCOORD1;
				float4 screenPos : TEXCOORD2;
				float3 worldNormal : TEXCOORD3;
			};

			v2f vert(appdata v) {
				v2f o;

				// 裁剪空间坐标
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.uv.xy = v.uv1;
				o.uv.zw = v.uv2;

				// 屏幕空间坐标
				o.screenPos = ComputeScreenPos(o.vertex);
				
				// 世界空间坐标
				o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
				o.worldNormal = UnityObjectToWorldNormal(v.normal);
				return o;
			}

			fixed4 frag(v2f i) : SV_Target {
				// 计算光照
				fixed3 worldNormal = normalize(i.worldNormal);
				fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
				fixed3 lambert = saturate(dot(worldNormal, worldLightDir));
				fixed3 albedo = lambert * _Diffuse.xyz * _LightColor0.xyz + UNITY_LIGHTMODEL_AMBIENT.xyz;

				fixed4 color = fixed4(albedo * tex2D(_MainTex, i.uv).rgb,tex2D(_MainTex, i.uv).a);

				// 物体顶点距离相机距离
				float distanceRamp = distance(i.worldPos, _WorldSpaceCameraPos.xyz);

				// 利用Smoothstep对距离进行约束
				distanceRamp = smoothstep(_FogNear, _FogFar, distanceRamp);

				// 构建抖动顺序矩阵
				float4x4 thresholdMatrix = {
					1.0 / 17.0, 9.0 / 17.0, 3.0 / 17.0, 11.0 / 17.0,
					13.0 / 17.0, 5.0 / 17.0, 15.0 / 17.0, 7.0 / 17.0,
					4.0 / 17.0, 12.0 / 17.0, 2.0 / 17.0, 10.0 / 17.0,
					16.0 / 17.0, 8.0 / 17.0, 14.0 / 17.0, 6.0 / 17.0
				};

				// 获取屏幕空间坐标(归一化
				float2 screenPos = i.screenPos.xy / i.screenPos.w;
				// 0-1的坐标范围乘以画面像素总数
				screenPos *= _ScreenParams.xy;
				// 依据动态抖动计算透明度
				half noise = distanceRamp - thresholdMatrix[fmod(screenPos.x, 4 * _Test)] * thresholdMatrix[fmod(screenPos.y, 4 * _Test)];
				clip(noise);

				return color;
			}

			ENDCG
		}
	}
	FallBack "Diffuse"
}

到了这里,关于Unity三种物体溶解方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 【Unity ShaderGraph】| 快速制作一个实用的 模型溶解效果

    【Unity ShaderGraph】| 快速制作一个实用的 模型溶解效果

    前言 本文将使用ShaderGraph制作一个模型溶解的效果,可以直接拿到项目中使用。 对ShaderGraph还不了解的小伙伴可以参考这篇文章:【Unity ShaderGraph】| Shader Graph入门介绍 | 简介 | 配置环境 | 窗口介绍 | 简单案例 下面就开始看一下具体的制作流程,然后自己动手制作一个吧! 资

    2024年02月08日
    浏览(10)
  • unity多个物体多种材质切换效果实现方法(方法比较笨,还有不足之处多多指导)

    unity多个物体多种材质切换效果实现方法(方法比较笨,还有不足之处多多指导)

    多种材质切换:获取物体的MeshRenderer组件上所有的材质球,并将其存放到数组中;创建另一个数组存放需要新材质球,通过循环遍历将将需要替换的材质球存放在创建好的数组内。 比如说同时给象棋的棋盘和棋子切换不同材质,具体步骤如下: 1.分别导入棋盘、棋子模型;黑

    2024年02月17日
    浏览(10)
  • Unity——使用铰链关节制作悬挂物体效果

    Unity——使用铰链关节制作悬挂物体效果

    目的 在场景中创建一个悬挂的物体,是把多个模型悬挂在一起可以自由摇摆,类似链条的效果 效果图 前言 什么是铰链关节? 铰链关节 将两个刚体(Rigid body)组会在一起,从而将其约束为如同通过铰链连接一样进行移动。它十分适合门、链条、钟摆等模拟效果。 步骤 打开

    2023年04月24日
    浏览(27)
  • unity实现玩家碰触物体打开提示效果

    unity实现玩家碰触物体打开提示效果

    玩家进入触碰某个物体,物体便会弹出提示框一个小效果。这个效果是在一个小demo里做的,需要多处使用,于是做成了单例。 两个部分,一个是物体的提示框,一个是玩家。当然玩家是提前做好的。 首先提示框关于脚本的部分。 (1)声明并获取,老样子,初始化时不可见

    2024年02月07日
    浏览(17)
  • 【Unity300个技巧】检测物体在地面的三种方式

    【Unity300个技巧】检测物体在地面的三种方式

    在游戏中,角色跳跃是普通且常见的能力。但就这么看似简单的功能,在实现过程中也会遇到很多问题。 在本篇文章,我将分享地面检测的三种方式。 GitHub B站视频 在游戏中。用户对在空中的角色和地面的角色可操作方式是不同的。 比如,空中和地面不同的攻击方式、地面

    2023年04月08日
    浏览(10)
  • 【Unity】API学习 --> GameObject(物体)创建的三种方式

    GameObject 就是Unity中最关键的物体 1 通过构造函数进行创建 可以直接new一个GameObject 在start函数里创建,游戏物体可以在任何地方创建,测试创建一次 默认只有Transform 可以在新建是进行传参,创建指定物体 2 Instance Instantiate是静态方法,可以通过 GameObject.Instantiate(); 调用,需要

    2024年02月06日
    浏览(19)
  • 使用Unity里的ShaderGraph实现物体边框呼吸灯效果

    使用Unity里的ShaderGraph实现物体边框呼吸灯效果

    提前声明一下,以下效果需要在hdrp项目中进行。 首先创建好我们的正方体: 用来接下来的边框显示。 这里需要创建两个材质球,一个用于显示方块的材质,另一个用于边框的显示。 (Material用于方块材质,OutlineMat用于边框线) 为了更好地突出边框的视觉效果我这里给它加

    2024年04月22日
    浏览(139)
  • Unity Dotween插件物体、ui的移动 旋转 缩放效果

    Unity Dotween插件物体、ui的移动 旋转 缩放效果 #脚本应用命名空间 using DG.Tweening; ##让游戏物体平移 //参数一:要移动到的位置 //参数二:动画完成要多少秒 transform.DOMove(new Vector3(1,3, 8.08f),5.5f); ##让游戏物体旋转 //参数一:要旋转成的样子的坐标 //参数二:旋转动画多少秒完成 trans

    2024年02月01日
    浏览(15)
  • 【UE 材质】简单的纹理失真、溶解效果

    【UE 材质】简单的纹理失真、溶解效果

    目录  1. 失真效果 2. 溶解效果 3. 失真+溶解 我们一开始有这样一个纹理 其中纹理节点“DistortTexture”的纹理为引擎自带的纹理“T_Noise01”,我们可以通过控制参数“失真度”来控制纹理的失真程度

    2024年01月18日
    浏览(7)
  • 使用手柄控制Unity及效果展示(1)

    使用手柄控制Unity及效果展示(1)

    Unity支持手柄的控制,效果图如下所示: 这是一篇针对手柄控制U3D入门的过程记载,主要以实现功能为目的,分四个部分进行过程展示: Input System包的下载 设备的查找 Input Actions控件的使用 主要代码的解释及编写 这里也将我使用过程中遇到的问题和解决方法也用红字进行标

    2024年02月05日
    浏览(11)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包