Прогаем с кенгурой
229 subscribers
190 photos
190 videos
17 files
156 links
Сидим с кенгурой под горой, запекаем текстуры...

{ программирование, процедурная генерация, графика, аудио, образование и немного про специфичные игры }

https://gostrobrod.dev
Download Telegram
Media is too big
VIEW IN TELEGRAM
Сечение пучка - боке принимает форму диафргамы.

Принцип
По сути ядро свертки - это проекция формы диафрагмы, соответственно, в зависимотсти от числа и формы лепестков вы будете получать разные фигуры на боке. Плюс чем сильнее закрыта диафргма, тем четче эта форма будет. Правда при этом у вас вырастет глубина резкости, но мы ее не имитируем.
3
Алгоритм
Тут по сути мы модифицируем форму ядра свретки, отбрасывая точки за пределами формы чем-нибудь типа

// 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 - Компилируем поверх исходной картинки или в еще одну и ее подблюриваем гаусом, а потом накладываем на исходную

Не факт, что это лучшее решение, но что пришло в голову быстро
🔥4
This media is not supported in your browser
VIEW IN TELEGRAM
Астигматизм

Немного отличается от того, что у вас, но суть +/- та же - изображение смазывается.

Есть два вида:
1 - тангенциальный (вдоль радиуса)
2 - радиальный (он же саггитальный) - вдоль окружности

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

Можно было бы копнуть глубже и рассказать про S и T фокусы, но я тут про общие принципы и реализацию рассказываю, а не школьный курс физики)))
4
This media is not supported in your browser
VIEW IN TELEGRAM
Алгоритм

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
Разбираюсь с build123d, чтобы процедурно генерить ракушки
🔥2
У меня на второй работе происходит жесткий церебральный коитус с экспортом и женитьбой разных кодеков на разных андроидофонах, поэтому пока посты про видео на паузе.

Вот зато ракушку сделал в перерыве на build123d
🤗4🤓1
😁3😢3🤔2
This media is not supported in your browser
VIEW IN TELEGRAM
Кома

Смещение пучка из центра пятна боке - получаются свеого рода кометы.
👍1
Принцип

Из-за неидеальности оптики вне центральной оптической оси лучи фокусируются неравномерно (см на картинке).

Соотвественно, чем дальше от оси, тем сильнее эффект.
👍1
Алгоритм

1. Как и с астигматизмом, сначала рассчитываем параметры радиально-тангенциального поля в точке (можно расширить функцию для астигаматизма
2. Для каждой точки свертки пересчитываем, куда она смещается


struct AstigCtx {
float2 e_r; // radial unit in uv metric
float2 e_t; // tangential unit (perp)
float s_r; // radial scale
float s_t; // tangential scale
float rhoN; // normalized field height (0 center .. 1 edge)
};

inline AstigCtx astigSetup(float2 uv, constant Parameters& P) {
AstigCtx C;

float ar = P.invSize.y / P.invSize.x; // width/height
float2 oc = P.opticalCenter;
float2 df = uv - oc;
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);
float2 e_r = normalize(float2(rIso.x / ar, rIso.y));
float2 e_t = float2(-e_r.y, e_r.x);

float mag = fabs(P.astigK) * (rhoN * rhoN);
float a = 1.0f + mag;
float s_r = (P.astigK >= 0.0f) ? (1.0f / a) : a;
float s_t = (P.astigK >= 0.0f) ? a : (1.0f / a);

C.e_r = e_r;
C.e_t = e_t;
C.s_r = s_r;
C.s_t = s_t;
C.rhoN = rhoN;

return C;
}

inline float2 comaApply(float2 d, AstigCtx C, float comaK) {
if (fabs(comaK) < 1e-6f) return d;
// Project onto radial/tangential axes
float dr = dot(d, C.e_r);
float dt = dot(d, C.e_t);
// Magnitude grows ~ rho^3 across the field (third-order behavior)
float mag = comaK * (C.rhoN * C.rhoN * C.rhoN);
// Quadratic skew in pupil coordinates → "comet" shape in image PSF
float2 delta = ( (dr*dr - 0.5f*dt*dt) * C.e_r
+ (dr*dt) * C.e_t );
return d + mag * delta;
}
👍2
Вообще, как видите, сверточные эффекты тоже опираются на линейную оптику, но, если для идеального фокуса мы можем использовать исключительно пересчет координат, то для объектов вне фокуса необходимо применять свертку и тут все крутится вокруг ядра этой свертки (ее формы, центра и тд).
👍3
Тут в соседнем чате скинули статью про настроечные таблицы и я вспомнил, что давно когда-то пробовал их использовать для реверсинжинирига цветокоррекций и эффектов, но они справлялись не очень (не для того их делали), поэтому пришлось сделать свою.

Из минусов - тут нет разного сатурейшена по цветам, поэтому для некоторых эффектов она не подходила, но подходил слайс (y)UV.

PS: серое поле между шахматной доской и угловым градиентом - тоже шахматная доска 1х1. Зачем-то она тоже была нужна, как и все остальные поля - не помню уже точно (лет 10 назад это было)
🔥1
This media is not supported in your browser
VIEW IN TELEGRAM
Полевая кривизна
При смещении от центра начинает усиливаться расфокус (на видео утрированно)
🔥3
This media is not supported in your browser
VIEW IN TELEGRAM
Принцип
Если плоскость изображения (сенсор) плоская, а поверхность наилучшего фокуса - сферическая (как глаз например), то дефокус будет увеличиваться с удаленем от центра

Алгоритм
Считаем радиус ядра свертки в зависимости от расстояния до центра и применяем его
👍1
This media is not supported in your browser
VIEW IN TELEGRAM
Продольная цветовая абберация
Изменение оттенка у объектов до и после плоскости фокуса

Пример не совсем корректный, но для корректного примера нам нужна картинка/видео с картой глубин - тут мы просто делаем имитацию
👍1
This media is not supported in your browser
VIEW IN TELEGRAM
Принцип
Из-за разного преломления лучей разной длины волны либо красные (недолет фокуса), либо синие (перелет) лучи будут вылетать из точки фокуса, что даст определнный оттенок.

Алгоритм
Считаем отдельные смещения для сэмплинга каждого канала. Потом собираем RGB
👍1
Яблоки релизнули иос26. Теперь телефон будет греться и садиться просто по факту своего существования 🤠