【发布时间】:2011-08-24 18:20:01
【问题描述】:
我正在重写一个基于 opengl 的 gis/mapping 程序。除其他外,该程序允许您加载海图的光栅图像,将它们固定到经度/纬度坐标,并在它们上进行缩放和平移。
该程序的先前版本使用自定义平铺系统,实质上它手动创建原始图像的 mipmap,以 256x256 像素的平铺形式在各种二次方缩放级别。缩放级别为 n - 1 的图块由缩放级别 n 的四个图块构建而成,使用简单的四点平均算法。因此,它关闭了 opengl mipmapping,而是在需要以某个缩放级别绘制图表的某些部分时,它使用最接近匹配缩放级别的图块(即图块处于二次方缩放级别,但程序允许任意缩放级别)然后缩放图块以匹配实际缩放级别。当然,它还必须在各个级别管理所有这些切片的缓存。
在我看来,这个平铺系统过于复杂。看起来我应该能够让图形硬件为我完成所有这些 mipmapping 工作。所以在新程序中,当我读入一张图片时,我将它切成每个 1024x1024 像素的纹理。然后我将每个纹理固定到它的 lon/lat 坐标,然后在我缩放和平移时让 opengl 处理其余部分。
它有效,但问题是:我的结果比原始程序有点模糊,这对这个应用程序很重要,因为您希望能够尽早阅读图表上的文本,放大。因此,就清晰度而言,原始程序使用的简单四点平均算法似乎比 opengl + 我的 GPU 提供了更好的结果。
我知道有几个 glTexParameter 设置可以控制 mipmap 工作的某些方面。我已经尝试了 GL_TEXTURE_MAX_LEVEL(从 0 到 10 的任意位置)与 GL_TEXTURE_MIN_FILTER 的各种设置的各种组合。当我将 GL_TEXTURE_MAX_LEVEL 设置为 0(无 mipmap)时,我当然会得到“锐利”的结果,但它们太锐利,因为像素只是在这里和那里掉落,所以数字在中间变焦。当我将 GL_TEXTURE_MAX_LEVEL 设置为更高的值时,当您拉远时(例如,当整个图表适合屏幕时),图像看起来非常好,但是当您放大到中间缩放时,您会注意到模糊,尤其是在查看时图表上的文字。 (即,如果不是文本,您可能会认为“哇,opengl 在平滑缩放我的图像方面做得很好。”但是对于文本,您会认为“为什么这张图表失焦了?”)
我的理解是,基本上你告诉 opengl 生成 mipmap,然后在放大时选择要使用的适当 mipmap,并且在两个最接近的 mipmap 级别之间进行插值有一些有限的选项,或者使用最接近的像素或平均附近的像素。但是,正如我所说,在图表上相同的缩放级别下,这些组合似乎都没有给出非常清晰的结果(即,文本很小但不是微不足道的缩放级别,例如相当于“7 点”或“ 8 点”大小),与之前基于图块的版本一样。
我的结论是,opengl 创建的 mipmap 比之前使用平均四点算法创建的程序更模糊,并且无论选择正确的 mipmap 或 LINEAR vs NEAREST 都不会获得我的清晰度需要。
具体问题:
(1) 与原始程序中的平均四点算法相比,opengl 实际上制作的 mipmap 看起来是否正确?
(2) 在使用 glTexParameter 时,我是否可能忽略了一些可以使用 opengl 正在制作的 mipmap 提供更清晰结果的东西?
(3) 有什么方法可以让 opengl 首先制作更清晰的 mipmap,例如使用“立方”过滤器或以其他方式控制 mipmap 创建过程?或者就此而言,我似乎可以使用相同的平均四点代码来手动生成 mipmap 并将它们交给 opengl。但我不知道该怎么做...
【问题讨论】:
-
从纹理坐标到像素的映射有点棘手。想象每个像素都是一个小方块。纹理坐标 0 和 1 不会击中中心的边界像素,但会击中边界。因此,通过对纹理内容进行简单的、基于像素的寻址,您可能会恰好到达像素之间的中间位置,从而引入一些“模糊”。
-
见this。此外,您似乎正在使用描述中的 GL_GENERATE_MIPMAP 。虽然可能相同,但使用 EXT_FRAMEBUFFER_OBJECT 的
glGenerateMipmap可能值得一试。如果着色器是一个选项,您可以使用硬件加速进行自己的 mip 过滤。最后,如果将文本标签与地形数据分开是一种可能的选择,您也可以这样做(例如,使用基于距离图的算法显示标签,该算法在所有放大倍率下都提供非常好的抗锯齿结果)。