I need to download an image from a server, then transform it in a Cubemap and finally put this CubeMap in my Skybox.
I work with C#.
I came up with this code :
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);
}
I commented all the code to explain what I think I am doing.
I made this "trick" of creating the Cubemap pixel by pixel because the Editor way to do it (which is incredibly simple by the way) seems to be not possible from other people posts I could read.
Eventually, the result was just a bunch of grey pixels.
I don't really know what screw up so much in my process, the only "shadow" point I see is the TextureFormat.
I chose RGBA32 because when I look at my Unity Editor, I see BC7 format, which is error logged as non possible for SetTexture and from the doc they explain it may be decompressed in RGBA32.
Of course there is no remaining error in the console.
I am really surprised there is not a easy way to do it. I mean not necessarily taking from http an image and put it in skybox, but just change the texture of a skybox. Am I missing something ?
Select Assets > Create > Legacy > Cubemap from the menu, and drag six textures into empty slots in the inspector. Textures for the corresponding cubemap face. Width and Height of each Cubemap face in pixels. The textures will be scaled automatically to fit this size.
A Cubemap Texture is a texture, where each mipmap level consists of six 2D images which must be square. The 6 images represent the faces of a cube. The texture coordinate used to access a cubemap is a 3D direction vector which represents a direction from the center of the cube to the value to be accessed.
Specular Indirect Lighting is stored in an array of cubemaps. These are defined by the Reflection Cubemap objects. They specify where to sample the scene's lighting and where to apply it.
I think I found a solution for you.
The following code is basically an extension to your code.
I fixed some stuff that was bothering me, but the code does basically the same.
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);
}
}
What the code basically does is:
www
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With