【问题标题】:Editing a Cubemap Skybox from remote image从远程图像编辑立方体贴图天空盒
【发布时间】:2017-12-15 09:36:01
【问题描述】:

我需要从服务器下载图像,然后将其转换为 Cubemap,最后将这个 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);
}

我评论了所有代码以解释我认为我在做什么。

我制作了这个逐像素创建 Cubemap 的“技巧”,因为编辑器的方法(顺便说一句,这非常简单)似乎无法从我可以阅读的其他人的帖子中获得。

最终,结果只是一堆灰色像素。

我真的不知道在我的过程中搞砸了什么,我看到的唯一“阴影”点是 TextureFormat。

我之所以选择 RGBA32,是因为当我查看 Unity 编辑器时,我看到了 BC7 格式,这对于 SetTexture 来说是不可能的错误记录,并且从 doc 他们解释说它可能在 RGBA32 中解压缩。

当然控制台没有剩余错误了。

我真的很惊讶没有简单的方法来做到这一点。我的意思是不一定要从 http 中获取图像并将其放入天空盒中,而只是更改天空盒的纹理。我错过了什么吗?

【问题讨论】:

  • 立方体贴图有 6 个面。您应该设置所有 6 个,但您只在代码中设置了一个 CubemapFace.PositiveX
  • 但是我应该如何将图像分成 6 部分呢?事实上,当我们为材质设置 Cubemap 属性时,我读到 Unity 编辑器正在自行执行此操作,但我没有找到任何使用 c# 脚本执行此操作的示例
  • 您是要在所有 6 个面上放置相同的图像还是要打开图像?
  • 嗯,这是一张故意拍摄的 360 度图像,所以我只想用同一张图像作为整个天空盒。我在编辑器中手动获取的内容基本上是这样的:youtube.com/watch?v=kUROoI6_SmA(1m30 视频)
  • Unity 不支持在运行时更改纹理导入设置。在检查器中看到的导入设置属于 AssetImporter 类,该类在 runtme 中不可用。而是尝试将 360 图像转换为 6 张图像,然后从服务器下载这些图像。现在将材质的着色器设置为 skybox/6 边并在运行时将所有这些纹理分配给它

标签: c# unity3d textures unity5 skybox


【解决方案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获取全景纹理
  • 为每个面计算纹理
  • 将生成的纹理分配给立方体贴图
  • 收集垃圾
  • 将立方体贴图分配给着色器

【讨论】:

  • 像魅力一样工作,非常感谢你是我的救星!!!
【解决方案2】:

我在计算机上使用了带有图像的解决方案。

我有一个问题是图像的颜色失去了强度,我发现这是因为 sRGB 没有设置为 true。 我通过替换来修复它:

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

setImage函数中:

Cubemap c = new Cubemap(CubeMapResolution, DefaultFormat.LDR, TextureCreationFlags.None);

【讨论】:

  • 嗨@BarbasOyun,我对天空盒的强度和分辨率也有疑问。我尝试了您的解决方案,但它仍然会创建一个像素化且强度较低的天空盒。这是我得到的和我想要的:snipboard.io/JLCd0B.jpg除了你回答的问题,你能否建议我可以尝试什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多