首页 > 编程 > C# > 正文

Unity3D Shader实现贴图切换效果

2020-01-24 00:08:15
字体:
来源:转载
供稿:网友

本文实例为大家分享了shader实现基于世界坐标的贴图置换效果。

效果如下:

设置面板如下:

可在面板上设置切换方向,与切换对象,及其切换速度。

shader实现如下:

Shader "XM/Effect/SwapTexture" { Properties { _Color ("Color", Color) = (1,1,1,1) _MainTex ("Albedo (RGB)", 2D) = "white" {} _TargetTex ("Target Tex", 2D) = "white" {}//目标贴图 [KeywordEnum(Up, Down, Left, Right, Forward, Back)] _mode ("Mode", Int) = 0//切换方向 _SwapBlend ("Blend", Range(0,1)) = 0//0-1混合值 _SwapMin("Min Value", Float) = 0//最小世界坐标 _SwapMax("Max Value", Float) = 0//最大世界坐标 _Glossiness ("Smoothness", Range(0,1)) = 0.5 _Metallic ("Metallic", Range(0,1)) = 0.0 } SubShader { Tags { "RenderType"="Opaque" } LOD 200 CGPROGRAM // Physically based Standard lighting model, and enable shadows on all light types #pragma surface surf Standard fullforwardshadows vertex:vert // Use shader model 3.0 target, to get nicer looking lighting #pragma target 3.0 sampler2D _MainTex; sampler2D _TargetTex; struct Input {  float2 uv_MainTex;  float3 worldPos; }; half _mode; half _SwapBlend; float _SwapMin; float _SwapMax; half _Glossiness; half _Metallic; fixed4 _Color; void vert (inout appdata_full v, out Input o) {  UNITY_INITIALIZE_OUTPUT(Input,o); } void surf (Input IN, inout SurfaceOutputStandard o) {  half useTarget = 0;  float targetValue = 0;  switch(_mode)//模式选择  {  case 0://up   targetValue = (_SwapMax - _SwapMin) * _SwapBlend + _SwapMin;   useTarget = IN.worldPos.y > targetValue?0:1;   break;  case 1://down   targetValue = (_SwapMax - _SwapMin) * (1 - _SwapBlend) + _SwapMin;   useTarget = IN.worldPos.y < targetValue?0:1;   break;  case 2://left   targetValue = (_SwapMax - _SwapMin) * (1 - _SwapBlend) + _SwapMin;   useTarget = IN.worldPos.x < targetValue?0:1;   break;  case 3://right   targetValue = (_SwapMax - _SwapMin) * _SwapBlend + _SwapMin;   useTarget = IN.worldPos.x > targetValue?0:1;   break;  case 4://forward   targetValue = (_SwapMax - _SwapMin) * _SwapBlend + _SwapMin;   useTarget = IN.worldPos.z > targetValue?0:1;   break;  case 5://back   targetValue = (_SwapMax - _SwapMin) * (1 - _SwapBlend) + _SwapMin;   useTarget = IN.worldPos.z < targetValue?0:1;   break;  }  // Albedo comes from a texture tinted by color  fixed4 c;  if(useTarget == 1)  {  c = tex2D (_TargetTex, IN.uv_MainTex);  }  else  {  c = tex2D (_MainTex, IN.uv_MainTex);  }  c *= _Color;  o.Albedo = c.rgb;  // Metallic and smoothness come from slider variables  o.Metallic = _Metallic;  o.Smoothness = _Glossiness;  o.Alpha = c.a; } ENDCG } FallBack "Diffuse"}

配合使用的脚本如下:

using System;using System.Collections;using UnityEngine;namespace XM.Effect{ public class SwapTexture : MonoBehaviour {  public enum SwapDirection  {   Up,   Down,   Left,   Right,   Forward,   Back  }  public Shader _shader;//"XM/Effect/SwapTexture” shader  public SwapDirection _swapDir;//切换方向  public Renderer _target;//目标对象  [Range(0, 1)]  public float _speed;//速度  private Material _matOld;  private Material _matNew;  public void Swap(Texture tex, Action<bool> onComplete)  {   if (_matOld != null)   {    StopAllCoroutines();    if (null != onComplete)    {     onComplete(false);    }    _target.material = _matOld;   }   _matOld = _target.material;   _matNew = new Material(_shader);   _matNew.SetTexture("_MainTex", _target.material.GetTexture("_MainTex"));   _matNew.SetTexture("_TargetTex", tex);   _matNew.SetInt("_mode", (int)_swapDir);   _matNew.SetFloat("_SwapBlend", 0);   StartCoroutine("_StartChange", onComplete);  }  private IEnumerator _StartChange(Action<bool> onComplete)  {   float deltaVal = 0;   _target.material = _matNew;   Vector3 vtMin;   Vector3 vtMax;   float minVal = 0;   float maxVal = 0;   while (deltaVal != 1)   {    vtMin = _target.bounds.min;    vtMax = _target.bounds.max;    switch (_swapDir)    {     case SwapDirection.Up:     case SwapDirection.Down:      minVal = vtMin.y;      maxVal = vtMax.y;      break;     case SwapDirection.Left:     case SwapDirection.Right:      minVal = vtMin.x;      maxVal = vtMax.x;      break;     case SwapDirection.Forward:     case SwapDirection.Back:      minVal = vtMin.z;      maxVal = vtMax.z;      break;    }    minVal -= 0.01f;    maxVal += 0.01f;    _matNew.SetFloat("_SwapMin", minVal);    _matNew.SetFloat("_SwapMax", maxVal);    deltaVal = Mathf.Clamp01(deltaVal + _speed * Time.deltaTime);    _matNew.SetFloat("_SwapBlend", deltaVal);    yield return null;   }   _matOld.SetTexture("_MainTex", _matNew.GetTexture("_TargetTex"));   _target.material = _matOld;   _matNew = null;   _matOld = null;   if (null != onComplete)   {    onComplete(true);   }  }  public void OnDrawGizmos()  {   if (_target != null)   {    Gizmos.DrawWireCube(_target.bounds.center, _target.bounds.size);    Gizmos.DrawWireSphere(_target.bounds.min, 0.1f);    Gizmos.DrawWireSphere(_target.bounds.max, 0.1f);   }  }  //test  public Texture testTex;  private void OnGUI()  {   if (GUILayout.Button("SwapTexture"))   {    Swap(testTex, (t) =>    {     Debug.Log("Swap>" + t);    });   }  }  // }}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持武林网。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表