OpenGL/GLSL - 纹理过滤的实现

4
我想在GLSL着色器中自己实现纹理过滤(min和magfilter),因为我想使用image_load_and_store而不是采样器,并且我想以特殊方式处理未定义像素。我正在寻找一篇讨论过滤过程的文章或其他资料。
我可以回忆起从我之前编写的光线追踪器中实现纹理过滤的方法 - 我认为你需要考虑每个像素处的UV梯度,并根据这些梯度的长度来缩放你的采样光栅。但是我那里使用了一个49个采样点的圆形核,我认为太重了。
我认为通过dFdx()和dFdy()函数可以获取UV梯度 - 但我想知道OpenGL用于过滤的核心是什么,并以相同的方式在我的GLSL着色器中实现它。
此外 - 如何区分是否需要应用minfilter或magfilter?过滤过程有什么不同吗?
最后但并非最不重要:如果是缩小过滤,则如何基于UV梯度选择适当的mipmap级别?

1
出于好奇,你为什么要那样做? - harold
通常情况下,纹理过滤和采样是使用硬件执行的。如果在着色器中实现这些功能,那肯定会很困难,更不用说对性能的要求非常高了。 - Ani
这是关于图形研究的内容,因此我们正在模拟未来硬件可能支持的功能。我这样做有两个原因:第一,我需要使用image_load_and_store(实际上我不知道是否可以使用与采样器相同的纹理作为ImageStore目标?)第二个原因是我想以特殊方式处理值为“NaN”的像素(常规过滤将使整个像素变为NaN,如果其中一个纹素为NaN)。 - matthias_buehlmann
1个回答

2

Codeproject上有一篇文章,它在GLSL中实现了不同的滤镜(其中包括双线性滤波器):链接


这已经很好了,谢谢。然而它只讨论了矩形放大(这相当琐碎),因此它没有考虑UV梯度和MipMapping... - matthias_buehlmann
1
Mipmaps通常使用类似于0.5*log2(fwidth())的函数自动计算(它有点更复杂,例如可配置偏差)。如果您绘制较小的四边形,则硬件通常会自动选择较小的mipmap,并且没有需要执行的“特殊过滤”。Mipmaps通常也只是盒式过滤。虽然存在一些复杂的缩小过滤器,但比我们更擅长此领域的人似乎都认为几乎没有任何可见的改进(但很可能会出现振铃)。 - Damon
嘿,这是个好信息。所以为了在着色器中正确地执行它,我将获取mipmap级别floor(0.5*log2(fwidth()))ceiling(0.5*log2(fwidth())),在每个级别中获取4个最接近的纹素,并进行双线性插值,然后根据(0.5*log2(fwidth())-floor(0.5*log2(fwidth())))之间的值在两个数值之间进行混合? - matthias_buehlmann
这大致就是硬件使用LINEAR_MIP_LINEAR过滤时会做的事情,可能会有一两个常数的差别。但这实际上有点毫无意义,因为这已经自动工作了。着色器中滤波看起来更好的唯一地方实际上是在放大时。虽然对我来说,着色器线性放大滤镜看起来与内置硬件滤镜完全相同,而立方体虽然略微好一些,但仍不如内置硬件滤镜好到需要承受巨大开销的程度。 - Damon
这并不是毫无意义的,因为我使用的是图像而不是采样器(它们不支持过滤),而且我还以一种特定的方式处理NaN值。 - matthias_buehlmann

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接