2017-07-11 113 views
4

我需要從服務器下載圖像,然後在Cubemap中轉換它,最後將此CubeMap放入我的Skybox。從遠程圖像編輯Cubemap Skybox

我使用C#。

我想出了這個代碼:

public string url = "image/url.jpg"; 

void Update() { 
    // When trigger, we start the process 
    if (Input.GetKeyDown("f")) { 

     // start Coroutine to handle the WWW asynchronous process 
     StartCoroutine("setImage"); 
    } 
} 

IEnumerator setImage() { 

    Texture2D tex; 
    tex = new Texture2D(2048, 2048, TextureFormat.RGBA32, false); 

    WWW www = new WWW(url); 
    //Texture myGUITexture = Resources.Load("23") as Texture; 

    Debug.Log (www.bytesDownloaded); 
    Debug.Log (www.progress); 
    Debug.Log (www.texture); 

    yield return www; 

    // we put the downloaded image into the new texture 
    www.LoadImageIntoTexture(tex); 

    // new cubemap 
    Cubemap c = new Cubemap(2048, TextureFormat.RGBA32, false); 
    Color[] CubeMapColors; 
    CubeMapColors = tex.GetPixels(); 
    c.SetPixels(CubeMapColors, CubemapFace.PositiveX); 
    // we set the cubemap from the texture pixel by pixel 
    c.Apply(); 

    //NewTexture.isPowerOfTwo = true; 

    //Debug.Log (RenderSettings.skybox.GetTexture ("_Tex")); 

    // We change the Cubemap of the Skybox 
    RenderSettings.skybox.SetTexture("_Tex", c); 
} 

我評論所有的代碼解釋什麼,我認爲我做的。

我做了這個「訣竅」創建立方像素像素,因爲編輯器的方式來做到這一點(這是令人難以置信的簡單)似乎是不可能從我可以閱讀的其他人的帖子。

最終,結果只是一堆灰色像素。

我真的不知道在我的過程中發生了什麼,我看到的唯一「陰影」點就是TextureFormat。

我選擇了RGBA32,因爲當我看着我的Unity編輯器時,我看到了BC7格式,這是錯誤記錄爲SetTexture不可能的,從doc他們解釋它可能會在RGBA32中解壓縮。

當然,控制檯中沒有剩餘的錯誤。

我真的很驚訝沒有一個簡單的方法來做到這一點。我的意思是不一定要從http上獲取圖像並將其放入天空盒,而只需更改天空盒的紋理。我錯過了什麼嗎?

+1

Cubemap有6個面。你應該設置它們全部6個,但是你只是在你的代碼中設置一個'CubemapFace.PositiveX'。 – Programmer

+0

但是,我應該如何在6部分中分割圖像呢?實際上,當我們爲素材設置Cubemap特性時,我發現Unity編輯器正在自己做這件事,但我沒有發現任何使用c#腳本的示例 – Alburkerk

+1

您是否試圖在所有6面上放置相同的圖像或者你想打開圖像? – user1767754

回答

1

我想我找到了適合您的解決方案。

以下代碼基本上是您的代碼的擴展。

我修復了一些困擾我的東西,但代碼基本上是一樣的。

using System.Collections; 
using UnityEngine; 

public class ReplaceCubemap : MonoBehaviour 
{ 
    public string url = "your file name"; 
    public int CubemapResolution = 256; 

    private Texture2D source; 

    /// <summary> 
    /// These are the faces of a cube 
    /// </summary> 
    private Vector3[][] faces = 
    { 
     new Vector3[] { 
      new Vector3(1.0f, 1.0f, -1.0f), 
      new Vector3(1.0f, 1.0f, 1.0f), 
      new Vector3(1.0f, -1.0f, -1.0f), 
      new Vector3(1.0f, -1.0f, 1.0f) 
     }, 
     new Vector3[] { 
      new Vector3(-1.0f, 1.0f, 1.0f), 
      new Vector3(-1.0f, 1.0f, -1.0f), 
      new Vector3(-1.0f, -1.0f, 1.0f), 
      new Vector3(-1.0f, -1.0f, -1.0f) 
     }, 
     new Vector3[] { 
      new Vector3(-1.0f, 1.0f, 1.0f), 
      new Vector3(1.0f, 1.0f, 1.0f), 
      new Vector3(-1.0f, 1.0f, -1.0f), 
      new Vector3(1.0f, 1.0f, -1.0f) 
     }, 
     new Vector3[] { 
      new Vector3(-1.0f, -1.0f, -1.0f), 
      new Vector3(1.0f, -1.0f, -1.0f), 
      new Vector3(-1.0f, -1.0f, 1.0f), 
      new Vector3(1.0f, -1.0f, 1.0f) 
     }, 
     new Vector3[] { 
      new Vector3(-1.0f, 1.0f, -1.0f), 
      new Vector3(1.0f, 1.0f, -1.0f), 
      new Vector3(-1.0f, -1.0f, -1.0f), 
      new Vector3(1.0f, -1.0f, -1.0f) 
     }, 
     new Vector3[] { 
      new Vector3(1.0f, 1.0f, 1.0f), 
      new Vector3(-1.0f, 1.0f, 1.0f), 
      new Vector3(1.0f, -1.0f, 1.0f), 
      new Vector3(-1.0f, -1.0f, 1.0f) 
     } 
    }; 

    void Update() 
    { 
     // When trigger, we start the process 
     if (Input.GetKeyDown(KeyCode.F)) 
     { 

      // start Coroutine to handle the WWW asynchronous process 
      StartCoroutine(setImage()); 
     } 
    } 

    IEnumerator setImage() 
    { 
     WWW www = new WWW(url); 
     //Texture myGUITexture = Resources.Load("23") as Texture; 

     Debug.Log(www.bytesDownloaded); 
     Debug.Log(www.progress); 
     Debug.Log(www.texture); 

     yield return www; 

     source = new Texture2D(www.texture.width, www.texture.height); 
     // we put the downloaded image into the new texture 
     www.LoadImageIntoTexture(source); 

     // new cubemap 
     Cubemap c = new Cubemap(CubemapResolution, TextureFormat.RGBA32, false); 

     Color[] CubeMapColors; 

     for (int i = 0; i < 6; i++) 
     { 
      CubeMapColors = CreateCubemapTexture(CubemapResolution, (CubemapFace)i); 
      c.SetPixels(CubeMapColors, (CubemapFace)i); 
     } 
     // we set the cubemap from the texture pixel by pixel 
     c.Apply(); 

     //Destroy all unused textures 
     DestroyImmediate(source); 
     DestroyImmediate(www.texture); 
     Texture2D[] texs = FindObjectsOfType<Texture2D>(); 
     for (int i = 0; i < texs.Length; i++) 
     { 
      DestroyImmediate(texs[i]); 
     } 

     // We change the Cubemap of the Skybox 
     RenderSettings.skybox.SetTexture("_Tex", c); 
    } 

    /// <summary> 
    /// Generates a Texture that represents the given face for the cubemap. 
    /// </summary> 
    /// <param name="resolution">The targetresolution in pixels</param> 
    /// <param name="face">The target face</param> 
    /// <returns></returns> 
    private Color[] CreateCubemapTexture(int resolution, CubemapFace face) 
    { 
     Texture2D texture = new Texture2D(resolution, resolution, TextureFormat.RGB24, false); 

     Vector3 texelX_Step = (faces[(int)face][1] - faces[(int)face][0])/resolution; 
     Vector3 texelY_Step = (faces[(int)face][3] - faces[(int)face][2])/resolution; 

     float texelSize = 1.0f/resolution; 
     float texelIndex = 0.0f; 

     //Create textured face 
     Color[] cols = new Color[resolution]; 
     for (int y = 0; y < resolution; y++) 
     { 
      Vector3 texelX = faces[(int)face][0]; 
      Vector3 texelY = faces[(int)face][2]; 
      for (int x = 0; x < resolution; x++) 
      { 
       cols[x] = Project(Vector3.Lerp(texelX, texelY, texelIndex).normalized); 
       texelX += texelX_Step; 
       texelY += texelY_Step; 
      } 
      texture.SetPixels(0, y, resolution, 1, cols); 
      texelIndex += texelSize; 
     } 
     texture.wrapMode = TextureWrapMode.Clamp; 
     texture.Apply(); 

     Color[] colors = texture.GetPixels(); 
     DestroyImmediate(texture); 

     return colors; 
    } 

    /// <summary> 
    /// Projects a directional vector to the texture using spherical mapping 
    /// </summary> 
    /// <param name="direction">The direction in which you view</param> 
    /// <returns></returns> 
    private Color Project(Vector3 direction) 
    { 
     float theta = Mathf.Atan2(direction.z, direction.x) + Mathf.PI/180.0f; 
     float phi = Mathf.Acos(direction.y); 

     int texelX = (int)(((theta/Mathf.PI) * 0.5f + 0.5f) * source.width); 
     if (texelX < 0) texelX = 0; 
     if (texelX >= source.width) texelX = source.width - 1; 
     int texelY = (int)((phi/Mathf.PI) * source.height); 
     if (texelY < 0) texelY = 0; 
     if (texelY >= source.height) texelY = source.height - 1; 

     return source.GetPixel(texelX, source.height - texelY - 1); 
    } 
} 

什麼代碼基本上做的是:

  • 獲得從www
  • 全景紋理每個面,計算紋理
  • 分配生成的紋理到立方體貼圖
  • 收集垃圾
  • 將立方體貼圖分配給着色器