Тут все максимально просто:
1. Переводим RGB -> YUV (используем только Y - яркость)
2. Применяем яркость, контраст, потом гамму - сначала линейные, потом нелинейные, чтобы первые не ломались
3. Используем яркость как коэффициент для градиента между цветами пигмента и подложки
Не забываем, что все операции с цветами должны проходить в линейном RGB, иначе будет некорректно
float brightness(float x, float v) {
return saturate(x + v);
}
float contrast(float x, float v) {
return exp(v) * (x - 0.5) + 0.5;
}
float gamma(float x, float v) {
return pow(x, exp(-v));
}
float3 tint(float x, float3 from, float3 to) {
return mix(from, to, x);
}