本系列主要参考《Unity Shaders and Effects Cookbook》一书(感谢原书作者),同时会加上一点个人理解或拓展。

这里是本书所有的插图。这里是本书所需的代码和资源(当然你也可以从官网下载)。

========================================== 分割线 ==========================================

写在前面

我们已经学了很多关于反射的内容,但是我们现在的反射并不能实时反射,即当反射物体移动时它们不能正确反射周围的环境。例如,如果你有一个由很多房间和走廊组成的环境,我们不可能提前渲染所有的Cubemap然后放到一个Cubemap中。这意味着我们不能随着房间的移动而正确反射。我们得到的是一个静态的、令人乏味的反射效果。

有很多方法可以解决这个问题,即一个房间的反射不同于另一个房间的反射。一个最基本的方法就是根据在房间中的位置替换Cubemap。因此,当你从一个房间移动到另一个房间时,Cubemap应该被换成当前房间的Cubemap。第二种方法是当我们角色在环境中移动时,实时更新Cubemap,最终在游戏进行的每一帧得到一个新的Cubemap。尽管第二种方法听起来非常吸引人,但是它比较消耗性能,因此你需要在其他游戏资源之间进行权衡。

这一篇将会讲述第一种方法,并且向你展示如何搭建一个非常简单的系统来基于你在环境中的不同位置去替换两个Cubemaps。更多的关于实时反射系统的内容你可以在本节最后找到,因此如果你对实时反射感兴趣并且想要看看两种技术之间的差别,你可以在那里找到!

准备工作

  1. 我们需要创建一个新的场景、一个新的平面以及一个球体。除此之外还需要一个平行光。
  2. 继续添加两个空对象,并分别命名为pos001和pos002。
  3. 给球体添加一个新的材质,并使用Fresnel Shader(上一篇)。这样你的场景应该看起来像下面这样。
  4. 最后,创建一个脚本,并命名为SwapCubemaps.cs,把它赋给球体。
最后的准备效果如下:




实现


  1. 首先在类名之前添加[ExecuteInEditMode]:

    [ExecuteInEditMode]
    public class SwapCubemaps : MonoBehaviour {
  2. 声明一些变量来存储系统需要的变量。我们将在下面解释它们的用途。
    	public Cubemap cubeA;
    public Cubemap cubeB; public Transform posA;
    public Transform posB; private Material curMat;
    private Cubemap curCube;
  3. 为了可以直观地看到Cubemaps所在的位置,我们需要利用Unity3D提供的gizmos 。因此,在脚本的最下方添加下面的代码:
    	void OnDrawGizmos()
    {
    Gizmos.color = Color.green; if(posA)
    {
    Gizmos.DrawWireSphere(posA.position, 0.5f);
    } if(posB)
    {
    Gizmos.DrawWireSphere(posB.position, 0.5f);
    }
    }
  4. 现在,我们需要创建一个新的方程来决定在不同的位置我们应该使用哪个Cubemap:
    	private Cubemap CheckProbeDistance()
    {
    float distA = Vector3.Distance(transform.position, posA.position);
    float distB = Vector3.Distance(transform.position, posB.position); if(distA < distB)
    {
    return cubeA;
    }
    else if(distB < distA)
    {
    return cubeB;
    }
    else
    {
    return cubeA;
    } }
  5. 最后,我们仅仅需要每一帧的时候计算物体距离每一个预定位置的距离,然后为球体的Material替换合适的Cubemap:
    	void Update () {
    curMat = renderer.sharedMaterial;
    if(curMat)
    {
    curCube = CheckProbeDistance();
    curMat.SetTexture("_Cubemap", curCube); }
    }
保存脚本,返回Unity编辑器。当编译完成后,点击Play按钮,并前后左右移动球体。你将会看到类似下面的效果:




解释


一开始,我们为类声明了[ExecuteInEditMode]属性。这将告诉Unity我们想要在编辑器状态时也运行我们的Cubemap替换脚本,而不仅仅是在Play状态。这可以使我们不需要点击Play按钮就可以检验Cubemap替换的脚本——这很方便不是吗~

这个脚本包含一些变量,包括两个Cubemaps和两个位置变量(用于比较距离),我们需要提前赋值给它们。最后我们需要两个私有变量来追踪运行时刻当前的球体材质和Cubemap。

当我们给四个共有变量赋值后,就可以使用内置的OnDrawGizmos()函数来真正显示两个空对象(位置对象)的位置。这些位置将会指导脚本什么时候去替换Cubemaps。

然后我们来看一下脚本中真正替换Cubemaps的函数。我们声明了自己的函数CheckProbeDistance(),它将使用Vector3.Distance计算球体和其他两个位置点的距离。然后它检查哪个距离更近,并返回那个位置对应的Cubemap。

最后,在Update ()函数中我们得到当前球体的材质,或者其他该脚本赋值的对象,然后根据返回的自定义Cubemap来赋值给该材质。

这仅仅是一个非常简单的脚本来参数这个概念,但是它可以被扩展成一个完整的系统,例如你可以每一个房间对应多个Cubemaps。这个系统可以实时自动生成所有的Cubemaps(但不需要每一帧都生成),这对于无法进行完全实时反射的游戏系统将非常有用。



更多……



你还可以看一下,如何创建一个实时反射系统,在这样的系统中每一帧都需要渲染更新Cubemap。这的确是一个非常吸引人的系统,但是需要以牺牲性能为代价:

【Unity Shaders】Reflecting Your World —— 在Unity3D中创建一个简单的动态Cubemap系统的更多相关文章

  1. 【Unity Shaders】Reflecting Your World —— 在Unity3D中创建Cubemaps

    本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...

  2. 如何在Liferay 7中创建一个简单的JSF Portlet

    这个将在Liferay IDE 3.1 M3的发布版中提供创建的选项,但是你也可以通过命令行来创建. 1.这是Liferay JSF团队的官网:http://liferayfaces.org/ 你能在 ...

  3. 在 Visual Studio 中创建一个简单的 C# 控制台应用程序

    转载:https://blog.csdn.net/qq_43994242/article/details/87260824 快速入门:使用 Visual Studio 创建第一个 C# 控制台应用 h ...

  4. 【Unity Shaders】游戏性和画面特效——创建一个夜视效果的画面特效

    本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...

  5. 【Unity Shaders】游戏性和画面特效——创建一个老电影式的画面特效

    本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...

  6. 在终端中创建一个简单的mysql表格

    打开终端后输入:/usr/local/MySQL/bin/mysql -u root –p 然后输入密码:***** 创建数据库:create database work; 使用当前数据库:use w ...

  7. Unity 2D游戏开发高速入门第1章创建一个简单的2D游戏

    Unity 2D游戏开发高速入门第1章创建一个简单的2D游戏 即使是如今,非常多初学游戏开发的同学.在谈到Unity的时候.依旧会觉得Unity仅仅能用于制作3D游戏的. 实际上.Unity在2013 ...

  8. PS网页设计教程XXVI——如何在PS中创建一个专业的网页布局

    作为编码者,美工基础是偏弱的.我们可以参考一些成熟的网页PS教程,提高自身的设计能力.套用一句话,“熟读唐诗三百首,不会作诗也会吟”. 本系列的教程来源于网上的PS教程,都是国外的,全英文的.本人尝试 ...

  9. PS网页设计教程XXVIII——如何在PS中创建一个干净的网页布局

    作为编码者,美工基础是偏弱的.我们可以参考一些成熟的网页PS教程,提高自身的设计能力.套用一句话,“熟读唐诗三百首,不会作诗也会吟”. 本系列的教程来源于网上的PS教程,都是国外的,全英文的.本人尝试 ...

随机推荐

  1. pycharm和shell中的sys.path不一样

    用pip安装了一个模块,在pycharm中不能调用,然后发现shell和pycharm中的sys.path不一样. 纳尼?还能不一样? 很明显左边的pycharm的sys.path中少了三个重要的路径 ...

  2. 安装Leanote极客范的云笔记

    前言 在这个互联网知识呈爆炸增长的时代,作为一个程序员要掌握的知识越来越多,然再好的记性也不如烂笔头,有了笔记我们就是可以时常扒拉扒拉以前的知识,顺便可以整理下自己的知识体系. 如今市面上云笔记产品, ...

  3. Java网络爬虫Hello world实现——Httpclient爬取百度首页

    1.创建Maven项目 2.Httpclient Maven地址 <dependency> <groupId>org.apache.httpcomponents</gro ...

  4. Linux下查看alert日志文件的两种方法

    --linux下查看alert日志文件的两种方法: --方法1: SQL> show parameter background_dump_dest; NAME TYPE VALUE ------ ...

  5. 使用WeihanLi.Redis操作Redis

    WeihanLi.Redis Intro StackExchange.Redis 扩展,更简单的泛型操作,并提供一些的适用于业务场景中的扩展 基于 Redis 的五种数据类型扩展出了一些应用: Str ...

  6. Elasticsearch+Hbase实现海量数据秒回查询

    ---------------------------------------------------------------------------------------------[版权申明:本 ...

  7. 《读书报告 -- Elasticsearch入门 》-- 安装以及简单使用(1)

    <读书报告 – Elasticsearch入门 > 第一章 Elasticsearch入门 Elasticsearch是一个实时的分布式搜索和分析引擎,使得人们可以在一定规模上和一定速度上 ...

  8. Node.js 撸第一个Web应用

    使用Node.js 创建Web 应用与使用PHP/Java 语言创建Web应用略有不同. 使用PHP/Java 来编写后台代码时,需要Apache 或者 Nginx 的HTTP 服务器,而接受请求和提 ...

  9. FORM内置系统变量

    常用 和输入焦点有关: SYSTEM.CURSOR_ITEM:返回系统当前正在操作的项名. SYSTEM.CURSOR_RECORD:返回系统当前正在操作的记录行号. SYSTEM.CURSOR_BL ...

  10. 磁盘管理,磁盘挂在mount,挂载光盘镜像文件,挂在U盘,umount 卸载命令, dd

    1 mount 命令格式: mount[-t vfstype] -o options device dir 其中: *-t vfstype 指定文件系统的类型,通常不必指定.mount会自动选择正确的 ...