zoukankan      html  css  js  c++  java
  • 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;
        }
    }

    就这样!

    拜拜~

  • 相关阅读:
    动态传参
    函数的介绍
    文件的操作
    send email with formatted table
    minimize and close window with customed winform
    python algorithm
    something important about docker
    book list
    which language is suitable for what to do
    Find Duplicate Items in list fast
  • 原文地址:https://www.cnblogs.com/yzxhz/p/14578937.html
Copyright © 2011-2022 走看看