private void Update()
    {
        float4   pl           = MathLib.GetPlane(plane.up, plane.position);
        float4x4 localToWorld = transform.localToWorldMatrix;

        txt.text = MathLib.BoxIntersect(ref localToWorld, 0, 0.5f, pl.Ptr(), 1).ToString();
    }
    void PrintTex2D()
    {
        uint2 size     = uint2((uint)texture.width, (uint)texture.height);
        int   mipCount = useMipMap ? min((int)(log2(size.x / 32) + 0.1), (int)(log2(size.y / 32) + 0.1)) : 1;

        Debug.Log(mipCount);
        TextureData data;

        data.width       = size.x;
        data.height      = size.y;
        data.depth       = 1;
        data.textureType = TextureType.Tex2D;
        data.mipCount    = (uint)mipCount;
        data.format      = tex2DFormat;
        NativeList <byte> lst       = new NativeList <byte>((int)(size.x * size.y * 1.4 * 8), Unity.Collections.Allocator.Temp);
        byte *            headerPtr = (byte *)data.Ptr();

        for (int i = 0; i < sizeof(TextureData); ++i)
        {
            lst.Add(headerPtr[i]);
        }

        if (tex2DFormat == TextureData.LoadFormat.LoadFormat_BC6H)
        {
            uint4[]       datas    = new uint4[size.x * size.y];
            CommandBuffer cbuffer  = new CommandBuffer();
            GPUCompress   compress = new GPUCompress(bc7Compress, bc6Compress, (int)size.x, (int)size.y, 0x80000, 0);
            for (int i = 0; i < mipCount; ++i)
            {
                compress.Compress(texture as Texture2D, (int)size.x, (int)size.y, i, cbuffer, true);
                Graphics.ExecuteCommandBuffer(cbuffer);
                var len = compress.GetData((int)size.x, (int)size.y, datas);
                for (int a = 0; a < len; ++a)
                {
                    uint4 value = datas[a];
                    byte *ptr   = (byte *)value.Ptr();
                    for (int b = 0; b < sizeof(uint4); ++b)
                    {
                        lst.Add(ptr[b]);
                    }
                }
                for (int a = datas.Length * sizeof(uint4); a < 512; ++a)
                {
                    lst.Add(0);
                }
                size /= 2;
                size  = max(size, 1);
            }

            compress.Dispose();
            cbuffer.Dispose();
        }
        else if (tex2DFormat == TextureData.LoadFormat.LoadFormat_BC7)
        {
            uint4[]       datas    = new uint4[size.x * size.y];
            CommandBuffer cbuffer  = new CommandBuffer();
            GPUCompress   compress = new GPUCompress(bc7Compress, bc6Compress, (int)size.x, (int)size.y, 0x80000, 0);
            for (int i = 0; i < mipCount; ++i)
            {
                compress.Compress(texture as Texture2D, (int)size.x, (int)size.y, i, cbuffer, false);
                Graphics.ExecuteCommandBuffer(cbuffer);
                var len = compress.GetData((int)size.x, (int)size.y, datas);
                for (int a = 0; a < len; ++a)
                {
                    uint4 value = datas[a];
                    byte *ptr   = (byte *)value.Ptr();
                    for (int b = 0; b < sizeof(uint4); ++b)
                    {
                        lst.Add(ptr[b]);
                    }
                }
                for (int a = datas.Length * sizeof(uint4); a < 512; ++a)
                {
                    lst.Add(0);
                }
                size /= 2;
                size  = max(size, 1);
            }

            compress.Dispose();
            cbuffer.Dispose();
        }
        else if ((int)tex2DFormat >= 8 && (int)tex2DFormat <= 10)
        {
            //integer texture

            int    pass      = 0;
            uint[] dataArray = null;
            readCS.SetVector("_TextureSize", float4(size.x - 0.5f, size.y - 0.5f, size.x, size.y));
            readCS.SetInt("_Count", (int)size.x);
            ComputeBuffer cb = null;
            switch (tex2DFormat)
            {
            case TextureData.LoadFormat.LoadFormat_UINT:
                pass      = 2;
                dataArray = new uint[size.x * size.y];
                cb        = new ComputeBuffer(dataArray.Length, sizeof(int));
                readCS.SetTexture(pass, "_UIntTexture", texture);
                readCS.SetBuffer(pass, "_ResultInt1Buffer", cb);
                break;

            case TextureData.LoadFormat.LoadFormat_UINT2:
                pass      = 3;
                dataArray = new uint[size.x * size.y * 2];
                cb        = new ComputeBuffer(dataArray.Length, sizeof(int));
                readCS.SetTexture(pass, "_UInt2Texture", texture);
                readCS.SetBuffer(pass, "_ResultInt2Buffer", cb);
                break;

            case TextureData.LoadFormat.LoadFormat_UINT4:
                pass      = 4;
                dataArray = new uint[size.x * size.y * 4];
                cb        = new ComputeBuffer(dataArray.Length, sizeof(int));
                readCS.SetTexture(pass, "_UInt4Texture", texture);
                readCS.SetBuffer(pass, "_ResultInt4Buffer", cb);
                break;
            }
            readCS.Dispatch(pass, (int)size.x / 8, (int)size.y / 8, 1);
            cb.GetData(dataArray);
            foreach (var i in dataArray)
            {
                uint  p   = i;
                byte *ptr = (byte *)p.Ptr();
                for (uint a = 0; a < sizeof(int); ++a)
                {
                    lst.Add(ptr[a]);
                }
            }

            cb.Dispose();
        }
        else
        {
            ComputeBuffer cb = new ComputeBuffer((int)size.x * (int)size.y, sizeof(float4), ComputeBufferType.Default);
            readCS.SetTexture(1, "_MainTex2D", texture);
            readCS.SetBuffer(1, "_ResultBuffer", cb);
            float4[] readbackValues = new float4[size.x * size.y];
            float *  byteArray      = stackalloc float[4];
            for (int i = 0; i < mipCount; ++i)
            {
                readCS.SetVector("_TextureSize", float4(size.x - 0.5f, size.y - 0.5f, size.x, size.y));
                readCS.SetInt("_Count", (int)size.x);
                readCS.SetInt("_TargetMipLevel", i);
                readCS.Dispatch(1, max(1, Mathf.CeilToInt(size.x / 8f)), max(1, Mathf.CeilToInt(size.y / 8f)), 1);
                int cum = (int)(size.x * size.y);
                cb.GetData(readbackValues, 0, 0, cum);
                switch (tex2DFormat)
                {
                case TextureData.LoadFormat.LoadFormat_RGBAFloat16:
                    for (int j = 0; j < cum; ++j)
                    {
                        half4 hlfResult = (half4)readbackValues[j];
                        byte *b         = (byte *)hlfResult.Ptr();
                        for (int z = 0; z < sizeof(half4); ++z)
                        {
                            lst.Add(b[z]);
                        }
                    }
                    for (int j = cum * sizeof(half4); j < 512; ++j)
                    {
                        lst.Add(0);
                    }
                    break;

                case TextureData.LoadFormat.LoadFormat_RGFLOAT16:
                    for (int j = 0; j < cum; ++j)
                    {
                        half2 hlfResult = (half2)readbackValues[j].xy;
                        byte *b         = (byte *)hlfResult.Ptr();
                        for (int z = 0; z < sizeof(half2); ++z)
                        {
                            lst.Add(b[z]);
                        }
                    }
                    for (int j = cum * sizeof(half2); j < 512; ++j)
                    {
                        lst.Add(0);
                    }
                    break;

                case TextureData.LoadFormat.LoadFormat_RGBAFloat32:
                    for (int j = 0; j < cum; ++j)
                    {
                        float4 hlfResult = readbackValues[j];
                        byte * b         = (byte *)hlfResult.Ptr();
                        for (int z = 0; z < sizeof(float4); ++z)
                        {
                            lst.Add(b[z]);
                        }
                    }
                    for (int j = cum * sizeof(float4); j < 512; ++j)
                    {
                        lst.Add(0);
                    }
                    break;

                case TextureData.LoadFormat.LoadFormat_RGBA16:
                    for (int j = 0; j < cum; ++j)
                    {
                        ushort *shorts = (ushort *)byteArray;
                        float * flt    = (float *)readbackValues[j].Ptr();
                        for (int bb = 0; bb < 4; ++bb)
                        {
                            shorts[bb] = (ushort)(flt[bb] * 65535);
                        }
                        byte *b = (byte *)shorts;
                        for (int z = 0; z < sizeof(ushort) * 4; ++z)
                        {
                            lst.Add(b[z]);
                        }
                    }
                    for (int j = cum * sizeof(ushort) * 4; j < 512; ++j)
                    {
                        lst.Add(0);
                    }
                    break;

                case TextureData.LoadFormat.LoadFormat_RG16:
                    for (int j = 0; j < cum; ++j)
                    {
                        ushort *shorts = (ushort *)byteArray;
                        float * flt    = (float *)readbackValues[j].Ptr();
                        for (int bb = 0; bb < 2; ++bb)
                        {
                            shorts[bb] = (ushort)(flt[bb] * 65535);
                        }
                        byte *b = (byte *)shorts;
                        for (int z = 0; z < sizeof(ushort) * 2; ++z)
                        {
                            lst.Add(b[z]);
                        }
                    }
                    for (int j = cum * sizeof(ushort) * 2; j < 512; ++j)
                    {
                        lst.Add(0);
                    }
                    break;

                case TextureData.LoadFormat.LoadFormat_RGBA8:
                    for (int j = 0; j < cum; ++j)
                    {
                        byte * shorts = (byte *)byteArray;
                        float *flt    = (float *)readbackValues[j].Ptr();
                        for (int bb = 0; bb < 4; ++bb)
                        {
                            shorts[bb] = (byte)(flt[bb] * 255);
                        }
                        for (int z = 0; z < sizeof(byte) * 4; ++z)
                        {
                            lst.Add(shorts[z]);
                        }
                    }
                    for (int j = cum * sizeof(byte) * 4; j < 512; ++j)
                    {
                        lst.Add(0);
                    }
                    break;

                    /*  case TextureData.LoadFormat.LoadFormat_BC7:
                     *    {
                     *
                     *
                     *        NativeArray<byte> compressedData = new NativeArray<byte>(cum, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
                     *        BC7CompressJob job;
                     *        job.dest = (uint4*)compressedData.GetUnsafePtr();
                     *        job.source = readbackValues.Ptr();
                     *        job.width = (int)size.x;
                     *        JobHandle handle = job.Schedule((cum / 16), max((cum / 16) / 20, 1));
                     *        handle.Complete();
                     *        for (int a = 0; a < compressedData.Length; ++a)
                     *        {
                     *            lst.Add(compressedData[a]);
                     *        }
                     *        for (int j = cum * sizeof(byte); j < 512; ++j)
                     *        {
                     *            lst.Add(0);
                     *        }
                     * }
                     * break;
                     * case TextureData.LoadFormat.LoadFormat_BC6H:
                     * {
                     *  NativeArray<byte> compressedData = new NativeArray<byte>(cum, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
                     *  BC6UHCompressJob job;
                     *  job.dest = (uint4*)compressedData.GetUnsafePtr();
                     *  job.source = readbackValues.Ptr();
                     *  job.width = (int)size.x;
                     *  JobHandle handle = job.Schedule((cum / 16), max((cum / 16) / 20, 1));
                     *  handle.Complete();
                     *  for (int a = 0; a < compressedData.Length; ++a)
                     *  {
                     *      lst.Add(compressedData[a]);
                     *  }
                     *  for (int j = cum * sizeof(byte); j < 512; ++j)
                     *  {
                     *      lst.Add(0);
                     *  }
                     * }
                     * break;*/
                }

                size /= 2;
                size  = max(size, 1);
            }
            cb.Dispose();
        }
        byte[] finalArray = new byte[lst.Length];
        UnsafeUtility.MemCpy(finalArray.Ptr(), lst.unsafePtr, lst.Length);
        using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write))
        {
            fs.Write(finalArray, 0, lst.Length);
        }
    }
    void PrintCubemap()
    {
        float3[][] forwd = new float3[6][];
        for (int i = 0; i < 6; ++i)
        {
            forwd[i] = new float3[4];
        }
        //Forward
        forwd[4][0] = normalize(float3(-1, 1, 1));
        forwd[4][1] = normalize(float3(1, 1, 1));
        forwd[4][2] = normalize(float3(-1, -1, 1));
        forwd[4][3] = normalize(float3(1, -1, 1));
        //Left
        forwd[1][0] = normalize(float3(-1, 1, -1));
        forwd[1][1] = normalize(float3(-1, 1, 1));
        forwd[1][2] = normalize(float3(-1, -1, -1));
        forwd[1][3] = normalize(float3(-1, -1, 1));
        //Back
        forwd[5][0] = normalize(float3(1, 1, -1));
        forwd[5][1] = normalize(float3(-1, 1, -1));
        forwd[5][2] = normalize(float3(1, -1, -1));
        forwd[5][3] = normalize(float3(-1, -1, -1));

        //Right
        forwd[0][0] = normalize(float3(1, 1, 1));
        forwd[0][1] = normalize(float3(1, 1, -1));
        forwd[0][2] = normalize(float3(1, -1, 1));
        forwd[0][3] = normalize(float3(1, -1, -1));

        //up
        forwd[2][0] = normalize(float3(-1, 1, -1));
        forwd[2][1] = normalize(float3(1, 1, -1));
        forwd[2][2] = normalize(float3(-1, 1, 1));
        forwd[2][3] = normalize(float3(1, 1, 1));

        //down
        forwd[3][0] = normalize(float3(-1, -1, 1));
        forwd[3][1] = normalize(float3(1, -1, 1));
        forwd[3][2] = normalize(float3(-1, -1, -1));
        forwd[3][3] = normalize(float3(1, -1, -1));
        uint2 size = uint2(max((uint)texture.width, 1024), max((uint)texture.height, 1024));

        ComputeBuffer cb       = new ComputeBuffer((int)size.x * (int)size.y, sizeof(float4), ComputeBufferType.Default);
        int           mipCount = useMipMap ? (int)(log2(size.x / 16) + 0.1) : 1;
        TextureData   data     = new TextureData
        {
            depth       = 6,
            width       = size.x,
            height      = size.y,
            mipCount    = (uint)mipCount,
            format      = TextureData.LoadFormat.LoadFormat_RGBAFloat16,
            textureType = TextureType.Cubemap
        };

        readCS.SetTexture(0, "_MainTex", texture);
        readCS.SetBuffer(0, "_ResultBuffer", cb);
        float4[]          readbackValues = new float4[size.x * size.y];
        NativeList <byte> lst            = new NativeList <byte>((int)(size.x * size.y * 1.4), Unity.Collections.Allocator.Temp);
        byte *            headerPtr      = (byte *)data.Ptr();

        for (int i = 0; i < sizeof(TextureData); ++i)
        {
            lst.Add(headerPtr[i]);
        }
        Vector4[] setterArray = new Vector4[4];
        for (int face = 0; face < 6; ++face)
        {
            size = uint2(max((uint)texture.width, 1024), max((uint)texture.height, 1024));
            for (int i = 0; i < mipCount; ++i)
            {
                readCS.SetInt("_TargetMipLevel", i);
                readCS.SetInt("_Count", (int)size.x);
                for (int j = 0; j < 4; ++j)
                {
                    setterArray[j] = (Vector3)forwd[face][j];
                }
                readCS.SetVectorArray("_Directions", setterArray);
                readCS.Dispatch(0, max(1, Mathf.CeilToInt(size.x / 8f)), max(1, Mathf.CeilToInt(size.y / 8f)), 1);
                int cum = (int)(size.x * size.y);
                cb.GetData(readbackValues, 0, 0, cum);
                int pixelSize = 0;
                if (isCubemapCompress)
                {
                    pixelSize = 1;
                    NativeArray <byte> compressedData = new NativeArray <byte>(cum, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
                    BC6UHCompressJob   job;
                    job.dest   = (uint4 *)compressedData.GetUnsafePtr();
                    job.source = readbackValues.Ptr();
                    job.width  = (int)size.x;
                    JobHandle handle = job.Schedule((cum / 16), max((cum / 16) / 20, 1));
                    handle.Complete();
                    for (int a = 0; a < compressedData.Length; ++a)
                    {
                        lst.Add(compressedData[a]);
                    }
                }
                else
                {
                    pixelSize = sizeof(half4);
                    for (int j = 0; j < cum; ++j)
                    {
                        half4 hlfResult = (half4)readbackValues[j];
                        byte *b         = (byte *)hlfResult.Ptr();
                        for (int z = 0; z < sizeof(half4); ++z)
                        {
                            lst.Add(b[z]);
                        }
                    }
                }
                for (int j = cum * pixelSize; j < 512; ++j)
                {
                    lst.Add(0);
                }
                size /= 2;
                size  = max(size, 1);
            }
        }
        byte[] finalArray = new byte[lst.Length];
        UnsafeUtility.MemCpy(finalArray.Ptr(), lst.unsafePtr, lst.Length);
        using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write))
        {
            fs.Write(finalArray, 0, lst.Length);
        }
    }