Ejemplo n.º 1
0
        public static KtxFile Load(Stream s, bool readKeyValuePairs)
        {
            using (BinaryReader br = new BinaryReader(s))
            {
                KtxHeader header = ReadStruct <KtxHeader>(br);

                KtxKeyValuePair[] kvps = null;
                if (readKeyValuePairs)
                {
                    int keyValuePairBytesRead            = 0;
                    List <KtxKeyValuePair> keyValuePairs = new List <KtxKeyValuePair>();
                    while (keyValuePairBytesRead < header.BytesOfKeyValueData)
                    {
                        int             bytesRemaining = (int)(header.BytesOfKeyValueData - keyValuePairBytesRead);
                        KtxKeyValuePair kvp            = ReadNextKeyValuePair(br, out int read);
                        keyValuePairBytesRead += read;
                        keyValuePairs.Add(kvp);
                    }

                    kvps = keyValuePairs.ToArray();
                }
                else
                {
                    br.BaseStream.Seek(header.BytesOfKeyValueData, SeekOrigin.Current); // Skip over header data.
                }

                uint numberOfMipmapLevels  = Math.Max(1, header.NumberOfMipmapLevels);
                uint numberOfArrayElements = Math.Max(1, header.NumberOfArrayElements);
                uint numberOfFaces         = Math.Max(1, header.NumberOfFaces);

                uint baseWidth  = Math.Max(1, header.PixelWidth);
                uint baseHeight = Math.Max(1, header.PixelHeight);
                uint baseDepth  = Math.Max(1, header.PixelDepth);

                KtxMipmapLevel[] images = new KtxMipmapLevel[numberOfMipmapLevels];
                for (int mip = 0; mip < numberOfMipmapLevels; mip++)
                {
                    uint mipWidth  = Math.Max(1, baseWidth / (uint)(Math.Pow(2, mip)));
                    uint mipHeight = Math.Max(1, baseHeight / (uint)(Math.Pow(2, mip)));
                    uint mipDepth  = Math.Max(1, baseDepth / (uint)(Math.Pow(2, mip)));

                    uint imageSize                  = br.ReadUInt32();
                    uint arrayElementSize           = imageSize / numberOfArrayElements;
                    KtxArrayElement[] arrayElements = new KtxArrayElement[numberOfArrayElements];
                    for (int arr = 0; arr < numberOfArrayElements; arr++)
                    {
                        uint      faceSize = arrayElementSize / numberOfFaces;
                        KtxFace[] faces    = new KtxFace[numberOfFaces];
                        for (int face = 0; face < numberOfFaces; face++)
                        {
                            faces[face] = new KtxFace(br.ReadBytes((int)faceSize));
                        }

                        arrayElements[arr] = new KtxArrayElement(faces);
                    }

                    images[mip] = new KtxMipmapLevel(
                        mipWidth,
                        mipHeight,
                        mipDepth,
                        imageSize,
                        arrayElementSize,
                        arrayElements);

                    uint mipPaddingBytes = 3 - ((imageSize + 3) % 4);
                    br.BaseStream.Seek(mipPaddingBytes, SeekOrigin.Current);
                }

                return(new KtxFile(header, kvps, images));
            }
        }
Ejemplo n.º 2
0
        public static unsafe Texture LoadTexture(
            GraphicsDevice gd,
            ResourceFactory factory,
            Stream assetStream,
            PixelFormat format)
        {
            KtxFile ktxTex2D = Load(assetStream, false);

            uint width  = ktxTex2D.Header.PixelWidth;
            uint height = ktxTex2D.Header.PixelHeight;

            if (height == 0)
            {
                height = width;
            }

            uint arrayLayers = Math.Max(1, ktxTex2D.Header.NumberOfArrayElements);
            uint mipLevels   = Math.Max(1, ktxTex2D.Header.NumberOfMipmapLevels);

            Texture ret = factory.CreateTexture(TextureDescription.Texture2D(
                                                    width, height, mipLevels, arrayLayers,
                                                    format, TextureUsage.Sampled));

            Texture stagingTex = factory.CreateTexture(TextureDescription.Texture2D(
                                                           width, height, mipLevels, arrayLayers,
                                                           format, TextureUsage.Staging));

            // Copy texture data into staging buffer
            for (uint level = 0; level < mipLevels; level++)
            {
                KtxMipmapLevel mipmap = ktxTex2D.Mipmaps[level];
                for (uint layer = 0; layer < arrayLayers; layer++)
                {
                    KtxArrayElement ktxLayer = mipmap.ArrayElements[layer];
                    Debug.Assert(ktxLayer.Faces.Length == 1);
                    byte[] pixelData = ktxLayer.Faces[0].Data;
                    fixed(byte *pixelDataPtr = &pixelData[0])
                    {
                        gd.UpdateTexture(stagingTex, (IntPtr)pixelDataPtr, (uint)pixelData.Length,
                                         0, 0, 0, mipmap.Width, mipmap.Height, 1, level, layer);
                    }
                }
            }

            CommandList copyCL = factory.CreateCommandList();

            copyCL.Begin();
            for (uint level = 0; level < mipLevels; level++)
            {
                KtxMipmapLevel mipLevel = ktxTex2D.Mipmaps[level];
                for (uint layer = 0; layer < arrayLayers; layer++)
                {
                    copyCL.CopyTexture(
                        stagingTex, 0, 0, 0, level, layer,
                        ret, 0, 0, 0, level, layer,
                        mipLevel.Width, mipLevel.Height, mipLevel.Depth,
                        1);
                }
            }
            copyCL.End();
            gd.SubmitCommands(copyCL);

            gd.DisposeWhenIdle(copyCL);
            gd.DisposeWhenIdle(stagingTex);

            return(ret);
        }