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

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

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


写在前面


为了在Shaders中创建反射的效果,我们将首先开始学习如何创建我们自己的Cubemaps。当然,你可以在网上找到许多已经做好的Cubemaps,但是你很快就会想,怎么制作自己的Cubemaps,因为网上那些是不能反射你自己游戏中的场景的。
制作你自己的Cubemaps是创建更真实的反射效果的关键。我们将会学习几个可以在Unity editor中直接使用的方法。另外,我们还将看看在单机游戏中的效果。这些知识将会帮助你理解下一章(光照模型)中的内容。

好啦,下面我们就正式学习如何为我们的Shaders创建Cubemaps吧!


开始工作


Unity为我们提供了JavaScript的代码来从我们创建的场景中生成Cubemap。所以,让我们来看一下它是怎么工作的。这个链接中的脚本是我们脚本的基础。接下来,我们将把它翻译成C#。在本章的最后一节(动态创建Cubemaps)中,我们将会学习如何创建一个简单的系统来从不同的位置创建Cubemaps,然后使用这些数据在reflection
maps中转换,模拟游戏角色在场景内移动的效果,这将最终得到一个半实时的反射系统。

这里,我们仅仅学习如何创建一个单独的Cubemap。
  1. 我们需要创建一些元素来当做Cubemaps的光源。因此,我们需要在场景中放置一些几何平面。你可以使用一个建模软件,例如Maya或者Max,当然你也可以使用Unity自带的plane。哪一种方式都行,这无所谓。你的场景应该可以像这样:

  2. 场景中的物体如下所示:



    其中,Position是一个空对象,它将仅仅作为观察的位置将从该点观察到的环境信息渲染到我们的Cubemap上。


实现


  1. 首先,我们需要创建一个新的脚本,但是由于我们想要一个弹出的编辑器窗口,因此我们必须把脚本放到一个叫做Editor的文件夹里。在你的Project面板中创建一个叫Editor的文件夹,然后再创建一个C#脚本,叫做GenerateStaticCubemap。

  2. 打开上述脚本,为了使用特定的函数,我们需要使用新的using指令:
    using UnityEngine;
    using UnityEditor;
    using System.Collections
  3. 为了让Unity认识到,这个脚本会是一个弹出的编辑器窗口,我们需要让GenerateStaticCubemap类继承ScriptableWizard类。这使得我们可以使用一些很好的底层函数。
    public class GenerateStaticCubemap : ScriptableWizard {
  4. 然后,我们需要添加一些新的变量来存储新的CubeMap以及它的位置(即上面提到的position空对象)。
    	public Transform renderPosition;
    public Cubemap cubemap;
  5. 第一个函数是Unity的内置函数OnWizardUpdate()。它在向导(wizard)第一次弹出或者当GUI被用户改变时(如拖进去某些对象,输入某些字符等)时被调用。因此,我们可以在这里检查用户已经向向导中填入我们需要的所有的资源。在这里,如果Cubemap或者它的位置(一个transform)没有被填充,那么就设置内置变量isValid为false,直到拿到所有资源。
    	void OnWizardUpdate() {
    helpString = "Select transform to render" +
    " from and cubemap to render into";
    if (renderPosition != null && cubemap != null) {
    isValid = true;
    }
    else {
    isValid = false;
    }
    }
  6. 当isValid变量为true时,向导将调用OnWizardCreate()函数。在这个函数里,我们将创建一个新的摄像机,然后把它放到之前设置的transform的位置上,再调用RenderToCubemap函数得到最终的Cubemap。
    	void OnWizardCreate() {
    GameObject go = new GameObject("CubeCam", typeof(Camera)); go.transform.position = renderPosition.position;
    go.transform.rotation = Quaternion.identity; go.camera.RenderToCubemap(cubemap); DestroyImmediate(go);
    }
  7. 最后,我们需要从Unit编辑器的菜单栏打开这个向导。这需要MenuItem关键词。
    	[MenuItem("CookBook/Render Cubemap")]
    static void RenderCubemap() {
    ScriptableWizard.DisplayWizard("Render CubeMap", typeof(GenerateStaticCubemap), "Render!");
    }

最后,整体代码如下:
using UnityEngine;
using UnityEditor;
using System.Collections; public class GenerateStaticCubemap : ScriptableWizard { public Transform renderPosition;
public Cubemap cubemap; void OnWizardUpdate() {
helpString = "Select transform to render" +
" from and cubemap to render into";
if (renderPosition != null && cubemap != null) {
isValid = true;
}
else {
isValid = false;
}
} void OnWizardCreate() {
GameObject go = new GameObject("CubeCam", typeof(Camera)); go.transform.position = renderPosition.position;
go.transform.rotation = Quaternion.identity; go.camera.RenderToCubemap(cubemap); DestroyImmediate(go);
} [MenuItem("CookBook/Render Cubemap")]
static void RenderCubemap() {
ScriptableWizard.DisplayWizard("Render CubeMap", typeof(GenerateStaticCubemap), "Render!");
}
}

此时,回到Unity编辑器页面,点击一下Unity菜单栏(有时需要点击才会刷新)就会看到出现一个新的选项:CookBook/Render Cubemap,如下所示:



点击它你将会打开一个向导界面,如下所示。它需要两个资源,一个是Render Position,这将决定观察位置(你可以理解成你将会在该位置放一面镜子,这里需要注意的是由于代码里设置的摄像机的rotation为初始值,这意味着摄像机将看向图中蓝色箭头所指方向),一个是Cubemap,可以理解成就是镜子反射的图像。我的例子中设置如下。



点击Render!按钮后,查看你的Cubemap,就会看到类似下面这样的情景。


可以发现,我们已经把图像渲染到了一个立方体里了。恭喜你,你已经完成了自己的一个Cubemap!你可以尝试在不同的场景中试验。



解释


还记得一开始我们继承了ScriptableWizard类,这是为了告诉Unity3D我们想要制作一个新的弹出窗口类型的用户编辑器,这也是为什么我们需要把脚本放到Editor文件夹里的原因。如果我们不这么做,Unity将不会把它识别为一个用户编辑器类型的脚本。

接下来我们声明的参数是用于存储Cubemap的渲染位置,以及把新的渲染得到的Cubemap放到Project的哪里,例如上面的名为First的Cubemap就是我提前在工程文件下创建的一个Cubemap。有了这些我们就可以生成自己的Cubemap了。

然后我们使用了OnWizardUpdate()函数,它是由ScriptableWizard类提供给我们的。同样的,isValid变量也是一个内置变量。它让我们可以方便的打开或者关闭向导下方的Create按钮(这里指的是Render!按钮)。这样可以防止用户使用空的transform或者Cubemap进行下面的操作。

一旦我们确定用户提供了正确的数据,我们就可以进入到OnWizardCreate()函数了。这是Cubemap真正被创建的地方。它首先创建了一个新的GameObject构造器,并把它的类型创建为Camera。然后把它放到用户提供的transform的位置上。

到了这里,我们剩下要做的就是把用户提供的Cubemap传递给RenderToCubemap函数,生成六张图片。

最后,我们为向导创建了一个菜单选项,以便让用户可以从Unity顶部的菜单栏打开这个工具。除了需要[MenuItem("CookBook/Render Cubemap")]关键词以外,我们还需要将函数声明为static函数。

至此,我们就完成了一个简单的工具,可以用于在Unity编辑器中直接生成Cubemaps!


【Unity Shaders】Reflecting Your World —— 在Unity3D中创建Cubemaps的更多相关文章

  1. 【Unity Shaders】Reflecting Your World —— 在Unity3D中创建一个简单的动态Cubemap系统

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

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

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

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

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

  4. [转]unity3d中创建双面材质

    在其它三维软件中设置好的双面材质导入到unity3d中就失去了效果,不过我们可以通过自定义材质来在unity3d中实现双面材质的效果.步骤如下:1.在资源库中新建一新shader:代码如下: Shad ...

  5. 【Unity Shaders】Reflecting Your World(反射吧!)介绍

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

  6. 【Unity Shaders】Diffuse Shading——创建一个基本的Surface Shader

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

  7. Unity3D中的shader基础知识

    1.Unity中配备了强大的阴影和材料的语言工具称为ShaderLab,以程式语言来看,它类似于CgFX和Direct3D的效果框架语法,它描述了材质所必须要的一切咨询,而不仅仅局限于平面顶点/像素着 ...

  8. Unity3d中使用log4net

    原地址:http://www.cnblogs.com/koalaylj/archive/2012/09/04/2670629.html 最近在用unity3d开发Android上的游戏,一直Debug ...

  9. 【Unity Shaders】Reflecting Your World —— Unity3D中简单的Cubemap反射

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

随机推荐

  1. day04 Java Web 开发入门

    day04 Java Web 开发入门 1. web 开发相关介绍 2. web 服务器 3. Tomcat服务器启动的问题 4. Tomcat目录结构 5. Web应用程序(虚拟目录映射,缺省web ...

  2. jenkins + pipeline构建自动化部署

    一.引言 Jenkins 2.x的精髓是Pipeline as Code,那为什么要用Pipeline呢?jenkins1.0也能实现自动化构建,但Pipeline能够将以前project中的配置信息 ...

  3. 判断当前设备是移动端或者PC端

    <script> function browserRedirect() { var sUserAgent = navigator.userAgent.toLowerCase(); var ...

  4. Linux 下的一个全新的性能测量和调式诊断工具 Systemtap, 第 2 部分: DTrace

    DTrace的原理本系列文章详细地介绍了一个 Linux 下的全新的调式.诊断和性能测量工具 Systemtap 和它所依赖的基础 kprobe 以及促使开发该工具的先驱 DTrace 并给出实际使用 ...

  5. Objective-C构造方法

    Objective-C构造方法 构造方法:用来初始化的方法 创建对象的原理 之前我们创建对象的方式一直是使用[Xxx new] 但是使用 new 创建的对象,都是给我们默认做了初始化的. 有的时候,我 ...

  6. dubbo安装

    dubbo 管控台可以对注册到 zookeeper 注册中心的服务或服务消费者进行管理,分享牛系列,分享牛专栏,分享牛.但管控台是否正常对 Dubbo 服务没有影响,管控台也不需要高可用,因此可以单节 ...

  7. 制作pypi上的安装库

    下载地址 如何制作分发工具呢 setuppy 源码包 其他文件 制作过程 首先上场的肯定是setuppy了如下 然后是LICENCE 注册 测试 总结 自从接触Python以来也有几个月了,虽然主要的 ...

  8. 【SSH系列】-- Hibernate持久化对象的三种状态

    在上一篇博文中,小编主要简单的介绍了[SSH系列]--hibernate基本原理&&入门demo,今天小编来继续介绍hibernate的相关知识, 大家知道,Java对象的生命周期,是 ...

  9. Java之继承深刻理解

    1.关于私有成员变量 无论父类中的成员变量是私有的.共有的.还是其它类型的,子类都会拥有父类中的这些成员变量.但是父类中的私有成员变量,无法在子类中直接访问,必须通过从父类中继承得到的protecte ...

  10. Dynamics CRM 2015 站点地图公告配置实体显示名称的变更

    CRM更新2015后,在设置里找不到公告配置了 在原来的位置上你会东西一个叫活动源配置的东西,点开看后就是原来的公告配置.