Существует ли поддельный алгоритм сглаживания с использованием буфера глубины?

Недавно я реализовал алгоритм FXAA в своем приложении OpenGL. Я еще не полностью понял этот алгоритм, но знаю, что он использует данные о контрасте конечного изображения для выборочного применения размытия. В качестве эффекта постобработки это имеет смысл. B поскольку я использую отложенное затенение в своем приложении, у меня уже есть текстура глубины сцены. Используя это, может быть намного проще и точнее найти края для применения размытия.

Итак, существует ли известный алгоритм сглаживания, использующий текстуру глубины вместо конечного изображения для поиска краев? Под подделками я подразумеваю алгоритм сглаживания, основанный на пиксельной, а не на вершинной основе.


person danijar    schedule 28.01.2013    source источник
comment
Мы сделали это. Он позволяет раннюю классификацию краев для постобработки, но имеет проблемы с обнаружением краев в очень тонкой геометрии, где глубина изменяется недостаточно. У меня нет непосредственной ссылки, мы просто применили наш обычный метод, но с буфером глубины в качестве входных данных (может быть, мы представили это на GDC, но у меня нет под рукой ссылки).   -  person JasonD    schedule 29.01.2013
comment
@ Джейсон Д. Спасибо, это начало. Я сам реализую что-то подобное в ближайшие дни.   -  person danijar    schedule 30.01.2013


Ответы (1)


После некоторых исследований я обнаружил, что моя идея широко используется уже в отложенных рендерерах. Я решил опубликовать этот ответ, потому что придумал свою собственную реализацию, которой хочу поделиться с сообществом.

На основе градиентных изменений глубины и угловых изменений нормалей к пикселю применяется размытие.

// GLSL fragment shader

#version 330

in vec2 coord;
out vec4 image;

uniform sampler2D image_tex;
uniform sampler2D position_tex;
uniform sampler2D normal_tex;
uniform vec2 frameBufSize;

void depth(out float value, in vec2 offset)
{
    value = texture2D(position_tex, coord + offset / frameBufSize).z / 1000.0f;
}

void normal(out vec3 value, in vec2 offset)
{
    value = texture2D(normal_tex, coord + offset / frameBufSize).xyz;
}

void main()
{
    // depth

    float dc, dn, ds, de, dw;
    depth(dc, vec2( 0,  0));
    depth(dn, vec2( 0, +1));
    depth(ds, vec2( 0, -1));
    depth(de, vec2(+1,  0));
    depth(dw, vec2(-1,  0));

    float dvertical   = abs(dc - ((dn + ds) / 2));
    float dhorizontal = abs(dc - ((de + dw) / 2));
    float damount = 1000 * (dvertical + dhorizontal);

    // normals

    vec3 nc, nn, ns, ne, nw;
    normal(nc, vec2( 0,  0));
    normal(nn, vec2( 0, +1));
    normal(ns, vec2( 0, -1));
    normal(ne, vec2(+1,  0));
    normal(nw, vec2(-1,  0));

    float nvertical   = dot(vec3(1), abs(nc - ((nn + ns) / 2.0)));
    float nhorizontal = dot(vec3(1), abs(nc - ((ne + nw) / 2.0)));
    float namount = 50 * (nvertical + nhorizontal);

    // blur

    const int radius = 1;
    vec3 blur = vec3(0);
    int n = 0;
    for(float u = -radius; u <= +radius; ++u)
    for(float v = -radius; v <= +radius; ++v)
    {
        blur += texture2D(image_tex, coord + vec2(u, v) / frameBufSize).rgb;
        n++;
    }
    blur /= n;

    // result

    float amount = mix(damount, namount, 0.5);
    vec3 color = texture2D(image_tex, coord).rgb;
    image = vec4(mix(color, blur, min(amount, 0.75)), 1.0);
}

Для сравнения, это сцена без сглаживания.

сцена без сглаживания

Это результат применения сглаживания.

сцена со сглаживанием

Возможно, вам придется просмотреть изображения в полном разрешении, чтобы оценить эффект. На мой взгляд, результат достаточен для простой реализации. Лучше всего то, что неровных артефактов при движении камеры почти нет.

person danijar    schedule 08.03.2013
comment
есть скриншоты как это выглядит с шейдером и без? - person Alnitak; 09.03.2013
comment
@SAKrisT Это расстояние прорисовки. Однако я предлагаю передать этот параметр как унифицированный. - person danijar; 01.12.2013
comment
@SAKrisT Текстура положения находится в пространстве обзора, поэтому значения глубины находятся между ближней и дальней плоскостями. Поскольку мы просто хотим найти разрывы в глубине, достаточно деления на дальнюю плоскость. Точнее было бы учесть ближний самолет (x - near) / (far - near). Кроме того, лучшим способом получения глубины будет чтение буфера глубины и преобразование его значений в линейное пространство. - person danijar; 01.12.2013
comment
@danijar спасибо за объяснение! У меня есть вопрос по стеку, может быть, вы можете помочь. Не могли бы вы посмотреть, пожалуйста? - person Volodymyr B.; 02.12.2013
comment
Найдена эта реализация FXAA. Может быть, будет полезно для вас. - person Volodymyr B.; 11.12.2013
comment
Можете ли вы предоставить мне полную кодовую базу? Реализация AA вместе с тестовой программой, формирующей заданное изображение. Я работаю в области рандомизированных алгоритмов. Мои текущие результаты могут быть полезны в методах АА, основанных на выборке. Я хочу проверить это. Не вдаваясь в подробности openGL. Вот почему я прошу об этом. ТИА - person manmatha; 24.06.2019