首页 > 其他分享 >【Unity3D】卷轴特效

【Unity3D】卷轴特效

时间:2023-03-21 10:04:40浏览次数:47  
标签:Unity3D 滚动 特效 float private 卷轴 rollMaterial trt

1 原理

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

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

img

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

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

2 代码实现

​ RollEffect.cs

using UnityEngine;
 
[RequireComponent(typeof(Camera))]  // 屏幕后处理特效一般都需要绑定在像机上
public class RollEffect : MonoBehaviour {
    public float radius = 0.05f; // 圆半径
    public float rollSpeed = 0.8f; // 圆滚动角速度
    private Texture rollTex; // 滚动轴纹理
    private Texture backTex; // 底部背景纹理
    private float rollTime = 0; // 滚动时间
    private float maxRollTime; // 最长滚动时间
    private float rollDirection = 1; // 滚动方向(1: 向右, -1: 向左)
    private Material rollMaterial; // 滚动特效材质
    private bool enableRoll = false; // 滚动特效开关
 
    private void Awake() {
        rollMaterial = new Material(Shader.Find("Custom/Curl/Roll"));
        rollMaterial.hideFlags = HideFlags.DontSave;
        rollTex = Resources.Load<Texture>("RollTex");
        backTex = Resources.Load<Texture>("BackTex");
    }
 
    private void Update() {
        if (Input.GetMouseButton(0)) {
            rollTime = 0;
            maxRollTime = 1 / rollSpeed / radius;
            enableRoll = true;
        }
    }
 
    private void OnRenderImage (RenderTexture source, RenderTexture destination) {
        if (enableRoll) {
            rollMaterial.SetTexture("_RollTex", rollTex);
            rollMaterial.SetTexture("_BackTex", backTex);
            rollMaterial.SetFloat("_theta", rollSpeed);
            rollMaterial.SetFloat("_r", radius);
            rollMaterial.SetFloat("_t", rollTime);
            IncreaseTime();
            Graphics.Blit (source, destination, rollMaterial);
        }  else {
            Graphics.Blit (source, destination);
        }
	}
 
    private void IncreaseTime() { // 时间自增
        rollTime += rollDirection * Time.deltaTime;
        if (rollTime > maxRollTime) {
            rollTime = maxRollTime;
            rollDirection = -rollDirection; // 反向卷轴
        } else if (rollTime < 0) {
            rollTime = 0;
            rollDirection = -rollDirection;
        }
    }
}

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

​ Roll.shader

Shader "Custom/Curl/Roll" // 小凸镜变换
{
	Properties 
	{
		_MainTex ("mainTex", 2D) = "white" {}
        _RollTex ("rollTex", 2D) = "white" {}
        _BackTex ("backTex", 2D) = "white" {}
	}
 
	SubShader 
	{
		Pass
		{
			ZTest Always
			Cull Off
			ZWrite Off
			Fog { Mode off }
 
			CGPROGRAM
 
			#pragma vertex vert_img // UnityCG.cginc中定义了vert_img方法, 对vertex和texcoord进行了处理, 输出v2f_img中的pos和uv
			#pragma fragment frag
			#pragma fragmentoption ARB_precision_hint_fastest
 
            #include "UnityCG.cginc"
 
            sampler2D _MainTex;
            sampler2D _RollTex; // 滚动轴纹理
            sampler2D _BackTex; // 底部背景纹理
            float _theta; // 圆滚动角速度
            float _r; // 圆半径
            float _t; // 滚动时间

            float4 roll(float rho, float v)
            { // 滚动变换, 将屏幕坐标映射到纹理坐标
                float trt = _theta * _r * _t;
                if (rho < trt - _r)
                {
                    return tex2D(_BackTex, float2(rho, v));
                }
                else if (rho < trt)
                {
                    float a = trt - rho;
                    float phi = acos(a / _r);
                    float u = trt - (UNITY_HALF_PI + phi) * _r;
                    if (u > 0)
                    {
                        return tex2D(_RollTex, float2(u, v)) * pow(sin(phi), 2);
                    }
                    u = trt - (UNITY_HALF_PI - phi) * _r;
                    return tex2D(_MainTex, float2(u, v)); // 刚开始卷动时会触发
                }
                else if (rho < trt + _r)
                {
                    float a = rho - trt;
                    float phi = acos(a / _r);
                    float u = trt - (3 * UNITY_HALF_PI - phi) * _r;
                    if (u > 0)
                    {
                        return tex2D(_RollTex, float2(u, v)) * pow(sin(phi), 2);
                    }
                    return tex2D(_MainTex, float2(rho, v)); // 刚开始卷动时会触发
                }
                else
                {
                    return tex2D(_MainTex, float2(rho, v));
                }
            }
 
            fixed4 frag(v2f_img i) : SV_Target // uv坐标的计算不能在顶点着色器中进行, 因为屏后处理的顶点只有屏幕的4个角顶点
            {
                return roll(i.pos.x / _ScreenParams.x, i.uv.y);
            }
 
			ENDCG
		}
	}
 
	Fallback off
}

3 运行效果

img

4 推荐阅读

​ 声明:本文转自【Unity3D】卷轴特效

标签:Unity3D,滚动,特效,float,private,卷轴,rollMaterial,trt
From: https://www.cnblogs.com/zhyan8/p/17237940.html

相关文章

  • 【Unity3D】水波特效
    1水波特效原理​水波特效属于Unity3D后处理特效,其原理是:对渲染后的纹理进行局部挤压和拉升变换,即对局部uv坐标进行周期性的偏移运动,实现波纹效果。​1)波形......
  • 【Unity3D】选中物体描边特效
    1前言​描边的难点在于如何检测和识别边缘,当前实现描边特效的方法主要有以下几种:​1)基于顶点膨胀的描边方法​在SubShader中开2个Pass渲染通道,第一......
  • 【Unity3D】绘制物体表面三角形网格
    1仅绘制三角形网格​1)创建游戏对象​创建一个空对象,重命名为Grid,并在其下添加需要绘制网格的对象,如下:​场景显示如下:​2)添加脚本组件​Grid......
  • 【Unity3D】绘制物体外框线条盒子
    1需求描述​点选物体、框选物体、绘制外边框中介绍了物体投影到屏幕上的二维外框绘制方法,本文将介绍物体外框线条盒子绘制方法。内框:选中物体后,绘制物体的内框(紧......
  • 【Unity3D】点选物体、框选物体、绘制外边框
    1需求描述​绘制物体外框线条盒子中介绍了绘制物体外框长方体的方法,本文将介绍物体投影到屏幕上的二维外框绘制方法。点选物体:点击物体,可以选中物体,按住Ctrl追......
  • 【Unity3D】使用GL绘制线段
    1前言​线段渲染器LineRenderer、拖尾TrailRenderer、绘制物体表面三角形网格从不同角度介绍了绘制线段的方法,本文再介绍一种新的绘制线段的方法:使用GL绘制线段。......
  • 【Unity3D】VideoPlayer组件
    1简介​AudioSource组件中介绍了音频的播放,本文将介绍基于VideoPlayer组件实现视频播放。​VideoPlayer属性面板如下:Source:视频源类型,有2种类型:VideoC......
  • 【Unity3D】固定管线着色器二
    1前言​固定管线着色器一中介绍了Shader中外部属性、光照、贴图等基础用法,本文将进一步讲解固定管线着色器,介绍正面与反面剔除、Alpha测试、深度测试、混合、渲......
  • 【Unity3D】固定管线着色器一
    1前言​着色器(Shader)是渲染管线中最重要的一环,Unity3D底层基于OpenGL实现,读者可以通过渲染管线了解Unity3D渲染流程。​OpenGL1.x为固定管线,2.x之后......
  • 【Unity3D】协同程序
    1简介​1)协程概念​协同程序(Coroutine)简称协程,是伴随主线程一起运行的程序片段,是一个能够暂停执行的函数,用于解决程序并行问题。协程是C#中的概念,由于Unity3......