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!

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM