【Unity Shaders】Reflecting Your World —— 在Unity3D中创建一个简单的动态Cubemap系统...-程序员宅基地

技术标签: 游戏  

本系列主要参考《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。这的确是一个非常吸引人的系统,但是需要以牺牲性能为代价:

转载于:https://www.cnblogs.com/xiaowangba/p/6314696.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_34226182/article/details/93970077

智能推荐

库存补单及销量预测_库存补单及销量预测数学建模-程序员宅基地

文章浏览阅读6.8k次,点赞15次,收藏94次。库存补单的数学模型摘要 根据顾客对商品的需求,科学合理的制定库存补单决策对于自家商店发展具有重大的影响,进而成为商家关注的热点问题。本文研究的是补单的策略问题。 针对问题一,是典型的预测问题,要求我们能够准确的预测出未来五天的日销售量。由于日销售量是个非线性的关系,因此,本文采用的是BP神经网络模型,利用梯度降维法,_库存补单及销量预测数学建模

C# Winform 拖放操作-程序员宅基地

文章浏览阅读107次。http://www.cnblogs.com/imlions/p/3189773.html在开发程序的时候,为了提高用户的使用体验,或满足相关用户的功能,总是离不开拖放功能。而本文是总结winform下的常用拖放操作。主要有1.textbox接受拖放的文件 2.listbox允许用户自定义排序 3.listbox之间的拖放 4.控件的拖放 5.console的拖放问题用户在进行拖放操作..._c# 启用 winform 的拖放功能

Kinect2.0+Unity之环境搭建_unity3d kinect 2.0-程序员宅基地

文章浏览阅读8.5k次,点赞3次,收藏14次。一.Kinect1.下载 kinect for windows sdk 2.0安装包2.直接安装十分钟左右,安装成功后在c盘program files目录下有两个文件夹。在此目录下C:\Program Files\Microsoft SDKs\Kinect\v2.0_1409\Tools有三个文件夹。其中Kinect studio文件夹中即有KSutdio.exe,SDKBrowser中即_unity3d kinect 2.0

android 布局之scrollview-程序员宅基地

文章浏览阅读131次。今天在布局页面的时候后犯了难,我要显示的内容一个页面展示不完,怎么办呢? 于是随便找了个app点开一看,哎呀原来还能翻动啊!这是啥布局呢?原来是ScrollView 官方api相关的内容全是英文,这可让三级b的我头大了好一通,不过没关系,不是有国内大神嘛 原来这个布局用法还真是粗暴: ..._android显示带有scrollview的布局

CentOS7安装配置Redis服务_centos7 安装msi-程序员宅基地

文章浏览阅读159次。CentOS7安装配置Redis服务需要的部分文件以及软件网盘地址链接: https://pan.baidu.com/s/1WOcQl9LpQOWCJeLieclGTg提取码:sfj6这是我第一次写博客,有不足的地方欢迎大家留言指教。我电脑使用的应用版本分别是VMware12,CentOS7,Redis-5.0.01.1下载redis5.0.0(我网盘仅提供了Linux的)redis-5.0.0.tar.gz(Linux)redis-x64-3.2.100.msi(window安装版)_centos7 安装msi

Kafka的下载安装以及使用_kafka下载-程序员宅基地

文章浏览阅读3.6k次,点赞3次,收藏12次。kafka安装与使用_kafka下载

随便推点

CSS中的基本选择器-程序员宅基地

文章浏览阅读1.8k次。CSS中的基本选择器什么是选择器?选择器就是通过标签选择一类元素进行控制,常用于HTML等语言中。css中的选择器种类有很多,下面介绍几种常见的基本选择器:标签选择器,类选择器和id选择器一、标签选择器标签选择器又叫元素选择器:文档的元素就是最基本的选择器。例如:/*对h1和p标签进行选择*/ <style> h1{ background: wheat; border-radius: 21px; } _基本选择器

抱怨Swagger不好用?好吧我换一个好用的-程序员宅基地

文章浏览阅读1.9k次。最近前端们一直反映Swagger看接口信息非常不爽,于是我花了俩小时把Swagger干掉,用上了传说中更好用的YApi。今天就简单分享一下心得体会。Swagger与YApi其实我个人认为S..._swagger 看着不方便

SeaJS简介二:模块编写_seajs 定义module-程序员宅基地

文章浏览阅读3.5k次。在介绍SeaJS模块编写和引用之前先介绍一下关于SeaJS模块化的使用原则。 使用SeaJS开发JavaScript的基本原则就是:一切皆为模块。引入SeaJS后,编写JavaScript代码就变成了编写一个又一个模块,SeaJS中模块的概念有点类似于面向对象中的类——模块可以拥有数据和方法,数据和方法可以定义为公共或私有,公共数据和方法可以供别的模块调用。 另外,每个模块应该都定义在一个单独js_seajs 定义module

螃蟹WiFi驱动中的Band Steering功能-程序员宅基地

文章浏览阅读5k次,点赞3次,收藏12次。螃蟹驱动中的Band Steering功能Band Steering功能简介基本原理流程总结Band Steering功能简介在双频路由器中,支持2.4G和5G频段同时接入。当把两个AP的SSID设为相同时,终端(如手机、笔记本)的无线网卡在连接指定的SSID时,可能会连到不同的频段上。一般地,5G频段干扰少,我们会优先连接5G(也可以反过来,优先2.4G),这样,只要用路由器上的Band Steering功能,就可以让终端接入时优先使用指定的频段。基本原理我们知道,无线终端在一个环境中,首先会进行_band steering

农夫过河狼羊白菜Java开放封闭_农夫过河——狼羊菜问题-程序员宅基地

文章浏览阅读1.2k次。话说一位农夫带着一只狼、一只羊和一个卷心菜过河,无奈船小,农夫每次只能运送一样东西,考虑到狼吃羊、羊吃菜,因此运送的顺序至关重要。在现实世界里解决这个问题并不困难,相信很多人都已经有了答案,但是如何用程序来解决这一问题,就需要动动脑筋了。这又是一个与移动物品有关的问题,在前面汉诺塔的例子中,我们已经领略了解决这类问题的方法,大致分为三个步骤:将现实问题转化为数学问题,即,建立模型;将数学问题转化为..._狼吃羊,羊吃卷心菜,怎么运过河

ubuntu18.04安装nomachine远程桌面服务黑屏问题_ubuntu18.04远程桌面黑屏-程序员宅基地

文章浏览阅读1w次,点赞9次,收藏48次。安装步骤如下:进入该网址下载DEB包https://www.nomachine.com/download/download&id=6wget https://download.nomachine.com/download/6.7/Linux/nomachine_6.7.6_11_amd64.debsudo dpkg -i nomachine_6.7.6_11_amd64.d..._ubuntu18.04远程桌面黑屏

推荐文章

热门文章

相关标签