unity shader 实现自由放大缩小效果

本文介绍了一种使用Unity Shader实现波纹效果的方法。通过编写Shader代码调整纹理坐标来模拟水面波动,配合C#脚本实时更新参数,实现鼠标位置为中心的动态波纹。文章详细展示了Shader代码及挂载于摄像机的C#脚本。


以下实现的shader代码:

Shader "Hidden/Wave"
{
	Properties
	{
		_MainTex ("Texture", 2D) = "white" {}
		_WaveWidth("Wave Width",float) = 0.5
		_CenterX("CenterX",float)=0.5
		_CenterY("CenterY",float)=0.5
	}
	SubShader
	{
		// No culling or depth
		Cull Off ZWrite Off ZTest Always

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

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

			struct v2f
			{
				float2 uv : TEXCOORD0;
				float4 vertex : SV_POSITION;
			};


			float _WaveWidth;
			float _CenterX;
			float _CenterY;
			v2f vert (appdata v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.uv = v.uv;
				return o;
			}
			
			sampler2D _MainTex;

			fixed4 frag (v2f i) : SV_Target
			{
				float2 center=float2(_CenterX,_CenterY);
				float2 distance= center - i.uv;
				float x=center.x+ center.x*(-distance.x/center.x) *(1-_WaveWidth);
				float y=center.y+ center.y*(-distance.y/center.y) *(1-_WaveWidth);
				float2 uv = float2(x,y);
				return tex2D(_MainTex, uv);   
			}
			ENDCG
		}
	}
}


主要的内容还是在frag中。



下面是挂在摄像机上的脚本:

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

public class WaveCreame : MonoBehaviour {


    public Shader waveShader = null;
    [Range(0.0f,1f)]
    public float waveWidth = 0.3f;
    private Material m_WaveMaterial = null;
    private float m_CenterX = 0.5f;
    private float m_CtenterY = 0.5f;
	// Use this for initialization
	void Start () {
        m_WaveMaterial = new Material(waveShader);
	}
	
	// Update is called once per frame
	void Update () {
        Vector3 pos = Input.mousePosition;
        m_CenterX = pos.x / Screen.width;
        m_CtenterY = pos.y / Screen.height;
        if (Input.GetMouseButton(0)) {
            waveWidth += Time.deltaTime * 0.5f;
        }
        if (Input.GetMouseButton(1))
        {
            waveWidth -= Time.deltaTime * 0.5f;
        }
    }

    private void OnRenderImage(RenderTexture source, RenderTexture destination)
    {
        if (waveShader == null || m_WaveMaterial == null) return;
        m_WaveMaterial.SetFloat("_WaveWidth", waveWidth);
        m_WaveMaterial.SetFloat("_CenterX", m_CenterX);
        m_WaveMaterial.SetFloat("_CenterY", m_CtenterY);
        Graphics.Blit(source, destination, m_WaveMaterial);
    }
}


Unity实现图片局部放大缩小可以通过以下几种常见方法: ### 使用Camera实现 可以创建一个辅助相机,将其视野限制在图片的局部区域,通过改变相机的正交大小(Orthographic Size)来实现局部的放大缩小。以下是示例代码: ```csharp using UnityEngine; public class LocalZoomCamera : MonoBehaviour { public Camera zoomCamera; public float minZoom = 1f; public float maxZoom = 10f; public float zoomSpeed = 1f; void Update() { float scroll = Input.GetAxis("Mouse ScrollWheel"); if (scroll != 0) { float newSize = zoomCamera.orthographicSize - scroll * zoomSpeed; newSize = Mathf.Clamp(newSize, minZoom, maxZoom); zoomCamera.orthographicSize = newSize; } } } ``` ### 使用Shader实现 通过自定义Shader实现局部放大缩小效果Shader可以根据鼠标位置等信息对图片的像素进行处理,实现局部的放大缩小。以下是一个简单的Shader示例: ```glsl Shader "Custom/LocalZoom" { Properties { _MainTex ("Texture", 2D) = "white" {} _ZoomCenter ("Zoom Center", Vector) = (0.5, 0.5, 0, 0) _ZoomFactor ("Zoom Factor", Range(1, 10)) = 1 } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; sampler2D _MainTex; float4 _MainTex_ST; float2 _ZoomCenter; float _ZoomFactor; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); return o; } fixed4 frag (v2f i) : SV_Target { float2 offset = i.uv - _ZoomCenter; offset *= _ZoomFactor; float2 newUV = _ZoomCenter + offset; fixed4 col = tex2D(_MainTex, newUV); return col; } ENDCG } } FallBack "Diffuse" } ``` ### 使用脚本控制Mesh变形 可以将图片贴在一个Mesh上,通过脚本控制Mesh的顶点位置来实现局部的放大缩小。以下是示例代码: ```csharp using UnityEngine; public class LocalZoomMesh : MonoBehaviour { public MeshFilter meshFilter; public float minZoom = 1f; public float maxZoom = 10f; public float zoomSpeed = 1f; private Mesh mesh; private Vector3[] originalVertices; void Start() { mesh = meshFilter.mesh; originalVertices = mesh.vertices; } void Update() { float scroll = Input.GetAxis("Mouse ScrollWheel"); if (scroll != 0) { Vector3[] vertices = mesh.vertices; for (int i = 0; i < vertices.Length; i++) { vertices[i] = originalVertices[i] * (1 + scroll * zoomSpeed); } mesh.vertices = vertices; mesh.RecalculateNormals(); } } } ```
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值