【C#/OpenGL】CSGL中2D纹理加载PNG等透明图片显示的黑边问题

来源:互联网 发布:js计算对象长度 编辑:程序博客网 时间:2024/04/28 04:05

CSGL加载PNG格式图片作为纹理映射显示后是有黑边的,使用的是CSGL封装的OpenGLTexture2D类。

后来查了很多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);        }


0 0
原创粉丝点击