Пример #1
0
        /// <summary>
        /// Read a KtxFile and decode it.
        /// </summary>
        public Image <Rgba32> Decode(KtxFile file)
        {
            if (IsSupportedRawFormat(file.Header.GlInternalFormat))
            {
                var decoder     = GetRawDecoder(file.Header.GlInternalFormat);
                var data        = file.MipMaps[0].Faces[0].Data;
                var pixelWidth  = file.MipMaps[0].Width;
                var pixelHeight = file.MipMaps[0].Height;

                var image  = new Image <Rgba32>((int)pixelWidth, (int)pixelHeight);
                var output = decoder.Decode(data, (int)pixelWidth, (int)pixelHeight);
                var pixels = image.GetPixelSpan();

                output.CopyTo(pixels);
                return(image);
            }
            else
            {
                var decoder = GetDecoder(file.Header.GlInternalFormat);
                if (decoder == null)
                {
                    throw new NotSupportedException($"This format is not supported: {file.Header.GlInternalFormat}");
                }

                var data        = file.MipMaps[0].Faces[0].Data;
                var pixelWidth  = file.MipMaps[0].Width;
                var pixelHeight = file.MipMaps[0].Height;

                var blocks = decoder.Decode(data, (int)pixelWidth, (int)pixelHeight, out var blockWidth, out var blockHeight);

                return(ImageToBlocks.ImageFromRawBlocks(blocks, blockWidth, blockHeight,
                                                        (int)pixelWidth, (int)pixelHeight));
            }
        }
Пример #2
0
        public static float DecodeCheckPSNR(string filename, Image <Rgba32> original)
        {
            using FileStream fs = File.OpenRead(filename);
            var ktx     = KtxFile.Load(fs);
            var decoder = new BcDecoder();

            using var img = decoder.Decode(ktx);
            var pixels  = original.GetPixelSpan();
            var pixels2 = img.GetPixelSpan();

            return(ImageQuality.PeakSignalToNoiseRatio(pixels, pixels2, true));
        }
Пример #3
0
 /// <summary>
 /// Encodes all mipmap levels into a ktx or a dds file and writes it to the output stream.
 /// </summary>
 public void Encode(Image <Rgba32> inputImage, Stream outputStream)
 {
     if (OutputOptions.fileFormat == OutputFileFormat.Ktx)
     {
         KtxFile output = EncodeToKtx(inputImage);
         output.Write(outputStream);
     }
     else if (OutputOptions.fileFormat == OutputFileFormat.Dds)
     {
         DdsFile output = EncodeToDds(inputImage);
         output.Write(outputStream);
     }
 }
Пример #4
0
 /// <summary>
 /// Encodes all cubemap faces and mipmap levels into Ktx file and writes it to the output stream.
 /// Order is +X, -X, +Y, -Y, +Z, -Z
 /// </summary>
 public void EncodeCubeMap(Image <Rgba32> right, Image <Rgba32> left, Image <Rgba32> top, Image <Rgba32> down,
                           Image <Rgba32> back, Image <Rgba32> front, Stream outputStream)
 {
     if (OutputOptions.fileFormat == OutputFileFormat.Ktx)
     {
         KtxFile output = EncodeCubeMapToKtx(right, left, top, down, back, front);
         output.Write(outputStream);
     }
     else if (OutputOptions.fileFormat == OutputFileFormat.Dds)
     {
         DdsFile output = EncodeCubeMapToDds(right, left, top, down, back, front);
         output.Write(outputStream);
     }
 }
Пример #5
0
        public ImageInfo Load(Stream input)
        {
            // Load Ktx file
            var ktxFile = KtxFile.Load(input);

            // Prepare main image data
            var imageData   = ktxFile.MipMaps[0].Faces[0].Data;
            var imageFormat = (int)ktxFile.header.GlInternalFormat;
            var size        = new Size((int)ktxFile.header.PixelWidth, (int)ktxFile.header.PixelHeight);

            // Prepare mip maps
            return(new ImageInfo(imageData, imageFormat, size)
            {
                MipMapData = ktxFile.MipMaps.Skip(1).Select(x => x.Faces[0].Data).ToArray()
            });
        }
Пример #6
0
        /// <summary>
        /// Read a Ktx or a Dds file from a stream and decode it.
        /// </summary>
        public Image <Rgba32>[] DecodeAllMipMaps(Stream inputStream)
        {
            var position = inputStream.Position;

            try {
                if (inputStream is FileStream fs)
                {
                    var extension = Path.GetExtension(fs.Name).ToLower();
                    if (extension == ".ktx")
                    {
                        KtxFile file = KtxFile.Load(inputStream);
                        return(DecodeAllMipMaps(file));
                    }
                    else if (extension == ".dds")
                    {
                        DdsFile file = DdsFile.Load(inputStream);
                        return(DecodeAllMipMaps(file));
                    }
                }

                bool isDDS = false;
                using (var br = new BinaryReader(inputStream, Encoding.UTF8, true)) {
                    var magic = br.ReadUInt32();
                    if (magic == 0x20534444U)
                    {
                        isDDS = true;
                    }
                }

                inputStream.Seek(position, SeekOrigin.Begin);

                if (isDDS)
                {
                    DdsFile dds = DdsFile.Load(inputStream);
                    return(DecodeAllMipMaps(dds));
                }
                else
                {
                    KtxFile ktx = KtxFile.Load(inputStream);
                    return(DecodeAllMipMaps(ktx));
                }
            }
            catch (Exception) {
                inputStream.Seek(position, SeekOrigin.Begin);
                throw;
            }
        }
Пример #7
0
        public void Save(Stream output, ImageInfo imageInfo)
        {
            // Create Ktx file
            var ktxHeader = CreateKtxHeader(imageInfo.ImageFormat, imageInfo.ImageSize);
            var ktxFile   = new KtxFile(ktxHeader);

            // Add main image to Ktx
            ktxFile.MipMaps.Add(CreateMipMap(imageInfo.ImageData, imageInfo.ImageSize));

            // Add mips to Ktx
            for (var i = 1; i <= imageInfo.MipMapCount; i++)
            {
                ktxFile.MipMaps.Add(CreateMipMap(imageInfo.MipMapData[i - 1], new Size(imageInfo.ImageSize.Width >> i, imageInfo.ImageSize.Height >> i)));
            }

            ktxFile.Write(output);
        }
Пример #8
0
        public void Bc4Decode()
        {
            using FileStream fs = File.OpenRead(@"../../../testImages/test_decompress_bc4_unorm.ktx");
            KtxFile file = KtxFile.Load(fs);

            Assert.True(file.Header.VerifyHeader());
            Assert.Equal((uint)1, file.Header.NumberOfFaces);

            BcDecoder decoder = new BcDecoder();

            using var image = decoder.Decode(file);

            Assert.Equal((uint)image.Width, file.Header.PixelWidth);
            Assert.Equal((uint)image.Height, file.Header.PixelHeight);

            using FileStream outFs = File.OpenWrite("decoding_test_bc4.png");
            image.SaveAsPng(outFs);
        }
Пример #9
0
        /// <summary>
        /// Encodes all mipmap levels into a Ktx file.
        /// </summary>
        public KtxFile EncodeToKtx(Image <Rgba32> inputImage)
        {
            KtxFile         output;
            IBcBlockEncoder compressedEncoder   = null;
            IRawEncoder     uncompressedEncoder = null;

            if (OutputOptions.format.IsCompressedFormat())
            {
                compressedEncoder = GetEncoder(OutputOptions.format);
                if (compressedEncoder == null)
                {
                    throw new NotSupportedException($"This format is not supported: {OutputOptions.format}");
                }
                output = new KtxFile(
                    KtxHeader.InitializeCompressed(inputImage.Width, inputImage.Height,
                                                   compressedEncoder.GetInternalFormat(),
                                                   compressedEncoder.GetBaseInternalFormat()));
            }
            else
            {
                uncompressedEncoder = GetRawEncoder(OutputOptions.format);
                output = new KtxFile(
                    KtxHeader.InitializeUncompressed(inputImage.Width, inputImage.Height,
                                                     uncompressedEncoder.GetGlType(),
                                                     uncompressedEncoder.GetGlFormat(),
                                                     uncompressedEncoder.GetGlTypeSize(),
                                                     uncompressedEncoder.GetInternalFormat(),
                                                     uncompressedEncoder.GetBaseInternalFormat()));
            }

            uint numMipMaps = (uint)OutputOptions.maxMipMapLevel;

            if (!OutputOptions.generateMipMaps)
            {
                numMipMaps = 1;
            }

            var mipChain = MipMapper.GenerateMipChain(inputImage, ref numMipMaps);

            for (int i = 0; i < numMipMaps; i++)
            {
                byte[] encoded = null;
                if (OutputOptions.format.IsCompressedFormat())
                {
                    var blocks = ImageToBlocks.ImageTo4X4(mipChain[i].Frames[0], out int blocksWidth, out int blocksHeight);
                    encoded = compressedEncoder.Encode(blocks, blocksWidth, blocksHeight, OutputOptions.quality,
                                                       !Debugger.IsAttached && Options.multiThreaded);
                }
                else
                {
                    encoded = uncompressedEncoder.Encode(mipChain[i].GetPixelSpan());
                }

                output.MipMaps.Add(new KtxMipmap((uint)encoded.Length,
                                                 (uint)inputImage.Width,
                                                 (uint)inputImage.Height, 1));
                output.MipMaps[i].Faces[0] = new KtxMipFace(encoded,
                                                            (uint)inputImage.Width,
                                                            (uint)inputImage.Height);
            }

            foreach (var image in mipChain)
            {
                image.Dispose();
            }

            output.Header.NumberOfFaces        = 1;
            output.Header.NumberOfMipmapLevels = numMipMaps;

            return(output);
        }
Пример #10
0
        protected override void CreateResources(ResourceFactory factory)
        {
            _vertexLayout = new VertexLayoutDescription(
                new VertexElementDescription("Position", VertexElementSemantic.Position, VertexElementFormat.Float3),
                new VertexElementDescription("UV", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float2),
                new VertexElementDescription("Color", VertexElementSemantic.Color, VertexElementFormat.Float3),
                new VertexElementDescription("Normal", VertexElementSemantic.Normal, VertexElementFormat.Float3));

            using (Stream planeModelStream = OpenEmbeddedAssetStream("plane2.dae"))
            {
                _planeModel = new Model(
                    GraphicsDevice,
                    factory,
                    planeModelStream,
                    "dae",
                    _vertexLayout,
                    new Model.ModelCreateInfo(new Vector3(0.5f, 0.5f, 0.5f), Vector2.One, Vector3.Zero));
            }

            using (Stream dragonModelStream = OpenEmbeddedAssetStream("chinesedragon.dae"))
            {
                _dragonModel = new Model(
                    GraphicsDevice,
                    factory,
                    dragonModelStream,
                    "dae",
                    _vertexLayout,
                    new Model.ModelCreateInfo(new Vector3(0.3f, -0.3f, 0.3f), Vector2.One, Vector3.Zero));
            }

            using (Stream colorMapStream = OpenEmbeddedAssetStream("darkmetal_bc3_unorm.ktx"))
            {
                _colorMap = KtxFile.LoadTexture(
                    GraphicsDevice,
                    factory,
                    colorMapStream,
                    PixelFormat.BC3_UNorm);
            }
            _colorView = factory.CreateTextureView(_colorMap);

            _offscreenColor = factory.CreateTexture(TextureDescription.Texture2D(
                                                        OffscreenWidth, OffscreenHeight, 1, 1,
                                                        PixelFormat.R8_G8_B8_A8_UNorm, TextureUsage.RenderTarget | TextureUsage.Sampled));
            _offscreenView = factory.CreateTextureView(_offscreenColor);
            Texture offscreenDepth = factory.CreateTexture(TextureDescription.Texture2D(
                                                               OffscreenWidth, OffscreenHeight, 1, 1, PixelFormat.R16_UNorm, TextureUsage.DepthStencil));

            _offscreenFB = factory.CreateFramebuffer(new FramebufferDescription(offscreenDepth, _offscreenColor));

            ShaderSetDescription phongShaders = new ShaderSetDescription(
                new[] { _vertexLayout },
                new[]
            {
                LoadShader(factory, "Phong", ShaderStages.Vertex, "VS"),
                LoadShader(factory, "Phong", ShaderStages.Fragment, "FS")
            });

            ResourceLayout phongLayout = factory.CreateResourceLayout(new ResourceLayoutDescription(
                                                                          new ResourceLayoutElementDescription("UBO", ResourceKind.UniformBuffer, ShaderStages.Vertex)));

            GraphicsPipelineDescription pd = new GraphicsPipelineDescription(
                BlendStateDescription.SingleOverrideBlend,
                DepthStencilStateDescription.DepthOnlyLessEqual,
                new RasterizerStateDescription(FaceCullMode.Front, PolygonFillMode.Solid, FrontFace.Clockwise, true, false),
                PrimitiveTopology.TriangleList,
                phongShaders,
                phongLayout,
                _offscreenFB.OutputDescription);

            _offscreenPipeline = factory.CreateGraphicsPipeline(pd);

            pd.Outputs         = GraphicsDevice.SwapchainFramebuffer.OutputDescription;
            pd.RasterizerState = RasterizerStateDescription.Default;
            _dragonPipeline    = factory.CreateGraphicsPipeline(pd);

            ResourceLayout mirrorLayout = factory.CreateResourceLayout(new ResourceLayoutDescription(
                                                                           new ResourceLayoutElementDescription("UBO", ResourceKind.UniformBuffer, ShaderStages.Vertex),
                                                                           new ResourceLayoutElementDescription("ReflectionMap", ResourceKind.TextureReadOnly, ShaderStages.Fragment),
                                                                           new ResourceLayoutElementDescription("ReflectionMapSampler", ResourceKind.Sampler, ShaderStages.Fragment),
                                                                           new ResourceLayoutElementDescription("ColorMap", ResourceKind.TextureReadOnly, ShaderStages.Fragment),
                                                                           new ResourceLayoutElementDescription("ColorMapSampler", ResourceKind.Sampler, ShaderStages.Fragment)));

            ShaderSetDescription mirrorShaders = new ShaderSetDescription(
                new[] { _vertexLayout },
                new[]
            {
                LoadShader(factory, "Mirror", ShaderStages.Vertex, "VS"),
                LoadShader(factory, "Mirror", ShaderStages.Fragment, "FS")
            });

            GraphicsPipelineDescription mirrorPD = new GraphicsPipelineDescription(
                BlendStateDescription.SingleOverrideBlend,
                DepthStencilStateDescription.DepthOnlyLessEqual,
                new RasterizerStateDescription(FaceCullMode.None, PolygonFillMode.Solid, FrontFace.Clockwise, true, false),
                PrimitiveTopology.TriangleList,
                mirrorShaders,
                mirrorLayout,
                GraphicsDevice.SwapchainFramebuffer.OutputDescription);

            _mirrorPipeline = factory.CreateGraphicsPipeline(ref mirrorPD);

            _uniformBuffers_vsShared    = factory.CreateBuffer(new BufferDescription(208, BufferUsage.UniformBuffer | BufferUsage.Dynamic));
            _uniformBuffers_vsMirror    = factory.CreateBuffer(new BufferDescription(208, BufferUsage.UniformBuffer | BufferUsage.Dynamic));
            _uniformBuffers_vsOffScreen = factory.CreateBuffer(new BufferDescription(208, BufferUsage.UniformBuffer | BufferUsage.Dynamic));

            _offscreenResourceSet = factory.CreateResourceSet(new ResourceSetDescription(phongLayout, _uniformBuffers_vsOffScreen));
            _dragonResourceSet    = factory.CreateResourceSet(new ResourceSetDescription(phongLayout, _uniformBuffers_vsShared));
            _mirrorResourceSet    = factory.CreateResourceSet(new ResourceSetDescription(mirrorLayout,
                                                                                         _uniformBuffers_vsMirror,
                                                                                         _offscreenView,
                                                                                         GraphicsDevice.LinearSampler,
                                                                                         _colorView,
                                                                                         GraphicsDevice.Aniso4xSampler));

            _cl = factory.CreateCommandList();
        }
Пример #11
0
 public void LoadFromStream(Stream file)
 {
     tex2D = KtxFile.Load(file, false);
 }
Пример #12
0
        private void TransferDataKtx(KtxFile tex2D)
        {
            using CommandBuffer copyCmd = device.GetCommandPool().Rent();

            VkMemoryAllocateInfo memAllocInfo = Initializers.memoryAllocateInfo();
            VkMemoryRequirements memReqs;

            copyCmd.Begin();

            // Create a host-visible staging buffer that contains the raw image data
            VkBuffer       stagingBuffer;
            VkDeviceMemory stagingMemory;

            VkBufferCreateInfo bufferCreateInfo = Initializers.bufferCreateInfo();

            bufferCreateInfo.size = tex2D.GetTotalSize();
            // This buffer is used as a transfer source for the buffer copy
            bufferCreateInfo.usage       = VkBufferUsageFlags.TransferSrc;
            bufferCreateInfo.sharingMode = VkSharingMode.Exclusive;

            Util.CheckResult(vkCreateBuffer(device.device, &bufferCreateInfo, null, &stagingBuffer));

            // Get memory requirements for the staging buffer (alignment, memory type bits)
            vkGetBufferMemoryRequirements(device.device, stagingBuffer, &memReqs);

            memAllocInfo.allocationSize = memReqs.size;
            // Get memory type index for a host visible buffer
            memAllocInfo.memoryTypeIndex = device.vulkanDevice.getMemoryType(memReqs.memoryTypeBits, VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent);

            Util.CheckResult(vkAllocateMemory(device.device, &memAllocInfo, null, &stagingMemory));
            Util.CheckResult(vkBindBufferMemory(device.device, stagingBuffer, stagingMemory, 0));

            // Copy texture data into staging buffer
            byte *data;

            Util.CheckResult(vkMapMemory(device.device, stagingMemory, 0, memReqs.size, 0, (void **)&data));
            byte[] pixelData = tex2D.GetAllTextureData();
            fixed(byte *pixelDataPtr = &pixelData[0])
            {
                Unsafe.CopyBlock(data, pixelDataPtr, (uint)pixelData.Length);
            }

            vkUnmapMemory(device.device, stagingMemory);

            // Setup buffer copy regions for each mip level
            using NativeList <VkBufferImageCopy> bufferCopyRegions = new NativeList <VkBufferImageCopy>();
            uint offset = 0;

            for (uint i = 0; i < mipLevels; i++)
            {
                VkBufferImageCopy bufferCopyRegion = new VkBufferImageCopy();
                bufferCopyRegion.imageSubresource.aspectMask     = VkImageAspectFlags.Color;
                bufferCopyRegion.imageSubresource.mipLevel       = i;
                bufferCopyRegion.imageSubresource.baseArrayLayer = 0;
                bufferCopyRegion.imageSubresource.layerCount     = 1;
                bufferCopyRegion.imageExtent.width  = tex2D.Faces[0].Mipmaps[i].Width;
                bufferCopyRegion.imageExtent.height = tex2D.Faces[0].Mipmaps[i].Height;
                bufferCopyRegion.imageExtent.depth  = 1;
                bufferCopyRegion.bufferOffset       = offset;

                bufferCopyRegions.Add(bufferCopyRegion);

                offset += tex2D.Faces[0].Mipmaps[i].SizeInBytes;
            }

            VkImageSubresourceRange subresourceRange = new VkImageSubresourceRange();

            subresourceRange.aspectMask   = VkImageAspectFlags.Color;
            subresourceRange.baseMipLevel = 0;
            subresourceRange.levelCount   = mipLevels;
            subresourceRange.layerCount   = 1;

            // Image barrier for optimal image (target)
            // Optimal image will be used as destination for the copy
            Tools.setImageLayout(
                copyCmd.vkCmd,
                image,
                VkImageAspectFlags.Color,
                VkImageLayout.Undefined,
                VkImageLayout.TransferDstOptimal,
                subresourceRange);

            // Copy mip levels from staging buffer
            vkCmdCopyBufferToImage(
                copyCmd.vkCmd,
                stagingBuffer,
                image,
                VkImageLayout.TransferDstOptimal,
                bufferCopyRegions.Count,
                bufferCopyRegions.Data);

            // Change texture image layout to shader read after all mip levels have been copied
            Tools.setImageLayout(
                copyCmd.vkCmd,
                image,
                VkImageAspectFlags.Color,
                VkImageLayout.TransferDstOptimal,
                imageLayout,
                subresourceRange);

            copyCmd.End();
            device.FlushCommandBuffer(copyCmd);

            //device.flushCommandBuffer(copyCmd, copyQueue);

            // Clean up staging resources
            vkFreeMemory(device.device, stagingMemory, null);
            vkDestroyBuffer(device.device, stagingBuffer, null);
        }
        protected override void CreateResources(ResourceFactory factory)
        {
            _projectionBuffer = factory.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer | BufferUsage.Dynamic));
            _viewBuffer       = factory.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer | BufferUsage.Dynamic));
            _worldBuffer      = factory.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer | BufferUsage.Dynamic));
            Matrix4x4 worldMatrix =
                Matrix4x4.CreateTranslation(0, 15000, -5000)
                * Matrix4x4.CreateRotationX(3 * (float)Math.PI / 2)
                * Matrix4x4.CreateScale(0.05f);

            GraphicsDevice.UpdateBuffer(_worldBuffer, 0, ref worldMatrix);

            ResourceLayout layout = factory.CreateResourceLayout(new ResourceLayoutDescription(
                                                                     new ResourceLayoutElementDescription("Projection", ResourceKind.UniformBuffer, ShaderStages.Vertex),
                                                                     new ResourceLayoutElementDescription("View", ResourceKind.UniformBuffer, ShaderStages.Vertex),
                                                                     new ResourceLayoutElementDescription("World", ResourceKind.UniformBuffer, ShaderStages.Vertex),
                                                                     new ResourceLayoutElementDescription("Bones", ResourceKind.UniformBuffer, ShaderStages.Vertex),
                                                                     new ResourceLayoutElementDescription("SurfaceTex", ResourceKind.TextureReadOnly, ShaderStages.Fragment),
                                                                     new ResourceLayoutElementDescription("SurfaceSampler", ResourceKind.Sampler, ShaderStages.Fragment)));

            Texture texture;

            using (Stream ktxStream = OpenEmbeddedAssetStream("goblin_bc3_unorm.ktx"))
            {
                texture = KtxFile.LoadTexture(
                    GraphicsDevice,
                    factory,
                    ktxStream,
                    PixelFormat.BC3_UNorm);
            }
            _texView = ResourceFactory.CreateTextureView(texture);

            VertexLayoutDescription vertexLayouts = new VertexLayoutDescription(
                new[]
            {
                new VertexElementDescription("Position", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float3),
                new VertexElementDescription("UV", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float2),
                new VertexElementDescription("BoneWeights", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float4),
                new VertexElementDescription("BoneIndices", VertexElementSemantic.TextureCoordinate, VertexElementFormat.UInt4),
            });

            GraphicsPipelineDescription gpd = new GraphicsPipelineDescription(
                BlendStateDescription.SingleOverrideBlend,
                DepthStencilStateDescription.DepthOnlyLessEqual,
                new RasterizerStateDescription(FaceCullMode.Back, PolygonFillMode.Solid, FrontFace.CounterClockwise, true, false),
                PrimitiveTopology.TriangleList,
                new ShaderSetDescription(
                    new[] { vertexLayouts },
                    factory.CreateFromSpirv(
                        new ShaderDescription(ShaderStages.Vertex, Encoding.UTF8.GetBytes(VertexCode), "main"),
                        new ShaderDescription(ShaderStages.Fragment, Encoding.UTF8.GetBytes(FragmentCode), "main"))),
                layout,
                GraphicsDevice.SwapchainFramebuffer.OutputDescription);

            _pipeline = factory.CreateGraphicsPipeline(ref gpd);

            AssimpContext ac = new AssimpContext();

            using (Stream modelStream = OpenEmbeddedAssetStream("goblin.dae"))
            {
                _scene = ac.ImportFileFromStream(modelStream, "dae");
            }
            _rootNodeInverseTransform = _scene.RootNode.Transform;
            _rootNodeInverseTransform.Inverse();

            _firstMesh = _scene.Meshes[0];
            AnimatedVertex[] vertices = new AnimatedVertex[_firstMesh.VertexCount];
            for (int i = 0; i < vertices.Length; i++)
            {
                vertices[i].Position = new Vector3(_firstMesh.Vertices[i].X, _firstMesh.Vertices[i].Y, _firstMesh.Vertices[i].Z);
                vertices[i].UV       = new Vector2(_firstMesh.TextureCoordinateChannels[0][i].X, _firstMesh.TextureCoordinateChannels[0][i].Y);
            }

            _animation = _scene.Animations[0];

            List <int> indices = new List <int>();

            foreach (Face face in _firstMesh.Faces)
            {
                if (face.IndexCount == 3)
                {
                    indices.Add(face.Indices[0]);
                    indices.Add(face.Indices[1]);
                    indices.Add(face.Indices[2]);
                }
            }

            for (uint boneID = 0; boneID < _firstMesh.BoneCount; boneID++)
            {
                Bone bone = _firstMesh.Bones[(int)boneID];
                _boneIDsByName.Add(bone.Name, boneID);
                foreach (VertexWeight weight in bone.VertexWeights)
                {
                    vertices[weight.VertexID].AddBone(boneID, weight.Weight);
                }
            }
            Array.Resize(ref _boneTransformations, _firstMesh.BoneCount);

            _bonesBuffer = ResourceFactory.CreateBuffer(new BufferDescription(
                                                            64 * 64, BufferUsage.UniformBuffer | BufferUsage.Dynamic));

            _rs = factory.CreateResourceSet(new ResourceSetDescription(layout,
                                                                       _projectionBuffer, _viewBuffer, _worldBuffer, _bonesBuffer, _texView, GraphicsDevice.Aniso4xSampler));

            _indexCount = (uint)indices.Count;

            _vertexBuffer = ResourceFactory.CreateBuffer(new BufferDescription(
                                                             (uint)(vertices.Length * Unsafe.SizeOf <AnimatedVertex>()), BufferUsage.VertexBuffer));
            GraphicsDevice.UpdateBuffer(_vertexBuffer, 0, vertices);

            _indexBuffer = ResourceFactory.CreateBuffer(new BufferDescription(
                                                            _indexCount * 4, BufferUsage.IndexBuffer));
            GraphicsDevice.UpdateBuffer(_indexBuffer, 0, indices.ToArray());

            _cl = factory.CreateCommandList();
            _camera.Position    = new Vector3(110, -87, -532);
            _camera.Yaw         = 0.45f;
            _camera.Pitch       = -0.55f;
            _camera.MoveSpeed   = 1000f;
            _camera.FarDistance = 100000;
        }
        protected override void CreateResources(ResourceFactory factory)
        {
            _instanceCount = 8000u;

            _camera.Position = new Vector3(-36f, 20f, 100f);
            _camera.Pitch    = -0.3f;
            _camera.Yaw      = 0.1f;

            _cameraProjViewBuffer = factory.CreateBuffer(
                new BufferDescription((uint)(Unsafe.SizeOf <Matrix4x4>() * 2), BufferUsage.UniformBuffer | BufferUsage.Dynamic));
            _lightInfoBuffer    = factory.CreateBuffer(new BufferDescription(32, BufferUsage.UniformBuffer | BufferUsage.Dynamic));
            _rotationInfoBuffer = factory.CreateBuffer(new BufferDescription(16, BufferUsage.UniformBuffer | BufferUsage.Dynamic));
            _lightDir           = Vector3.Normalize(new Vector3(0.3f, -0.75f, -0.3f));

            VertexLayoutDescription sharedVertexLayout = new VertexLayoutDescription(
                new VertexElementDescription("Position", VertexElementSemantic.Position, VertexElementFormat.Float3),
                new VertexElementDescription("Normal", VertexElementSemantic.Normal, VertexElementFormat.Float3),
                new VertexElementDescription("TexCoord", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float2));

            bool etc2Supported = GraphicsDevice.GetPixelFormatSupport(
                PixelFormat.ETC2_R8_G8_B8_UNorm,
                TextureType.Texture2D,
                TextureUsage.Sampled);
            PixelFormat pixelFormat = etc2Supported ? PixelFormat.ETC2_R8_G8_B8_UNorm : PixelFormat.BC3_UNorm;

            byte[] rockTextureData = LoadEmbeddedAsset <byte[]>(
                etc2Supported
                    ? "texturearray_rocks_etc2_unorm.binary"
                    : "texturearray_rocks_bc3_unorm.binary");
            Texture rockTexture = KtxFile.LoadTexture(
                GraphicsDevice,
                ResourceFactory,
                rockTextureData,
                pixelFormat);
            TextureView rockTextureView = ResourceFactory.CreateTextureView(rockTexture);

            ResourceLayoutElementDescription[] resourceLayoutElementDescriptions =
            {
                new ResourceLayoutElementDescription("ProjView",     ResourceKind.UniformBuffer, ShaderStages.Vertex),
                new ResourceLayoutElementDescription("RotationInfo", ResourceKind.UniformBuffer, ShaderStages.Vertex),
                new ResourceLayoutElementDescription("LightInfo",    ResourceKind.UniformBuffer, ShaderStages.Fragment),
            };
            ResourceLayoutDescription resourceLayoutDescription = new ResourceLayoutDescription(resourceLayoutElementDescriptions);
            ResourceLayout            sharedLayout = factory.CreateResourceLayout(resourceLayoutDescription);

            ResourceLayoutElementDescription[] textureLayoutDescriptions =
            {
                new ResourceLayoutElementDescription("Tex",  ResourceKind.TextureReadOnly, ShaderStages.Fragment),
                new ResourceLayoutElementDescription("Samp", ResourceKind.Sampler,         ShaderStages.Fragment)
            };
            ResourceLayout textureLayout = factory.CreateResourceLayout(new ResourceLayoutDescription(textureLayoutDescriptions));

            BindableResource[]     bindableResources      = new BindableResource[] { _cameraProjViewBuffer, _rotationInfoBuffer, _lightInfoBuffer };
            ResourceSetDescription resourceSetDescription = new ResourceSetDescription(sharedLayout, bindableResources);

            _sharedResourceSet = factory.CreateResourceSet(resourceSetDescription);

            BindableResource[] instanceBindableResources = { rockTextureView, GraphicsDevice.LinearSampler };
            _instanceTextureSet = factory.CreateResourceSet(new ResourceSetDescription(textureLayout, instanceBindableResources));

            ProcessedModel rock = LoadEmbeddedAsset <ProcessedModel>("rock01.binary");

            _rockModel = rock.MeshParts[0].CreateDeviceResources(GraphicsDevice, ResourceFactory);

            VertexLayoutDescription vertexLayoutPerInstance = new VertexLayoutDescription(
                new VertexElementDescription("InstancePosition", VertexElementSemantic.Position, VertexElementFormat.Float3),
                new VertexElementDescription("InstanceRotation", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float3),
                new VertexElementDescription("InstanceScale", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float3),
                new VertexElementDescription("InstanceTexArrayIndex", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Int1));

            vertexLayoutPerInstance.InstanceStepRate = 1;
            _instanceVB = ResourceFactory.CreateBuffer(new BufferDescription(InstanceInfo.Size * _instanceCount, BufferUsage.VertexBuffer));
            InstanceInfo[] infos         = new InstanceInfo[_instanceCount];
            Random         r             = new Random();
            float          orbitDistance = 50f;

            for (uint i = 0; i < _instanceCount / 2; i++)
            {
                float angle = (float)(r.NextDouble() * Math.PI * 2);
                infos[i] = new InstanceInfo(
                    new Vector3(
                        ((float)Math.Cos(angle) * orbitDistance) + (float)(-10 + r.NextDouble() * 20),
                        (float)(-1.5 + r.NextDouble() * 3),
                        ((float)Math.Sin(angle) * orbitDistance) + (float)(-10 + r.NextDouble() * 20)),
                    new Vector3(
                        (float)(r.NextDouble() * Math.PI * 2),
                        (float)(r.NextDouble() * Math.PI * 2),
                        (float)(r.NextDouble() * Math.PI * 2)),
                    new Vector3((float)(0.65 + r.NextDouble() * 0.35)),
                    r.Next(0, (int)rockTexture.ArrayLayers));
            }

            orbitDistance = 100f;
            for (uint i = _instanceCount / 2; i < _instanceCount; i++)
            {
                float angle = (float)(r.NextDouble() * Math.PI * 2);
                infos[i] = new InstanceInfo(
                    new Vector3(
                        ((float)Math.Cos(angle) * orbitDistance) + (float)(-10 + r.NextDouble() * 20),
                        (float)(-1.5 + r.NextDouble() * 3),
                        ((float)Math.Sin(angle) * orbitDistance) + (float)(-10 + r.NextDouble() * 20)),
                    new Vector3(
                        (float)(r.NextDouble() * Math.PI * 2),
                        (float)(r.NextDouble() * Math.PI * 2),
                        (float)(r.NextDouble() * Math.PI * 2)),
                    new Vector3((float)(0.65 + r.NextDouble() * 0.35)),
                    r.Next(0, (int)rockTexture.ArrayLayers));
            }

            GraphicsDevice.UpdateBuffer(_instanceVB, 0, infos);

            Shader instanceVS = LoadShader(ResourceFactory, "Instance", ShaderStages.Vertex, "VS");
            Shader instanceFS = LoadShader(ResourceFactory, "Instance", ShaderStages.Fragment, "FS");

            GraphicsPipelineDescription pipelineDescription = new GraphicsPipelineDescription()
            {
                BlendState        = BlendStateDescription.SingleOverrideBlend,
                DepthStencilState = new DepthStencilStateDescription(
                    depthTestEnabled: true,
                    depthWriteEnabled: true,
                    comparisonKind: ComparisonKind.LessEqual),
                RasterizerState = new RasterizerStateDescription(
                    cullMode: FaceCullMode.Back,
                    fillMode: PolygonFillMode.Solid,
                    frontFace: FrontFace.Clockwise,
                    depthClipEnabled: true,
                    scissorTestEnabled: false
                    ),
                PrimitiveTopology = PrimitiveTopology.TriangleList,
                ResourceLayouts   = new ResourceLayout[] { sharedLayout, textureLayout },
                ShaderSet         = new ShaderSetDescription(
                    // The ordering of layouts directly impacts shader layout schemes
                    vertexLayouts: new VertexLayoutDescription[] { sharedVertexLayout, vertexLayoutPerInstance },
                    shaders: new Shader[] { instanceVS, instanceFS }
                    ),
                Outputs = MainSwapchain.Framebuffer.OutputDescription
            };

            _instancePipeline = factory.CreateGraphicsPipeline(pipelineDescription);

            // Create planet Pipeline
            // Almost everything is the same as the rock Pipeline,
            // except no instance vertex buffer is needed, and different shaders are used.
            pipelineDescription.ShaderSet = new ShaderSetDescription(
                new[] { sharedVertexLayout },
                new[]
            {
                LoadShader(ResourceFactory, "Planet", ShaderStages.Vertex, "VS"),
                LoadShader(ResourceFactory, "Planet", ShaderStages.Fragment, "FS"),
            });
            _planetPipeline = ResourceFactory.CreateGraphicsPipeline(pipelineDescription);

            ProcessedModel planet = LoadEmbeddedAsset <ProcessedModel>("sphere.binary");

            _planetModel = planet.MeshParts[0].CreateDeviceResources(GraphicsDevice, ResourceFactory);

            byte[] planetTexData = LoadEmbeddedAsset <byte[]>(
                etc2Supported
                    ? "lavaplanet_etc2_unorm.binary"
                    : "lavaplanet_bc3_unorm.binary");
            Texture     planetTexture     = KtxFile.LoadTexture(GraphicsDevice, ResourceFactory, planetTexData, pixelFormat);
            TextureView planetTextureView = ResourceFactory.CreateTextureView(planetTexture);

            _planetTextureSet = ResourceFactory.CreateResourceSet(new ResourceSetDescription(textureLayout, planetTextureView, GraphicsDevice.Aniso4xSampler));

            // Starfield resources
            ResourceLayout invCameraInfoLayout = ResourceFactory.CreateResourceLayout(new ResourceLayoutDescription(
                                                                                          new ResourceLayoutElementDescription("InvCameraInfo", ResourceKind.UniformBuffer, ShaderStages.Fragment)));

            _viewInfoBuffer = ResourceFactory.CreateBuffer(new BufferDescription((uint)Unsafe.SizeOf <InvCameraInfo>(), BufferUsage.UniformBuffer | BufferUsage.Dynamic));
            _viewInfoSet    = ResourceFactory.CreateResourceSet(new ResourceSetDescription(invCameraInfoLayout, _viewInfoBuffer));

            ShaderSetDescription starfieldShaders = new ShaderSetDescription(
                Array.Empty <VertexLayoutDescription>(),
                new[]
            {
                LoadShader(ResourceFactory, "Starfield", ShaderStages.Vertex, "VS"),
                LoadShader(ResourceFactory, "Starfield", ShaderStages.Fragment, "FS"),
            });

            _starfieldPipeline = ResourceFactory.CreateGraphicsPipeline(new GraphicsPipelineDescription(
                                                                            BlendStateDescription.SingleOverrideBlend,
                                                                            DepthStencilStateDescription.Disabled,
                                                                            RasterizerStateDescription.CullNone,
                                                                            PrimitiveTopology.TriangleList,
                                                                            starfieldShaders,
                                                                            new[] { invCameraInfoLayout },
                                                                            MainSwapchain.Framebuffer.OutputDescription));

            _commandList = factory.CreateCommandList();
        }
Пример #15
0
        protected override void CreateResources(ResourceFactory factory)
        {
            _instanceCount = 1 << 14;

            _camera.Position = new Vector3(-36f, 20f, 100f);
            _camera.Pitch    = -0.3f;
            _camera.Yaw      = 0.1f;

            _cameraProjViewBuffer = factory.CreateBuffer(
                new BufferDescription((uint)(Unsafe.SizeOf <Matrix4x4>() * 2), BufferUsage.UniformBuffer | BufferUsage.Dynamic));
            _lightInfoBuffer    = factory.CreateBuffer(new BufferDescription(32, BufferUsage.UniformBuffer | BufferUsage.Dynamic));
            _rotationInfoBuffer = factory.CreateBuffer(new BufferDescription(16, BufferUsage.UniformBuffer | BufferUsage.Dynamic));
            _lightDir           = Vector3.Normalize(new Vector3(0.3f, -0.75f, -0.3f));

            VertexLayoutDescription sharedVertexLayout = new VertexLayoutDescription(
                new VertexElementDescription("Position", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float3),
                new VertexElementDescription("Normal", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float3),
                new VertexElementDescription("TexCoord", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float2));

            bool etc2Supported = GraphicsDevice.GetPixelFormatSupport(
                PixelFormat.ETC2_R8_G8_B8_UNorm,
                TextureType.Texture2D,
                TextureUsage.Sampled);
            PixelFormat pixelFormat = etc2Supported ? PixelFormat.ETC2_R8_G8_B8_UNorm : PixelFormat.BC3_UNorm;

            byte[] rockTextureData = LoadEmbeddedAsset <byte[]>(
                etc2Supported
                    ? "texturearray_rocks_etc2_unorm.binary"
                    : "texturearray_rocks_bc3_unorm.binary");
            Texture rockTexture = KtxFile.LoadTexture(
                GraphicsDevice,
                ResourceFactory,
                rockTextureData,
                pixelFormat);
            TextureView rockTextureView = ResourceFactory.CreateTextureView(rockTexture);

            ResourceLayoutElementDescription[] resourceLayoutElementDescriptions =
            {
                new ResourceLayoutElementDescription("LightInfo",    ResourceKind.UniformBuffer, ShaderStages.Fragment),
                new ResourceLayoutElementDescription("ProjView",     ResourceKind.UniformBuffer, ShaderStages.Vertex),
                new ResourceLayoutElementDescription("RotationInfo", ResourceKind.UniformBuffer, ShaderStages.Vertex),
            };
            ResourceLayoutDescription resourceLayoutDescription = new ResourceLayoutDescription(resourceLayoutElementDescriptions);
            ResourceLayout            sharedLayout = factory.CreateResourceLayout(resourceLayoutDescription);

            ResourceLayoutElementDescription[] textureLayoutDescriptions =
            {
                new ResourceLayoutElementDescription("Tex",  ResourceKind.TextureReadOnly, ShaderStages.Fragment),
                new ResourceLayoutElementDescription("Samp", ResourceKind.Sampler,         ShaderStages.Fragment)
            };
            ResourceLayout textureLayout = factory.CreateResourceLayout(new ResourceLayoutDescription(textureLayoutDescriptions));

            BindableResource[]     bindableResources      = new BindableResource[] { _lightInfoBuffer, _cameraProjViewBuffer, _rotationInfoBuffer };
            ResourceSetDescription resourceSetDescription = new ResourceSetDescription(sharedLayout, bindableResources);

            _sharedResourceSet = factory.CreateResourceSet(resourceSetDescription);

            BindableResource[] instanceBindableResources = { rockTextureView, GraphicsDevice.LinearSampler };
            _instanceTextureSet = factory.CreateResourceSet(new ResourceSetDescription(textureLayout, instanceBindableResources));

            ProcessedModel rock = LoadEmbeddedAsset <ProcessedModel>("sphere.binary");

            _rockModel = rock.MeshParts[0].CreateDeviceResources(GraphicsDevice, ResourceFactory);

            VertexLayoutDescription vertexLayoutPerInstancePos = new VertexLayoutDescription(
                new VertexElementDescription("InstancePosition", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float3));

            VertexLayoutDescription vertexLayoutPerInstanceScale = new VertexLayoutDescription(
                new VertexElementDescription("InstanceScale", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float3));

            VertexLayoutDescription vertexLayoutPerInstanceColor = new VertexLayoutDescription(
                new VertexElementDescription("InstanceColor", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float3));


            vertexLayoutPerInstancePos.InstanceStepRate   = 1;
            vertexLayoutPerInstanceScale.InstanceStepRate = 1;
            vertexLayoutPerInstanceColor.InstanceStepRate = 1;

            _instanceVBPos   = ResourceFactory.CreateBuffer(new BufferDescription(Vector3.Size * _instanceCount, BufferUsage.VertexBuffer));
            _instanceVBScale = ResourceFactory.CreateBuffer(new BufferDescription(Vector3.Size * _instanceCount, BufferUsage.VertexBuffer));
            _instanceVBColor = ResourceFactory.CreateBuffer(new BufferDescription(Vector3.Size * _instanceCount, BufferUsage.VertexBuffer));


            Vector3[] instancePos    = new Vector3[_instanceCount];
            Vector3[] instanceScale  = new Vector3[_instanceCount];
            Vector3[] instanceColors = new Vector3[_instanceCount];
            Random    r = new Random();

            for (uint i = 0; i < _instanceCount; i++)
            {
                instancePos[i] = new Vector3(
                    1000.0f * ((float)r.NextDouble() - 0.5f),
                    200.0f * ((float)r.NextDouble() - 0.5f),
                    1000.0f * ((float)r.NextDouble() - 0.5f));

                instanceScale[i] = new Vector3((float)(r.NextDouble() * 0.3));

                instanceColors[i] = new Vector3((float)r.NextDouble() * 0.5f + 0.5f,
                                                (float)r.NextDouble() * 0.5f + 0.5f,
                                                (float)r.NextDouble() * 0.5f + 0.5f);
            }


            GraphicsDevice.UpdateBuffer(_instanceVBPos, 0, instancePos);
            GraphicsDevice.UpdateBuffer(_instanceVBScale, 0, instanceScale);
            GraphicsDevice.UpdateBuffer(_instanceVBColor, 0, instanceColors);

            GraphicsPipelineDescription pipelineDescriptionRocks = new GraphicsPipelineDescription()
            {
                BlendState        = BlendStateDescription.SingleOverrideBlend,
                DepthStencilState = new DepthStencilStateDescription(
                    depthTestEnabled: true,
                    depthWriteEnabled: true,
                    comparisonKind: ComparisonKind.LessEqual),
                RasterizerState = new RasterizerStateDescription(
                    cullMode: FaceCullMode.Back,
                    fillMode: PolygonFillMode.Solid,
                    frontFace: FrontFace.Clockwise,
                    depthClipEnabled: true,
                    scissorTestEnabled: false
                    ),
                PrimitiveTopology = PrimitiveTopology.TriangleList,
                ResourceLayouts   = new ResourceLayout[] { sharedLayout, textureLayout },
                ShaderSet         = new ShaderSetDescription(
                    // The ordering of layouts directly impacts shader layout schemes
                    vertexLayouts: new VertexLayoutDescription[] { sharedVertexLayout, vertexLayoutPerInstancePos, vertexLayoutPerInstanceScale, vertexLayoutPerInstanceColor },
                    shaders: LoadShaders("Instance")
                    ),
                Outputs = MainSwapchain.Framebuffer.OutputDescription
            };

            _instancePipeline = factory.CreateGraphicsPipeline(pipelineDescriptionRocks);

            // Starfield resources
            ResourceLayout invCameraInfoLayout = ResourceFactory.CreateResourceLayout(new ResourceLayoutDescription(
                                                                                          new ResourceLayoutElementDescription("InvCameraInfo", ResourceKind.UniformBuffer, ShaderStages.Fragment)));

            _viewInfoBuffer = ResourceFactory.CreateBuffer(new BufferDescription((uint)Unsafe.SizeOf <MatrixPair>(), BufferUsage.UniformBuffer | BufferUsage.Dynamic));

            _commandList = factory.CreateCommandList();
        }
Пример #16
0
 public void Dispose()
 {
     tex2D = null;
 }
Пример #17
0
        /// <summary>
        /// Encodes all cubemap faces and mipmap levels into a Ktx file.
        /// Order is +X, -X, +Y, -Y, +Z, -Z. Back maps to positive Z and front to negative Z.
        /// </summary>
        public KtxFile EncodeCubeMapToKtx(Image <Rgba32> right, Image <Rgba32> left, Image <Rgba32> top, Image <Rgba32> down,
                                          Image <Rgba32> back, Image <Rgba32> front)
        {
            KtxFile         output;
            IBcBlockEncoder compressedEncoder   = null;
            IRawEncoder     uncompressedEncoder = null;

            if (right.Width != left.Width || right.Width != top.Width || right.Width != down.Width ||
                right.Width != back.Width || right.Width != front.Width ||
                right.Height != left.Height || right.Height != top.Height || right.Height != down.Height ||
                right.Height != back.Height || right.Height != front.Height)
            {
                throw new ArgumentException("All input images of a cubemap should be the same size.");
            }

            Image <Rgba32>[] faces = new[] { right, left, top, down, back, front };

            if (OutputOptions.format.IsCompressedFormat())
            {
                compressedEncoder = GetEncoder(OutputOptions.format);
                if (compressedEncoder == null)
                {
                    throw new NotSupportedException($"This format is not supported: {OutputOptions.format}");
                }
                output = new KtxFile(
                    KtxHeader.InitializeCompressed(right.Width, right.Height,
                                                   compressedEncoder.GetInternalFormat(),
                                                   compressedEncoder.GetBaseInternalFormat()));
            }
            else
            {
                uncompressedEncoder = GetRawEncoder(OutputOptions.format);
                output = new KtxFile(
                    KtxHeader.InitializeUncompressed(right.Width, right.Height,
                                                     uncompressedEncoder.GetGlType(),
                                                     uncompressedEncoder.GetGlFormat(),
                                                     uncompressedEncoder.GetGlTypeSize(),
                                                     uncompressedEncoder.GetInternalFormat(),
                                                     uncompressedEncoder.GetBaseInternalFormat()));
            }
            uint numMipMaps = (uint)OutputOptions.maxMipMapLevel;

            if (!OutputOptions.generateMipMaps)
            {
                numMipMaps = 1;
            }

            uint mipLength = MipMapper.CalculateMipChainLength(right.Width, right.Height, numMipMaps);

            for (uint i = 0; i < mipLength; i++)
            {
                output.MipMaps.Add(new KtxMipmap(0, 0, 0, (uint)faces.Length));
            }

            for (int f = 0; f < faces.Length; f++)
            {
                var mipChain = MipMapper.GenerateMipChain(faces[f], ref numMipMaps);

                for (int i = 0; i < numMipMaps; i++)
                {
                    byte[] encoded = null;
                    if (OutputOptions.format.IsCompressedFormat())
                    {
                        var blocks = ImageToBlocks.ImageTo4X4(mipChain[i].Frames[0], out int blocksWidth, out int blocksHeight);
                        encoded = compressedEncoder.Encode(blocks, blocksWidth, blocksHeight, OutputOptions.quality,
                                                           !Debugger.IsAttached && Options.multiThreaded);
                    }
                    else
                    {
                        encoded = uncompressedEncoder.Encode(mipChain[i].GetPixelSpan());
                    }

                    if (f == 0)
                    {
                        output.MipMaps[i] = new KtxMipmap((uint)encoded.Length,
                                                          (uint)mipChain[i].Width,
                                                          (uint)mipChain[i].Height, (uint)faces.Length);
                    }

                    output.MipMaps[i].Faces[f] = new KtxMipFace(encoded,
                                                                (uint)mipChain[i].Width,
                                                                (uint)mipChain[i].Height);
                }

                foreach (var image in mipChain)
                {
                    image.Dispose();
                }
            }

            output.Header.NumberOfFaces        = (uint)faces.Length;
            output.Header.NumberOfMipmapLevels = mipLength;

            return(output);
        }
Пример #18
0
        /**
         * Load a 2D texture including all mip levels
         *
         * @param filename File to load (supports .ktx and .dds)
         * @param format Vulkan format of the image data stored in the file
         * @param device Vulkan device to create the texture on
         * @param copyQueue Queue used for the texture staging copy commands (must support transfer)
         * @param (Optional) imageUsageFlags Usage flags for the texture's image (defaults to VK_IMAGE_USAGE_SAMPLED_BIT)
         * @param (Optional) imageLayout Usage layout for the texture (defaults VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
         * @param (Optional) forceLinear Force linear tiling (not advised, defaults to false)
         *
         */
        public void FromTextureAsset(
            TextureAsset asset,
            GraphicsDevice device,
            VkImageUsageFlags imageUsageFlags = VkImageUsageFlags.Sampled,
            VkImageLayout imageLayout         = VkImageLayout.ShaderReadOnlyOptimal)
        {
            VkFormat format = VkFormat.Undefined;

            KtxFile tex2D = asset.GetTexture();

            format = GlFormatToVulkanFormat.vkGetFormatFromOpenGLInternalFormat(tex2D.Header.GlInternalFormat, tex2D.Header.GlFormat, tex2D.Header.GlType);

            width  = tex2D.Header.PixelWidth;
            height = tex2D.Header.PixelHeight;
            if (height == 0)
            {
                height = width;
            }
            mipLevels = tex2D.Header.NumberOfMipmapLevels;

            this.imageLayout = imageLayout;
            this.format      = format;
            this.device      = device;

            // Get device properites for the requested texture format
            VkFormatProperties formatProperties;

            vkGetPhysicalDeviceFormatProperties(device.physicalDevice, format, out formatProperties);

            VkMemoryAllocateInfo memAllocInfo = Initializers.memoryAllocateInfo();
            VkMemoryRequirements memReqs;

            // Create optimal tiled target image
            VkImageCreateInfo imageCreateInfo = Initializers.imageCreateInfo();

            imageCreateInfo.imageType     = VkImageType.Image2D;
            imageCreateInfo.format        = format;
            imageCreateInfo.mipLevels     = mipLevels;
            imageCreateInfo.arrayLayers   = 1;
            imageCreateInfo.samples       = VkSampleCountFlags.Count1;
            imageCreateInfo.tiling        = VkImageTiling.Optimal;
            imageCreateInfo.sharingMode   = VkSharingMode.Exclusive;
            imageCreateInfo.initialLayout = VkImageLayout.Undefined;
            imageCreateInfo.extent        = new VkExtent3D {
                width = width, height = height, depth = 1
            };
            imageCreateInfo.usage = imageUsageFlags;
            // Ensure that the TRANSFER_DST bit is set for staging
            if ((imageCreateInfo.usage & VkImageUsageFlags.TransferDst) == 0)
            {
                imageCreateInfo.usage |= VkImageUsageFlags.TransferDst;
            }
            Util.CheckResult(vkCreateImage(device.device, &imageCreateInfo, null, out image));

            vkGetImageMemoryRequirements(device.device, image, &memReqs);

            memAllocInfo.allocationSize = memReqs.size;

            memory = device.memoryAllocator.Allocate(memReqs.size, memReqs.alignment, memReqs.memoryTypeBits, false);
            Util.CheckResult(vkBindImageMemory(device.device, image, memory.vkDeviceMemory, memory.offset));

            //memAllocInfo.memoryTypeIndex = device.vulkanDevice.getMemoryType(memReqs.memoryTypeBits, VkMemoryPropertyFlags.DeviceLocal);
            //Util.CheckResult(vkAllocateMemory(device.device, &memAllocInfo, null, out deviceMemory));
            //Util.CheckResult(vkBindImageMemory(device.device, image, deviceMemory, 0));

            TransferDataKtx(tex2D);

            CreateSampler();

            CreateView();

            // Update descriptor image info member that can be used for setting up descriptor sets
            UpdateDescriptor();
        }