Unity Shader-热空气扭曲效果

简介


千等万等终于等到了《耻辱2》打折,本以为可以爽一发了,然而各种出问题,先是steam下载速度奇慢无比,下了三天晚上好不容易下完的游戏,第一次打开给弹了个3D11CreateDeviceAndSwapChain Failed,折腾半天装了个补丁算是能打开游戏了,然而过完新手教学显卡驱动就崩了,崩了!崩了,连崩三回,差点想把坑爹的A卡从机箱掏出来顺着窗户扔出去,后来想想,为了楼下同学的生命安全,我还是忍了。好在AMD有专门为《耻辱2》R9380崩溃打了个补丁,算是拯救我于水火之中了。《耻辱2》用了ID Tech5衍生的Void引擎,看起来画面比《耻辱1》用的虚幻3好了不少。先来张帅帅哒截图,最近每天沉迷于杀杀杀,感觉自己好颓废:

一时间差点忘了自己是个程序员,差点变成游戏鉴赏博客,尴尬...下面步入正题,今天打游戏的时候路过了一个火炉,看到了火炉旁边的热空气扭曲的效果,感觉做的还是蛮逼真的,今天打算自己实现一发玩一玩:


实现原理


扭曲效果是游戏里面经常有的一个效果,说道扭曲效果,一般就是当前的画面发生了扭曲,在现实世界中一般是折射导致的,但是在图形学中,我们要模拟这种效果,原理就大不一样了。首先,我们并不会真正影响光线的传播,只是用uv的偏移来模拟扭曲的效果。有一种全屏的扭曲效果,这种是基于屏幕后处理的,可以参考前面的一篇文章 屏幕水波纹效果,但是,往往我们并不希望全屏幕都发生扭曲,而是只希望某些地方发生了扭曲,比如上面的火炉的做法,拼关的同学肯定是希望在火炉的上方放一个特效片,就能够出扭曲的效果。那么,我们的这个片就需要是一个可以显示后面所有物体的片,换句话说,我们需要在这个面片上渲染面片后面所有的东西,这样,面片看起来就是透明的了。然后我们在采样uv的时候将uv进行偏移,就能够得到扭曲的效果了。恩,听起来很简单的样子,但是我们要怎么得到面片后面的所有东西呢?其实Unity已经为我们提供了这样的一个功能,GrabPass。下面看一下Grabpass的使用。

GrabPass


GrabPass是Unity为我们提供的一个很方便的功能,可以直接将当前屏幕内容渲染到一张贴图上,我们可以直接在shader中使用这张贴图而不用自己去实现渲染到贴图这样的一个过程,大大的方便了我们的shader编写。GrabPass的使用非常简单,我们在写vertex fragment shader的时候都需要写一个pass,GrabPass也是一个pass,只不过是Unity为我们实现好的一个pass。我们只需要在我们正常的Pass前面加一个GrabPass{}就可以了。
官方文档上有两种GrabPass的写法,第一种是直接GrabPass{}的写法,这种写法抓屏的图片就直接存到_GrabTexture这个系统预定义的贴图变量中了,我们可以直接访问该贴图,但是这种写法会导致每个使用GrabPass的物体进行一次这种旷日持久的抓屏操作!如果用这种shader的物体多了的话,想想就很可怕。另一种是GrabPass{"TextureName"}的写法,其中TextureName是我们自定义的一个贴图名称,这种写法,Unity每帧只会为第一个使用了该名称的物体进行抓屏操作,之后的就可以复用这张贴图了。所以,我们还是使用第二种方式更好一点。下面附上一份最简单的抓屏代码:
//Grabpass shader
//by: puppet_master
//2017.4.23
Shader "ApcShader/GrabPass" 
{
	SubShader
	{
		ZWrite Off
		//GrabPass
		GrabPass
		{
			//此处给出一个抓屏贴图的名称,抓屏的贴图就可以通过这张贴图来获取,而且每一帧不管有多个物体使用了该shader,只会有一个进行抓屏操作
			//如果此处为空,则默认抓屏到_GrabTexture中,但是据说每个用了这个shader的都会进行一次抓屏!
			"_GrabTempTex"
		}

		Pass
		{
			Tags
			{ 
				"RenderType" = "Transparent"
				"Queue" = "Transparent+1"
			}

			CGPROGRAM
			sampler2D _GrabTempTex;
			float4 _GrabTempTex_ST;
			#include "UnityCG.cginc"
			struct v2f
			{
				float4 pos : SV_POSITION;
				float4 grabPos : TEXCOORD0;
			};

			v2f vert(appdata_base v)
			{
				v2f o;
				o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
				//计算抓屏的位置,其中主要是将坐标从(-1,1)转化到(0,1)空间并处理DX和GL纹理反向的问题
				o.grabPos = ComputeGrabScreenPos(o.pos);
				return o;
			}

			fixed4 frag(v2f i) : SV_Target
			{
				//根据抓屏位置采样Grab贴图,tex2Dproj等同于tex2D(grabPos.xy / grabPos.w)
				fixed4 color = tex2Dproj(_GrabTempTex, i.grabPos);
				return 1 - color;
			}

			#pragma vertex vert
			#pragma fragment frag
			ENDCG
		}
	}
}
我们找个面片,附上这个shader的材质。为了更方便的看一下效果,我们就参照官网的写法,直接将最终输出的颜色反向,也就是1-原颜色作为输出(这个颜色不禁让我想起了宇智波鼬的月读........)
  • 56
    点赞
  • 187
    收藏
    觉得还不错? 一键收藏
  • 24
    评论
要实现图像扭曲过场效果,可以使用Unity3D中的Shader。具体实现步骤如下: 1. 创建一个新的Shader,并将其属性设置为Unlit/Texture。 2. 在Shader中添加一个名为“Distortion”的属性,类型为2D纹理,用于存储扭曲图像。 3. 在Shader中添加一个名为“DistortionStrength”的属性,类型为Range,用于控制扭曲强度。 4. 在Shader的片段着色器中,使用tex2D函数获取原始纹理的颜色,并使用uv坐标对扭曲图像进行采样。 5. 将扭曲图像的采样值与“DistortionStrength”属性相乘,并将结果添加到原始颜色中。 6. 最后,将新的颜色值输出到屏幕。 下面是一个简单的Shader示例: ``` Shader "Custom/DistortionTransition" { Properties { _MainTex ("Texture", 2D) = "white" {} _Distortion ("Distortion", 2D) = "white" {} _DistortionStrength ("Distortion Strength", Range(0.0, 1.0)) = 0.5 } SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; sampler2D _MainTex; sampler2D _Distortion; float _DistortionStrength; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = v.uv; return o; } fixed4 frag (v2f i) : SV_Target { // Get the original color fixed4 texColor = tex2D(_MainTex, i.uv); // Get the distortion value float4 distortion = tex2D(_Distortion, i.uv); // Calculate the distortion offset float2 offset = (distortion.rg * 2.0 - 1.0) * _DistortionStrength; // Apply the distortion to the UV coordinates float2 distortedUV = i.uv + offset; // Get the color from the distorted UV coordinates fixed4 distortedColor = tex2D(_MainTex, distortedUV); // Add the distortion to the original color return texColor + (distortedColor - texColor); } ENDCG } } FallBack "Diffuse" } ``` 在使用这个Shader时,可以将原始纹理作为“_MainTex”属性的值,将扭曲图像作为“_Distortion”属性的值,然后通过修改“_DistortionStrength”属性的值来控制扭曲强度。 希望这个示例能够帮助你实现所需的效果

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 24
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值