public unsafe static Texture2DContent Build(Stream dataStream) { using (var rawImage = SixLabors.ImageSharp.Image.Load(dataStream)) using (var image = rawImage.CloneAs <Rgba32>()) { var pixels = image.GetPixelSpan(); var imageData = new int[pixels.Length]; fixed(int *imageDataPointer = imageData) { var casted = new Span <Rgba32>(imageDataPointer, imageData.Length); pixels.CopyTo(casted); } //We're only supporting R8G8B8A8 right now, so texel size in bytes is always 4. //We don't compute mips during at content time. We could, but... there's not much reason to. //The font builder does because it uses a nonstandard mip process, but this builder is expected to be used to with normal data. var content = new Texture2DContent(image.Width, image.Height, 1, sizeof(Rgba32)); var data = (Rgba32 *)content.Pin(); //Copy the image data into the Texture2DContent. for (int rowIndex = 0; rowIndex < image.Height; ++rowIndex) { var sourceRow = image.GetPixelRowSpan(rowIndex); var targetRow = data + content.GetRowOffsetForMip0(rowIndex); Unsafe.CopyBlockUnaligned(ref *(byte *)targetRow, ref Unsafe.As <Rgba32, byte>(ref sourceRow[0]), (uint)(sizeof(Rgba32) * image.Width)); } content.Unpin(); return(content); } }
/// <summary> /// Uploads the mip0 stored in the Content to the Texture2D and generates new mips. /// </summary> public unsafe void UploadContentToTexture() { GL.BindTexture(TextureTarget.Texture2D, Texture); var data = Content.Pin(); GL.TexImage2D(TextureTarget.Texture2D, 0, srgb ? PixelInternalFormat.Rgba8Snorm : PixelInternalFormat.Rgba8, Content.Width, Content.Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, new IntPtr(data + Content.GetMipStartIndex(0)) ); Content.Unpin(); GL.GenerateMipmap(GenerateMipmapTarget.Texture2D); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); GL.BindTexture(TextureTarget.Texture2D, 0); }