Texture2D和CubeMap的相互转换

有两种转换:

1.使用6个正方形组成的CubeMap。

这种比较简单,排版好就行:

 

 

2.全景图转成CubeMap。

借鉴Unity商店里面的插件:PanoramaToCubemap

可以直接将鱼眼那种的全景贴图转为CubeMap。

 

需要注意的是这两种转换后,得到的贴图都存在水平或者垂直方向的翻转问题。

完整代码:

 

using UnityEngine;

public static class CubeMapAndTexture2D
{
    /// <summary>
    /// 使用6平面贴图得到CubeMap
    /// </summary>
    /// <param name="tempTex"></param>
    /// <returns></returns>
    public static Cubemap GetCubeMapByCubeTexture2D(Texture2D tempTex)
    {
        tempTex = FlipPixels(tempTex, false, true);
        int everyW = (int)(tempTex.width / 4f);
        int everyH = (int)(tempTex.height / 3f);
        int cubeMapSize = Mathf.Min(everyW, everyH);

        Cubemap cubemap = new Cubemap(cubeMapSize, TextureFormat.RGB24, false);
        cubemap.SetPixels(tempTex.GetPixels(cubeMapSize, 0, cubeMapSize, cubeMapSize), CubemapFace.PositiveY);
        cubemap.SetPixels(tempTex.GetPixels(0, cubeMapSize, cubeMapSize, cubeMapSize), CubemapFace.NegativeX);
        cubemap.SetPixels(tempTex.GetPixels(cubeMapSize, cubeMapSize, cubeMapSize, cubeMapSize), CubemapFace.PositiveZ);
        cubemap.SetPixels(tempTex.GetPixels(2 * cubeMapSize, cubeMapSize, cubeMapSize, cubeMapSize), CubemapFace.PositiveX);
        cubemap.SetPixels(tempTex.GetPixels(3 * cubeMapSize, cubeMapSize, cubeMapSize, cubeMapSize), CubemapFace.NegativeZ);
        cubemap.SetPixels(tempTex.GetPixels(cubeMapSize, 2 * cubeMapSize, cubeMapSize, cubeMapSize), CubemapFace.NegativeY);
        cubemap.Apply();
        return cubemap;
    }
    /// <summary>
    /// 使用Panorado全景图获取CubeMap
    /// </summary>
    /// <param name="tempTex"></param>
    /// <returns></returns>
    public static Cubemap GetCubeMapByPanoradoTexture2D(Texture2D tempTex)
    {
        int everyW = (int)(tempTex.width / 4f);
        int everyH = (int)(tempTex.height / 3f);
        int cubeMapSize = Mathf.Min(everyW, everyH);

        Cubemap cubemap = new Cubemap(cubeMapSize, TextureFormat.RGB24, false);
        cubemap.SetPixels(CreateCubemapTexture(tempTex, cubeMapSize, 0).GetPixels(), CubemapFace.PositiveZ);
        cubemap.SetPixels(CreateCubemapTexture(tempTex, cubeMapSize, 1).GetPixels(), CubemapFace.NegativeZ);
        cubemap.SetPixels(CreateCubemapTexture(tempTex, cubeMapSize, 2).GetPixels(), CubemapFace.NegativeX);
        cubemap.SetPixels(CreateCubemapTexture(tempTex, cubeMapSize, 3).GetPixels(), CubemapFace.PositiveX);
        cubemap.SetPixels(CreateCubemapTexture(tempTex, cubeMapSize, 4).GetPixels(), CubemapFace.PositiveY);
        cubemap.SetPixels(CreateCubemapTexture(tempTex, cubeMapSize, 5).GetPixels(), CubemapFace.NegativeY);
        cubemap.Apply();
        return cubemap;
    }

    static Texture2D CreateCubemapTexture(Texture2D m_srcTexture, int texSize, int faceIndex, string fileName = null)
    {
        Texture2D tex = new Texture2D(texSize, texSize, TextureFormat.RGB24, false);

        Vector3[] vDirA = new Vector3[4];
        if (faceIndex == 0)
        {
            vDirA[0] = new Vector3(-1.0f, -1.0f, -1.0f);
            vDirA[1] = new Vector3(1.0f, -1.0f, -1.0f);
            vDirA[2] = new Vector3(-1.0f, 1.0f, -1.0f);
            vDirA[3] = new Vector3(1.0f, 1.0f, -1.0f);
        }
        if (faceIndex == 1)
        {
            vDirA[0] = new Vector3(1.0f, -1.0f, 1.0f);
            vDirA[1] = new Vector3(-1.0f, -1.0f, 1.0f);
            vDirA[2] = new Vector3(1.0f, 1.0f, 1.0f);
            vDirA[3] = new Vector3(-1.0f, 1.0f, 1.0f);
        }
        if (faceIndex == 2)
        {
            vDirA[0] = new Vector3(1.0f, -1.0f, -1.0f);
            vDirA[1] = new Vector3(1.0f, -1.0f, 1.0f);
            vDirA[2] = new Vector3(1.0f, 1.0f, -1.0f);
            vDirA[3] = new Vector3(1.0f, 1.0f, 1.0f);
        }
        if (faceIndex == 3)
        {
            vDirA[0] = new Vector3(-1.0f, -1.0f, 1.0f);
            vDirA[1] = new Vector3(-1.0f, -1.0f, -1.0f);
            vDirA[2] = new Vector3(-1.0f, 1.0f, 1.0f);
            vDirA[3] = new Vector3(-1.0f, 1.0f, -1.0f);
        }
        if (faceIndex == 4)
        {
            vDirA[0] = new Vector3(-1.0f, 1.0f, -1.0f);
            vDirA[1] = new Vector3(1.0f, 1.0f, -1.0f);
            vDirA[2] = new Vector3(-1.0f, 1.0f, 1.0f);
            vDirA[3] = new Vector3(1.0f, 1.0f, 1.0f);
        }
        if (faceIndex == 5)
        {
            vDirA[0] = new Vector3(-1.0f, -1.0f, 1.0f);
            vDirA[1] = new Vector3(1.0f, -1.0f, 1.0f);
            vDirA[2] = new Vector3(-1.0f, -1.0f, -1.0f);
            vDirA[3] = new Vector3(1.0f, -1.0f, -1.0f);
        }

        Vector3 rotDX1 = (vDirA[1] - vDirA[0]) / (float)texSize;
        Vector3 rotDX2 = (vDirA[3] - vDirA[2]) / (float)texSize;

        float dy = 1.0f / (float)texSize;
        float fy = 0.0f;

        Color[] cols = new Color[texSize];
        for (int y = 0; y < texSize; y++)
        {
            Vector3 xv1 = vDirA[0];
            Vector3 xv2 = vDirA[2];
            for (int x = 0; x < texSize; x++)
            {
                Vector3 v = ((xv2 - xv1) * fy) + xv1;
                v.Normalize();
                cols[x] = CalcProjectionSpherical(m_srcTexture, v);
                xv1 += rotDX1;
                xv2 += rotDX2;
            }
            tex.SetPixels(0, y, texSize, 1, cols);
            fy += dy;
        }
        tex.wrapMode = TextureWrapMode.Clamp;       // 在cubemap的情况下,如果不在wrapMode上Clapp的话,就会看到边界。
        tex.Apply();
        tex = FlipPixels(tex, true, true);
        return tex;
    }

    static Color CalcProjectionSpherical(Texture2D m_srcTexture, Vector3 vDir)
    {
        float theta = Mathf.Atan2(vDir.z, vDir.x);      // -π ~ +π(水平方向旋转).
        float phi = Mathf.Acos(vDir.y);             //  0  ~ +π(垂直方向旋转).

        while (theta < -Mathf.PI) theta += Mathf.PI + Mathf.PI;
        while (theta > Mathf.PI) theta -= Mathf.PI + Mathf.PI;

        float dx = theta / Mathf.PI;        // -1.0 ~ +1.0.
        float dy = phi / Mathf.PI;          //  0.0 ~ +1.0.

        dx = dx * 0.5f + 0.5f;
        int px = (int)(dx * (float)m_srcTexture.width);
        if (px < 0) px = 0;
        if (px >= m_srcTexture.width) px = m_srcTexture.width - 1;
        int py = (int)(dy * (float)m_srcTexture.height);
        if (py < 0) py = 0;
        if (py >= m_srcTexture.height) py = m_srcTexture.height - 1;

        Color col = m_srcTexture.GetPixel(px, m_srcTexture.height - py - 1);
        return col;
    }

    /// <summary>
    /// 水平/垂直反转帖图象素
    /// </summary>
    /// <param name="texture"></param>
    /// <param name="flipX"></param>
    /// <param name="flipY"></param>
    /// <returns></returns>
    public static Texture2D FlipPixels(Texture2D texture, bool flipX, bool flipY)
    {
        if (!flipX && !flipY)
        {
            return texture;
        }
        if (flipX)
        {
            for (int i = 0; i < texture.width / 2; i++)
            {
                for (int j = 0; j < texture.height; j++)
                {
                    Color tempC = texture.GetPixel(i, j);
                    texture.SetPixel(i, j, texture.GetPixel(texture.width - 1 - i, j));
                    texture.SetPixel(texture.width - 1 - i, j, tempC);
                }
            }
        }
        if (flipY)
        {
            for (int i = 0; i < texture.width; i++)
            {
                for (int j = 0; j < texture.height / 2; j++)
                {
                    Color tempC = texture.GetPixel(i, j);
                    texture.SetPixel(i, j, texture.GetPixel(i, texture.height - 1 - j));
                    texture.SetPixel(i, texture.height - 1 - j, tempC);
                }
            }
        }
        texture.Apply();
        return texture;
    }

    /// <summary>
    /// 将CubeMap转为普通贴图
    /// </summary>
    /// <param name="cubemap"></param>
    /// <returns></returns>
    public static Texture2D GetTexture2DByCubeMap(Cubemap cubemap)
    {
        int everyW = cubemap.width;
        int everyH = cubemap.height;

        Texture2D texture2D = new Texture2D(everyW * 4, everyH * 3);
        texture2D.SetPixels(everyW, 0, everyW, everyH, cubemap.GetPixels(CubemapFace.PositiveY));
        texture2D.SetPixels(0, everyH, everyW, everyH, cubemap.GetPixels(CubemapFace.NegativeX));
        texture2D.SetPixels(everyW, everyH, everyW, everyH, cubemap.GetPixels(CubemapFace.PositiveZ));
        texture2D.SetPixels(2 * everyW, everyH, everyW, everyH, cubemap.GetPixels(CubemapFace.PositiveX));
        texture2D.SetPixels(3 * everyW, everyH, everyW, everyH, cubemap.GetPixels(CubemapFace.NegativeZ));
        texture2D.SetPixels(everyW, 2 * everyH, everyW, everyH, cubemap.GetPixels(CubemapFace.NegativeY));
        texture2D.Apply();
        texture2D = FlipPixels(texture2D, false, true);
        return texture2D;
    }
}

 

 

 

就这样!

拜拜~

posted @ 2021-03-25 19:41  有只小耗子  阅读(1267)  评论(0编辑  收藏  举报