我注意到 Java & JOGL 和 C# & Tao.OpenGL 在将 PNG 从存储加载到内存时以及在加载 BufferedImage (java) 或 Bitmap (C# - 两者都是硬盘上的 PNG) '进入'OpenGL 时存在很大的性能差异.
这种差异非常大,所以我认为我做错了什么,但是经过大量搜索和尝试不同的加载技术后,我无法减少这种差异。
使用 Java,我在 248 毫秒内加载图像并在 728 毫秒内加载到 OpenGL 中。在 C# 上,加载图像需要 54 毫秒,加载/创建纹理需要 34 毫秒。
上面有问题的图像是一个包含透明度的 PNG,大小为 7200x255,用于 2D 动画精灵。我意识到尺寸真的很荒谬,并且正在考虑切割精灵,但是仍然存在很大的差异(并且令人困惑)。
在 Java 端,代码如下所示:
BufferedImage image = ImageIO.read(new File(fileName));
texture = TextureIO.newTexture(image, false);
texture.setTexParameteri(GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
texture.setTexParameteri(GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
C# 代码使用:
Bitmap t = new Bitmap(fileName);
t.RotateFlip(RotateFlipType.RotateNoneFlipY);
Rectangle r = new Rectangle(0, 0, t.Width, t.Height);
BitmapData bd = t.LockBits(r, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
Gl.glBindTexture(Gl.GL_TEXTURE_2D, tID);
Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0, Gl.GL_RGBA, t.Width, t.Height, 0, Gl.GL_BGRA, Gl.GL_UNSIGNED_BYTE, bd.Scan0);
Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MIN_FILTER, Gl.GL_LINEAR);
Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAG_FILTER, Gl.GL_LINEAR);
t.UnlockBits(bd);
t.Dispose();
经过大量测试后,我只能得出结论,Java/JOGL 在这里速度较慢 - PNG 读取可能没有那么快,或者我仍然做错了什么。
谢谢。
编辑2:
我发现创建格式为 TYPE_INT_ARGB_PRE 的新 BufferedImage 将 OpenGL 纹理加载时间减少了近一半 - 这包括必须创建新的 BufferedImage,从中获取 Graphics2D,然后将先前加载的图像渲染到它。
Edit3:5 种变体的基准测试结果。我写了一个小基准测试工具,下面的结果来自加载一组 33 个 png,大多数都很宽,5 倍。
testStart: ImageIO.read(file) -> TextureIO.newTexture(image)
result: avg = 10250ms, total = 51251
testStart: ImageIO.read(bis) -> TextureIO.newTexture(image)
result: avg = 10029ms, total = 50147
testStart: ImageIO.read(file) -> TextureIO.newTexture(argbImage)
result: avg = 5343ms, total = 26717
testStart: ImageIO.read(bis) -> TextureIO.newTexture(argbImage)
result: avg = 5534ms, total = 27673
testStart: TextureIO.newTexture(file)
result: avg = 10395ms, total = 51979
ImageIO.read(bis) 指的是 James Branigan 在下面的回答中描述的技术。argbImage 指的是我之前编辑中描述的技术:
img = ImageIO.read(file);
argbImg = new BufferedImage(img.getWidth(), img.getHeight(), TYPE_INT_ARGB_PRE);
g = argbImg.createGraphics();
g.drawImage(img, 0, 0, null);
texture = TextureIO.newTexture(argbImg, false);
任何更多的加载方法(来自文件的图像,或图像到 OpenGL)将不胜感激,我将更新这些基准。