• 【Unity3D】卷轴特效


    1 原理

            当一个圆在地面上沿直线匀速滚动时,圆上固定点的运动轨迹称为旋轮线(或摆线、圆滚线)。本文实现的卷轴特效使用了旋轮线相关理论。

            以下是卷轴特效原理及公式推导,将屏幕坐标 (x) 映射到纹理坐标 (u)。

             注意:屏幕坐标 x 值域为 [0, ScreenWidth],这里已归一化到 [0, 1]。

            本文代码资源见→Unity3D Shader卷轴滚动特效

    2 代码实现

            RollEffect.cs

    1. using UnityEngine;
    2. [RequireComponent(typeof(Camera))] // 屏幕后处理特效一般都需要绑定在像机上
    3. public class RollEffect : MonoBehaviour {
    4. public float radius = 0.05f; // 圆半径
    5. public float rollSpeed = 0.8f; // 圆滚动角速度
    6. private Texture rollTex; // 滚动轴纹理
    7. private Texture backTex; // 底部背景纹理
    8. private float rollTime = 0; // 滚动时间
    9. private float maxRollTime; // 最长滚动时间
    10. private float rollDirection = 1; // 滚动方向(1: 向右, -1: 向左)
    11. private Material rollMaterial; // 滚动特效材质
    12. private bool enableRoll = false; // 滚动特效开关
    13. private void Awake() {
    14. rollMaterial = new Material(Shader.Find("Custom/Curl/Roll"));
    15. rollMaterial.hideFlags = HideFlags.DontSave;
    16. rollTex = Resources.Load("RollTex");
    17. backTex = Resources.Load("BackTex");
    18. }
    19. private void Update() {
    20. if (Input.GetMouseButton(0)) {
    21. rollTime = 0;
    22. maxRollTime = 1 / rollSpeed / radius;
    23. enableRoll = true;
    24. }
    25. }
    26. private void OnRenderImage (RenderTexture source, RenderTexture destination) {
    27. if (enableRoll) {
    28. rollMaterial.SetTexture("_RollTex", rollTex);
    29. rollMaterial.SetTexture("_BackTex", backTex);
    30. rollMaterial.SetFloat("_theta", rollSpeed);
    31. rollMaterial.SetFloat("_r", radius);
    32. rollMaterial.SetFloat("_t", rollTime);
    33. IncreaseTime();
    34. Graphics.Blit (source, destination, rollMaterial);
    35. } else {
    36. Graphics.Blit (source, destination);
    37. }
    38. }
    39. private void IncreaseTime() { // 时间自增
    40. rollTime += rollDirection * Time.deltaTime;
    41. if (rollTime > maxRollTime) {
    42. rollTime = maxRollTime;
    43. rollDirection = -rollDirection; // 反向卷轴
    44. } else if (rollTime < 0) {
    45. rollTime = 0;
    46. rollDirection = -rollDirection;
    47. }
    48. }
    49. }

            说明: RollEffect 脚本组件需要挂在相机上。

            Roll.shader

    1. Shader "Custom/Curl/Roll"
    2. {
    3. Properties
    4. {
    5. _MainTex ("mainTex", 2D) = "white" {}
    6. _RollTex ("rollTex", 2D) = "white" {}
    7. _BackTex ("backTex", 2D) = "white" {}
    8. }
    9. SubShader
    10. {
    11. Pass
    12. {
    13. ZTest Always
    14. Cull Off
    15. ZWrite Off
    16. Fog { Mode off }
    17. CGPROGRAM
    18. #pragma vertex vert_img // UnityCG.cginc中定义了vert_img方法, 对vertex和texcoord进行了处理, 输出v2f_img中的pos和uv
    19. #pragma fragment frag
    20. #pragma fragmentoption ARB_precision_hint_fastest
    21. #include "UnityCG.cginc"
    22. sampler2D _MainTex;
    23. sampler2D _RollTex; // 滚动轴纹理
    24. sampler2D _BackTex; // 底部背景纹理
    25. float _theta; // 圆滚动角速度
    26. float _r; // 圆半径
    27. float _t; // 滚动时间
    28. fixed4 roll(float rho, float v)
    29. { // 滚动变换, 将屏幕坐标映射到纹理坐标
    30. float trt = _theta * _r * _t;
    31. if (rho < trt - _r)
    32. {
    33. return tex2D(_BackTex, float2(rho, v));
    34. }
    35. else if (rho < trt)
    36. {
    37. float a = trt - rho;
    38. float phi = acos(a / _r);
    39. float u = trt - (UNITY_HALF_PI + phi) * _r;
    40. if (u > 0)
    41. {
    42. return tex2D(_RollTex, float2(u, v)) * pow(sin(phi), 2);
    43. }
    44. u = trt - (UNITY_HALF_PI - phi) * _r;
    45. return tex2D(_MainTex, float2(u, v)); // 刚开始卷动时会触发
    46. }
    47. else if (rho < trt + _r)
    48. {
    49. float a = rho - trt;
    50. float phi = acos(a / _r);
    51. float u = trt - (3 * UNITY_HALF_PI - phi) * _r;
    52. if (u > 0)
    53. {
    54. return tex2D(_RollTex, float2(u, v)) * pow(sin(phi), 2);
    55. }
    56. return tex2D(_MainTex, float2(rho, v)); // 刚开始卷动时会触发
    57. }
    58. else
    59. {
    60. return tex2D(_MainTex, float2(rho, v));
    61. }
    62. }
    63. fixed4 frag(v2f_img i) : SV_Target // uv坐标的计算不能在顶点着色器中进行, 因为屏后处理的顶点只有屏幕的4个角顶点
    64. {
    65. return roll(i.pos.x / _ScreenParams.x, i.uv.y);
    66. }
    67. ENDCG
    68. }
    69. }
    70. Fallback off
    71. }

    3 运行效果

    4 推荐阅读

  • 相关阅读:
    【超好懂的比赛题解】HNCPC Multi-university Training Round3 比赛题解
    图像文本跨模态细粒度语义对齐-置信度校正机制 AAAI2022
    在Android中实现来自Material设计的Ripple效果:RippleEffect
    基于soft-RoCE运行OSU Micro Benchmark
    Sqoop使用的一些问题
    Docker 入门及实践
    git使用
    实验2 Python数字类型实验
    高速DSP系统设计参考指南(五)印制电路板或PCB布局
    字节一面:说说TCP的三次握手
  • 原文地址:https://blog.csdn.net/m0_37602827/article/details/128069999