有個著名的扭曲效果的SHADER如下所示
// Upgrade NOTE: replaced 'glstate.matrix.modelview[0]' with 'UNITY_MATRIX_MV'
// Upgrade NOTE: replaced 'glstate.matrix.mvp' with 'UNITY_MATRIX_MVP'
Shader "HeatDistortion" {
Properties {
_NoiseTex ("Noise Texture (RG)", 2D) = "white" {}
strength("strength", Range(0.1, 0.3)) = 0.2
transparency("transparency", Range(0.01, 0.1)) = 0.05
}
Category {
Tags { "Queue" = "Transparent+10" }
SubShader {
GrabPass {
Name "BASE"
Tags { "LightMode" = "Always" }
}
Pass {
Name "BASE"
Tags { "LightMode" = "Always" }
Fog { Color (0,0,0,0) }
Lighting Off
Cull Off
ZWrite On
ZTest LEqual
Blend SrcAlpha OneMinusSrcAlpha
AlphaTest Greater 0
CGPROGRAM
// Upgrade NOTE: excluded shader from DX11 and Xbox360; has structs without semantics (struct v2f members distortion)
#pragma exclude_renderers d3d11 xbox360
// Upgrade NOTE: excluded shader from Xbox360; has structs without semantics (struct v2f members distortion)
#pragma exclude_renderers xbox360
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#pragma fragmentoption ARB_fog_exp2
#include "UnityCG.cginc"
sampler2D _GrabTexture : register(s0);
float4 _NoiseTex_ST;
sampler2D _NoiseTex;
float strength;
float transparency;
struct data {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
struct v2f {
float4 position : POSITION;
float4 screenPos : TEXCOORD0;
float2 uvmain : TEXCOORD2;
float distortion;
};
v2f vert(data i){
v2f o;
o.position = mul(UNITY_MATRIX_MVP, i.vertex); // compute transformed vertex position
o.uvmain = TRANSFORM_TEX(i.texcoord, _NoiseTex); // compute the texcoords of the noise
//float viewAngle = dot(normalize(mul((float3x3)glstate.matrix.invtrans.modelview[0], i.normal)),
// float3(0,0,1));
float viewAngle = dot(normalize(ObjSpaceViewDir(i.vertex)),
i.normal);
o.distortion = viewAngle * viewAngle; // square viewAngle to make the effect fall off stronger
float depth = -mul( UNITY_MATRIX_MV, i.vertex ).z; // compute vertex depth
o.distortion /= 1+depth; // scale effect with vertex depth
o.distortion *= strength; // multiply with user controlled strength
o.screenPos = o.position; // pass the position to the pixel shader
return o;
}
half4 frag( v2f i ) : COLOR
{
// compute the texture coordinates
float2 screenPos = i.screenPos.xy / i.screenPos.w; // screenpos ranges from -1 to 1
screenPos.x = (screenPos.x + 1) * 0.5; // I need 0 to 1
screenPos.y = (screenPos.y + 1) * 0.5; // I need 0 to 1
if (_ProjectionParams.x < 0)
screenPos.y = 1 - screenPos.y;
// get two offset values by looking up the noise texture shifted in different directions
half4 offsetColor1 = tex2D(_NoiseTex, i.uvmain + _Time.xz);
half4 offsetColor2 = tex2D(_NoiseTex, i.uvmain - _Time.yx);
// use the r values from the noise texture lookups and combine them for x offset
// use the g values from the noise texture lookups and combine them for y offset
// use minus one to shift the texture back to the center
// scale with distortion amount
screenPos.x += ((offsetColor1.r + offsetColor2.r) - 1) * i.distortion;
screenPos.y += ((offsetColor1.g + offsetColor2.g) - 1) * i.distortion;
half4 col = tex2D( _GrabTexture, screenPos );
col.a = i.distortion/transparency;
return col;
}
ENDCG
}
}
}
}
這個SHADER是一個很好的SHADER,它可以用來做火焰的扭曲模仿效果也可以用來做地震波的效果。
做地震波的效果的方法是先做一個環形的MESH,然后將這個SHADER給MESH材質使用,然后
通過腳本改變MESH的半徑從而實現地震波使地形扭曲的效果。
在IOS上當然是沒有問題了,可是在某些android機上發現這個效果竟然實現不了,跟蹤程序發現,原來是
在這些Aandroid機上SHADER里的GrabPass方法失效了。這可如何是好呢?
經過分析發現GrabPass無非就是采集了當前的texture而已,所以試着用CAMERA的render texture功能,結果輕松的
實現了GrabPass的功能。
首先將上面的SHADER改為如下:(具體改的地方請自己比對)
// Upgrade NOTE: replaced 'glstate.matrix.modelview[0]' with 'UNITY_MATRIX_MV'
// Upgrade NOTE: replaced 'glstate.matrix.mvp' with 'UNITY_MATRIX_MVP'
Shader "HeatDistortionNew" {
Properties {
_MainTex ("Main Texture (RG)", 2D) = "white" {}
_NoiseTex ("Noise Texture (RG)", 2D) = "white" {}
strength("strength", Range(0.01, 0.1)) = 0.04
transparency("transparency", Range(0.01, 0.1)) = 0.01
}
Category {
//Tags { "Queue" = "Transparent+10" }
Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Opaque"}
SubShader {
// GrabPass {
// Name "BASE"
// Tags { "LightMode" = "Always" }
//}
Pass {
Name "BASE"
Tags { "LightMode" = "Always" }
Fog { Color (0,0,0,0) }
Lighting Off
Cull Off
ZWrite On
ZTest LEqual
Blend SrcAlpha OneMinusSrcAlpha
AlphaTest Greater 0
CGPROGRAM
// Upgrade NOTE: excluded shader from DX11 and Xbox360; has structs without semantics (struct v2f members distortion)
#pragma exclude_renderers d3d11 xbox360
// Upgrade NOTE: excluded shader from Xbox360; has structs without semantics (struct v2f members distortion)
#pragma exclude_renderers xbox360
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#pragma fragmentoption ARB_fog_exp2
#include "UnityCG.cginc"
sampler2D _MainTex : register(s0);
float4 _NoiseTex_ST;
sampler2D _NoiseTex;
float strength;
float transparency;
uniform float _BumpAmt;
float4 _MainTex_TexelSize;
struct data {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
struct v2f {
float4 position : POSITION;
float4 screenPos : TEXCOORD0;
float2 uvmain : TEXCOORD2;
float distortion;
};
v2f vert(data i){
v2f o;
o.position = mul(UNITY_MATRIX_MVP, i.vertex); // compute transformed vertex position
o.uvmain = TRANSFORM_TEX(i.texcoord, _NoiseTex); // compute the texcoords of the noise
//float viewAngle = dot(normalize(mul((float3x3)glstate.matrix.invtrans.modelview[0], i.normal)),
// float3(0,0,1));
float viewAngle = dot(normalize(ObjSpaceViewDir(i.vertex)),
i.normal);
o.distortion = viewAngle * viewAngle; // square viewAngle to make the effect fall off stronger
float depth = -mul( UNITY_MATRIX_MV, i.vertex ).z; // compute vertex depth
o.distortion /= 1+depth; // scale effect with vertex depth
o.distortion *= strength; // multiply with user controlled strength
o.screenPos = o.position; // pass the position to the pixel shader
return o;
}
half4 frag( v2f i ) : COLOR
{
// compute the texture coordinates
float2 screenPos = i.screenPos.xy / i.screenPos.w; // screenpos ranges from -1 to 1
screenPos.x = (screenPos.x + 1) * 0.5; // I need 0 to 1
screenPos.y = (screenPos.y + 1) * 0.5; // I need 0 to 1
if (_ProjectionParams.x < 0)
screenPos.y = 1 - screenPos.y;
// get two offset values by looking up the noise texture shifted in different directions
half4 offsetColor1 = tex2D(_NoiseTex, i.uvmain + _Time.xz);
half4 offsetColor2 = tex2D(_NoiseTex, i.uvmain - _Time.yx);
// use the r values from the noise texture lookups and combine them for x offset
// use the g values from the noise texture lookups and combine them for y offset
// use minus one to shift the texture back to the center
// scale with distortion amount
screenPos.x += ((offsetColor1.r + offsetColor2.r) - 1) * i.distortion;
screenPos.y += ((offsetColor1.g + offsetColor2.g) - 1) * i.distortion;
half4 col = tex2D( _MainTex, screenPos );
col.a = i.distortion/transparency;
return col;
}
ENDCG
}
}
}
}
然后再寫一個腳本如下:
using UnityEngine;
using System.Collections;
public class Heat : MonoBehaviour {
public Camera c;
Material m;
public RenderTexture t;
// Use this for initialization
void Start () {
m = GetComponent<MeshRenderer>().material;
Instantiate(c, Camera.mainCamera.transform.position, Camera.mainCamera.transform.rotation);
}
// Update is called once per frame
void Update () {
m.SetTexture("_MainTex", t);
}
}
注意的地方是:CAMERA當然是你的相機了,RenderTexture t 是你要綁上去的。
這個問題就得到了解決。。。。。