Unity 自制Cubemap及使用

Unity 自制Cubemap及使用

首先,什么是Cubemap?

         Cubemap是一个由六个独立的正方形纹理组成的集合。通常被用来作为具有反射属性物体的反射源。类似与MAX里的HDR属性。

如何创建自己的Cubemap

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


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

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





实现



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


  2. 打开上述脚本,为了使用特定的函数,我们需要使用新的using指令:

3.     using UnityEngine;
4.     using UnityEditor;
using System.Collections
  1. 为了让Unity认识到,这个脚本会是一个弹出的编辑器窗口,我们需要让GenerateStaticCubemap类继承ScriptableWizard类。这使得我们可以使用一些很好的底层函数。

public class GenerateStaticCubemap : ScriptableWizard {



  1. 然后,我们需要添加一些新的变量来存储新的CubeMap以及它的位置(即上面提到的position空对象)。

  2. 第一个函数是Unity的内置函数OnWizardUpdate()。它在向导(wizard)第一次弹出或者当GUI被用户改变时(如拖进去某些对象,输入某些字符等)时被调用。因此,我们可以在这里检查用户已经向向导中填入我们需要的所有的资源。在这里,如果Cubemap或者它的位置(一个transform)没有被填充,那么就设置内置变量isValid为false,直到拿到所有资源。

  3. 当isValid变量为true时,向导将调用OnWizardCreate()函数。在这个函数里,我们将创建一个新的摄像机,然后把它放到之前设置的transform的位置上,再调用RenderToCubemap函数得到最终的Cubemap。

  4. 最后,我们需要从Unit编辑器的菜单栏打开这个向导。这需要MenuItem关键词。

                
public Transform renderPosition;
               public Cubemap cubemap;
9.                    void OnWizardUpdate() {
10.                                 helpString = "Select transform to render" +
11.                                                " from and cubemap to render into";
12.                                 if (renderPosition != null && cubemap != null) {
13.                                                isValid = true;
14.                                 }
15.                                 else {
16.                                                isValid = false;
17.                                 }
               }
19.                 void OnWizardCreate() {
20.                                 GameObject go = new GameObject("CubeCam", typeof(Camera));
21.   
22.                                 go.transform.position = renderPosition.position;
23.                                 go.transform.rotation = Quaternion.identity;
24.   
25.                                 go.camera.RenderToCubemap(cubemap);
26.   
27.                                 DestroyImmediate(go);
               }
29.                 [MenuItem("CookBook/Render Cubemap")]
30.                 static void RenderCubemap() {
31.                                 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!

 

原文地址:https://www.cnblogs.com/muyouking/p/6441705.html