private Texture2D LoadTexture(glTFLoader.Schema.Texture texture) { string path = "Assets/cache_" + texture.Name + ".png"; string sourceID = texture.Source; glTFLoader.Schema.Image image = m_model.Images[sourceID]; Bitmap bitmap = image.Uri; bitmap.Save(path); byte[] data = File.ReadAllBytes(path); Texture2D res = new Texture2D(2, 2); res.LoadImage(data); // auto resize string samplerID = texture.Sampler; Sampler sampler = m_model.Samplers[samplerID]; TextureWrapMode wrapS = s_wrapSMode[sampler.WrapS]; TextureWrapMode wrapT = s_wrapTMode[sampler.WrapT]; if (wrapS == wrapT) { res.wrapMode = wrapS; } else { throw new System.NotImplementedException("Texture wrap mode not supported"); } return(res); }
static byte[] loadDataUri (GL.Image img) { int idxComa = img.Uri.IndexOf (",", 5, StringComparison.Ordinal); return Convert.FromBase64String (img.Uri.Substring (idxComa + 1)); }
///// <summary> ///// build texture array ///// </summary> ///// <returns>The images.</returns> ///// <param name="textureSize">Uniformized Texture size for all images</param> public void BuildTexArray (ref Image texArray, uint firstImg = 0) { int texDim = (int)texArray.CreateInfo.extent.width; PrimaryCommandBuffer cmd = cmdPool.AllocateAndStart (VkCommandBufferUsageFlags.OneTimeSubmit); texArray.SetLayout (cmd, VkImageAspectFlags.Color, VkImageLayout.Undefined, VkImageLayout.TransferDstOptimal, VkPipelineStageFlags.BottomOfPipe, VkPipelineStageFlags.Transfer); transferQ.EndSubmitAndWait (cmd, true); VkImageBlit imageBlit = new VkImageBlit { srcSubresource = new VkImageSubresourceLayers (VkImageAspectFlags.Color, 1, 0), dstOffsets_1 = new VkOffset3D (texDim, texDim, 1) }; for (int l = 0; l < gltf.Images.Length; l++) { GL.Image img = gltf.Images[l]; Image vkimg = null; if (img.BufferView != null) {//load image from gltf buffer view GL.BufferView bv = gltf.BufferViews[(int)img.BufferView]; ensureBufferIsLoaded (bv.Buffer); vkimg = Image.Load (dev, loadedBuffers[bv.Buffer].Slice (bv.ByteOffset), (ulong)bv.ByteLength, VkImageUsageFlags.TransferSrc); } else if (img.Uri.StartsWith ("data:", StringComparison.Ordinal)) {//load base64 encoded image Debug.WriteLine ("loading embedded image {0} : {1}", img.Name, img.MimeType); vkimg = Image.Load (dev, glTFLoader.loadDataUri (img), VkImageUsageFlags.TransferSrc); } else { Debug.WriteLine ("loading image {0} : {1} : {2}", img.Name, img.MimeType, img.Uri);//load image from file path in uri vkimg = Image.Load (dev, Path.Combine (baseDirectory, img.Uri), VkImageUsageFlags.TransferSrc); } imageBlit.srcOffsets_1 = new VkOffset3D ((int)vkimg.CreateInfo.extent.width, (int)vkimg.CreateInfo.extent.height, 1); imageBlit.dstSubresource = new VkImageSubresourceLayers (VkImageAspectFlags.Color, 1, 0, (uint)l + firstImg); cmd = cmdPool.AllocateAndStart (VkCommandBufferUsageFlags.OneTimeSubmit); vkimg.SetLayout (cmd, VkImageAspectFlags.Color, VkAccessFlags.HostWrite, VkAccessFlags.TransferRead, VkImageLayout.Undefined, VkImageLayout.TransferSrcOptimal, VkPipelineStageFlags.Host, VkPipelineStageFlags.Transfer); Vk.vkCmdBlitImage (cmd.Handle, vkimg.Handle, VkImageLayout.TransferSrcOptimal, texArray.Handle, VkImageLayout.TransferDstOptimal, 1, ref imageBlit, VkFilter.Linear); transferQ.EndSubmitAndWait (cmd, true); vkimg.Dispose (); } cmd = cmdPool.AllocateAndStart (VkCommandBufferUsageFlags.OneTimeSubmit); uint imgCount = (uint)gltf.Images.Length; VkImageSubresourceRange mipSubRange = new VkImageSubresourceRange (VkImageAspectFlags.Color, 0, 1, firstImg, imgCount); for (int i = 1; i < texArray.CreateInfo.mipLevels; i++) { imageBlit = new VkImageBlit { srcSubresource = new VkImageSubresourceLayers (VkImageAspectFlags.Color, imgCount, (uint)i - 1, firstImg), srcOffsets_1 = new VkOffset3D ((int)texDim >> (i - 1), (int)texDim >> (i - 1), 1), dstSubresource = new VkImageSubresourceLayers (VkImageAspectFlags.Color, imgCount, (uint)i, firstImg), dstOffsets_1 = new VkOffset3D ((int)texDim >> i, (int)texDim >> i, 1) }; texArray.SetLayout (cmd, VkAccessFlags.TransferWrite, VkAccessFlags.TransferRead, VkImageLayout.TransferDstOptimal, VkImageLayout.TransferSrcOptimal, mipSubRange, VkPipelineStageFlags.Transfer, VkPipelineStageFlags.Transfer); Vk.vkCmdBlitImage (cmd.Handle, texArray.Handle, VkImageLayout.TransferSrcOptimal, texArray.Handle, VkImageLayout.TransferDstOptimal, 1, ref imageBlit, VkFilter.Linear); texArray.SetLayout (cmd, VkImageLayout.TransferSrcOptimal, VkImageLayout.ShaderReadOnlyOptimal, mipSubRange, VkPipelineStageFlags.Transfer, VkPipelineStageFlags.FragmentShader); mipSubRange.baseMipLevel = (uint)i; } mipSubRange.baseMipLevel = texArray.CreateInfo.mipLevels - 1; texArray.SetLayout (cmd, VkImageLayout.TransferDstOptimal, VkImageLayout.ShaderReadOnlyOptimal, mipSubRange, VkPipelineStageFlags.Transfer, VkPipelineStageFlags.FragmentShader); cmd.End (); transferQ.Submit (cmd); transferQ.WaitIdle (); cmd.Free (); }
internal static Dictionary <string, int> AddMaterials(this Gltf gltf, IList <Material> materials, List <byte> buffer, List <BufferView> bufferViews) { var materialDict = new Dictionary <string, int>(); var newMaterials = new List <glTFLoader.Schema.Material>(); var textureDict = new Dictionary <string, int>(); // the name of the texture image, the id of the texture var textures = new List <glTFLoader.Schema.Texture>(); var images = new List <glTFLoader.Schema.Image>(); var samplers = new List <glTFLoader.Schema.Sampler>(); var matId = 0; var texId = 0; var imageId = 0; var samplerId = 0; foreach (var material in materials) { if (materialDict.ContainsKey(material.Name)) { continue; } var m = new glTFLoader.Schema.Material(); newMaterials.Add(m); m.PbrMetallicRoughness = new MaterialPbrMetallicRoughness(); m.PbrMetallicRoughness.BaseColorFactor = material.Color.ToArray(); m.PbrMetallicRoughness.MetallicFactor = 1.0f; m.DoubleSided = material.DoubleSided; m.Name = material.Name; if (material.Unlit) { m.Extensions = new Dictionary <string, object> { { "KHR_materials_unlit", new Dictionary <string, object> { } } }; } else { m.Extensions = new Dictionary <string, object> { { "KHR_materials_pbrSpecularGlossiness", new Dictionary <string, object> { { "diffuseFactor", new[] { material.Color.Red, material.Color.Green, material.Color.Blue, material.Color.Alpha } }, { "specularFactor", new[] { material.SpecularFactor, material.SpecularFactor, material.SpecularFactor } }, { "glossinessFactor", material.GlossinessFactor } } } }; } if (material.Texture != null && File.Exists(material.Texture)) { // Add the texture var ti = new TextureInfo(); m.PbrMetallicRoughness.BaseColorTexture = ti; ti.Index = texId; ti.TexCoord = 0; ((Dictionary <string, object>)m.Extensions["KHR_materials_pbrSpecularGlossiness"])["diffuseTexture"] = ti; if (textureDict.ContainsKey(material.Texture)) { ti.Index = textureDict[material.Texture]; } else { var tex = new Texture(); textures.Add(tex); var image = new glTFLoader.Schema.Image(); using (var ms = new MemoryStream()) { // Flip the texture image vertically // to align with OpenGL convention. // 0,1 1,1 // 0,0 1,0 using (var texImage = SixLabors.ImageSharp.Image.Load(material.Texture)) { texImage.Mutate(x => x.Flip(FlipMode.Vertical)); texImage.Save(ms, new SixLabors.ImageSharp.Formats.Png.PngEncoder()); } var imageData = ms.ToArray(); image.BufferView = AddBufferView(bufferViews, 0, buffer.Count, imageData.Length, null, null); buffer.AddRange(imageData); } while (buffer.Count % 4 != 0) { // Console.WriteLine("Padding..."); buffer.Add(0); } image.MimeType = glTFLoader.Schema.Image.MimeTypeEnum.image_png; tex.Source = imageId; images.Add(image); var sampler = new Sampler(); sampler.MagFilter = Sampler.MagFilterEnum.LINEAR; sampler.MinFilter = Sampler.MinFilterEnum.LINEAR; sampler.WrapS = Sampler.WrapSEnum.REPEAT; sampler.WrapT = Sampler.WrapTEnum.REPEAT; tex.Sampler = samplerId; samplers.Add(sampler); textureDict.Add(material.Texture, texId); texId++; imageId++; samplerId++; } } if (material.Color.Alpha < 1.0) { m.AlphaMode = glTFLoader.Schema.Material.AlphaModeEnum.BLEND; } else { m.AlphaMode = glTFLoader.Schema.Material.AlphaModeEnum.OPAQUE; } materialDict.Add(m.Name, matId); matId++; } if (materials.Count > 0) { gltf.Materials = newMaterials.ToArray(); } if (textures.Count > 0) { gltf.Textures = textures.ToArray(); } if (images.Count > 0) { gltf.Images = images.ToArray(); } if (samplers.Count > 0) { gltf.Samplers = samplers.ToArray(); } return(materialDict); }