3

I've recently been looking into optimising a gaussian blur shader by using a linear sampling method instead of a discrete method.

I read a very informative article:

Efficient Gaussian Blur With Linear Sampling

In case of such a merge of two texels we have to adjust the coordinates that the distance of the determined coordinate from the texel #1 center should be equal to the weight of texel #2 divided by the sum of the two weights. In the same style, the distance of the determined coordinate from the texel #2 center should be equal to the weight of texel #1 divided by the sum of the two weights.

While I understand the logic behind this, I'm not sure how they arrived at the figures for the offset with the given weights. Would anyone be kind enough to shed more light on this for me and to also explain how, given uniform weight variables we could calculate correct offsets?

Regarding non hard coded offsets, I found another post which recommended a method of calculating the offsets, however no solution was posted for a variable amount of samples. How could I achieve that?

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];

Fragment Offset

4

1 に答える 1

1

同じ記事に出くわしたところ、非常に便利であることがわかりました。重みとオフセットを計算する式は、次のとおりです。

方式
(出典:rastergrid.com

著者は、パスカルの三角形の12行目を使用して重みに到達しました。したがって、たとえば、2番目のオフセットは次のように計算されます。

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

2番目の重みは次のように計算されます。

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 に答える