【发布时间】:2018-12-28 17:29:39
【问题描述】:
我正在尝试在 OpenGL ES 中进行一些后期处理,所以为了安全起见,我决定使用两种纹理大小的幂。然而,源图像是矩形的,并不完全适合 PoT 纹理,所以我缩小比例并将其绘制到帧缓冲区中(没有拉伸,我稍后会谈到),如下图所示:
所以纹理中有一个间隙/空白区域,它是黑色或我清除它的任何颜色。然后这成为我使用的源纹理,我多次对其应用效果。我试图概述我认为我将在图片中面临的问题。基本上,当我使用从相邻像素采样的模糊或绽放之类的着色器时,边缘上的像素将从空白区域采样。如果我使用 npot 纹理或对其进行拉伸,CLAMP_TO_EDGE 可以让我摆脱这种情况,但我无法解决如何在我的情况下做到这一点。以下是我提出的一些想法:
- 拉伸图像以填充整个纹理:我觉得边缘检测等一些着色器可能会导致最终图像中拉伸轴和未拉伸轴的不平衡。我希望这适用于所有类型的着色器。这个假设我错了吗?
- 尝试通过使用源图像的边缘颜色填充空白区域来手动模拟 CAMP_TO_EDGE:感觉很麻烦,并且必须在每个乒乓步骤中完成。
- 在片段着色器中钳制纹理坐标(例如,水平 0.7 为最大值):我认为这在着色器中会很重,尤其是在采样多个坐标时。
那么,有什么方法可以有效地做到这一点,比如将纹理坐标设置为边缘或其他什么?我知道 NPoT 纹理会让这一切变得更容易,但我想先探索我的 PoT 选项。而且由于即使是桌面 GPU 一开始也不是 NPoT 友好的,所以我觉得这一定是一个已经解决的问题,并且必须存在一些最佳实践。
【问题讨论】:
-
我不确定坐标钳制是否像您想象的那样昂贵,尤其是与实际的纹理提取相比。但是,如果你使用双线性过滤并且没有奇怪的各向异性,每一次通过只会从边界外 1px 处读取数据,所以基本上,如果你事先知道通过次数,你可以最初重复
n像素的图像数据,然后在每个后续通道中处理n-1到0额外像素。 -
您的第一个和第三个选项都会产生非常好的性能结果。此外,如果你知道你的最大水平坐标是 0.7,你可以简单地改变你的水平 UV 值以适应
[0.0, 0.7]范围,这样你就不需要在你的片段着色器中执行任何钳制。 -
@derhass 问题是我计划使用的一些着色器可能会读到很远的空白区域(某种细长/星形轨迹着色器)。我想找到一种通用的方法,而不是我将要使用的一些特定着色器的解决方法。
-
@Marquizzo 我如何在不明确夹在着色器中的情况下夹住我的 uv?我的意思是假设我用从 0.0 到 0.7 的水平 uvs 对四边形进行了纹理处理,并且我使用了一个对 n 个相邻像素进行采样的模糊内核。当着色器为0.7的边界像素运行时,它不会从超过0.7的坐标中采样吗?我想会的。
-
啊,我的错。我错过了你需要模糊的部分,它会采样相邻的片段。话虽如此,
clamp()是一个非常便宜的功能,你不应该害怕使用它。事实上,执行高斯模糊比简单地限制 UV 值的计算成本要高得多。
标签: opengl-es glsl webgl shader