/// <summary> /// イメージデータからテクスチャの作成を行います。 /// </summary> public bool Create(Bitmap image, bool toPremultipliedAlpha = false) { if (image == null) { throw new ArgumentNullException("image"); } ValidateContext(); int[] textureMaxSize = { 0 }; GLWrap.Wrap(() => GL.GetInteger(GetPName.MaxTextureSize, textureMaxSize)); // 2のn乗値の中から、元の画像サイズを超えるような // 一番小さな値を探します。 int targetWidth = textureMaxSize[0]; for (int size = 1; size <= textureMaxSize[0]; size *= 2) { if (image.Width < size) { targetWidth = size; break; } } int targetHeight = textureMaxSize[0]; for (int size = 1; size <= textureMaxSize[0]; size *= 2) { if (image.Height < size) { targetHeight = size; break; } } // 画像のリサイズが必要な場合 var result = false; if (image.Width != targetWidth || image.Height != targetHeight) { using (var newImage = new Bitmap(targetWidth, targetHeight)) { DrawHighQuality( newImage, image, Math.Min(image.Width, newImage.Width), Math.Min(image.Height, newImage.Height)); result = CreateInternal(newImage, image.Size, toPremultipliedAlpha); } } else { // imageの内容が変わる可能性があるため、ここでCloneしています。 using (var newImage = (Bitmap)image.Clone()) { result = CreateInternal(newImage, image.Size, toPremultipliedAlpha); } } GC.Collect(); return(result); }
/// <summary> /// テクスチャデータの作成を行います。 /// </summary> /// <remarks> /// イメージからテクスチャを作成するのみで /// サイズの変更などの余計なことは一切行いません。 /// /// またこのメソッドには所有権を渡してもよいイメージオブジェクトを /// 与えてください。 /// </remarks> private bool CreateInternal(Bitmap image, Size originalSize, bool toPremultipliedAlpha) { uint texture = 0; GLWrap.Wrap(() => GL.GenTextures(1, out texture)); // Lock the image bits (so that we can pass them to OGL). var bitmapData = image.LockBits( new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadOnly, Imaging.PixelFormat.Format32bppArgb); try { if (toPremultipliedAlpha) { MakePremutipliedAlpha(bitmapData); } GLWrap.Wrap(() => GL.BindTexture(TextureTarget.Texture2D, texture)); // TexParameterのGenerateMipmapを使う場合 if (GenerateMipmapSupportLevel == 1) { // glTexImage2Dの前にmipmapの使用設定を行う //GLWrap.Wrap(() => GL.Hint(HintTarget.GenerateMipmapHint, HintMode.Nicest)); GLWrap.Wrap(() => GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.GenerateMipmap, 1)); } // テクスチャデータをセットします。 #if true GLWrap.Wrap(() => GL.TexImage2D( TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba8, image.Width, image.Height, 0, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, bitmapData.Scan0)); #else GLWrap.Wrap(() => GL.Build2DMipmaps( TextureTarget.Texture2D, (int)OpenGL.GL_RGBA, image.Width, image.Height, OpenTK.Graphics.OpenGL.GL_BGRA, GL.GL_UNSIGNED_BYTE, bitmapData.Scan0)); #endif } finally { image.UnlockBits(bitmapData); } GLWrap.Wrap(() => GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Clamp)); GLWrap.Wrap(() => GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Clamp)); // glGenerateMipmapを使う場合 if (GenerateMipmapSupportLevel == 2) { GL.GenerateMipmap(GenerateMipmapTarget.Texture2D); } if (GenerateMipmapSupportLevel > 0) { // Mipmapを使う場合はフィルターを設定 GLWrap.Wrap(() => GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear)); GLWrap.Wrap(() => GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear)); } else { GLWrap.Wrap(() => GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear)); GLWrap.Wrap(() => GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear)); } GL.BindTexture(TextureTarget.Texture2D, 0); // テクスチャの作成に成功したら、古いテクスチャを削除します。 Destroy(); this.glTexture = texture; Width = image.Width; Height = image.Height; OriginalWidth = originalSize.Width; OriginalHeight = originalSize.Height; IsPremultipliedAlpha = toPremultipliedAlpha; return(true); }