本系列主要参考《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. Ubuntu 16.04+.Net Core+Docker+Uginx安装部署

    前言 最近公司的项目打算移植到.Net Core平台,所以调研了一下.Net Core在Linux下的安装部署.本篇文章会一步步的描述从安装到配置到部署的全部过程.在文章的结构和内容里,笔者借鉴了很多 ...

  2. Python中如何将二维列表转换成一维列表

    已知:a = [(4,2,3), (5, 9, 1), (7,8,9)]希望将二维列表转换成一维列表:["4,2,3", "5, 9, 1", "7, ...

  3. DOS/Windows 文本格式与 Unix 文本各式转换

    命令简介: dos2unix是将Windows格式文件转换为Unix.Linux格式的实用命令.Windows格式文件的换行符为\r\n ,而Unix&Linux文件的换行符为\n. dos2 ...

  4. Docker容器如何互联

    容器的连接(linking)系统是除了端口映射外,另一种跟容器中应用交互的方式. 该系统会在源和接收容器之间创建一个隧道,接收容器可以看到源容器指定的信息. 自定义容器命名 连接系统依据容器的名称来执 ...

  5. Git幕后的“故事”

    因为做操作系统实验的原因,所以通读了一遍<Understanding git conceptually>,觉得确实不错,于是就简单地记录一下.有的地方理解的还不是很深,可能不够准确,等抽时 ...

  6. 5秒让你的View变3D,ThreeDLayout使用和实现

    在很久很久以前,写了一篇自定义3d view的博客.但是只是讲了如何实现,实现起来还是比较耗时,所以本着平易近人的心态,把他封装成了一个ViewGroup,只需要在你的view或者布局外面包裹一层Th ...

  7. Linux 性能监测:IO

    磁盘通常是计算机最慢的子系统,也是最容易出现性能瓶颈的地方,因为磁盘离 CPU 距离最远而且 CPU 访问磁盘要涉及到机械操作,比如转轴.寻轨等.访问硬盘和访问内存之间的速度差别是以数量级来计算的,就 ...

  8. Dynamics CRM 不同的站点地图下设置默认不同的仪表板

    CRM的默认仪表板只能设置一个,也就是说每个引用仪表板的站点地图下点开仪表板后都是看到的默认仪表板,例如我下图中的"日常维修仪表板" 那如果我要在不同的站点地图下看到的默认仪表板不 ...

  9. 查看oracle数据库的连接数以及用户 (转:http://blog.itpub.net/24558279/viewspace-752293/)

    select2.查询oracle的并发连接数4select3.查看不同用户的连接数6select4.查看所有用户:8select5.查看用户或角色系统权限(直接赋值给用户或角色的系统权限):10sel ...

  10. linux找不到动态链接库 .so文件的解决方法(转自:http://www.cnblogs.com/xudong-bupt/p/3698294.html)

    linux找不到动态链接库 .so文件的解决方法 如果使用自己手动生成的动态链接库.so文件,但是这个.so文件,没有加入库文件搜索路劲中,程序运行时可能会出现找不到动态链接库的情形. 可以通过ldd ...