2017-07-11 6 views
4

Ich muss ein Bild von einem Server herunterladen, dann in eine Cubemap transformieren und schließlich diese CubeMap in meine Skybox legen.Bearbeiten einer Cubemap Skybox von einem Remote-Image

Ich arbeite mit C#.

kam ich mit diesem Code auf:

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); 
} 

ich den gesamten Code kommentiert zu erklären, was ich denke, ich tue.

Ich habe diesen "Trick" gemacht, die Cubemap Pixel für Pixel zu erstellen, weil die Art und Weise des Editors (die übrigens unglaublich einfach ist) von anderen Leuten, die ich lesen konnte, nicht möglich ist.

Schließlich war das Ergebnis nur ein paar graue Pixel.

Ich weiß nicht wirklich, was in meinem Prozess so viel vermasselt, der einzige "Schatten" Punkt, den ich sehe, ist das TextureFormat.

Ich wählte RGBA32, weil, wenn ich auf meine Unity Editor schaue, ich BC7-Format, die Fehler als nicht möglich für SetTexture protokolliert und aus der doc erklären sie in RGBA32 dekomprimiert werden kann.

Natürlich gibt es keinen verbleibenden Fehler in der Konsole.

Ich bin wirklich überrascht, es gibt keinen einfachen Weg, es zu tun. Ich meine, ich nehme nicht unbedingt ein Bild von http und lege es in Skybox, sondern verändere einfach die Textur einer Skybox. Fehle ich etwas?

+1

Cubemap haben 6 Gesichter. Sie sollten alle 6 davon einstellen, aber Sie setzen nur einen 'CubemapFace.PositiveX' in Ihrem Code. – Programmer

+0

Aber wie soll ich dann das Bild in 6 Teile teilen? In der Tat habe ich gelesen, dass der Unity Editor das gemacht hat, als wir das Cubemap-Material für das Material gesetzt haben, aber ich habe kein Beispiel dafür gefunden mit C# script – Alburkerk

+1

Versuchen Sie, das gleiche Bild auf allen 6 Seiten zu platzieren oder willst du das Bild auspacken? – user1767754

Antwort

1

Ich denke, ich habe eine Lösung für Sie gefunden.

Der folgende Code ist im Grunde eine Erweiterung Ihres Codes.

Ich reparierte einige Sachen, die mich störten, aber der Code tut im Grunde das selbe.

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); 
    } 
} 

Was der Code im Grunde tut, ist:

  • das Panorama Textur Holen von www
  • Für jedes Gesicht, berechnet die Textur
  • die erzeugte Textur auf die Cubemap Weisen
  • Collect Müll
  • Weisen Sie die Cube-Map dem Shader
  • zu