OpenGL中是否有一种通用的方法,当以原生大小(包括边缘像素)绘制时,允许从图集中完美地2D绘制纹理,并在过滤到非原生大小时进行高质量缩放?
假设您正在编写某种用于从纹理图集中绘制精灵的系统,以便用户可以指定精灵,以及绘制精灵的大小和位置.另外,他们可能只想绘制精灵的子矩形.
例如,这是一个64x64棋盘:

......并且单独在其纹理图集中:

注意:我们假设视口设置为将1:1映射到设备像素.
为清晰起见进行编辑:请注意,下面的前两个方法没有给出所需的结果,并且专门用于概述不起作用的内容.
1.要以原生大小绘制精灵,只需使用GL_NEAREST即可
这适用于以原始大小绘制,但是当用户以64x64以外的大小绘制对象时,NEAREST过滤会产生较差的结果.它还会强制纹理像素与像素网格对齐,在非整数像素位置绘制对象时效果不佳:

2.启用GL_LINEAR
(0.5/atlas_size,0.5/atlas_size)to (63.5/atlas_size,63.5/atlas_size).否则,对于最外面的像素,线性过滤将对图集中的精灵的邻居进行采样.

请注意,除了与背景混合的边缘像素之外,我们得到像素精确的绘图,因为顶点边界落在像素之间的中间.
编辑:还要注意,此行为还取决于是否启用了抗锯齿功能.如果不是,前一种方法实际上确实提供像素完美渲染,但是当精灵从像素对齐移动到子像素位置时不提供良好的转换.在许多情况下,加抗锯齿是必须的.
3.在纹理图集中填充精灵
边缘像素问题的两个明显的解决方案涉及在纹理图集中用1px边框填充精灵的边缘.你可以:
这基本上为我们提供了线性缩放的像素精确绘图.但是,如果我们允许用户只绘制精灵的子矩形,则这些方法中的任何一个都会失败,因为子矩阵显然没有所需的填充.
我错过了什么吗?这个问题有一般的解决方案吗?
很难确切地知道您正在寻找的“正确的东西”是什么。如果您有一个 64x64 的精灵,并且想要将其缩放到 65x65 或 63x63,那么再多的过滤也不会让其看起来很好。当您将抗锯齿加入到混合中时,请记住多重采样不是超级采样,因此您的纹理不会神奇地获得更柔和的内部效果。
也就是说,真正的非最近过滤应该可以通过多重采样很好地开箱即用。我认为您的 GL_LINEAR 方法走在正确的轨道上,但我认为您可能存在实施问题。
特别是,线性过滤应该在沿着纹素边界时进行过滤。例如,如果您有两个相邻的三角形,则可能会发生这种情况。事实上,您应该期望沿着精灵边缘进行线性过滤,而这种过滤是正确的。
您不应该尝试通过调整纹理坐标(以及顶点)来纠正此问题,因为这会错误地在纹理上缩放纹理坐标。相反,我建议在着色器中将纹理坐标限制在所需的范围正/负 0.5/texture_res 内。
您会发现这解决了原生缩放时获得完美像素结果的问题以及良好的放大质量。缩小看起来不错,但我建议使用三线性(mipmap)过滤以获得最佳结果。
| 归档时间: |
|
| 查看次数: |
3788 次 |
| 最近记录: |