用Shader实现的常用效果2

unity实现透明水波纹扭曲///

Shader "Unlit/Water"
{
 Properties
 {
 _MainTex ("Texture", 2D) = "white" {}
 _WaterUV("WaterUV",2D)="while"{}
 _WaterIntensity("WaterIntensity",float)=500
 }
 SubShader
 {

 GrabPass{
 Name "BASE"
 Tags { "Mode" = "Always" }
 }

 Tags { "Queue"="Transparent+100" "RenderType"="Transparent" }
 

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

 struct appdata
 {
 float4 vertex : POSITION;
 float2 uv : TEXCOORD0;
 float3 normal:Normal;
 };

 struct v2f
 {
 float2 uv : TEXCOORD0;
 float4 grabuv:TEXCOORD1;
 float4 vertex : SV_POSITION;
 float3 normal:Normal;
 };

 sampler2D _MainTex;
 float4 _MainTex_ST;
 sampler2D _GrabTexture;
 sampler2D _WaterUV;
 float4 _GrabTexture_TexelSize;
 float _WaterIntensity;

 v2f vert (appdata v)
 {
 v2f o;
 o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
 o.uv = TRANSFORM_TEX(v.uv, _MainTex);

 UNITY_TRANSFER_FOG(o,o.vertex);
 o.grabuv=ComputeGrabScreenPos(o.vertex);

 o.normal=v.normal;


 return o;
 }
 
 fixed4 frag (v2f i) : SV_Target
 {
 fixed4 col = tex2D(_MainTex, i.uv);
 float2 uv=tex2D(_WaterUV,i.uv).xy;

  uv= (uv-0.5)*2;

 float2 offset_ =uv * _GrabTexture_TexelSize.xy*_WaterIntensity;
 
 float4 grabuv=i.grabuv;
 grabuv.xy+=sin(offset_);

 fixed4 grabCol=tex2Dproj(_GrabTexture,UNITY_PROJ_COORD(grabuv));
 
 
 return col*grabCol;
 }
 ENDCG
 }
 }
}

using UnityEngine;
using System.Collections;
using System.Threading;

public class Water : MonoBehaviour
{


 public int m_texHeight = 512;

 public int m_texWidth = 512;

 public Texture2D m_waterTexture = null;

 private Material m_waterMatrial;

 private float[,] waveA;
 private float[,] waveB;

 public float decrement=0.025f;

 public Camera m_waterCam;

 private int time;
 void Start()
 {

  m_waterTexture = new Texture2D(m_texWidth, m_texHeight, TextureFormat.RGBA32, false);

  m_waterMatrial = GetComponent<MeshRenderer>().material;

  waveA = new float[m_texWidth, m_texHeight];
  waveB = new float[m_texWidth, m_texHeight];
 
  m_waterMatrial.SetTexture("_WaterUV", m_waterTexture);

  allColor = new Color[m_texWidth* m_texHeight];

  Thread t = new Thread(new ThreadStart(ThreadWave));
  t.Start();

  // m_waterMatrial.SetTexture("_MainTex", m_waterTexture);
 }

 public void PopWater(Vector2 pos)
 {
  float x=pos.x;
  float y=pos.y;
  waveA[(int)(m_texWidth * x) , (int)(m_texHeight * y)] = 1;
  //waveA[(int)(m_texWidth * x) - 1, (int)(m_texHeight * y) ] = 1;
  //waveA[(int)(m_texWidth * x) + 1, (int)(m_texHeight * y) ] = 1;
  //waveA[(int)(m_texWidth * x) , (int)(m_texHeight * y) - 1] = 1;
  //waveA[(int)(m_texWidth * x), (int)(m_texHeight * y) + 1] = 1;
  //waveA[(int)(m_texWidth * x) - 1, (int)(m_texHeight * y) - 1] = 1;
  //waveA[(int)(m_texWidth * x) - 1, (int)(m_texHeight * y) + 1] = 1;
  //waveA[(int)(m_texWidth * x) + 1, (int)(m_texHeight * y) - 1] = 1;
  //waveA[(int)(m_texWidth * x) + 1, (int)(m_texHeight * y) + 1] = 1;
 }
 public void PopWater()
 {
  waveA[(int)(m_texWidth / 2), (int)(m_texHeight / 2)] = 1;
  waveA[(int)(m_texWidth / 2) - 1, (int)(m_texHeight / 2)] = 1;
  waveA[(int)(m_texWidth / 2) + 1, (int)(m_texHeight / 2)] = 1;
  waveA[(int)(m_texWidth / 2), (int)(m_texHeight / 2) - 1] = 1;
  waveA[(int)(m_texWidth / 2), (int)(m_texHeight / 2) + 1] = 1;
  waveA[(int)(m_texWidth / 2) - 1, (int)(m_texHeight / 2) - 1] = 1;
  waveA[(int)(m_texWidth / 2) - 1, (int)(m_texHeight / 2) + 1] = 1;
  waveA[(int)(m_texWidth / 2) + 1, (int)(m_texHeight / 2) - 1] = 1;
  waveA[(int)(m_texWidth / 2) + 1, (int)(m_texHeight / 2) + 1] = 1;
 }


 void Update()
 {
  ComputeWave();


  if (Input.GetMouseButtonDown(0))
  {
   RaycastHit rh;
   if (Physics.Raycast(m_waterCam.ScreenPointToRay(Input.mousePosition), out rh))
   {
    

    PopWater(rh.textureCoord);
   }

  }

  time = (int)Time.deltaTime * 1000;
 
 }

 void OnDestroy()
 {
  f = false;

 }

 bool f = true;
 void ThreadWave()
 {
  while (f)
  {
   Thread.Sleep(time);
   for (int w = 1; w < m_texWidth - 1; w++)
   {

    for (int h = 1; h < m_texHeight - 1; h++)
    {
     waveB[w, h] =
      (waveA[w - 1, h] +
      waveA[w + 1, h] +
      waveA[w, h - 1] +
      waveA[w, h + 1] +
      waveA[w - 1, h - 1] +
      waveA[w + 1, h - 1] +
      waveA[w - 1, h + 1] +
      waveA[w + 1, h + 1]) / 4 - waveB[w, h];


     float value = waveB[w, h];
     if (value > 1)
     {
      waveB[w, h] = 1;
     }

     if (value < -1)
     {
      waveB[w, h] = -1;
     }


     if (value > -0.0001 && value < 0.0001)
     {
      waveB[w, h] = 0;
     }


     float offset_u = (waveB[w - 1, h] - waveB[w + 1, h]) / 2;

     float offset_v = ((waveB[w, h - 1]) - waveB[w, h + 1]) / 2;


     float r = offset_u / 2 + 0.5f;
     float g = offset_v / 2 + 0.5f;
     Color c = new Color(r, g, 0);
     

     waveB[w, h] -= waveB[w, h] * decrement;
     allColor[w + m_texWidth * h] = c;


    }
   }

   float[,] temp;
   temp = waveA;
   waveA = waveB;
   waveB = temp;
  }

 }

 private Color[] allColor;

 void ComputeWave()
 {
  m_waterTexture.SetPixels(allColor);
  m_waterTexture.Apply();

 }

}

//Unity3D Shader实现镜子效果//

Shader "Custom/FanShe" {
Properties{
_MainTex("Albedo",2D) = "white"{}
_MainTint("Diffuse Color",Color)=(1,1,1,1)
_Cubemap("Cubemap",CUBE) = ""{}
_ReflAmount("Reflection Amount",Range(0.1,1.0))=0.5
}
SubShader{
Tags{"RenderType"="Opaque"}
LOD 200
 
 
CGPROGRAM
#pragma surface surf Lambert
#pragma target 3.0
struct Input {
float2 uv_MainTex;
float3 worldRefl;
};
sampler2D _MainTex;
samplerCUBE _Cubemap;
fixed4 _MainTint;
half _ReflAmount;
void surf(Input IN, inout SurfaceOutput o)
{
fixed4 c = tex2D(_MainTex, IN.uv_MainTex)*_MainTint;
o.Albedo = c.rgb;
o.Emission = texCUBE(_Cubemap, IN.worldRefl)*_ReflAmount;
o.Alpha = c.a;
}
ENDCG
}
 
FallBack "Diffuse"
 
}

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
 
public class Shader_FanShe : MonoBehaviour {
  public Cubemap cubeMap;
  public Camera cam;
  Material curmat;
// Use this for initialization
void Start () {
    InvokeRepeating("change", 1, 0.1f);
    curmat = gameObject.GetComponent<Renderer>().material;
    if (curmat == null)
    {
      Debug.Log("cw");
    }
    
}
 
// Update is called once per frame
void Update () {
 
}
  void change()
  {
    cam.transform.rotation = Quaternion.identity;
    cam.RenderToCubemap(cubeMap);
    curmat.SetTexture("_Cubemap",cubeMap);
  }
 
}

/Unity shader实现移动端模拟深度水效果///

Shader "Game_XXX/whater"
{
 Properties 
 {
 _WaterTex ("Normal Map (RGB), Foam (A)", 2D) = "white" {}
 _AlphaTex("AlphaTex", 2D) = "black" {}
 _shadowLight ("shadowLight",range(0,1)) = 0
 _Tiling ("Wave Scale", Range(0.00025, 0.007)) = 0.25
 _WaveSpeed("Wave Speed", Float) = 0.4
 _SpecularRatio ("Specular Ratio", Range(10,500)) = 200
 _outSideColor("outSideColor",Color) = (0,0,0,0)
 _outSideLight("outSideLight",Range(0,10))=1
 _inSideColor("inSideColor",Color) = (0,0,0,0)
 _inSideLight("intSideLight",Range(0,10))=1
 _Alpha("Alpha",Range(0,1)) = 1
 //模拟灯光颜色
 _LightColorSelf ("LightColorSelf",Color) = (1,1,1,1)
 //模拟灯光方向
 _LightDir ("LightDir",vector) = (0,1,0,0)
 //高光强度
 _specularLight("specularLight",range(0.1,2)) =1 
 }
 
 SubShader { 
 Tags {
 "Queue"="Transparent-200"
 "RenderType"="Transparent" 
 "IgnoreProjector" = "True"
 "LightMode" = "ForwardBase"
 }
 LOD 250
 Pass
 {
 
 ZWrite Off
 Blend SrcAlpha OneMinusSrcAlpha
 CGPROGRAM
 
 #pragma vertex Vert
 #pragma fragment Frag
 #include "UnityCG.cginc"
 
 float _Tiling;
 float _WaveSpeed;
 float _SpecularRatio;
 sampler2D _WaterTex;
 sampler2D _AlphaTex;
 float4 _LightColorSelf;
 float4 _LightDir;
 float4 _outSideColor;
 float _outSideLight;
 float4 _inSideColor;
 float _inSideLight;
 float _shadowLight;
 float _specularLight;
 float _Alpha;
 
 struct v2f
 {
 float4 position : POSITION;
 float3 worldView : TEXCOORD0;
 float3 tilingAndOffset:TEXCOORD2;
 float3x3 tangentTransform:TEXCOORD4; 
 float2 alphaUV :TEXCOORD7;
 
 };
 
 
 
 v2f Vert(appdata_full v)
 {
 v2f o;
 float4 worldPos = mul(unity_ObjectToWorld, v.vertex);
 //视向量(世界空间)
 o.worldView = -normalize(worldPos - _WorldSpaceCameraPos);
 o.position = UnityObjectToClipPos(v.vertex);
 //uv动画
 o.tilingAndOffset.z =frac( _Time.x * _WaveSpeed);//frac :返回标量或矢量的小数
 o.tilingAndOffset.xy = worldPos.xz*_Tiling;
 o.alphaUV = v.texcoord;
 //求世界法线三件套 
 float3 normal =normalize( UnityObjectToWorldNormal(v.normal)); 
    float3 tangentDir = normalize( mul( unity_ObjectToWorld, float4( v.tangent.xyz, 0.0 ) ).xyz );//切线空间转化为世界空间 
    float3 bitangentDir = normalize(cross(normal, tangentDir) * v.tangent.w);//切线 法线 计算副切线 
 
 o.tangentTransform = float3x3( tangentDir, bitangentDir, normal); 
 return o;
 }
 
 float4 Frag(v2f i):COLOR
 {
 
  
 
  //法线采样
  fixed3 BumpMap01 = UnpackNormal(tex2D(_WaterTex,i.tilingAndOffset.xy + i.tilingAndOffset.z ));
  fixed3 BumpMap02 = UnpackNormal(tex2D(_WaterTex,i.tilingAndOffset.xy*1.1 - i.tilingAndOffset.z));
  //两张法线相混合
  //fixed3 N1 =saturate( normalize(mul( BumpMap01.rgb, i.tangentTransform )));
  //fixed3 N2 =saturate( normalize(mul( BumpMap02.rgb, i.tangentTransform )));
  //fixed3 worldNormal = N1 - float3(N2.x,0,N2.z);
 
  fixed3 N1 = normalize(mul( BumpMap01.rgb, i.tangentTransform ));
  fixed3 N2 = normalize(mul( BumpMap02.rgb, i.tangentTransform ));
  fixed3 worldNormal = N1*0.5 +N2*0.5;
 
 
 
 
  float LdotN = dot(worldNormal, _LightDir.xyz); //_LightDir为模拟灯光
 
 
  //高光 
  float dotSpecular = dot(worldNormal, normalize( i.worldView+_LightDir.xyz));
  fixed3 specularReflection = pow(saturate(dotSpecular), _SpecularRatio)*_specularLight;
 
 
  //通道贴图采样
  fixed4 alphaTex = tex2D (_AlphaTex,i.alphaUV);
  //模拟灯光的颜色 * 漫反射系数= 基础水的颜色
  fixed4 col =_LightColorSelf*2 * saturate (LdotN) ;
  //用alpha贴图的r通道来模拟水的深浅的颜色,白色为深色,黑色为浅色 ,同时乘以想要的颜色
  col.rgb = col.rgb * alphaTex.r *_inSideColor * _inSideLight + col.rgb * (1-alphaTex.r) * _outSideColor *_outSideLight + specularReflection;
 
  //控制透明度,根据alpha的r通道 来控制深浅的透明度,深色的透明度小 浅色的透明度大
  col.a = _Alpha * alphaTex.r;
 
  //手动绘制阴影 用alpha贴图的g通道 跟col相乘 来模拟阴影 
  alphaTex.g = saturate(alphaTex.g + _shadowLight);
  col.rgb *= alphaTex.g;
  return col;
 }
  ENDCG 
  } 
 }
 
 FallBack "Diffuse"
}

 

/Unity Shader模拟玻璃效果//

Shader "Glass Refraction" {
  Properties {
    _MainTex ("Main Tex", 2D) = "white" {}
    _BumpMap ("Normal Map", 2D) = "bump" {}
    _Cubemap ("Environment Cubemap", Cube) = "_Skybox" {}
    _Distortion ("Distortion", Range(0, 100)) = 10
    _RefractAmount ("Refract Amount", Range(0.0, 1.0)) = 1.0
  }
  SubShader {
    // 1.队列设置成透明的可以保证渲染该物体的时候,其他所有不透明的物体都已经被渲染到屏幕上了
    //  这样GrabPass保存屏幕图像的时候才能完整
    // 2.渲染类型设置为不透明是为了使用着色器替换的时候,物体可以在被需要时正确的渲染
    Tags { "Queue"="Transparent" "RenderType"="Opaque" }

    // 抓取屏幕图像并保存到纹理 _RefractionTex 中
    GrabPass { "_RefractionTex" }

    Pass {   
      CGPROGRAM

      #pragma vertex vert
      #pragma fragment frag

      #include "UnityCG.cginc"

      sampler2D _MainTex;
      float4 _MainTex_ST;
      sampler2D _BumpMap;
      float4 _BumpMap_ST;
      samplerCUBE _Cubemap;
      float _Distortion;
      fixed _RefractAmount;
      sampler2D _RefractionTex;
      // 可以得到系统保存的纹素的尺寸大小 1/256,1/512
      // 对屏幕图像坐标采样进行偏移的时候需要使用该变量
      float4 _RefractionTex_TexelSize;

      struct a2v {
        float4 vertex : POSITION;
        float3 normal : NORMAL;
        float4 tangent : TANGENT; 
        float2 texcoord: TEXCOORD0;
      };

      struct v2f {
        float4 pos : SV_POSITION;
        float4 scrPos : TEXCOORD0;
        float4 uv : TEXCOORD1;
        float4 TtoW0 : TEXCOORD2; 
        float4 TtoW1 : TEXCOORD3; 
        float4 TtoW2 : TEXCOORD4; 
      };

      v2f vert (a2v v) {
        v2f o;
        o.pos = mul(UNITY_MATRIX_MVP, v.vertex);

        // 得到对应被抓取的屏幕图像的采样坐标
        o.scrPos = ComputeGrabScreenPos(o.pos);

        // 原图和法线贴图公用同一套UV坐标,进行纹理偏移缩放设置
        o.uv.xy = TRANSFORM_TEX(v.texcoord, _MainTex);
        o.uv.zw = TRANSFORM_TEX(v.texcoord, _BumpMap);

        // 世界方向
        float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz; 

        // 法线世界方向
        fixed3 worldNormal = UnityObjectToWorldNormal(v.normal); 

        // 切线世界方向
        fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz); 

        // 世界副切线方向
        fixed3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w;

        // 定义:切线空间到世界空间的变换矩阵
        // 所有的TBN都从切线空间转换到了世界空间
        o.TtoW0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x); 
        o.TtoW1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y); 
        o.TtoW2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z); 

        return o;
      }

      fixed4 frag (v2f i) : SV_Target {    
        // 世界空间
        float3 worldPos = float3(i.TtoW0.w, i.TtoW1.w, i.TtoW2.w);

        // 世界空间下的观察方向
        fixed3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));

        // 对法线贴图进行采样,并使用UnpackNormal解压*2-1,但实际上法线贴图在切线空间下
        // 所以需要将bump从切线空间转换到世界空间
        fixed3 bump = UnpackNormal(tex2D(_BumpMap, i.uv.zw)); 

        // 对采样坐标进行偏移
        float2 offset = bump.xy * _Distortion * _RefractionTex_TexelSize.xy;
        i.scrPos.xy = offset * i.scrPos.z + i.scrPos.xy;

        // 对屏幕纹理进行采样
        fixed3 refrCol = tex2D(_RefractionTex, i.scrPos.xy/i.scrPos.w).rgb;

        // 将bump从切线空间转换到世界空间
        // TtoW0的xyz:T的X,B的X,N的X
        // 用点积得到一个常量
        bump = normalize(half3(dot(i.TtoW0.xyz, bump), dot(i.TtoW1.xyz, bump), dot(i.TtoW2.xyz, bump)));

        // 用法线贴图求反射方向
        fixed3 reflDir = reflect(-worldViewDir, bump);

        // 主纹理采样
        fixed4 texColor = tex2D(_MainTex, i.uv.xy);

        // 对_Cubemap进行纹理采样,使用反射方向
        fixed3 reflCol = texCUBE(_Cubemap, reflDir).rgb * texColor.rgb;

        // 反射颜色+折射颜色
        fixed3 finalColor = reflCol * (1 - _RefractAmount) + refrCol * _RefractAmount;

        return fixed4(finalColor, 1);
      }

      ENDCG
    }
  }

  FallBack "Diffuse"
}

//Unity shader实现多光源漫反射以及阴影/

Shader "Unlit/MulLight"
{
 Properties
 {
  _MainTex ("Texture", 2D) = "white" {}
 }
 SubShader
 {
  //一盏主灯
  Pass
  {
   //Always: 总是渲染;没有光照模式。
   //ForwardBase: 适用于前渲染、环境、主要方向灯、光/sh光和烘焙图。
   //ForwardAdd: 适用于前渲染, 叠加每一盏灯,每一盏灯就多一个pass。
   //Deferred: 延迟渲染,渲染g缓冲区 。
   //ShadowCaster:将物体深度渲染到阴影贴图或者深度纹理上 。
   //PrepassBase: 用于传统的延迟光照,渲染法线和高光效果。
   //PrepassFinal:用于传统的延迟光照,通过结合文理、灯光、和法线来渲染最终的结果。
   //Vertex:当对象不是光映射时,用于遗留顶点的渲染,所有顶点灯都被利用。 
   //VertexLMRGBM: 当对象被光映射时,在遗留的顶点上使用渲染,在LightMap是RGBM编码的平台上(pc和控制台)。
   //VertexLM: 当对象被光映射时,在遗留的顶点上使用渲染,在LightMap是双idr编码的(移动平台)平台上。
   Tags { "RenderType"="Opaque" "LightMode" = "ForwardBase"}//
   CGPROGRAM
   #pragma vertex vert
   #pragma fragment frag
   #include "UnityCG.cginc"
    #pragma target 3.0 
 
   //衰减与阴影的实现
   #include "AutoLight.cginc"//
    //fwdadd:ForwardBase的阴影显示,在下面的ForwardAdd里得用fwdadd; 必须结合fallback,两者缺一不可 
   #pragma multi_compile_fwdadd_fullshadows//
   sampler2D _MainTex;
   float4 _MainTex_ST;
   //定义一个灯光,名字为固定格式,会自动取场景中灯光
   float4 _LightColor0;//
 
   struct appdata
   {
    float4 vertex : POSITION;
    float2 uv : TEXCOORD0;
    float4 normal:NORMAL;//
   };
 
   struct v2f
   {
    float2 uv : TEXCOORD0;
    float4 pos: SV_POSITION;
    float3 normal :TEXCOORD1;//
     //点光源需要的衰减 
    LIGHTING_COORDS(3,4)//#include "AutoLight.cginc"
   };
   v2f vert (appdata v)
   {
    v2f o;
    //这里一般用 o.pos,用o.vertex有时候会报错 
    o.pos= UnityObjectToClipPos(v.vertex);
    o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    o.normal = v.normal;//
    //点光源需要的衰减 
    TRANSFER_VERTEX_TO_FRAGMENT(o)//#include "AutoLight.cginc"
    return o;
   }
   fixed4 frag (v2f i) : SV_Target
   {
    //物体法向量转化为世界法向量
    float3 N = normalize(UnityObjectToWorldNormal(i.normal));//
    //世界光向量:unity封装好的光向量,会自动调用场景里面的存在的灯光
    float3 L =normalize( _WorldSpaceLightPos0.xyz);//
             //点光源需要的衰减系数
    float atten = LIGHT_ATTENUATION(i);//#include "AutoLight.cginc"
 
    fixed4 col = tex2D(_MainTex, i.uv);
    //最终颜色 = 主颜色 x( 灯光颜色 x 漫反射系数 x衰减系数 + 环境光)
    col.rgb = col.rgb * (_LightColor0.rgb* saturate(dot(N,L)) *atten + UNITY_LIGHTMODEL_AMBIENT);//
 
    return col;
   }
   ENDCG
   }
 
   //多盏灯叠加
  Pass//
  {
   Tags { "RenderType"="Opaque" "LightMode" = "ForwardAdd"} //ForwardAdd :多灯混合//
   Blend One One//
   CGPROGRAM
   #pragma vertex vert
   #pragma fragment frag
   #include "UnityCG.cginc"
   #pragma target 3.0
 
   //衰减与阴影的实现
   #include "AutoLight.cginc"//
    //fwdadd:ForwardAdd的阴影显示,在上面的ForwardBase里得用fwdbase; 必须结合fallback,两者缺一不可 
   #pragma multi_compile_fwdadd_fullshadows//
 
   sampler2D _MainTex;
   float4 _MainTex_ST;
   //定义一个灯光,名字为固定格式,会自动取场景中灯光
   float4 _LightColor0;//
 
   struct appdata
   {
    float4 vertex : POSITION;
    float2 uv : TEXCOORD0;
    float4 normal:NORMAL;//
   };
 
   struct v2f
   {
    float2 uv : TEXCOORD0;
    float4 pos: SV_POSITION;
    float3 normal :TEXCOORD1;//
    float4 wPos :TEXCOORD2;//
    //点光源需要的衰减 
    LIGHTING_COORDS(3,4)//#include "AutoLight.cginc"
   };
   v2f vert (appdata v)
   {
    v2f o;
     //这里一般用 o.pos,用o.vertex有时候会报错
    o.pos= UnityObjectToClipPos(v.vertex);
    o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    o.wPos= mul(unity_ObjectToWorld, v.vertex);//
    o.normal = v.normal;//
    //点光源需要的衰减
    TRANSFER_VERTEX_TO_FRAGMENT(o)//#include "AutoLight.cginc"
    return o;
   }
   fixed4 frag (v2f i) : SV_Target
   {
    //物体法向量转化为世界法向量
    float3 N = normalize(UnityObjectToWorldNormal(i.normal));//
 
    //世界光向量:这里计算的是点光源,按照灯光的距离来算衰减,第一个pass不需要
    float3 L = normalize (lerp(_WorldSpaceLightPos0.xyz , _WorldSpaceLightPos0.xyz - i.wPos.xyz , _WorldSpaceLightPos0.w));//
 
    //点光源需要的衰减
    float atten = LIGHT_ATTENUATION(i);//#include "AutoLight.cginc"
 
    fixed4 col = tex2D(_MainTex, i.uv);
 
    //最终颜色 = 主颜色 x 灯光颜色 x 漫反射系数 x 衰减系数 第一个pass已经有了环境色 这里就不能加了
    col.rgb = col.rgb * _LightColor0.rgb * saturate(dot(N,L))*atten;//
 
    return col;
   }
  ENDCG
  }
 }
   //需要产生阴影 
   FallBack "Diffuse" 
}

/Unity Shader实现水波纹效果//

Shader "Custom/shuibowen"{
 Properties{
 _MainTex("Base (RGB)",2D)="white"{}
 _distanceFactor("Distancefactor",float)=1
 _timeFactor("time factor",float)=2
 _totalFactor("total factor",float)=3
 _waveWidth("wave width",float)=4
 _curWaveDis("curwave dis",float)=5
 _startPos("star pos",Vector) = (1,1,1,1)
 _MainTex_TexelSize("Maintex_texelSize",vector)=(1,1,1,1)
 }
 CGINCLUDE
 #include "UnityCG.cginc"
 uniform sampler2D _MainTex; 
 float4 _MainTex_TexelSize;
 uniform float _distanceFactor; 
 uniform float _timeFactor; 
 uniform float _totalFactor; 
 uniform float _waveWidth; 
 uniform float _curWaveDis; 
 uniform float4 _startPos;
 fixed4 frag(v2f_img i) : SV_Target 
 { 
  //DX下纹理坐标反向问题 
  #if UNITY_UV_STARTS_AT_TOP 
  if (_MainTex_TexelSize.y < 0) 
   _startPos.y = 1 - _startPos.y; 
  #endif 
  //计算uv到中间点的向量(向外扩,反过来就是向里缩) 
  float2 dv = _startPos.xy - i.uv; 
  //按照屏幕长宽比进行缩放 
  dv = dv * float2(_ScreenParams.x / _ScreenParams.y, 1); 
  //计算像素点距中点的距离 
  float dis = sqrt(dv.x * dv.x + dv.y * dv.y); 
  //用sin函数计算出波形的偏移值factor 
  //dis在这里都是小于1的,所以我们需要乘以一个比较大的数,比如60,这样就有多个波峰波谷 
  //sin函数是(-1,1)的值域,我们希望偏移值很小,所以这里我们缩小100倍,据说乘法比较快,so... 
  float sinFactor = sin(dis * _distanceFactor + _Time.y * _timeFactor) * _totalFactor * 0.01; 
  //距离当前波纹运动点的距离,如果小于waveWidth才予以保留,否则已经出了波纹范围,factor通过clamp设置为0 
  float discardFactor = clamp(_waveWidth - abs(_curWaveDis - dis), 0, 1) / _waveWidth; 
  //归一化 
  float2 dv1 = normalize(dv); 
  //计算每个像素uv的偏移值 
  float2 offset = dv1 * sinFactor * discardFactor; 
  //像素采样时偏移offset 
  float2 uv = offset + i.uv; 
  return tex2D(_MainTex, uv); 
 } 
 ENDCG 
 SubShader 
 { 
  Pass 
  { 
   ZTest Always 
   Cull Off 
   ZWrite Off 
   Fog { Mode off } 
 
   CGPROGRAM 
   #pragma vertex vert_img 
   #pragma fragment frag 
   #pragma fragmentoption ARB_precision_hint_fastest 
   ENDCG 
  } 
 } 
 Fallback off 
}

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class WaterWaveEffect : PostEffectsBase {
 //距离系数 
 public float distanceFactor = 60.0f;
 //时间系数 
 public float timeFactor = -30.0f;
 //sin函数结果系数 
 public float totalFactor = 1.0f;

 //波纹宽度 
 public float waveWidth = 0.3f;
 //波纹扩散的速度 
 public float waveSpeed = 0.3f;

 private float waveStartTime;
 private Vector4 startPos = new Vector4(0.5f, 0.5f, 0, 0);
 public Material _Material;

 void OnRenderImage(RenderTexture source, RenderTexture destination)
 {
  //计算波纹移动的距离,根据enable到目前的时间*速度求解 
  float curWaveDistance = (Time.time - waveStartTime) * waveSpeed;
  //设置一系列参数 
  _Material.SetFloat("_distanceFactor", distanceFactor);
  _Material.SetFloat("_timeFactor", timeFactor);
  _Material.SetFloat("_totalFactor", totalFactor);
  _Material.SetFloat("_waveWidth", waveWidth);
  _Material.SetFloat("_curWaveDis", curWaveDistance);
  _Material.SetVector("_startPos", startPos);
  Graphics.Blit(source, destination, _Material);
 }

 void Update()
 {
  if (Input.GetMouseButton(0))
  {
   Vector2 mousePos = Input.mousePosition;
   //将mousePos转化为(0,1)区间 
   startPos = new Vector4(mousePos.x / Screen.width, mousePos.y / Screen.height, 0, 0);
   waveStartTime = Time.time;
  }

 }
}

///

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值