游戏观察 游戏产业媒体
手机端下载
当前位置:游戏观察 > 新闻 > 研发资讯 > 正文

Unity特效设计教程:怎样实现“梦幻旋屏”效果

2019-01-19 11:00 来源:罗培羽

  游戏观察1月19日消息,在游戏场景的设计中,经常会用到需要设计屏幕特效的时候,比如“旋屏”就是一种被经常使用的特效,应用于穿越等情景中。下面我们就来了解一下如何通过Unity特效设计实现“梦幻旋屏”效果。

  游戏开发中,往往会用到一些屏幕特效。下图展现的是一种“旋屏”效果,它会旋转屏幕图像,且距离中心点越远的点旋转角度越大。这种效果特别适合营造“梦幻”感,比如,在RPG游戏中,经过一段“旋屏”特效,主角穿越到了10年前。

Unity特效设计教程:怎样实现“梦幻旋屏”效果

  1、编写Shader

  下面的着色器代码使用了顶点/片元着色器处理旋屏特效的功能。这里定义3个属性,其中_MainTex代表屏幕贴图,_Rot 代表基准的旋转角度。核心代码在片元着色器frag中实现。

  如下图所示,屏幕图像被归一到[0,1]的空间中,中心点为(0.5,0.5)。假设某个点的uv坐标为(x,y),经过一系列处理,它的坐标变为(x1,y1),而(x1,y1)便是实现旋转效果后的uv坐标。

Unity特效设计教程:怎样实现“梦幻旋屏”效果

  由“float distance = sqrt((i.uv.x - 0.5)*(i.uv.x - 0.5) +(i.uv.y - 0.5)*(i.uv.y - 0.5));”可以计算点到屏幕中心的距离distance。由于距离越远旋转角度越大,使用“_Rot *=distance”将角度增量基准与距离联系起来,即可获取需要旋转的角度:angle = _Rot*distance + A。

  由反正切公式可得∠A = atan((y - 0.5)/(x - 0.5)),由于atan的取值为[-π/2,π/2],还需根据y值确定∠A所在的象限,故而∠A = step(x,0.5)*PI+ atan((y - 0.5)/(x - 0.5)) 。计算∠A 后,便可由angle = _Rot*distance + A计算总的旋转角度。

  前面已经计算了点到屏幕中心的距离distance,故而:

  x1 = 0.5 + distance *cos(angle)

  y1 = 0.5 + distance *sin(angle)

  Shader代码如下所示:

  Shader "Lpy/ScreenRot"

  {

  Properties

  {

  _MainTex ("Main Tex", 2D) = "white" {}

  _Rot ("Rotation", float) = 0

  }

  SubShader

  {

  Tags {"Queue"="Geometry"}

  Pass

  {

  Tags { "LightMode"="ForwardBase" }

  ZWrite Off

  CGPROGRAM

  #pragma vertex vert

  #pragma fragment frag

  #include "UnityCG.cginc"

  #define PI 3.14159265358979

  sampler2D _MainTex;

  float _Rot;

  struct a2v

  {

  float4 vertex : POSITION;

  float3 texcoord : TEXCOORD0;

  };

  struct v2f

  {

  float4 pos : SV_POSITION;

  float2 uv : TEXCOORD0;

  };

  v2f vert (a2v v)

  {

  v2f o;

  o.pos = mul(UNITY_MATRIX_MVP, v.vertex);

  o.uv = v.texcoord;

  return o;

  }

  fixed4 frag (v2f i) : SV_Target

  {

  //与中心点(0.5,0.5)的距离

  float distance = sqrt((i.uv.x - 0.5)*(i.uv.x - 0.5) +(i.uv.y - 0.5)*(i.uv.y - 0.5));

  //距离越大,旋转角度越大

  _Rot *=distance;

  //计算旋转角度

  float angle = step(i.uv.x,0.5)*PI+ atan((i.uv.y - 0.5)/(i.uv.x - 0.5)) + _Rot;

  //计算坐标

  i.uv.x = 0.5 + distance *cos(angle);

  i.uv.y = 0.5 + distance *sin(angle);

  fixed4 c = tex2D(_MainTex, i.uv);

  return c;

  }

  ENDCG

  }

  }

  FallBack "Specular"

  }

  2、使用材质

  新建c#文件,编写ScreenRot类,它由一个共有变量mtl,在它的OnRenderImage方法中调用Graphics.Blit将屏幕图像(对应shader中的_MainTex)与材质混合起来。

  using UnityEngine;

  using System.Collections;

  public class ScreenRot : MonoBehaviour

  {

  public Material mtl;

  void OnRenderImage(RenderTexture src, RenderTexture dest)

  {

  Graphics.Blit (src, dest,mtl);

  }

  }

  然后给新建一个名为ScreenRot的材质,使用上述编写的Shader。然后给摄像机添加ScreenRot组件,设置刚刚创建的材质,如下图所示。

Unity特效设计教程:怎样实现“梦幻旋屏”效果

  运行游戏,调整材质的“Rotation”属性,即可看到旋转特效。

Unity特效设计教程:怎样实现“梦幻旋屏”效果

  3、代码中引用

  Shader中并没有涉及时间的控制,旋转速度需要由c#代码控制,将ScreenRot修改成下面的代码,即可让屏幕自动旋转。

  using UnityEngine;

  using System.Collections;

  public class ScreenRot : MonoBehaviour

  {

  public Material mtl;

  public float rot;

  // Update is called once per frame

  void Update ()

  {

  rot += 0.1f;

  }

  void OnRenderImage(RenderTexture src, RenderTexture dest)

  {

  if (rot == 0.0)

  return;

  mtl.SetFloat("_Rot", rot);

  Graphics.Blit (src, dest,mtl);

  }

  }

  这个效果能够运用在很多场合,比如使用“正向旋转→切换场景→反向旋转”实现切屏特效。

本网站所收集的资料来源于互联网公开信息或网友自助投稿,转载的目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。如果您发现网站上有侵犯您知识产权的资料,请与我们取得联系,本站会在3个工作日内删除。

游戏观察

聚焦极有价值的游戏产业资讯。打造有影响力的游戏产业媒体。

赋能游戏跨端开发,Unity于2021 ChinaJoy推出跨端移植服务