1 原理

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

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

​ 注意:屏幕坐标 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; // 滚动时间 fixed4 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 运行效果

4 推荐阅读

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

【Unity3D】卷轴特效的更多相关文章

  1. Unity3d学习 预设体(prefab)的一些理解

    之前一直在想如果要在Unity3d上创建很多个具有相同结构的对象,是如何做的,后来查了相关资料发现预设体可以解决这个问题! 预设体的概念: 组件的集合体 , 预制物体可以实例化成游戏对象. 创建预设体 ...

  2. Unity3d入门 - 关于unity工具的熟悉

    上周由于工作内容较多,花在unity上学习的时间不多,但总归还是学习了一些东西,内容如下: .1 根据相关的教程在mac上安装了unity. .2 学习了unity的主要的工具分布和对应工具的相关的功 ...

  3. TDD在Unity3D游戏项目开发中的实践

    0x00 前言 关于TDD测试驱动开发的文章已经有很多了,但是在游戏开发尤其是使用Unity3D开发游戏时,却听不到特别多关于TDD的声音.那么本文就来简单聊一聊TDD如何在U3D项目中使用以及如何使 ...

  4. warensoft unity3d 更新说明

    warensoft unity3d 组件的Alpha版本已经发布了将近一年,很多网友发送了改进的Email,感谢大家的支持. Warensoft Unity3D组件将继续更新,将改进的功能如下: 1. ...

  5. Unity3D框架插件uFrame实践记录(一)

    1.概览 uFrame是提供给Unity3D开发者使用的一个框架插件,它本身模仿了MVVM这种架构模式(事实上并不包含Model部分,且多出了Controller部分).因为用于Unity3D,所以它 ...

  6. Unity3D 5.3 新版AssetBundle使用方案及策略

    1.概览 Unity3D 5.0版本之后的AssetBundle机制和之前的4.x版本已经发生了很大的变化,一些曾经常用的流程已经不再使用,甚至一些老的API已经被新的API所取代. 因此,本文的主要 ...

  7. 山寨Unity3D?搜狐畅游的免费开源游戏引擎Genesis-3D

    在CSDN上看到了<搜狐畅游发布3D游戏引擎Genesis-3D 基于MIT协议开源>(http://www.csdn.net/article/2013-11-21/2817585-cha ...

  8. 从Unity3D编译器升级聊起Mono

    接前篇Unity 5.3.5p8 C#编译器升级,本文侧重了解一些Mono的知识. Unity3D的编译器升级 新升级的Mono C#编译器(对应Mono 4.4) Unity编辑器及播放器所使用的M ...

  9. Unity3D和Egret3D的基情

    Unity3D依靠多平台发布这个核心特点,目前如日中天,屌丝引擎之王绝无来者.Egret白鹭引擎,也着实在微信上刷了一屏又一屏.这二者似乎风马牛不相及,但是这个无处不搞基的年代,让一切皆有可能. U3 ...

  10. Egret3D研究报告(二)从Unity3D导出场景到Egret3D

    Egret3D暂时没有场编的计划,但是我们知道unity3D是一个很好的场编. 有一些游戏即使不是使用Unity3D开发,也使用Unity3D做场编.这里就不点名了,而且并不在少数. 我们就这么干. ...

随机推荐

  1. GoMusic-歌单迁移工具网站 一键迁移网易云/QQ音乐歌单至 Apple/Youtube/Spotify Music

    GoMusic是什么: GoMusic是一个在线歌单迁移工具网站,帮助用户一键迁移网易云/QQ音乐歌单至 Apple/Youtube/Spotify Music,直接输入歌单链接,复制查询结果,打开 ...

  2. [1036]Linux启动时间分析

    简述 今天有同事咨询:项目上有台服务器操作系统启动时间较长,如何分析? 果然,好问题都来自实践. 经过查找,对于所有基于systemd的系统,可以使用systemd-analyze来分析系统启动时间. ...

  3. 使用smem 计算Oracle用户下内存占用情况.

    1. 本来计划使用 ps 命令进行查看, 但是发现ps 最多查询出来的是 RSS的内存数据, 会多添加很多冗余的内存数据量进来, 于是作罢 2. 找了下公司的方神, 说可以使用smem 然后简单看了下 ...

  4. 如何抓取http请求/拦截器用法

    我们都知道postman是模拟接口向服务端发送请求的,在编写请求数据的时候非常 麻烦,那么如果我们可以先抓取该接口后直接使用,就方便的很多 抓取http请求 1.我们打开postman时就会看见右上角 ...

  5. 高性能MySQL实战(三):性能优化 | 京东物流技术团队

    这篇主要介绍对慢 SQL 优化的一些手段,而在讲解具体的优化措施之前,我想先对 EXPLAIN 进行介绍,它是我们在分析查询时必要的操作,理解了它输出结果的内容更有利于我们优化 SQL.为了方便大家的 ...

  6. echarts给每个柱状图配置不同的颜色

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  7. 文字溢出hover展示

    我这个后端返回的是html结构,不然不用加v-html,需要依赖element Ui 的文字提示 <el-tooltip placement="top"> <p ...

  8. 强化学习技巧三:Python多进程

    1.Python多进程模块 Python中的多进程是通过multiprocessing包来实现的,和多线程的threading.Thread差不多,它可以利用multiprocessing.Proce ...

  9. 21.7 Python 使用Request库

    Request库可以用来发送各种HTTP请求,该框架的特点是简单易用,同时支持同步和异步请求,支持HTTP协议的各种方法和重定向.它还支持Cookie.HTTPS和认证等特性. Request库的使用 ...

  10. C/C++可变参数模版和函数指针的结合

    目录 1.说明 2.模板类传入固定参数的C函数指针 3.模板类传入固定参数的C++函数指针 3.1.用函数对象替代函数指针存储 4.模板类传入不定参数的C函数指针 5.模板类传入不定参数的C++成员函 ...