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

    就这样!

    拜拜~

  • 相关阅读:
    percona-toolkit 之 【pt-heartbeat】说明
    sql-索引的作用(超详细)
    SqlServer2005 海量数据 数据表分区解决难题
    怎样玩转千万级别的数据(表分区)
    SQL数据缓存依赖总结
    关于缓存中Cookie,Session,Cache的使用
    Anti-Forgery Request Recipes For ASP.NET MVC And AJAX
    jquery 父、子页面之间页面元素的获取,方法的调用
    win7系统部分软件显示乱码怎么办
    转:mvc 当中 [ValidateAntiForgeryToken] 的作用
  • 原文地址:https://www.cnblogs.com/yzxhz/p/14578937.html
Copyright © 2011-2022 走看看