Войти
ПрограммированиеТерминыГрафика

Depth-based blur

Автор:

Depth-based blur — размытие, при котором учитывается глубина сцены. Обычно используется для размытия теней или текстуры Screen Space Ambient Occlusion в пространстве экрана.

Depth-based blur основан на обычном размытии по Гауссу (начальная точка имеет больший вес, по сравнению с последующими, веса которых убывают по мере удаления от начальной точки). Но выполняется с учетом разницы глубины соседних размываемых фрагментов: если глубина отличается на заданную величину, то не следует учитывать данный фрагмент в размытии.

Сравнение обычного размытия и размытия с учетом глубины (в красном канале - затененность, в зеленом SSAO):

Сравнение обычного размытия и размытия с учетом глубины | Depth-based blur

GLSL шейдер, с помощью которого реализуется такое размытие:

uniform sampler2D depth_texture; // текстура, содержащая глубину сцены
uniform sampler2D color_texture; // текстура, которую необходимо размыть с учетом глубины
uniform vec4 texel_clipplane; 
// в первых двух компонентах (.xy) - направление, в котором следует размывать текстуру. 
// обычно размытие выполняется в два прохода. 
// В первом проходе .xy = (1.0 / texture_size_X, 0.0), во втором .xy = (0.0, 1.0 / texture_size_Y)
// в zw - дальность до плоскотей отсечения

// получение линейной глубины (расстояния до камеры)
float sample_linear_depth(vec2 texC)
{
 float fDepth = texture2D( depth_texture, texC ).x;

// коэффициент 0.5 можно подобрать эмпирически для наилучшего вида вашей сцены
 return 0.5 * texel_clipplane.z * texel_clipplane.w / 
        ( texel_clipplane.w - fDepth * (texel_clipplane.w - texel_clipplane.z) );
}

const int blur_radius = 4; // радиус размытия
 
void main (void) 
{
 float fDepth = sample_linear_depth(gl_TexCoord[0].st); // получаем глубину начальной точки

 float fMultiplier = (float(blur_radius) + 1.0);
 vec4 vColor = texture2D(color_texture, gl_TexCoord[0].st) * fMultiplier; // и цвет в начальной точке

 for (int k = 1; k <= blur_radius; k++) 
  {
   float fStep = float(k);

   float fScale = (1.0 + float(blur_radius) - fStep ); 
   float fNextDepth = sample_linear_depth(gl_TexCoord[0].st + texel_clipplane.xy * fStep);
 // получаем глубину следующего фрагмента в положительном направлении
   float fPrevDepth = sample_linear_depth(gl_TexCoord[0].st - texel_clipplane.xy * fStep);
 // и в отрицательном
   float fPrevDiff = min(1.0, 1.0 / (1.0e-7 + abs(fPrevDepth - fDepth)));
   float fNextDiff = min(1.0, 1.0 / (1.0e-7 + abs(fNextDepth - fDepth)));
// получаем разницу глубины текущего и фрагмента и новых. Чем меньше разница, тем боьше коэффициент

   vColor += texture2D(color_texture, gl_TexCoord[0].st + texel_clipplane.xy * fStep ) * fScale * fNextDiff;
   vColor += texture2D(color_texture, gl_TexCoord[0].st - texel_clipplane.xy * fStep ) * fScale * fPrevDiff;
// добавляем к цвету в начальной точке два цвета с учетом коэффициентов размытия и разницы глубины
   fMultiplier += fScale * (fPrevDiff + fNextDiff);
  };

 gl_FragColor = vec4( vColor.xyz / fMultiplier, 1.0 );
}

Ссылки

Размытие по гауссу - общие сведения
Реализация размытия по Гауссу на языке GLSL
Техника Screen-Space Ambient Occlusion

Что такое Depth-based blur?

#blur, #depth

11 июня 2009 (Обновление: 28 сен. 2013)

Комментарии [6]