您的位置:首页 > 移动开发 > Unity3D

U3D Distortion

2016-05-30 22:48 459 查看
我们的美术希望游戏可以更炫一点,想在刀光特效上加上空气扭曲的效果,就是类似燃烧的火焰上方空气扰动的那种效果。这个效果其实很多游戏都有。网络上流传的有一个叫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
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  unity3d