es
Feedback

¡No caigas en manos de tramposos! Telemetrio encuentra y marca estos canales 👉 Si quieres ver la etiqueta, suscríbete 👈

Прогаем с кенгурой

Прогаем с кенгурой

Ir al canal en Telegram

Сидим с кенгурой под горой, запекаем текстуры... { программирование, процедурная генерация, графика, аудио, образование и немного про специфичные игры } https://gostrobrod.dev https://boosty.to/gostrobrod

Mostrar más
236
Suscriptores
Sin datos24 horas
Sin datos7 días
+130 días
Archivo de publicaciones
Прежде чем начать пердолить видео, в идеале, нужно понимать, что именно, в каком случае и в какой последовательности нужно эт
Прежде чем начать пердолить видео, в идеале, нужно понимать, что именно, в каком случае и в какой последовательности нужно это делать. Я набросал очень высокоуровневую схему, которая примерно показывает этапы жизни видео, когда его может потрепать эта самая жизнь. Еще раз, это очень высокоуровневая схема, и в ней не учитывается, что вы можете снять видео на пленку, показать по тв, где записать сначала на VHS, потом оцифровать, несколько раз перекодировать, послать сигнал в космос, потом принять и показать на каком-нибудь осциллографе. Тем не менее эта схема дает (надеюсь) понятие, что мы получаем видеосигнал, переводим в какую-то форму для хранения, передаем, читаем обратно в форму для воспроизведения и, наконец, воспроизводим. На каждом этапе видео может быть искажено, а искажения могут наложиться. То есть итоговый глитч может быть не просто "пленочным"/"цифровым"/"VHS" и тд, хотя это и удобно для продакт-дизайнеров, а комбинацией отдельных поломок сигнала на разных этапах.

Крабэ недоволен
Крабэ недоволен

Там вышел гпт5, но мы все еще в безопасности
Там вышел гпт5, но мы все еще в безопасности

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

Абсолютный оффтопик, но смешно https://youtu.be/hlm17Pqvd4o?si=ruh5Aswvka1fW7JJ

А. Забыл один бесполезные для практики, но все равно интересный факт. Вот тут на графике изображены значения для базовых цвет
А. Забыл один бесполезные для практики, но все равно интересный факт. Вот тут на графике изображены значения для базовых цветов, необходимые для получения цвета заданной длины волны. Как это делали: человеку светили светом определенной длины волны и давали крутить RGB ручки, чтобы он намешал такой же. Так вот на участке между λb и λg человек выкручивал ручку для красного ниже базового значения (условного нуля).

Ну и кислотное безумие на последок, как заключение темы цветов и градиентов. Дальше могу рассказать про глитчи и искажения в разных видео носителях. Заодно и сам вспомню.

Вот вам файлик со всеми функциями и конверсиями для поиграться.

Для совсем безумцев, кто считает, что можно смешивать в цилиндрических моделях (HSL, HSV) - нельзя. Потому что получите вы не
Для совсем безумцев, кто считает, что можно смешивать в цилиндрических моделях (HSL, HSV) - нельзя. Потому что получите вы не переход между двумя цветами, а карусель по hue (это угол). Хотя если вам нужно больше безумия - то можно)))

Итого. Чтобы сделать достаточно простой/быстрый и при этом качественный градиент, нужно его делать в linearRGB и мешать не линейно, а через smoothstep. В итоге получится максимально быстро и красиво.

А вот с lab (сверху) уже есть
А вот с lab (сверху) уже есть

На этом можно было бы остановиться, но это, во-первых, скучно, во-вторых, не правильно, поэтому пойдем глубже и будем мешать
На этом можно было бы остановиться, но это, во-первых, скучно, во-вторых, не правильно, поэтому пойдем глубже и будем мешать цвета в разных цветовых моделях. Как минимум, увидим, как цвета лежат где Начнем с yuv - как видим, разницы нет. C XYZ, кстати, - тоже

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

inline float3 smoothLerp(float3 a, float3 b, float t)
{
    t = clamp(t, 0.0, 1.0);
    t = t * t * (3.0 - 2.0 * t);
    return a + (b - a) * t;
}


float3 gradientSmooth4(float3 r, float3 g, float3 b, float x)
{
    float3 seg0 = smoothLerp(r, g, x * 3.0);
    float3 seg1 = smoothLerp(g, b, x * 3.0 - 1.0);
    float3 seg2 = smoothLerp(b, r, x * 3.0 - 2.0);

    return select(select(seg0, seg1, x > 1.0 / 3.0), seg2, x > 2.0 / 3.0);
}
Как видим, тут (сверху) результат даже лучше, чем у катмул-рома (снизу)

Сверху катмулл-ром, снизу - линейная интерполяция float3 catmullRom(float3 r, float3 g, float3 b, float3 a, float x, float t0
Сверху катмулл-ром, снизу - линейная интерполяция

float3 catmullRom(float3 r, float3 g, float3 b, float3 a, float x, float t0) {
    float t1 = t0 + 1.0 / 3.0;
    float t2 = t1 + 1.0 / 3.0;
    float t3 = t2 + 1.0 / 3.0;
    float t = x;
    
    float3 D0 = r;
    float3 D1 = g;
    float3 D2 = b;
    float3 D3 = a;
        
    float3 C1 = (t1-t)/(t1-t0)*D0 + (t-t0)/(t1-t0)*D1;
    float3 C2 = (t2-t)/(t2-t1)*D1 + (t-t1)/(t2-t1)*D2;
    float3 C3 = (t3-t)/(t3-t2)*D2 + (t-t2)/(t3-t2)*D3;
    
    float3 B1 = (t2-t)/(t2-t0)*C1 + (t-t0)/(t2-t0)*C2;
    float3 B2 = (t3-t)/(t3-t1)*C2 + (t-t1)/(t3-t1)*C3;

    float3 A = (t2-t)/(t2-t1)*B1 + (t-t1)/(t2-t1)*B2;
    
    return A;
}



float3 gradientCatmullRom(float3 r, float3 g, float3 b, float x) {
    return select(select(catmullRom(b, r, g, b, x, -1.0 / 3.0), 
                         catmullRom(r, g, b, r, x, 0), 
                         x > 1.0 / 3.0),
                  catmullRom(g, b, r, g, x, 1.0 / 3.0),
                  x > 2.0 / 3.0);
}

Почему нельзя в sRGB? Цвет в нем попердолен кривой, которую можно аппроксимировать гаммой 2.2 или тупо 2 (грубо, но приемелем
Почему нельзя в sRGB? Цвет в нем попердолен кривой, которую можно аппроксимировать гаммой 2.2 или тупо 2 (грубо, но приемелемо для графических редакторов). То есть значения в канале идут нелинейно, а значит при их смешении будут искажения. Вот тупой вариант:

float3 lrgb = sqrt(gradient4(r * r, g * g, b * b, uv.x));
На картинке снизу sRGB, сверху - псевдо-linear RGB. Как видим, переходы стади чище, но видны экстремумы и некоторое выцветание.

Итак, градиенты и смешение цветов. Чтобы было удобно с этим всем разбираться, сделал такую функцию: float3 gradient4(float3 r
Итак, градиенты и смешение цветов. Чтобы было удобно с этим всем разбираться, сделал такую функцию:

float3 gradient4(float3 r, float3 g, float3 b, float x) {
    return select(select(mix(r, g, x * 3), 
                      mix(g, b, x * 3 - 1.0), 
                      x > 1.0 / 3.0),
                  mix(b, r, x * 3 - 2.0),
                  x > 2.0 / 3.0);
}
r, g, b - условны (в первых примерах буду использовать чистые цвета, но по сути там может быть что угодно) градиент будет r-g-b-r На картинке - результат для sRGB (без каких-либо преобразований дополнительных). Как видно, цвета грязные и темнят, хотя так быть не должно. НИКОГДА НЕ МЕШАЙТЕ ЦВЕТА В sRGB (а это почти всегда дефолтное цветовое пространство) - мешайте как минимум в linear RGB

Вот вам красивый градиент без смешения цветов для начала - наткнулся на него в куче шейдеров пока диск разбирал float area(fl
Вот вам красивый градиент без смешения цветов для начала - наткнулся на него в куче шейдеров пока диск разбирал

float area(float center, float width, float x) {
    return smoothstep(center - width, center, x) - smoothstep(center, center + width, x);
}

float3 gradient(float t) {
    return float3(
        area(0.25, 0.5, t),
        area(0.5, 0.5, t),
        area(0.75, 0.5, t)
    );
}

fragment
float4 fs_main(
    FS_INPUT In [[stage_in]],
    constant FS_UNIFORM& uniform [[buffer(16)]])
{
    return float4(gradient(In.v_texcoord.x), 1);
}

А как вы храните 100500 девайсов для разработки? (отжал коробку у ребенка)
+1
А как вы храните 100500 девайсов для разработки? (отжал коробку у ребенка)

Хочу такой знак (с кенгуру, переворачивающим машину) где-то раздобыть.
Хочу такой знак (с кенгуру, переворачивающим машину) где-то раздобыть.