【C#/OpenGL】CSGL中2D纹理加载PNG等透明图片显示的黑边问题
2015-03-19 22:07
489 查看
CSGL加载PNG格式图片作为纹理映射显示后是有黑边的,使用的是CSGL封装的OpenGLTexture2D类。
后来查了很多OpenGL透明纹理的资料,网上找了各种其他语言的透明纹理实现,在CSGL库上均不起效,最后怀疑是CSGL底层封装时对像素的处理有问题。
反正是开源库,那就打开源码看看,最后自己实现了一个加载纹理的函数,和一个绘制纹理到二维坐标系的函数。
有效解决了黑边的问题,但是还有如下小问题没有解决:
1.只能区分透明和不透明(0或255 Alpha),中间的其他半透明效果均无法正确融合显示
2.图片缩放后会有空白像素点,可能是线性过滤导致的,但不开启过滤也无法正常显示纹理。
后来查了很多OpenGL透明纹理的资料,网上找了各种其他语言的透明纹理实现,在CSGL库上均不起效,最后怀疑是CSGL底层封装时对像素的处理有问题。
反正是开源库,那就打开源码看看,最后自己实现了一个加载纹理的函数,和一个绘制纹理到二维坐标系的函数。
有效解决了黑边的问题,但是还有如下小问题没有解决:
1.只能区分透明和不透明(0或255 Alpha),中间的其他半透明效果均无法正确融合显示
2.图片缩放后会有空白像素点,可能是线性过滤导致的,但不开启过滤也无法正常显示纹理。
/// <summary> /// 从文件创建2D纹理 /// </summary> /// <param name="fileName">文件名(路径)</param> /// <returns>纹理ID</returns> public static uint[] CreateTexture2D(string fileName) { // 用GDI将原始图像转换为32位png格式图像 Bitmap bmp_orign = new Bitmap(fileName); Bitmap bmp_new = new Bitmap(bmp_orign.Width, bmp_orign.Height, PixelFormat.Format32bppArgb); Graphics g = Graphics.FromImage(bmp_new); g.DrawImage(bmp_orign, new Rectangle(0, 0, bmp_orign.Width, bmp_orign.Height)); // 锁定内存 BitmapData tex = bmp_new.LockBits(new Rectangle(0, 0, bmp_new.Width, bmp_new.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); // 像素处理 IntPtr ptr = tex.Scan0; int bytesLength = tex.Stride * tex.Height; byte[] rgbValues = new byte[bytesLength]; Marshal.Copy(ptr, rgbValues, 0, bytesLength); for (int i = 0; i < rgbValues.Length; i += 4) { //rgbValues[i] = 255; // B //rgbValues[i + 1] = 255; // G //rgbValues[i + 2] = 255; // R //rgbValues[i + 3] = 255; // A if (rgbValues[i + 3] == 0) rgbValues[i + 3] = 150; } Marshal.Copy(rgbValues, 0, ptr, bytesLength); // 创建纹理 uint[] texture = new uint[1]; GL.glGenTextures(texture.Length, texture); GL.glBindTexture(GL.GL_TEXTURE_2D, texture[0]); // 设置像素对齐 GL.glPixelStoref(GL.GL_PACK_ALIGNMENT, 1); // 设置环境融合方式和线性过滤参数 GL.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, (int)GL.GL_MODULATE); GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR); GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR); GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP); GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP); // 创建纹理 bool IsBorder = true; bool IsMipmaped = true; if (IsMipmaped) { GL.gluBuild2DMipmaps(GL.GL_TEXTURE_2D, (int)GL.GL_BGRA, bmp_new.Width, bmp_new.Height, GL.GL_BGRA, GL.GL_UNSIGNED_BYTE, tex.Scan0); } else { GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, (int)GL.GL_BGRA, bmp_new.Width, bmp_new.Height, IsBorder ? 1 : 0, GL.GL_BGRA, GL.GL_UNSIGNED_BYTE, tex.Scan0); } // 解锁内存 bmp_new.UnlockBits(tex); // 返回纹理ID return texture; } /// <summary> /// 绘制纹理 /// </summary> /// <param name="texture">纹理ID</param> /// <param name="x">起点x</param> /// <param name="y">起点y</param> /// <param name="width">宽度</param> /// <param name="height">高度</param> public static void DrawImage(uint[] texture, int x, int y, int width, int height) { // 允许使用纹理 GL.glEnable(GL.GL_TEXTURE_2D); // 启用颜色混合 GL.glEnable(GL.GL_BLEND); GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_DST_ALPHA); // 绑定纹理 GL.glBindTexture(GL.GL_TEXTURE_2D, texture[0]); // 坐标转换 y = General.Win_Rect.Height - y - height; GL.glBegin(GL.GL_QUADS); { // 纹理坐标映射 GL.glTexCoord2f(0.0f, 1.0f); GL.glVertex2f(x, y); GL.glTexCoord2f(1.0f, 1.0f); GL.glVertex2f(x + width, y); GL.glTexCoord2f(1.0f, 0.0f); GL.glVertex2f(x + width, y + height); GL.glTexCoord2f(0.0f, 0.0f); GL.glVertex2f(x, y + height); } GL.glEnd(); // 禁用混合 GL.glDisable(GL.GL_BLEND); }
相关文章推荐
- opengl下png图片的加载与显示
- html学习笔记-解决ie6中png图片透明不能正常显示问题
- C# Winform控件贴透明png图片遇到的问题
- 关于CImage和AlphaBlend的透明PNG图片显示问题
- C# Winform控件贴透明png图片遇到的问题
- C# Winform控件贴透明png图片遇到的问题
- Android-加载透明PNG图片变黑的问题
- [MAC]OpenGL中SOIL库与stbi_load库加载图片,透明黑色问题,遇到的坑及解决办法
- 安卓开发——问题:PNG图片的透明部分不显示Layout的背景色
- 解决IE6下的,不能显示透明PNG图片的问题(转载)
- png图片透明在ie6中显示问题
- 让IE6显示透明PNG背景图片
- 【搜集】卸载adobe cs4后PNG图片无法显示问题的解决办法
- IE6下PNG图片透明问题
- 使用CImage显示透明的PNG图片
- [Javascript] 解决 IE6 中 png 图片背景不支持透明效果的问题
- 完美解决ie6不支持png 透明图片 和标签背景的问题
- VC利用GDI+显示透明的PNG图片
- 【转】CSS解决IE6下PNG图片背景不透明的问题