Exemple #1
0
        private void InitWithKTXTexture(BinaryReader reader)
        {
            var identifier = reader.ReadBytes(12);

            if (identifier[1] != 'K' || identifier[2] != 'T' || identifier[3] != 'X')
            {
                throw new InvalidDataException("Invalid KTX header");
            }
            var endiannes = reader.ReadUInt32();

            if (endiannes != 0x04030201)
            {
                throw new InvalidDataException("Unsupported endiannes");
            }
            var glType                = reader.ReadInt32();
            var glTypeSize            = reader.ReadInt32();
            var glFormat              = reader.ReadInt32();
            var glInternalFormat      = reader.ReadInt32();
            var glBaseInternalFormat  = reader.ReadInt32();
            var pixelWidth            = reader.ReadInt32();
            var pixelHeight           = reader.ReadInt32();
            var pixelDepth            = reader.ReadInt32();
            var numberOfArrayElements = reader.ReadInt32();
            var numberOfFaces         = reader.ReadInt32();
            var numberOfMipmapLevels  = reader.ReadInt32();
            var bytesOfKeyValueData   = reader.ReadInt32();

            reader.ReadBytes(bytesOfKeyValueData);
            if (numberOfArrayElements != 0)
            {
                throw new InvalidDataException("Array textures are not supported");
            }
            if (numberOfFaces != 1)
            {
                throw new InvalidDataException("Cubemap textures are not supported");
            }
            if (pixelDepth != 0)
            {
                throw new InvalidDataException("3D Textures are not supported");
            }
            if ((pixelWidth & 3) != 0 || (pixelHeight & 3) != 0)
            {
                throw new InvalidDataException("Texture dimensions should multiple of 4");
            }
            SurfaceSize = ImageSize = new Size(pixelWidth, pixelHeight);
            Action glCommands = PrepareOpenGLTexture;

            PrepareOpenGLTexture();
            for (int i = 0; i < Math.Max(1, numberOfMipmapLevels); i++)
            {
                var dataLength = reader.ReadInt32();
                MemoryUsed = 0;
                if (i > 0 && (pixelWidth < 8 || pixelHeight < 8))
                {
                    continue;
                }
                // Copy variables because they will be captured.
                int mipLevel = i;
                int width    = pixelWidth;
                int height   = pixelHeight;
                if (glFormat == 0)
                {
                    var data = ReadTextureData(reader, dataLength);
                    glCommands += () => {
                        if (!etc2Checked)
                        {
                            etc2Checked = true;
                            if (PlatformRenderer.GetGLESMajorVersion() >= 3)
                            {
                                etc2Supported = true;
                            }
                            else
                            {
                                var ext = GL.GetString(StringName.Extensions);
                                etc2Supported = ext?.Contains("ETC2_RGBA8") ?? false;
                            }
                            Debug.Write(etc2Supported ? "ETC2 textures supported." : "ETC2 textures not supported.");
                        }
                        PlatformRenderer.PushTexture(handle, 0);
                        const int etc1Rgb8Oes = 36196;
                        if (etc2Supported || (Application.Platform == PlatformId.Android && glInternalFormat == etc1Rgb8Oes))
                        {
                            GL.CompressedTexImage2D(
                                TextureTarget.Texture2D, mipLevel, (PixelInternalFormat)glInternalFormat,
                                width, height, 0, dataLength, data);
                        }
                        else
                        {
                            var rgba8Data = Marshal.AllocHGlobal(width * height * 4);
                            Etc2Decoder.Decode(data, rgba8Data, width, height, glInternalFormat);
                            GL.TexImage2D(TextureTarget.Texture2D, mipLevel, PixelInternalFormat.Rgba, width, height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, rgba8Data);
                            Marshal.FreeHGlobal(rgba8Data);
                        }
                        PlatformRenderer.PopTexture(0);
                        PlatformRenderer.CheckErrors();
                    };
                }
                else
                {
                    var data = ReadTextureData(reader, dataLength);
                    glCommands += () => {
                        PlatformRenderer.PushTexture(handle, 0);
                        GL.TexImage2D(
                            TextureTarget.Texture2D, mipLevel, (PixelInternalFormat)glInternalFormat,
                            width, height, 0, (PixelFormat)glFormat, (PixelType)glType, data);
                        PlatformRenderer.PopTexture(0);
                        PlatformRenderer.CheckErrors();
                    };
                }
                pixelWidth  /= 2;
                pixelHeight /= 2;
            }
            Application.InvokeOnMainThread(glCommands);
        }