当前位置: 移动技术网 > IT编程>开发语言>c# > Unity3D Shader实现贴图切换效果

Unity3D Shader实现贴图切换效果

2019年07月18日  | 移动技术网IT编程  | 我要评论

本文实例为大家分享了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);
    });
   }
  }
  //
 }
}

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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网