3

我最近一直在研究通过使用线性采样方法而不是离散方法来优化高斯模糊着色器。

我读了一篇内容丰富的文章:

线性采样的高效高斯模糊

在两个纹理像素合并的情况下,我们必须调整坐标,使确定的坐标到纹理像素#1 中心的距离应该等于纹理像素#2 的权重除以两个权重的总和。在相同的样式中,确定的坐标到 texel #2 中心的距离应该等于 texel #1 的权重除以两个权重的总和。

虽然我理解这背后的逻辑,但我不确定他们是如何得出给定权重的偏移数字的。是否有人愿意为我提供更多的信息,并解释如何在给定统一的权重变量的情况下计算正确的偏移量?

关于非硬编码偏移量,我发现另一篇文章推荐了一种计算偏移量的方法,但是没有针对可变数量的样本发布解决方案。我怎么能做到这一点?

vec2 offsets[3];
offsets[0] = vec2(0.0, 0.0);

offsets[1] = vec2(dFdx(gl_TexCoord[0].s), dFdy(gl_TexCoord[0].t));

offsets[2] = offsets[1] + offsets[1];

片段偏移

4

1 回答 1

1

我刚看到同一篇文章,发现它也非常有用。其中给出了计算权重和偏移量的公式:

公式
(来源:rastergrid.com

作者通过使用帕斯卡三角形中的第 12 行得出了权重。因此,例如,第二个偏移量通过以下方式计算:

1.3846153846 = (1 * 792 + 2 * 495) / (792 + 495)

第二个权重计算如下:

0.1945945946 = (792 + 495) / 4070

我不确定计算给定统一权重变量的偏移量是什么意思,但如果有帮助,我在这篇文章的末尾包含了一个 C++ 程序,它输出帕斯卡三角形中任意行的偏移量和权重。

如果我了解您关于非硬编码偏移量的问题,那么您希望能够在 GLSL 中即时计算偏移量吗?您可以通过移植下面的程序来做到这一点,但您仍然需要对二项式系数进行硬编码,或者还需要即时计算这些系数。然而,这将是昂贵的,因为它必须为每个像素完成。我认为更好的选择是预先计算 C(或您正在使用的任何编程语言)中的偏移量和权重,然后将它们绑定到 GLSL 中的统一数组值。这是我的意思的GLSL片段:

    uniform float offset[5];
    uniform float weight[5];"
    uniform int numOffsets;

您需要将“5”替换为您计划使用的最大偏移量/权重,并将 numOffsets 设置为您用于特定操作的数字。

这是输出权重和偏移量的程序。“coeffs”应替换为帕斯卡表中所需行的二项式系数。这里包括的一个来自第 22 行

#include <iostream>
#include <vector>

using namespace std;

int main(int argc, char* argv[])
{
  float coeffs[] = { 705432, 646646, 497420, 319770, 170544, 74613, 26334, 7315, 1540, 231 };
  double total = coeffs[0];
  for (int i = 1; i < sizeof(coeffs) / sizeof(float); i++)
    {
      total += 2 * coeffs[i];
    }
  vector<float> offsets;
  vector<float> weights;

  offsets.push_back(0);
  weights.push_back(coeffs[0] / total);

  for (int i = 1;  i <= (sizeof(coeffs) / sizeof(float) - 1) / 2; i++) 
    {
      int index = (i - 1) * 2 + 1;
      float weight = coeffs[index] + coeffs[index + 1]; 
      offsets.push_back((coeffs[index] * index + coeffs[index + 1] * (index + 1)) /  weight);
      weights.push_back(weight / total);
    }

  for (int i = 0; i < offsets.size(); i++)
    {
      cout << offsets[i] << ", ";
    }
  cout << "\n";

  for (int i = 0; i < weights.size(); i++)
    {
      cout << weights[i] << ", ";
    }
  cout << "\n";
}
于 2012-10-04T18:39:48.270 回答