U3D Distortion

原创 2016年05月30日 22:48:55

我们的美术希望游戏可以更炫一点,想在刀光特效上加上空气扭曲的效果,就是类似燃烧的火焰上方空气扰动的那种效果。这个效果其实很多游戏都有。网络上流传的有一个叫heat_distortion的shader,这个shader使用grabTexture实现的,实现方法很多人都讲过,这里就不细说了。grabTexture比较坑爹,在移动设备上效率很成问题,而且有些机型也不支持,所以我们需要用其他办法实现。
我们用的是后处理的办法.

1. 我们在特效上挂一个片A,给A单独设一个layer L1,然后在Main  Camera上挂一个带摄像机的子节点Sub(back ground清成黑色),MainCamera的mask剔除掉L1 ,让Sub只渲染L1。
2. A的材质shader使用heat_distortion,这个shader通过一张噪声图计算出一个UV值,从mainTex中取颜色给后面后处理的时候当UV用。
3. main camera挂载脚步DistortImageEffect。在OnRenderImage中获取Sub的RenderTexture,将这个RT给shader:IE_heat_distortion使用并生成最终结果。


代码:

using UnityEngine;
using System.Collections;


public class DistortImageEffect : MonoBehaviour
{
	// 记录参数的rt
	RenderTexture rt;


	public Material IEHeatMaterial = null;
	public Camera sub = null;
	// Use this for initialization
	void Start()
	{
		Camera cam = GetComponent<Camera>();


		sub.fieldOfView = cam.fieldOfView;
		sub.nearClipPlane = cam.nearClipPlane;
		sub.farClipPlane = cam.farClipPlane;
		sub.aspect = cam.aspect;
		int w = Screen.width / 2;
		int h = Screen.height / 2;
		if (w > SystemInfo.maxTextureSize)
		{
			h = h * SystemInfo.maxTextureSize / w;
			w = SystemInfo.maxTextureSize;
		}
		if (h > SystemInfo.maxTextureSize)
		{
			w = w * SystemInfo.maxTextureSize / h;
			h = SystemInfo.maxTextureSize;
		}


		rt = RenderTexture.GetTemporary(Screen.width / 2, Screen.height / 2);
		sub.targetTexture = rt;
	}


	void OnDestroy()
	{
		RenderTexture.ReleaseTemporary(rt);
	}


	void OnRenderImage(RenderTexture source, RenderTexture destination)
	{
		if (sub == null)
		{
			Graphics.Blit(source, destination);
			return;
		}


		IEHeatMaterial.SetTexture("_NormalTex", rt);
 		Graphics.Blit(source, destination, IEHeatMaterial, 0);
	}	
}



Shader "Distortion" {
Properties {
	_NoiseTex ("Noise (RG)", 2D) = "white" {}
	_MainTex ("Alpha (A)", 2D) = "white" {}
	_HeatTime  ("Heat Time", range (0,1.5)) = 1
	_HeatForce  ("Heat Force", float) = 0.1
}

Category {
	Tags { "RenderType"="Opaque" }
	Cull Off Lighting Off ZWrite Off Blend Off Fog {Mode Off}
	LOD 100
	

	SubShader {

		Pass {			
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma fragmentoption ARB_precision_hint_fastest
			#include "UnityCG.cginc"

			struct appdata_t {
				float4 vertex : POSITION;
				float2 texcoord: TEXCOORD0;
			};

			struct v2f {
				float4 vertex : POSITION;
				float4 uvgrab : TEXCOORD0;
				float2 uvmain : TEXCOORD1;
				float2 uv : TEXCOORD2;
			};

			sampler2D _NoiseTex;
			float4 _NoiseTex_ST;
			sampler2D _MainTex;
			float4 _MainTex_ST;
			float _HeatForce;
			float _HeatTime;

			v2f vert (appdata_t v)
			{
				v2f o;
				o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
				#if UNITY_UV_STARTS_AT_TOP
				float scale = -1.0;
				#else
				float scale = 1.0;
				#endif
				o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y*scale) + o.vertex.w) * 0.5;
				o.uvgrab.zw = o.vertex.zw; 
				o.uvmain = TRANSFORM_TEX( v.texcoord, _MainTex );
				o.uv = v.texcoord;

				return o;
			}

			half4 frag( v2f i ) : COLOR
			{
				half4 offsetColor1 = tex2D(_NoiseTex, i.uvmain + _Time.xz*_HeatTime);
				half4 offsetColor2 = tex2D(_NoiseTex, i.uvmain - _Time.yx*_HeatTime);

				i.uvgrab.x += ((offsetColor1.r + offsetColor2.r) - 1) * _HeatForce;
				i.uvgrab.y += ((offsetColor1.g + offsetColor2.g) - 1) * _HeatForce;

				return tex2D(_MainTex, i.uvgrab);
			}
			ENDCG
		}
	}
}

Fallback off
}


Shader "IEHeatDistortion" {
Properties {
	_MainTex ("Base (RGB)", 2D) = "white" {}
	_NormalTex ("Noise Texture (RGB)", 2D) = "white" {}
}

Category {	
	ZTest Off Cull Off ZWrite Off Blend Off

	SubShader {
		Pass {
			Fog { Mode off }
			
				CGPROGRAM
				#pragma vertex vert
				#pragma fragment frag
				#include "UnityCG.cginc"

				struct appdata_t {
					float4 vertex : POSITION;
					float2 texcoord: TEXCOORD0;
				};

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

				float4 _MainTex_ST;
				float4 _NormalTex_ST;
				sampler2D _NormalTex;
				sampler2D _MainTex;

				v2f vert (appdata_t v)
				{
					v2f o;

					v.vertex.z = 0.1;
					o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
					o.uv = v.texcoord;
					
					return o;
				}

				half4 frag( v2f i ) : COLOR
				{
					half4 col = tex2D( _NormalTex, i.uv);
					half4 tint = tex2D( _MainTex, i.uv + col);
					return tint;
				}
				ENDCG
		}
	}
}
}

相关文章推荐

Unity Shader Example 4 (扭曲)

// 简单的扭曲效果 Shader "CGwell FX/Distortion Bump" { Properties { _BumpAmt ("Distortion", range (0,1...

u3d做自己的第一个射击游戏demo,实现开火效果和跟随鼠标朝向

233

U3D批处理的静态与动态问题

在屏幕上渲染物体,引擎需要发出一个绘制调用来访问图形API(iOS系统中为OpenGL ES)。每个绘制调用需要进行大量的工作来访问图形API,从而导致了CPU方面显著的性能开销。 Unity在...

u3d网格编程-绘制多面片长方体

写在前面: unity3d中可以使用Mesh类,实现动态生成网格体,指定uv、法线等操作。本文将绘制一个指定长宽高的长方体,并在其内部划分指定距离的网格,多余的部分的顶底和uv也做了适当的使用。适合...

关于3dmax模型导入到u3d中时,坐标会旋转的问题

最近很多新人询问Max导入Unity遗留的旋转角度问题,具体方法发个帖备份下以方便新人查找。 首先使用Maya建模的左手坐标系软件可以略过~ 其实方法很简单,在Max中 以模型的本地坐...

U3D场景制作规范(转)

本文提到的所有数字模型制作,全部是用3D MAX建立的模型,即使是不同的驱动引擎,对模型的要求基本是相同的。当一个VR模型制作完成时,它所包含的基本内容包括:场景尺寸、单位,模型归类塌陷、命名、节点编...
  • jataflf
  • jataflf
  • 2016年08月11日 17:25
  • 1102

U3D各向异性Shader

原文链接:各项异高光shader 一.描述:            这个材质提供了一种类似于在拉丝的金属或头发上的各向异高光。这种各项异性高光基于镜面地图specular map的蓝色通道来与Bli...

u3D开发学习之路--鼠标控制摄像机旋转

先说说编程习惯的问题,在写代码的时候我们应该尽量让别人对自己的代码的来龙去脉一目了然。我在最开始写代码的时候,只是一味的往上面写,无论是从可读性还是对内存的分配空间的利用率都很差,如果代码出现问题根本...
  • ballshe
  • ballshe
  • 2016年08月21日 21:49
  • 3187

【U3d】渲染统计窗口详细介绍(Rendering Statistics Window)

Statistics窗口,全称叫做 Rendering Statistics Window,即渲染统计窗口(或渲染数据统计窗口),窗口中罗列出关于声音、图像等多种统计信息。 Batches:即Batc...

【小松教你手游开发】【系统模块开发】u3d c# 写一个通用倒计时器

计时器管理类using UnityEngine; using System.Collections; using System; public class TimerManager : MonoBe...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:U3D Distortion
举报原因:
原因补充:

(最多只允许输入30个字)