Как использовать таблицу поиска 3D и сопоставить ее значение пикселя с изображением? - PullRequest
0 голосов
/ 16 февраля 2019

Я пытаюсь применить таблицу цветов PNG к изображению, но не могу сопоставить пиксель PNG с целевым изображением.

Таблица цветов имеет значение PNG 64 ^ 3

Из того, что я понимаю, каждый пиксель в изображении с большим шрифтом, необходимо использовать аналогичныйзначение в таблице цветов.Похоже, что это ограничивает цвета до 262144 = 64 x 64 x 64. Но я не уверен, что это был эффект, который я получил, в результате получается абсолютно черное изображение, которое не имеет значения, или очень странные цвета выглядят.

Это мой код


// The table is 64 x 64 x 64
float size = 64.0;

// This is the original image
// This function returns a pixel value inside a 3d space
//  and the `rgb` method will return a vector with the rgb values
vec3 source_image = sample(src_i, samplerCoord(src_i)).rgb;
// Here I take the pixel value of the image for the red channel
//  and multiply it by 64.0, then divide by 255.0 for the 8-bit image
float x = floor(floor(source_image.r * size)/255.0);
// The same thing for the green value on the y axis
float y = floor(floor(source_image.g * size)/255.0);

// Match a value from the image in the color table
vec3 color = sample(src_l, vec2(x, y)).rgb;

src_i.r = color.r;
src_i.g = color.g;
// The blue should be on the z axis, or the nth tile, so I think for this
//   case it will be easier to convert the color table to one long row
src_i.b = floor(floor(source_image.b * size)/255.0);

// The image is black

Исходное изображение

Ожидаемый результат

Если вместо этого умножить на 255 (что кажется правильным), то я получу этот результат

float x = floor(source_image.r * 255.0);
float y = floor(source_image.g * 255.0);

Буду очень признателен, если вы укажете, что не так с математикой

Ответы [ 2 ]

0 голосов
/ 17 февраля 2019

Расчет для поиска соответствующей позиции в таблице цветов, кажется, выключен.Я думаю, что вам нужно будет найти смещение для посадки внутри правильной «красно-зеленой плоскости» (определяется синим каналом ввода, с учетом шага 8 из-за расположения 8x8 на карте), а затемдобавьте это смещение к вычислению значений x и y.

Однако я бы рекомендовал сначала проверить встроенный фильтр CIColorCube , поскольку онименно то, что вы хотите достичь.

0 голосов
/ 17 февраля 2019

Таблица поиска не 64 * 64 * 64, но 64 * 64 в растре 8 * 8.Цветовые каналы, которые считываются texture2D, находятся в диапазоне [0, 1], а координаты текстуры тоже находятся в диапазоне [0, 1].

vec2 tiles    = vec2(8.0);
vec2 tileSize = vec2(64.0);

vec3 imageColor = texture(src_i, samplerCoord(src_i)).rgb;

Индекс элемента мозаичного изображения кодируется вканал синего цвета.Всего существует 64 элемента, первый элемент имеет индекс 0, а последний элемент имеет индекс 63. Это означает, что канал синего цвета в диапазоне [0, 1] должен отображаться в диапазон [0, 63]:

float index = imageColor.b * (tiles.x * tiles.y - 1.0);

Для формирования этого линейного индекса плитки необходимо рассчитать двухмерный индекс плитки в диапазоне [0, 8]:

vec2 tileIndex;
tileIndex.y = floor(index / tiles.x);
tileIndex.x = floor(index - tileIndex.y * tiles.x);

Функция минимизации текстуры (GL_TEXTURE_MIN_FILTER) и функцию увеличения текстуры (GL_TEXTURE_MAG_FILTER следует установить на GL_LINEAR. Это приводит к линейной интерполяции цветов на каждом тайле.
Каждая ячейка имеет тексель 64x64. Относительная координата нижнего левого текселя равна (0,5 / 64,0, 0,5 / 64,0), а относительная координата верхнего правого текселя равна (63,5 / 64,0, 63,5 / 64,0).канал зеленого цвета в диапазоне [0, 1] должен отображаться в диапазон [0,5 / 64,0, 63,5 / 64,0]:

vec2 tileUV = mix(0.5/tileSize, (tileSize-0.5)/tileSize, imageColor.rg);

Наконец, координата текстуры для таблицы поиска цветов в диапазоне[0, 1] c может быть рассчитано:

vec2 tableUV = tileIndex / tiles + tileUV / tiles;

Окончательный код, который расшифровываетсяЕсли цвет фрагментированного шейдера может выглядеть следующим образом:

vec2 tiles    = vec2(8.0, 8.0);
vec2 tileSize = vec2(64.0);

vec4 imageColor = texture(src_i, samplerCoord(src_i));

float index = imageColor.b * (tiles.x * tiles.y - 1.0);

vec2 tileIndex;
tileIndex.y = floor(index / tiles.x);
tileIndex.x = floor(index - tileIndex.y * tiles.x);

vec2 tileUV = mix(0.5/tileSize, (tileSize-0.5)/tileSize, imageColor.rg);

vec2 tableUV = tileIndex / tiles + tileUV / tiles;

vec3 lookUpColor = texture(src_l, tableUV).rgb;

Этот алгоритм может быть улучшен путем интерполяции между двумя фрагментами таблицы.Вычислите индекс плитки ниже синего цветового канала и индекс плитки выше синего цветового канала:

float index     = imageColor.b * (tiles.x * tiles.y - 1.0);
float index_min = min(62.0, floor(index));
float index_max = index_min + 1.0;

Наконец, интерполируйте между цветами из обеих плиток, используя mix функция:

vec3 lookUpColor_1 = texture(src_l, tableUV_1).rgb;
vec3 lookUpColor_2 = texture(src_l, tableUV_1).rgb;
vec3 lookUpColor   = mix(lookUpColor_1, lookUpColor_2, index-index_min); 

Окончательный код:

vec2 tiles    = vec2(8.0, 8.0);
vec2 tileSize = vec2(64.0);

vec4 imageColor = texture(src_i, samplerCoord(src_i));

float index     = imageColor.b * (tiles.x * tiles.y - 1.0);
float index_min = min(62.0, floor(index));
float index_max = index_min + 1.0;

vec2 tileIndex_min;
tileIndex_min.y = floor(index_min / tiles.x);
tileIndex_min.x = floor(index_min - tileIndex_min.y * tiles.x);
vec2 tileIndex_max;
tileIndex_max.y = floor(index_max / tiles.x);
tileIndex_max.x = floor(index_max - tileIndex_max.y * tiles.x);

vec2 tileUV = mix(0.5/tileSize, (tileSize-0.5)/tileSize, imageColor.rg);

vec2 tableUV_1 = tileIndex_min / tiles + tileUV / tiles;
vec2 tableUV_2 = tileIndex_max / tiles + tileUV / tiles;

vec3 lookUpColor_1 = texture(src_l, tableUV_1).rgb;
vec3 lookUpColor_2 = texture(src_l, tableUV_2).rgb;
vec3 lookUpColor   = mix(lookUpColor_1, lookUpColor_2, index-index_min); 

См. Изображение, которое сравнивает исходное изображение (вверху слева) и с измененным изображением поиска цвета (внизу справа):

...