Example #1
0
        public override Resource LoadResource(string name)
        {
            if (!MatchExtension(name))
            {
                return(null);
            }

            using (var stream = FileSystem.GetFile(name))
            {
                if (stream == null)
                {
                    return(null);
                }

                byte[]      newData;
                Pfim.IImage image = Pfim.Pfim.FromStream(stream);
                if (image.Compressed)
                {
                    image.Decompress();
                }

                var tightStride = image.Width * image.BitsPerPixel / 8;
                if (image.Stride != tightStride)
                {
                    newData = new byte[image.Height * tightStride];
                    for (int i = 0; i < image.Height; i++)
                    {
                        System.Buffer.BlockCopy(image.Data, i * image.Stride, newData, i * tightStride, tightStride);
                    }
                }
                else
                {
                    newData = image.Data;
                }

                MipmapLevel[] mipmaps = new MipmapLevel[image.MipMaps.Length + 1];
                mipmaps[0] = new MipmapLevel((uint)image.DataLen, newData.AsSpan(0, image.DataLen).ToArray(),
                                             (uint)image.Width, (uint)image.Height, 1);
                for (int i = 1; i < mipmaps.Length; i++)
                {
                    var  mip       = image.MipMaps[i - 1];
                    uint imageSize = (uint)mip.DataLen;
                    mipmaps[i] = new MipmapLevel(imageSize, newData.AsSpan(mip.DataOffset, mip.DataLen).ToArray(), (uint)mip.Width, (uint)mip.Height, 1);
                }

                VkFormat fmt = VkFormat.R8G8B8A8UNorm;
                switch (image.Format)
                {
                case Pfim.ImageFormat.Rgb8:
                    fmt = VkFormat.R4G4UNormPack8;
                    break;

                case Pfim.ImageFormat.R5g5b5:
                    //fmt = VkFormat.R5g5b5UnormPack16;
                    break;

                case Pfim.ImageFormat.R5g6b5:
                    fmt = VkFormat.R5G6B5UNormPack16;
                    break;

                case Pfim.ImageFormat.R5g5b5a1:
                    fmt = VkFormat.R5G5B5A1UNormPack16;
                    break;

                case Pfim.ImageFormat.Rgba16:
                    fmt = VkFormat.R4G4B4A4UNormPack16;
                    break;

                case Pfim.ImageFormat.Rgb24:
                    fmt = VkFormat.R8G8B8UNorm;
                    break;

                case Pfim.ImageFormat.Rgba32:
                    fmt = VkFormat.B8G8R8A8UNorm;
                    break;
                }

                Texture tex = new Texture
                {
                    extent          = new VkExtent3D((uint)image.Width, (uint)image.Height, 1),
                    mipLevels       = (uint)mipmaps.Length,
                    format          = fmt,
                    imageUsageFlags = VkImageUsageFlags.Sampled,
                    imageLayout     = VkImageLayout.ShaderReadOnlyOptimal,
                };

                tex.SetImageData(mipmaps);
                return(tex);
            }
        }
Example #2
0
        public static KtxFile Load(File file, bool readKeyValuePairs)
        {
            KtxHeader header = ReadStruct <KtxHeader>(file);

            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(file, out int read);
                    keyValuePairBytesRead += read;
                    keyValuePairs.Add(kvp);
                }

                kvps = keyValuePairs.ToArray();
            }
            else
            {
                file.Skip((int)header.BytesOfKeyValueData); // 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);
            List <uint> imageSizes = new List <uint>();

            MipmapLevel[] images = new MipmapLevel[numberOfMipmapLevels];

            long dataSize  = file.Length - file.Position;
            uint totalSize = 0;

            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 = file.Read <uint>();

                if (mip == 11)
                {
                    //bug?
                    imageSize = Math.Min(imageSizes.Back() >> 2, imageSize);
                    //imageSize = 1;
                }

                imageSizes.Add(imageSize);
                ArrayElement[] arrayElements = new ArrayElement[numberOfArrayElements];
                bool           isCubemap     = header.NumberOfFaces == 6 && header.NumberOfArrayElements == 0;

                uint arrayElementSize = imageSize / numberOfArrayElements;

                for (int arr = 0; arr < numberOfArrayElements; arr++)
                {
                    uint        faceSize = arrayElementSize;
                    ImageFace[] faces    = new ImageFace[numberOfFaces];
                    for (int face = 0; face < numberOfFaces; face++)
                    {
                        faces[face] = new ImageFace(file.ReadBytes((int)faceSize));
                        uint cubePadding = 0u;
                        if (isCubemap)
                        {
                            cubePadding = 3 - ((imageSize + 3) % 4);
                        }

                        file.Skip((int)cubePadding);
                        totalSize += faceSize;
                    }

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

                images[mip] = new MipmapLevel(
                    mipWidth,
                    mipHeight,
                    mipDepth,
                    imageSize,
                    arrayElements, header.NumberOfArrayElements);

                uint mipPaddingBytes = 3 - ((imageSize + 3) % 4);
                //Debug.Assert(mipPaddingBytes == 0);
                file.Skip((int)mipPaddingBytes);
            }

            //Debug.Assert(dataSize == numberOfMipmapLevels * 4 + totalSize);

            return(new KtxFile(header, kvps, images));
        }