Низкая стоимость преобразования изображения в NSData для подачи на вход SCNTechnique sampler2D
Иногда единственный способ передать ценные данные из CPU в GPU - это скрыть их в текстурах.
Я попытался обмануть SCNTechnique и просто передать [NSData dataWithBytes:length:]
или CGDataProviderRef
содержит мои аккуратно подготовленные необработанные байты данных пикселей, но SceneKit достаточно умен, чтобы обнаружить мои зловещие попытки.
Но я не сдался и нашел лазейку
[_sceneView.technique setValue: UIImagePNGRepresentation(encodeInSinglePixelUIImage(pos.x, pos.y)) forKey:@"blob_pos_"];
Вы можете себе позволить кодировать и декодировать однопиксельные PNG-изображения со скоростью 60 кадров в секунду на мобильном устройстве, на iPhone X он стоит всего 2 мс и сохраняет вашу ладонь чуть теплее. Однако мне не нужны никакие тепловыделяющие свойства до ноября, поэтому мне было интересно, есть ли классная альтернатива этому методу.
1 ответ
Самый эффективный способ, который я нашел, - это создание TIFF-файлов с плавающей точкой. Это все еще не супер быстро, потребляя 0,7 мс на iPhone X, но намного быстрее, чем метод PNG.
Наличие текстуры с плавающей точкой также имеет преимущества прямой передачи с плавающей точкой, то есть отсутствие кодирования для нескольких значений RGBA uint8 в ЦП и восстановление операций с плавающей запятой в графическом процессоре.
Вот как:
NSData * tiffencode(float x, float y)
{
const uint8_t tags = 9;
const uint8_t headerlen = 8+2+tags*12+4;
const uint8_t width = 1;
const uint8_t height = 1;
const uint8_t datalen = width*height*3*4;
static uint8_t tiff[headerlen+datalen] = {
'I', 'I', 0x2a, 0, //little endian/'I'ntel
8, 0, 0, 0, //index of metadata
tags, 0,
0x00, 1, 4, 0, 1, 0, 0, 0, width, 0, 0, 0, //width
0x01, 1, 4, 0, 1, 0, 0, 0, height, 0, 0, 0, //height
0x02, 1, 3, 0, 1, 0, 0, 0, 32, 0, 0, 0, //bits per sample(s)
0x06, 1, 3, 0, 1, 0, 0, 0, 2, 0, 0, 0, //photometric interpretation: RGB
0x11, 1, 4, 0, 1, 0, 0, 0, headerlen, 0, 0, 0,//strip offset
0x15, 1, 3, 0, 1, 0, 0, 0, 3, 0, 0, 0, //samples per pixel: 3
0x16, 1, 4, 0, 1, 0, 0, 0, height, 0, 0, 0, //rows per strip: height
0x17, 1, 4, 0, 1, 0, 0, 0, datalen, 0, 0, 0, //strip byte length
0x53, 1, 3, 0, 1, 0, 0, 0, 3, 0, 0, 0, //sampleformat: float
0, 0, 0, 0, //end of metadata
//RGBRGB.. pixeldata here
};
float *rawData = tiff+headerlen;
rawData[0] = x;
rawData[1] = y;
NSData *data = [NSData dataWithBytes:&tiff length:sizeof(tiff)];
return data;
}
Полезные ссылки TIFF, которые я использовал:
http://www.fileformat.info/format/tiff/corion.htm
http://paulbourke.net/dataformats/tiff/
https://www.fileformat.info/format/tiff/egff.htm
https://www.awaresystems.be/imaging/tiff/tifftags/sampleformat.html