有个著名的扭曲效果的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 是你要绑上去的。
这个问题就得到了解决。。。。。
|