【Unity3D】卷轴特效
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】卷轴特效的更多相关文章
- Unity3d学习 预设体(prefab)的一些理解
之前一直在想如果要在Unity3d上创建很多个具有相同结构的对象,是如何做的,后来查了相关资料发现预设体可以解决这个问题! 预设体的概念: 组件的集合体 , 预制物体可以实例化成游戏对象. 创建预设体 ...
- Unity3d入门 - 关于unity工具的熟悉
上周由于工作内容较多,花在unity上学习的时间不多,但总归还是学习了一些东西,内容如下: .1 根据相关的教程在mac上安装了unity. .2 学习了unity的主要的工具分布和对应工具的相关的功 ...
- TDD在Unity3D游戏项目开发中的实践
0x00 前言 关于TDD测试驱动开发的文章已经有很多了,但是在游戏开发尤其是使用Unity3D开发游戏时,却听不到特别多关于TDD的声音.那么本文就来简单聊一聊TDD如何在U3D项目中使用以及如何使 ...
- warensoft unity3d 更新说明
warensoft unity3d 组件的Alpha版本已经发布了将近一年,很多网友发送了改进的Email,感谢大家的支持. Warensoft Unity3D组件将继续更新,将改进的功能如下: 1. ...
- Unity3D框架插件uFrame实践记录(一)
1.概览 uFrame是提供给Unity3D开发者使用的一个框架插件,它本身模仿了MVVM这种架构模式(事实上并不包含Model部分,且多出了Controller部分).因为用于Unity3D,所以它 ...
- Unity3D 5.3 新版AssetBundle使用方案及策略
1.概览 Unity3D 5.0版本之后的AssetBundle机制和之前的4.x版本已经发生了很大的变化,一些曾经常用的流程已经不再使用,甚至一些老的API已经被新的API所取代. 因此,本文的主要 ...
- 山寨Unity3D?搜狐畅游的免费开源游戏引擎Genesis-3D
在CSDN上看到了<搜狐畅游发布3D游戏引擎Genesis-3D 基于MIT协议开源>(http://www.csdn.net/article/2013-11-21/2817585-cha ...
- 从Unity3D编译器升级聊起Mono
接前篇Unity 5.3.5p8 C#编译器升级,本文侧重了解一些Mono的知识. Unity3D的编译器升级 新升级的Mono C#编译器(对应Mono 4.4) Unity编辑器及播放器所使用的M ...
- Unity3D和Egret3D的基情
Unity3D依靠多平台发布这个核心特点,目前如日中天,屌丝引擎之王绝无来者.Egret白鹭引擎,也着实在微信上刷了一屏又一屏.这二者似乎风马牛不相及,但是这个无处不搞基的年代,让一切皆有可能. U3 ...
- Egret3D研究报告(二)从Unity3D导出场景到Egret3D
Egret3D暂时没有场编的计划,但是我们知道unity3D是一个很好的场编. 有一些游戏即使不是使用Unity3D开发,也使用Unity3D做场编.这里就不点名了,而且并不在少数. 我们就这么干. ...
随机推荐
- GoMusic-歌单迁移工具网站 一键迁移网易云/QQ音乐歌单至 Apple/Youtube/Spotify Music
GoMusic是什么: GoMusic是一个在线歌单迁移工具网站,帮助用户一键迁移网易云/QQ音乐歌单至 Apple/Youtube/Spotify Music,直接输入歌单链接,复制查询结果,打开 ...
- [1036]Linux启动时间分析
简述 今天有同事咨询:项目上有台服务器操作系统启动时间较长,如何分析? 果然,好问题都来自实践. 经过查找,对于所有基于systemd的系统,可以使用systemd-analyze来分析系统启动时间. ...
- 使用smem 计算Oracle用户下内存占用情况.
1. 本来计划使用 ps 命令进行查看, 但是发现ps 最多查询出来的是 RSS的内存数据, 会多添加很多冗余的内存数据量进来, 于是作罢 2. 找了下公司的方神, 说可以使用smem 然后简单看了下 ...
- 如何抓取http请求/拦截器用法
我们都知道postman是模拟接口向服务端发送请求的,在编写请求数据的时候非常 麻烦,那么如果我们可以先抓取该接口后直接使用,就方便的很多 抓取http请求 1.我们打开postman时就会看见右上角 ...
- 高性能MySQL实战(三):性能优化 | 京东物流技术团队
这篇主要介绍对慢 SQL 优化的一些手段,而在讲解具体的优化措施之前,我想先对 EXPLAIN 进行介绍,它是我们在分析查询时必要的操作,理解了它输出结果的内容更有利于我们优化 SQL.为了方便大家的 ...
- echarts给每个柱状图配置不同的颜色
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- 文字溢出hover展示
我这个后端返回的是html结构,不然不用加v-html,需要依赖element Ui 的文字提示 <el-tooltip placement="top"> <p ...
- 强化学习技巧三:Python多进程
1.Python多进程模块 Python中的多进程是通过multiprocessing包来实现的,和多线程的threading.Thread差不多,它可以利用multiprocessing.Proce ...
- 21.7 Python 使用Request库
Request库可以用来发送各种HTTP请求,该框架的特点是简单易用,同时支持同步和异步请求,支持HTTP协议的各种方法和重定向.它还支持Cookie.HTTPS和认证等特性. Request库的使用 ...
- C/C++可变参数模版和函数指针的结合
目录 1.说明 2.模板类传入固定参数的C函数指针 3.模板类传入固定参数的C++函数指针 3.1.用函数对象替代函数指针存储 4.模板类传入不定参数的C函数指针 5.模板类传入不定参数的C++成员函 ...