课时60 Fragment shader – UV动画 1

课时60 Fragment shader – UV动画 1

1.需求:将具有m行n列格子的图片在一个平面上,按照从上向下,从左至右顺序播放每一个格子;也可以设置播放顺序为从下向上,从右制作反序播放。

2.代码:

using UnityEngine;
using System.Collections;
 
public class SetTextureUVST : MonoBehaviour
{
    public int rowCount;    //行数
    public int columCount;  //列数
 
    public int fps;         //播放速度
	public bool toUpper;//从上至下,从做到右
 
    private int currentIndex;//当前播放索引值
	float itemWidth ;
	float itemHeight;

	private	Material mat ;
 
    void Start()
    {
       	itemWidth = 1.0f / rowCount;      //每一帧宽度
        itemHeight = 1.0f / columCount;   //每一帧高度
		mat = GetComponent<Renderer>().material;
		if(toUpper)
		{
			StartCoroutine(OneToNine());
		}else
		{
			StartCoroutine(NineToOne());
		}
    }
	IEnumerator OneToNine()
	{
        while (true)
        {
            float offset_x = currentIndex % columCount * itemWidth;
            float offset_y =- currentIndex / rowCount * itemHeight+itemHeight*2;
 
            mat.SetTextureScale("_MainTex", new Vector2(itemWidth, itemHeight));
            mat.SetTextureOffset("_MainTex", new Vector2(offset_x, offset_y));
 
            yield return new WaitForSeconds(1 / fps);
 
            currentIndex = (++currentIndex) % (rowCount * columCount);
        }
	}
	IEnumerator NineToOne()
	{
        while (true)
        {
            float offset_x = -currentIndex % columCount * itemWidth+itemWidth*2;
            float offset_y = currentIndex / rowCount * itemHeight;
 
            mat.SetTextureScale("_MainTex", new Vector2(itemWidth, itemHeight));
            mat.SetTextureOffset("_MainTex", new Vector2(offset_x, offset_y));
 
            yield return new WaitForSeconds(1 / fps);
 
            currentIndex = (++currentIndex) % (rowCount * columCount);
        }
	}
}
 

3.效果:

  • 课时60 Fragment shader – UV动画 1

 

1.需求,实现在波光粼粼的水面中间叠加一个水波纹效果。

2.代码:

Shader "Custom/Lesson61"
{
	//课时60 Fragment shader – UV动画 1
	Properties
	{
		_MainTex ("Texture", 2D) = "white" {}
		_Speed("Speed",Range(1,10))=1
		_F("F",Range(1,30))=10
		_A("A",Range(0,0.1))=0.01
		_R("R",Range(0,1))=0//半径
	}
	SubShader
	{ 
		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#include "UnityCG.cginc"

			sampler2D _MainTex;
			float4 _MainTex_ST;
			float _F;
			float _A;
			float _R;

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

			
			v2f vert (appdata_full v)
			{
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
				return o;
			}
			
			fixed4 frag (v2f IN) : SV_Target
			{
				// IN.uv.x+=sin(IN.uv.x*3.14*_F+_Time.y)*0.01;
				// IN.uv.y+=sin(IN.uv.y*3.14*_F+_Time.y)*0.01;
				IN.uv+=0.08*sin(IN.uv*3.14*_F+_Time.y)*_A;//水波荡漾效果,sin可以对一个向量进行求值,这里变化因子是UV
				float dis=distance(IN.uv,float2(0.5,0.5));
				float scale=0;
				
				_A*=saturate(1-dis/_R);//振幅,波浪高度 https://blog.csdn.net/qq_26941173/article/details/81156278
				scale=_A*sin(-dis*3.14*_F+_Time.y);//这里变化因子是距中心点距离和时间
				IN.uv+=IN.uv*scale;
				fixed4 color = tex2D(_MainTex, IN.uv);//+fixed4(1,1,1,1)*saturate(scale)*100;
				return color;
			}
			ENDCG
		}
	}
}

效果:

  • 课时62 Fragment shader – UV动画 3

1.需求,实现物体表面从背对到面向摄像机过程中,逐渐变清晰效果。

2.代码:

Shader "Custom/Lesson62"
{
	//课时62 Fragment shader – UV动画 3
	Properties
	{
		_MainTex ("Texture", 2D) = "white" {}
		_Speed("Speed",Range(1,10))=1
		_F("F",Range(1,30))=10
		_A("A",Range(0,0.1))=0.01
		_R("R",Range(0,1))=0//半径
	}
	SubShader
	{ 
		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#include "UnityCG.cginc"
			#pragma target 3.0

			sampler2D _MainTex;
			float4 _MainTex_ST;
			float _F;
			float _A;
			float _R;

			struct v2f
			{
				float4 pos:POSITION;
				float2 uv:TEXCOORD0;
				float z:TEXCOORD1;
			};

			
			v2f vert (appdata_full v)
			{
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
				o.z=UnityObjectToViewPos(v.vertex).z;
				return o;
			}
			//实现表面与视线夹角越大,像素越模糊
			fixed4 frag (v2f IN) : SV_Target
			{ 
				float2 dsdx=ddx(IN.z)*10;//ddx,ddy灵活返回float和float2类型
				float2 dsdy=ddx(IN.z)*10;
				fixed4 color=tex2D(_MainTex,IN.uv,dsdx,dsdy);//tex2D重载函数,导数形式采样,需要SM3.0
				return color;
			}
			//实现图片模糊效果的两种方式
			fixed4 frag111 (v2f IN) : SV_Target
			{

				//=================简单模糊效果=====================================
				// float offset_uv=0.01;
				// float2 uv=IN.uv;
				// fixed4 color=tex2D(_MainTex,uv);
				// uv.y=IN.uv.y+offset_uv;
				// color.rgb+= tex2D(_MainTex, uv)/2; 
				// uv.y=IN.uv.y-offset_uv;
				// color.rgb+= tex2D(_MainTex, uv)/5; 
				// color.rgb/=3;
				//=================end===================================
				
				//=================模糊效果=====================================
				float dx=ddx(IN.uv.x)*10;//一节偏导数,反映的是x轴向上像素变化率。见 https://baike.baidu.com/item/%E4%B8%80%E9%98%B6%E5%AF%BC%E6%95%B0/4026914?fr=aladdin
				float2 dsdx=float2(dx,dx);
				float dy=ddy(IN.uv.y)*10;
				float2 dsdy=float2(dy,dy);
				fixed4 color=tex2D(_MainTex,IN.uv,dsdx,dsdy);//tex2D重载函数,导数形式采样,需要SM3.0
				//=================end===================================

				return color;
			}
			ENDCG
		}
	}
}

效果:

  • 课时63 Fragment shader –纹理混合动画 1

1.需求:利用一张星空图片,实现星星朝向两个不同方向运动扭曲效果。

2.代码:

Shader "Custom/Lesson63"
{
	//课时63 Fragment shader –纹理混合动画 1
	Properties
	{
		_F("F",Range(1,10))=4
		_MainTex ("Texture", 2D) = "white" {}
	}
	SubShader
	{ 
		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#include "UnityCG.cginc"

			float _F;
			sampler2D _MainTex;

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

			
			v2f vert (appdata_full v)
			{
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				o.uv=v.texcoord.xy;
				return o;
			}
			//两次采样,运动方向相反
			fixed4 frag (v2f IN) : SV_Target
			{ 
				float2 uv=IN.uv;
				float2 uv_offset=sin(IN.uv*_F+_Time.x*4)*0.05;

				uv+=uv_offset;
				fixed4 color_1=tex2D(_MainTex,uv); 

				uv=IN.uv;
				uv-=uv_offset*1;
				fixed4 color_2=tex2D(_MainTex,uv); 
				return (color_1+color_2)/2;
			} 
			ENDCG
		}
	}
}

效果:

  • 课时64 Fragment shader –纹理混合动画 2

1.需求:将星空图片和下面的清晨图片混合,实现朦胧的效果。

2.代码:

Shader "Custom/Lesson64"
{
	//课时64 Fragment shader –纹理混合动画 2
	Properties
	{
		_F("F",Range(1,10))=4
		_MainTex ("Texture", 2D) = "white" {}
		_SecondTex("SecondTex",2D)="white"{}
	}
	SubShader
	{ 
		Pass
		{
			ColorMask rg //决定哪个颜色通道可以输出
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#include "UnityCG.cginc"

			float _F;
			sampler2D _MainTex;
			sampler2D _SecondTex;

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

			
			v2f vert (appdata_full v)
			{
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				o.uv=v.texcoord.xy;
				return o;
			}
			//多次采样。不用blend和多pass,透明
			fixed4 frag (v2f IN) : SV_Target
			{ 
				fixed4 mainColor=tex2D(_MainTex,IN.uv); 

				float2 offset_uv=sin(IN.uv*_F+_Time.x*4)*0.05;
				float2 uv=IN.uv+offset_uv;
				uv.y+=0.3;

				fixed4 color_1=tex2D(_SecondTex,uv);

				mainColor.rgb*=color_1.b;
				mainColor.rgb*=2;

				uv=IN.uv-offset_uv;
				uv.y+=0.3;
				fixed4 color_2=tex2D(_SecondTex,uv);

				mainColor.rgb*=color_2.b;
				mainColor.rgb*=2;

				return mainColor;


				// float2 uv=IN.uv;

				// uv+=uv_offset;
				// fixed4 color_1=tex2D(_MainTex,uv); 

				// uv=IN.uv;
				// uv-=uv_offset*1;
				// fixed4 color_2=tex2D(_MainTex,uv); 
				// return (color_1+color_2)/2;
			} 
			ENDCG
		}
	}
}

效果:

  • 课时65 Fragment shader – 程序纹理

水波纹理C#仿真Project资源:https://download.csdn.net/download/a592733740/11827202

  • 课时66 Fragment shader – 程序纹理水波仿真1

  • 课时67 Fragment shader – 程序纹理水波仿真2

  • 课时68 Fragment shader – 程序纹理水波仿真3

  • 课时69 Fragment shader – 程序纹理水波仿真4

1.需求:①要求鼠标在模型上点击或拖动,产生水波纹效果。

2.代码:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;
//优化:1.使用多线程计算并缓存颜色数据;2.关闭垂直同步;3.和CPU协同的异构平台的通用化计算GP-GPU,例如opencell,CUDA,DirectCompute(对应ComputeShader)
public class WaveTexture : MonoBehaviour {
	public int waveWidth;
	public int waveHeight;
	public int radius=8;//水波初始半径
	float[,] waveA;
	float[,] waveB;
	Color[] ColorBuffer;

	Texture2D tex_uv;  
	
	bool isRun=true;
	int sleepTime;
	// Use this for initialization
	void Start () {
		waveA=new float[waveWidth,waveHeight];
		waveB=new float[waveWidth,waveHeight];

		tex_uv=new Texture2D(waveWidth,waveHeight);
		ColorBuffer=new Color[waveWidth*waveHeight];

		GetComponent<Renderer>().material.SetTexture("_WaveTex",tex_uv);

		PutDrop(0,0);

		Thread thread=new Thread(new ThreadStart(ComputeWave));
		thread.Start();
	}
	
	// Update is called once per frame
	void Update () {
		sleepTime=(int)Time.deltaTime*1000;
		tex_uv.SetPixels(ColorBuffer); 
		tex_uv.Apply();

		if(Input.GetMouseButton(0))
		{
			RaycastHit hit;
			Ray ray=Camera.main.ScreenPointToRay(Input.mousePosition);
			if(Physics.Raycast(ray,out hit))
			{
				Vector3 pos=hit.point;
				pos=transform.worldToLocalMatrix.MultiplyPoint(pos);
				pos=pos+new Vector3(0.5f,0.5f,0);
				PutDrop((int)(waveWidth*pos.x),(int)(waveHeight*pos.y));
			}
		}
		// ComputeWave();
	}
	void setPixels()
	{
		 
		tex_uv.Apply();
	}
	void PutDrop(int x,int y)
	{
		float dist;
		for(int i=-radius;i<=radius;i++)	
		{
			for(int j=-radius;j<=radius;j++)
			{
				if(((x+i>=0)&&(x+i<waveWidth-1))&&((y+j>=0)&&(y+j<waveHeight-1)))
				{
					dist=Mathf.Sqrt(i*i+j*j);
					if(dist<radius)
					waveA[x+i,y+j]=Mathf.Cos(dist*Mathf.PI/radius);
				}
			}
		}
	}
    private void ComputeWave()
    {
		while(isRun)
		{

			for(int w=1;w<waveWidth-1;w++){
				for(int h=1;h<waveHeight-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;
					}
					//做插值,计算折射用
					float offset_u=(waveB[w-1,h]-waveB[w+1,h])/2;//-1~1
					float offset_v=(waveB[w,h-1]-waveB[w,h+1])/2;

					float r=offset_u/2+0.5f;//0~1
					float g=offset_v/2+0.5f;

					// tex_uv.SetPixel(w,h,new Color(r,g,0)); 
					ColorBuffer[waveWidth*h+w]=new Color(r,g,0);

					waveB[w,h]-=waveB[w,h]*0.015f;//衰减
				}
				Thread.Sleep(sleepTime);//与Update调用频率一致
		}
		// tex_uv.Apply();
		float[,] temp =waveA;
		waveA=waveB;
		waveB=temp;
		}
    }
	void OnDestroy()
	{
		isRun=false; 
	}
}
Shader "Custom/Lesson66-69"
{
	//课时66 Fragment shader – 程序纹理水波仿真1
	Properties
	{
		_MainTex ("Texture", 2D) = "white" {}
	}
	SubShader
	{

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

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

			sampler2D _MainTex;
			sampler2D _WaveTex;

			v2f vert (appdata_full v)
			{
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				o.uv = v.texcoord.xy; 
				return o;
			}
			
			fixed4 frag (v2f IN) : COLOR
			{
				float2 uv=tex2D(_WaveTex,IN.uv).xy;
				uv=uv*2-1;//-1~1
				uv*=0.025;

				IN.uv+=uv;

				fixed4 col = tex2D(_MainTex, IN.uv);
				return col;
			}
			ENDCG
		}
	}
}

效果:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值