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

Кое-что о размытии изображения с помощью шейдеров. (комментарии) (2 стр)

Страницы: 1 2 3 Следующая »
#15
20:06, 30 сен. 2013

В статье не хватает распределения, где вклад пикселя убывает с квадратом расстояния. Я реализовал это размытие на GLSL в виде такой функции:

vec4 Blur(sampler2D s, vec2 center, float r, vec2 dir)
{
  vec4 sum=vec4(0.0);
  float rn=r/length(dir), rn2=rn*rn;
  for(float i=-rn; i<=rn; i++) sum+=texture(s, center+i*dir)*(rn2-i*i);
  return sum*0.75/(rn2*rn);
}
Это размытие по любому направлению dir с любым радиусом r. dir должен быть единичным: если больше, то цикл будет перепрыгивать через пиксели и будет смотреться не очень, а если длина меньше единицы, то просто нет смысла этого делать. Производительность всего на 1%-2% ниже, чем у варианта размытия с одинаковым вкладом каждого пикселя, зато выглядит намного лучше.
Чтобы получить размытие всего изображения по обеим осям надо пройтись по нему 2 раза этим алгоритмом, где векторы dir этих проходов перпендикулярны.


#16
20:12, 30 сен. 2013

Mikle
Грубо говоря - представь карту высот. Низы надо разукрасить синим (водой), середину - зеленым (трава), вершины гор - белым (снег). То есть высота на карте высот, это по сути дела "индекс" цвета (от 0 до 255), а само значение цвета надо хранить в отдельной текстуре, либо одномерной 1х256, либо, возможно, двухмерной, если надо для разнообразия задавать какое-нибудь смещение.

Но это всё оффтоп в данной ветке форума, просто хочу знать, 8..10 выборок в полноэкранном шейдере - это много или нормально. С проверкой трудности, в виртуальной машине производительность не та, а версии под мак - основной системе - нет и вряд ли будет в ближайшее время.

#17
21:03, 30 сен. 2013

Вопрос мой, скорее всего, отпадает. Испытал в виртуальной машине. 30 (тридцать) последовательных зависимых выборок при разрешении FullHD 1920x1080 выдали 45 фпс. И это в виртуальной машине. Хотя дрова пробрасывают всё в хост-машину, так что удивляться нечему. Графика - Intel HD4000.

Код выглядит вот так.

    while (f < 30.0) {
        f = f + 1.001;
        c = c + texture2D(u_sampler, uv + vec2(c.r+c.g+c.b)*0.01 );
    };

30 выборок, текстурные координаты каждой выборки берутся из результатов предыдущей. 45 fps на 1080p. Intel HD4000. Счастье то какое.

Кстати, красиво получилось:

+ Показать

P.S. Прошу прощения за весь этот оффтоп.

#18
10:25, 1 окт. 2013

Роман Шувалов
> 30 выборок, текстурные координаты каждой выборки берутся из результатов
> предыдущей. 45 fps на 1080p. Intel HD4000.
Скорость выборок очень сильно зависит от локальности. Т. е. если квадрат пикселей 16х16 делает выборки примерно из одного места текстуры, то попадает в кеш и все ок. А если широко или, вообще, рандомно, то может быть просадка по производительности.

А по теме, было недавно про гауссово размытие: http://www.gamedev.ru/code/forum/?id=174569, я там писал свои варианты.

#19
3:41, 4 окт. 2013

Ooooo....

я вот что с помнил  http://www.gamedev.ru/code/forum/?id=149191

и к чему прошел тогда...

+ Показать

4 прохода для X и 4 прохода для Y.

const float countPass = 4;
const float Gb[] = { 12.442, 5.3114, 26.169, 3.7436};
const float Gc[] = { 1.2, 2.7, 58.42, 66.5 };

const float kA[] = { 0.1348,0.2481,0.3669,0.1867 };
const float kB[] = { 0.2494,0.2453,0.2155,0.229 };
const float kC[] = { 0.1507,0.2834,0.0519,0.1181 };


for( i=0;i<countPass; i++ )
{
  vec2 step(Gb[i],Gc[i])
  vec3 K( kA[i], kB[i], kC[i] )
  passX   step,K; 
  passY   step,K; 
}
Для RGB10_2  очень быстро.
Пробовал делать 3 проходов но уже с 7 выборками почему то получалось медленней,  да и качество хуже.
Это не идеальный фильтр гауса это его приближение свертками ( причем не оптимальное ).
Ну и это всего лишь был эксперимент.
+ Показать

Еще есть фича можно перед началом изображение обработать как eColor = exp(color*A+B)-1  обработать фильтром, а потом получить color=(log(eColor+1)-B)/A; А и B можно взять любыми причем для каждого канала свое значение.

#20
12:06, 4 окт. 2013

Если уж на то пошло, то в случае фиксированного количества вычисление дельты и других координат для выборки нужно переносить в вершинный шейдер.

#21
12:22, 4 окт. 2013

gammaker
> float rn=r/length(dir), rn2=rn*rn;
кстати, может просто

float rn2 = r/squaredLength(dir),

float squaredLength(float3 dir)
{
return dot(dir, dir);
}

или я туплю

#22
12:25, 4 окт. 2013

Sergio

Есть предложение дописать вариант на CS

#23
12:25, 4 окт. 2013
 float rn=r/length(dir), rn2=rn*rn; 
тогда уж
 float rn2 = r*r/dot(dir, dir); 
#24
14:50, 4 окт. 2013

В статье никак не объясняется правомерность перехода от большого количества выборок в один проход к меньшему количеству выборок в два прохода. Как я понимаю, результаты получаются вовсе не математически эквивалентные, поэтому хотелось бы посмотреть на разницу. Плюс не понятно, как влияет порядок проходов(сначала горизонтальный, потом вертикальный или наоборот).

#25
16:41, 4 окт. 2013

Suslik
> В статье никак не объясняется правомерность перехода от большого количества
> выборок в один проход к меньшему количеству выборок в два прохода. Как я
> понимаю, результаты получаются вовсе не математически эквивалентные, поэтому
> хотелось бы посмотреть на разницу.
Это все очень просто проверяется через Фурье-образы. Для одного фильтра они строятся элементарно, как сумма нескольких косинусов. Для двух -- просто перемножаем образы обоих фильтров. Дальше сравниваем с Гауссом и сразу видим ошибку.

> Плюс не понятно, как влияет порядок проходов(сначала горизонтальный, потом
> вертикальный или наоборот).
Никак (с точностью до ошибок округления). Можно даже чередовать: первый фильтр по X, потом первый по Y, потом второй по X и т. д. Также фильтры вдоль одной координаты можно менять местами. А все потому, что умножение в Фурье-пространстве коммутативно.

#26
18:05, 4 окт. 2013

Mr F
> кстати, может просто
> float rn2 = r/squaredLength(dir),
Ну во-первых r в квадрате тогда будет, а во-вторых rn же тоже используется. Да и вообще самый тормоз в цикле.

Suslik
> В статье никак не объясняется правомерность перехода от большого количества
> выборок в один проход к меньшему количеству выборок в два прохода. Как я
> понимаю, результаты получаются вовсе не математически эквивалентные, поэтому
> хотелось бы посмотреть на разницу. Плюс не понятно, как влияет порядок
> проходов(сначала горизонтальный, потом вертикальный или наоборот).
А какая разница? Выглядит хорошо, проблем с качеством нет, производительность выше, так как меньше операций => профит.
Я предположил, а потом и на практике убедился, что любые два перпендикулярные направления размытия дают одинаковый результат (по крайней мере на глаз).

#27
18:08, 4 окт. 2013

Если я понял, то два прохода отличаются от одного с большим количеством выборок формой ядра: для двух проходов это квадрат(в общем случае - ромб), для одного - круг. Короче если размыть точку должен бы получиться круг, а получится квадрат - судя по всему, это и есть артефакт, который получается из-за меньших вычислительных затрат.

#28
22:54, 4 окт. 2013

Sergio
> Если уж на то пошло, то в случае фиксированного количества вычисление дельты и
> других координат для выборки нужно переносить в вершинный шейдер.
Оо что то об этом тогда не думал, хотя можно вычислить дельту и на CPU.

Suslik
> Если я понял, то два прохода отличаются от одного с большим количеством выборок
> формой ядра: для двух проходов это квадрат(в общем случае - ромб), для одного -
> круг. Короче если размыть точку должен бы получиться круг, а получится квадрат
> - судя по всему, это и есть артефакт, который получается из-за меньших
> вычислительных затрат.
Два прохода  получается матрица M[k.j] = C[k]*C[j]  - не знаю как она называется, но название точно есть.
Если фильтр можно представить в виде такой матрице то будет точное соответствие( с учетом точности вычислений).
Для exp(-L*L) получим  M[k.j] = exp(-k^2-j^2) = exp(-k^2)*exp(-j^2);  C[k] = exp(-k^2);

#29
6:01, 5 окт. 2013

Suslik
> Плюс не понятно, как влияет порядок проходов(сначала горизонтальный, потом
> вертикальный или наоборот).

Никак ибо сепарабельно.

> Если я понял, то два прохода отличаются от одного с большим количеством выборок
> формой ядра: для двух проходов это квадрат(в общем случае - ромб), для одного -
> круг.

Оно как бы для простоты в обоих случаях квадрат

Страницы: 1 2 3 Следующая »
ПрограммированиеФорумГрафика

Тема в архиве.