Сырые байты 7C 6E 00 FF
в BGRA.Это, конечно, не то, о чем сообщил цифровой измеритель цвета, но это также очень далеко от того, что я ожидаю.
То, что равно , о чем сообщал измеритель цвета.Эта последовательность байтов соответствует (0, 0,43, 0,49).
Я бы ожидал 33 29 00 ff
.Так как функция текстуры жестко закодирована в return float4(0, 0.16, 0.20, 1);
, а формат пикселей sRGB, я ожидаю, что 0.2
в синем канале даст 0,2 * 255 = 51 (десятичное число) = 0x33, а не 0x7c.
Ваше ожидание неверно.В шейдерах цвета всегда линейные, а не sRGB.Если текстура sRGB, то ее чтение преобразуется из sRGB в линейную, а запись в нее преобразуется из линейной в sRGB.
Учитывая линейный (0, 0,16, 0,2) в вашем шейдере, описывается преобразование в sRGB.в разделе 7.7.7 спецификации Metal Shading Language (PDF) будет получено (0, 0,44, 0,48) для плавающей запятой и (0, 111, 124) aka (0, 0x6f, 0x7c) дляRGBA8Unorm.Это очень близко к тому, что вы получаете.Итак, результат кажется правильным для sRGB.
Алгоритм преобразования из линейного в sRGB, как указано в спецификации:
if (isnan(c)) c = 0.0;
if (c > 1.0)
c = 1.0;
else if (c < 0.0)
c = 0.0;
else if (c < 0.0031308)
c = 12.92 * c;
else
c = 1.055 * powr(c, 1.0/2.4) - 0.055;
Алгоритм преобразования из sRGB в линейный:
if (c <= 0.04045)
result = c / 12.92;
else
result = powr((c + 0.055) / 1.055, 2.4);
Я также вижу, что он явно намного ярче, чем тот же цвет, нарисованный без металла (например, в -drawRect :).
Как вы создали цвет для рисования для этого случая?Обратите внимание, что общее (калиброванное) цветовое пространство RGB не линейное.Имеет гамму ~ 1,8.Базовая графика имеет kCGColorSpaceGenericRGBLinear
, которая является линейной.
Загадка заключается в том, почему вы видите намного более темный цвет, когда используете текстуру не-sRGB.Жестко закодированный цвет в вашем шейдере должен всегда представлять один и тот же цвет.Пиксельный формат текстуры не должен влиять на то, как она в конечном итоге проявляется (в пределах ошибки округления).То есть он преобразуется из линейного в пиксельный формат текстуры и, на дисплее, из пиксельного формата текстуры в цветовой профиль дисплея.Это транзитивно, поэтому результат должен быть таким же, как переход от линейного к цветному профилю дисплея.
Вы уверены, что не извлекаете байты из этой текстуры, а затем интерпретируете их, как если бы они были sRGB?Или, может быть, используя -newTextureViewWithPixelFormat:...
?