Комментарии 10
Иными словами, следующий шаг реализма — получить значение света (хотя бы RGB) в точке отражения и использовать его как вес для спектральной функции. Тогда можно будет увидеть зелёные блики от зелёного фонаря и красно-синие — от розового.
float3 xyz = 0;
for (float j = 0; j < 64; j += 1) {
float intensity = InterpolateLambdaNm(5.0*j+390, /*массив значений после рассчётов для нескольких длин волн*/);
xyz += intensity * cie_colour_match_2012_2deg_390_705_5[j];
}
finalColor = mul(xyz_to_linear_srgb, xyz*5.0);
Но я не об этом, я о том, что
color += gi.light.color * spectral_zucconi6(wavelength);
// Стыдно, не знаю, нормирован ли вектор цвета, будем считать, что да
![image](https://habrastorage.org/getpro/habr/comment_images/53e/9b4/c4d/53e9b4c4de48a010c4e4a7fe578b7b8f.jpg)
Промахнулся, ответил отдельной веткой
Хотя, если мы перейдём к одномерным текстурам спектра, то сможем и дёшево их пришивать к игровым объектам (как освещению, так и материалу), и достаточно дёшево их умножать, ведь для пары тип_освещения-тип_материала это нужно будет сделать единожды, и добавить перделок, как, например, эффект Доплера.
Но я этого, того, размечтался. Я, в конце концов, шейдеры не колупал и понятия не имею, как это делается.
дномерным текстурам спектра, то сможем и дёшево их пришивать к игровым объектам (как освещению, так и материалу), и достаточно дёшево их умножать
Дёшево не выйдет, так как вычисления придётся проводить отдельно для каждой моделируемой длины волны и в конце переводить в RGB. Хотя наверное можно предрассчитать всё для каждой длины волны и угла отражения и положить в 2D текстуру.
Я упоминал, но видимо слишком туманно :) Берем длины волн, для которых будем всё считать, и интенсивности излучения источника света на этих же длинах волн. Выйдет примерно так в цикле:
float[iLambda] result = getLightIntensity(iLambda)*calculateSomethingLikeCDreflectionAtWawelength(iLambda);
В статье всего три длины волны, и для сложного спектра понятно что этого слишком мало. result потом подставляется в InterpolateLambdaNm из моего предыдущего комментария. getLightIntensity() — возвращает значение спектрограммы источника света для данной длины волны. У автора там просто значения интенсивностей для rgb, что маловато для сложного спектра. tldr: нужно считать всё для большого количества длин волн, особенно если спектр источника сложный, но так как это дорого, то обычно считают для трёх длин волн примерно соответствующих rgb значениям, что "прокатывает" для равномерного спектра.
ru.wikipedia.org/wiki/Интерференция_света#Интерференция_света_в_тонких_плёнках
приблизительно 299 792 458 метров в секунду
точно 299 792 458 метров в секунду — см. определение метра.
Имитируем иридисценцию: шейдер CD-ROM