Поэтому я хочу реализовать дизеринг как режим наложения между разделениями моей каскадной карты теней.
Я понятия не имел, что это такое, поэтому посмотрел это видео, чтобы попытаться понять это.
Насколько я понимаю, это способ сопоставить цвета изображения с ограниченной палитрой, пытаясь сохранить убедительный градиент между разноцветными пикселями.
Теперь из этого видео я понимаю, как рассчитать, какой цвет увидит мой глаз, на основе веса шаблона дизеринга. Я не понимаю, как мы берем изображение с 4-байтовыми пиксельными данными и, например, пытаемся сопоставить его с 1-байтовыми пиксельными данными. Как мы можем сопоставить каждый цвет пикселя в исходном изображении с шаблоном дизеринга, чтобы его средневзвешенное значение выглядело так, как будто это исходный цвет, если мы в основном ограничены? Скажем, мы были ограничены только 5 цветами, я предполагаю, что не каждая возможная средневзвешенная комбинация шаблона дизеринга с использованием этих 5 цветов палитры может привести к исходному цвету пикселя, так как же это может быть достигнуто? Также рассчитывается ли шаблон дизеринга для каждого пикселя, чтобы получить размытое изображение?
Помимо этого общего вопроса о сглаживании изображения, мне все еще трудно понять, как этот метод помогает нам смешивать каскадные разбиения, где, что касается его фактической реализации в коде, я видел пример, где он использует пространственные координаты фрагмента и вычислить дизеринг (не уверен, что он вычисляет на самом деле, потому что он не возвращает матрицу, а возвращает число с плавающей запятой):
float GetDither2(ivec2 p)
{
float d = 0.0;
if((p.x & 1) != (p.y & 1))
d += 2.0;
if((p.y & 1) == 1)
d += 1.0;
d *= 0.25;
return d;
}
float GetDither4(ivec2 p)
{
float d = GetDither2(p);
d = d * 0.25 + GetDither2(p >> 1);
return d;
}
float threshold = GetDither4(ivec2(gl_FragCoord.xy));
if(factor <= threshold)
{
// sample current cascade
}
else
{
// sample next cascade
}
И затем он производит выборку любой каскадной карты на основе этого возвращенного числа с плавающей запятой. Так что мой мозг не может перевести то, что я узнал о том, что у вас может быть шаблон дизеринга для имитации большого цветового рисунка, в этот пример, который использует возвращаемый плавающий элемент в качестве порогового коэффициента и сравнивает его с некоторым коэффициентом смешения, просто для выборки из любой карты теней. Так что это меня еще больше сбило с толку.
Был бы признателен за хорошее объяснение этого ????
РЕДАКТИРОВАТЬ:
Хорошо, я вижу корреляцию между алгоритмом, который мне предоставили, с статьей в Википедии об упорядоченном дизеринге, которая насколько я понимаю, это предпочтительный алгоритм дизеринга, потому что согласно статье:
Кроме того, поскольку расположение шаблонов дизеринга всегда остается неизменным относительно кадра дисплея, он менее подвержен дрожанию, чем методы распространения ошибок, что делает его пригодным для анимации.
Теперь я вижу, что код пытается получить это пороговое значение для данной пространственной координаты, хотя мне кажется, что он ошибся, потому что следующий расчет порога выглядит следующим образом: Mpre(i,j) = (Mint(i,j)+1) / n^2
И он должен установить: float d = 1.0
вместо float d = 0.0
, если я не ошибаюсь. Во-вторых, я не уверен, как сдвинуть влево пространственную координату ivec2
(я даже не уверен, каково поведение побитового сдвига вектора в glsl…), но я предполагаю, что это просто компонентная побитовая операция, и я попробовал плагин (head вычисление) для заданной пространственной координаты (2,1)
(в соответствии с моими предположениями о поразрядной операции) и получил другой пороговый результат для того, что должно быть пороговым значением этой позиции в матрице Байера 4x4.
Поэтому я скептически отношусь к тому, насколько хорошо этот код реализует алгоритм упорядоченного дизеринга.
Во-вторых, я все еще не уверен, как это пороговое значение имеет какое-либо отношение к выбору между картой теней 1 или 2, а не только к уменьшению цветовой палитры данного пикселя, эта логика еще не обосновалась в моей голове, поскольку я не понимаю использование порогового значения дизеринга для заданной пространственной координаты для выбора правильной карты для выборки.
Напоследок не вызовет ли выбор пространственной координаты дрожь? Данный фрагмент в мировом положении (x,y,z)
затенен. Учитывая, что координаты пространства фрагмента для данного кадра равны (i,j)
. Если камера перемещается, не изменится ли эта пространственная координата фрагмента, в результате чего порог сглаживания, вычисленный для этого фрагмента, будет изменяться с каждым движением, вызывающим дрожание шаблона сглаживания?
РЕДАКТИРОВАТЬ2: Пытались совместить карты, как показано ниже, хотя результат не очень хорош, есть идеи?
const int indexMatrix8x8[64] = int[](
0, 32, 8, 40, 2, 34, 10, 42,
48, 16, 56, 24, 50, 18, 58, 26,
12, 44, 4, 36, 14, 46, 6, 38,
60, 28, 52, 20, 62, 30, 54, 22,
3, 35, 11, 43, 1, 33, 9, 41,
51, 19, 59, 27, 49, 17, 57, 25,
15, 47, 7, 39, 13, 45, 5, 37,
63, 31, 55, 23, 61, 29, 53, 21
);
for (int i = 0; i < NR_LIGHT_SPACE; i++) {
if (fs_in.v_FragPosClipSpaceZ <= u_CascadeEndClipSpace[i]) {
shadow = isInShadow(fs_in.v_FragPosLightSpace[i], normal, lightDirection, i) * u_ShadowStrength;
int x = int(mod(gl_FragCoord.x, 8));
int y = int(mod(gl_FragCoord.y, 8));
float threshold = (indexMatrix8x8[(x + y * 8)] + 1) / 64.0;
if (u_CascadeBlend >= threshold)
{
shadow = isInShadow(fs_in.v_FragPosLightSpace[i + 1], normal, lightDirection, i + 1) * u_ShadowStrength;
}
}
break;
}
}
В основном, если я понимаю, что я делаю, это получаю пороговое значение из матрицы для каждой пространственной координаты затененного пикселя, и если оно (с учетом вероятности) выше, чем коэффициент смешения, то вместо этого я выбираю вторую карту.
Вот результаты: Большое красное поле - это место разделения между картами.
Меньшее красное поле указывает на то, что есть некоторый узор дизеринга, но изображение не так смешано, как я думаю.