Математика:
Описывается законом cos^4 и зависит исключительно от угла между осью и лучом. Удобно считать в координатах/расстояниях, нормированных к половине меньшего размера кадра (хотя математически - без разницы - можно и в абсолютных, только не забудьте про соотношение сторон)
Вот вам дезмос для наглдядности
https://www.desmos.com/calculator/nlvg9l3nlx
Описывается законом cos^4 и зависит исключительно от угла между осью и лучом. Удобно считать в координатах/расстояниях, нормированных к половине меньшего размера кадра (хотя математически - без разницы - можно и в абсолютных, только не забудьте про соотношение сторон)
Вот вам дезмос для наглдядности
https://www.desmos.com/calculator/nlvg9l3nlx
Desmos
cos4 vignette
Explore math with our beautiful, free online graphing calculator. Graph functions, plot points, visualize algebraic equations, add sliders, animate graphs, and more.
Алгоритм:
Тут особо нечего сказать, потому вот функция, которая возвращает интенсивность
Тут добавлены минимальное значение и усиление в параметрах, чтобы "можно было выбирать" (с).
Тут особо нечего сказать, потому вот функция, которая возвращает интенсивность
static inline float vignette_cos4(float2 uv, constant Parameters& params) {
float2 d = uv - params.center;
float2 xy = float2(d.x * params.aspect.x, d.y) * 2.0;
float f2 = params.fRel * params.fRel;
float r2 = dot(xy, xy);
float cos2 = f2 / (f2 + r2);
float V = cos2 * cos2;
return mix(params.minV, 1.0, V) * params.gain;
}
Тут добавлены минимальное значение и усиление в параметрах, чтобы "можно было выбирать" (с).
Дальше пойдут искажения на свертках: расфокусы, повороты линз, боке, продольные абберации и прочее. И это мы еще не довели наше изображение до сенсора.
Вообще, заметьте, что понимая принцип работы эффекта, нам не нужно воспроизводить физически верную симуляцию и персчитывать рейтрейсинг, а достаточно упрощенной модели, которая позволит достичь довольно близкого результата.
Вообще, заметьте, что понимая принцип работы эффекта, нам не нужно воспроизводить физически верную симуляцию и персчитывать рейтрейсинг, а достаточно упрощенной модели, которая позволит достичь довольно близкого результата.
❤5
Записали с товарищем вчера подкаст на тему книг и программирования
https://www.youtube.com/watch?v=2YRuBd02Hzg
https://www.youtube.com/watch?v=2YRuBd02Hzg
YouTube
Стоит ли читать книги программисту? Говорим о литературе, развитии, коде и опыте
В этом выпуске мы с Данилом обсуждаем книги для программистов: с чего начинать, какие стоит читать, а какие могут только запутать. Говорим о первых шагах с ZX Spectrum и «C++ для чайников», делимся опытом чтения Таненбаума, SICP, Мартина, Фаулера и др.
Затрагиваем…
Затрагиваем…
👍1
https://www.makingsoftware.com/chapters/color-spaces-models-and-gamuts
Нашел классную статью про цвета. Ну и в принципе, судя по сайту, у автора большие планы
Нашел классную статью про цвета. Ну и в принципе, судя по сайту, у автора большие планы
🔥4❤3
Так, от краски уже болит голова, да и кончилась она, возвращаюсь к искажениям.
Как я уже говорил, следующим этапом за геометрией идет PSF (Point Spread Function), который, хоть и отражает несколько разных искажений
- дефокус,
- продольная цветовая абберация,
- скос линзы,
- размытие к краю,
- кома,
- астигматизм,
- жировые полосы/царапины,
сводится к свертке с ядром, отражающим все перечисленные эффекты - разбить на части не получится правильным образом.
Тем не менее, я буду рассказывать про каждый по отдельности, а в конце соберу в один эффект.
Как я уже говорил, следующим этапом за геометрией идет PSF (Point Spread Function), который, хоть и отражает несколько разных искажений
- дефокус,
- продольная цветовая абберация,
- скос линзы,
- размытие к краю,
- кома,
- астигматизм,
- жировые полосы/царапины,
сводится к свертке с ядром, отражающим все перечисленные эффекты - разбить на части не получится правильным образом.
Тем не менее, я буду рассказывать про каждый по отдельности, а в конце соберу в один эффект.
❤4
Небольшое отступление:
Есть два эффекта, которые применить к обычному видео проблематично (возможно, нейронка поможет):
1 - Глубина резкости (если есть карта глубин для каждого кадра, то, в принципе, возможно)
2 - Искажения проекции на разных фокусных расстояния
Так как их нормальным путем реализовать не получится, то и рассказывать я о них не буду, но если интересна физика/геометрия процесса - напишите - распишу на пальцах
Есть два эффекта, которые применить к обычному видео проблематично (возможно, нейронка поможет):
1 - Глубина резкости (если есть карта глубин для каждого кадра, то, в принципе, возможно)
2 - Искажения проекции на разных фокусных расстояния
Так как их нормальным путем реализовать не получится, то и рассказывать я о них не буду, но если интересна физика/геометрия процесса - напишите - распишу на пальцах
❤5
Media is too big
VIEW IN TELEGRAM
Дефокус
Размытие объекта на картинке из-за непопадания его проекции в фокус.
В идеале - именно объекта, а не всей картинке - так будет физически вернее. Но для этого нам нужна карта глубин, коей как правило, нет, поэтому будем делать просто размытие всей картинки.
Размытие объекта на картинке из-за непопадания его проекции в фокус.
В идеале - именно объекта, а не всей картинке - так будет физически вернее. Но для этого нам нужна карта глубин, коей как правило, нет, поэтому будем делать просто размытие всей картинки.
❤3🔥1
Media is too big
VIEW IN TELEGRAM
Принцип:
Когда объект уходит из фокуса, то лучи от него не сходятся в точку на плоскости сенсора, где они должны быть, а в круг, что приводит к размытию картинки.
Причем в зависимости от расстояния до плоскости резкости размытие должно быть больше (но мы упростим и будем делать везде одинаковое).
То есть радиус диска ядра свертки зависит от диафрагмы, расстояния до плоскости резкости и от шага пикселя/зерна на сенсоре
Когда объект уходит из фокуса, то лучи от него не сходятся в точку на плоскости сенсора, где они должны быть, а в круг, что приводит к размытию картинки.
Причем в зависимости от расстояния до плоскости резкости размытие должно быть больше (но мы упростим и будем делать везде одинаковое).
То есть радиус диска ядра свертки зависит от диафрагмы, расстояния до плоскости резкости и от шага пикселя/зерна на сенсоре
❤2🔥2
This media is not supported in your browser
VIEW IN TELEGRAM
Алгоритм:
1. Можно пойти простым путем и взять MPSImageGaussianBlur - это даже будет выглядеть правдоподобно на малых значениях размытия, но неестественно на больших. Зато будет очень быстро
2. Можно пойти сложным путем и гонять свертку диском. Честно это делать супер дорого, поэтому вместо этого ограничиваются псевдослучайными равномерными сэмплами по нему (иначе вам придется гонять террабайты в секунду - видюха будет не рада такому). Зато у вас будет +/- красивое боке, кастомные формы диафрагмы. Ну и остальные эффекты требуют кастомной свертки
На видео сравнение, как выглядит гаусс и диск (разница, думаю, очевидна)
1. Можно пойти простым путем и взять MPSImageGaussianBlur - это даже будет выглядеть правдоподобно на малых значениях размытия, но неестественно на больших. Зато будет очень быстро
2. Можно пойти сложным путем и гонять свертку диском. Честно это делать супер дорого, поэтому вместо этого ограничиваются псевдослучайными равномерными сэмплами по нему (иначе вам придется гонять террабайты в секунду - видюха будет не рада такому). Зато у вас будет +/- красивое боке, кастомные формы диафрагмы. Ну и остальные эффекты требуют кастомной свертки
На видео сравнение, как выглядит гаусс и диск (разница, думаю, очевидна)
🔥4❤1
Media is too big
VIEW IN TELEGRAM
Сечение пучка - боке принимает форму диафргамы.
Принцип
По сути ядро свертки - это проекция формы диафрагмы, соответственно, в зависимотсти от числа и формы лепестков вы будете получать разные фигуры на боке. Плюс чем сильнее закрыта диафргма, тем четче эта форма будет. Правда при этом у вас вырастет глубина резкости, но мы ее не имитируем.
Принцип
По сути ядро свертки - это проекция формы диафрагмы, соответственно, в зависимотсти от числа и формы лепестков вы будете получать разные фигуры на боке. Плюс чем сильнее закрыта диафргма, тем четче эта форма будет. Правда при этом у вас вырастет глубина резкости, но мы ее не имитируем.
❤3
Алгоритм
Тут по сути мы модифицируем форму ядра свретки, отбрасывая точки за пределами формы чем-нибудь типа
Что можно еще "поломать":
- сделать скругление маски через SDF например
- сделать искажение формы, например неоднородным масштабом и поворотом
- исказить один из секторов лепестков
- сделать любую форму в принципе
Тут по сути мы модифицируем форму ядра свретки, отбрасывая точки за пределами формы чем-нибудь типа
// Regular n-gon aperture test (inscribed in unit circle). blades<3 → circle (always inside).
inline bool insideAperture(float2 d, int blades) {
if (blades < 3) return true; // circle
float N = float(blades);
// polar angle
float a = atan2(d.y, d.x);
// sector size and half-sector
float sector = 2.0f * M_PI_F / N;
float halfSec = 0.5f * sector;
// wrap angle to [0, sector)
float m = fmod(a + M_PI_F, sector);
if (m < 0.0f) m += sector;
// offset to nearest edge normal (in [-half, half])
float delta = m - halfSec;
// allowed radius along this direction for polygon with circumradius=1
float rAllowed = cos(M_PI_F / N) / max(cos(delta), 1e-4f);
float r = length(d);
return r <= rAllowed;
}
Что можно еще "поломать":
- сделать скругление маски через SDF например
- сделать искажение формы, например неоднородным масштабом и поворотом
- исказить один из секторов лепестков
- сделать любую форму в принципе
🔥3
Media is too big
VIEW IN TELEGRAM
Вот эти вот звездочки - это дифракция
Принцип:
Возникает она тем сильнее, чем сильнее у нас закрыта диафрагма. Число лучей зависит от числа лепестков, а вид - от их формы.
Как видно из названия, основано искажение на дифракции: в нашем случае - огибании грани лепестка, что даёт вдоль её нормали усиления, формируя направленные лучи.
Для круга симметрия полная - направленных пиков нет, только свечение или кольца (их в примере нет, но, думаю, вы их видели на фото и глазами: когда на фонари таращились).
Принцип:
Возникает она тем сильнее, чем сильнее у нас закрыта диафрагма. Число лучей зависит от числа лепестков, а вид - от их формы.
Как видно из названия, основано искажение на дифракции: в нашем случае - огибании грани лепестка, что даёт вдоль её нормали усиления, формируя направленные лучи.
Для круга симметрия полная - направленных пиков нет, только свечение или кольца (их в примере нет, но, думаю, вы их видели на фото и глазами: когда на фонари таращились).
❤5
Алгоритм:
Тут мы не трогаем свертку, а делаем блюр вдоль каждого луча (перпендикулярно лепестку). При этом каждую прочитанную точку мы проверяем на яркость и, если она недостаточная, игнорируем ее вклад. Таким образом "звездочки" будут только от якрих источников света.
Можно в принципе сделать нелинейную функцию, чтобы ближе к источнику света луч звездочки был более ярким, чем по мере удаления.
Дополнительно можете сделать еще небольшой блюр перпендикулярно направлению лучей звезды.
Проблема этого эффекта в том, что, если его считать честно, он выходит довольно тяжелым, поэтому можно делать в низком качестве на первью и честно пересчитывать для экспорта.
Кстати, пришла идея как можно ускорить, сделав в несколько проходов, но потребуется сильно больше памяти:
1 - Вытаскиваем в одтельную текстуру меньшего размера (не более чем в два раза) яркие пиксели - сразу уменьшаем нагрузку на пересчет яркости
2 - Делаем несколько копий, повернутых в нужных направлениях
3 - По каждой пробегаем одномерным ядром (вертикальным или горизонтальным)
4 - Поворачиваем обратно
5 - Компилируем поверх исходной картинки или в еще одну и ее подблюриваем гаусом, а потом накладываем на исходную
Не факт, что это лучшее решение, но что пришло в голову быстро
Тут мы не трогаем свертку, а делаем блюр вдоль каждого луча (перпендикулярно лепестку). При этом каждую прочитанную точку мы проверяем на яркость и, если она недостаточная, игнорируем ее вклад. Таким образом "звездочки" будут только от якрих источников света.
Можно в принципе сделать нелинейную функцию, чтобы ближе к источнику света луч звездочки был более ярким, чем по мере удаления.
Дополнительно можете сделать еще небольшой блюр перпендикулярно направлению лучей звезды.
Проблема этого эффекта в том, что, если его считать честно, он выходит довольно тяжелым, поэтому можно делать в низком качестве на первью и честно пересчитывать для экспорта.
Кстати, пришла идея как можно ускорить, сделав в несколько проходов, но потребуется сильно больше памяти:
1 - Вытаскиваем в одтельную текстуру меньшего размера (не более чем в два раза) яркие пиксели - сразу уменьшаем нагрузку на пересчет яркости
2 - Делаем несколько копий, повернутых в нужных направлениях
3 - По каждой пробегаем одномерным ядром (вертикальным или горизонтальным)
4 - Поворачиваем обратно
5 - Компилируем поверх исходной картинки или в еще одну и ее подблюриваем гаусом, а потом накладываем на исходную
Не факт, что это лучшее решение, но что пришло в голову быстро
🔥4
This media is not supported in your browser
VIEW IN TELEGRAM
Астигматизм
Немного отличается от того, что у вас, но суть +/- та же - изображение смазывается.
Есть два вида:
1 - тангенциальный (вдоль радиуса)
2 - радиальный (он же саггитальный) - вдоль окружности
Принцип:
Как мы уже знаем, идеально все работает только вдоль оптической оси, вне ее лучи фокусируются как правило вне соответствующей оси (если провести от исходной точки через центр условной линзы) из-за чего объекты так или иначе искажаются (вспоминаем геометрические искажения) и становятся смазанными.
Можно было бы копнуть глубже и рассказать про S и T фокусы, но я тут про общие принципы и реализацию рассказываю, а не школьный курс физики)))
Немного отличается от того, что у вас, но суть +/- та же - изображение смазывается.
Есть два вида:
1 - тангенциальный (вдоль радиуса)
2 - радиальный (он же саггитальный) - вдоль окружности
Принцип:
Как мы уже знаем, идеально все работает только вдоль оптической оси, вне ее лучи фокусируются как правило вне соответствующей оси (если провести от исходной точки через центр условной линзы) из-за чего объекты так или иначе искажаются (вспоминаем геометрические искажения) и становятся смазанными.
Можно было бы копнуть глубже и рассказать про S и T фокусы, но я тут про общие принципы и реализацию рассказываю, а не школьный курс физики)))
❤4
This media is not supported in your browser
VIEW IN TELEGRAM
Алгоритм
Cчитаем параметры пространства, и когда считаем точки для свертки - применяем его
Cчитаем параметры пространства, и когда считаем точки для свертки - применяем его
struct AstigCtx {
float2 e_r;
float2 e_t;
float s_r;
float s_t;
};
struct Parameters {
float2 invSize;
float2 opticalCenter;
float astigK;
};
inline AstigCtx astigSetup(float2 uv, Parameters params) {
AstigCtx C;
float ar = params.invSize.y / params.invSize.x;
float2 df = uv - params.opticalCenter;
float2 dfIso= float2(df.x * ar, df.y);
float rhoN = clamp(length(dfIso) * 2.0f, 0.0f, 1.0f);
float2 rIso = (length(dfIso) > 1e-6f) ? normalize(dfIso) : float2(1.0f, 0.0f);
C.e_r = normalize(float2(rIso.x / ar, rIso.y));
C.e_t = float2(-C.e_r.y, C.e_r.x);
float mag = fabs(params.astigK) * (rhoN * rhoN);
float a = 1.0f + mag;
C.s_r = (params.astigK >= 0.0f) ? (1.0f / a) : a;
C.s_t = (params.astigK >= 0.0f) ? a : (1.0f / a);
return C;
}
inline float2 astigApply(float2 d, AstigCtx C) {
float dr = dot(d, C.e_r);
float dt = dot(d, C.e_t);
return dr * C.s_r * C.e_r + dt * C.s_t * C.e_t;
}
❤3👏1
Из искажений входной оптики осталось всего ничего:
- кома
- продольная цветовая абберация - засветы - виньетка на сенсоре Потом пойдет интереснее. Пока можете выбрать, что интереснее:
- кома
- продольная цветовая абберация - засветы - виньетка на сенсоре Потом пойдет интереснее. Пока можете выбрать, что интереснее:
Anonymous Poll
60%
пленочная камера
30%
ТВ трубка
10%
ПЗС матрица
🔥2