【问题标题】:OpenGL Post Processing using Power of Two Textures使用两个纹理的幂的 OpenGL 后处理
【发布时间】: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-10 额外像素。
  • 您的第一个和第三个选项都会产生非常好的性能结果。此外,如果你知道你的最大水平坐标是 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


【解决方案1】:

在生成 POT 版本的纹理时,您可以模拟从钳位到边缘。

当生成 POT 帧缓冲区而不是只渲染与原始纹理匹配的帧缓冲区部分时,渲染一些稍微过大的东西(例如,足够的额外像素来覆盖您的过滤器内核宽度)。如果您使用CLAMP_TO_EDGE 对原始 NPOT 纹理进行渲染,则您只需将原始纹理的边缘扩展到内核的溢出区域。

然后您可以使用您计划的坐标范围正常读取它,它应该就像您正在读取应用了CLAMP_TO_EDGE 的原始纹理一样工作。尽管夹具很便宜,但我希望它会更便宜......

【讨论】:

  • 问题是 POT 版本被用于多通道效果。我可以为第一个副本模拟 CLAMP_TO_EDGE,但是当我围绕它进行乒乓球运动并对其进行修改时,假设我只在帧缓冲区的相关部分上渲染,假设使用模糊着色器;边缘部分不再适合我的纹理,它是原始图像的边缘。
  • 在这种情况下,我猜你会坚持在原始坐标上使用clamp()。您可以通过渲染两个绘图调用来避免大部分额外成本——一个四边形覆盖不需要clamp() 的部分,一个覆盖需要的部分。至少那时您只需要在需要时支付额外费用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多