Низкая стоимость преобразования изображения в NSData для подачи на вход SCNTechnique sampler2D - PullRequest
0 голосов
/ 25 июня 2018

Иногда единственный способ передать ценные данные из 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 Ответ

0 голосов
/ 26 июня 2018

Самый эффективный способ, который я нашел, - это создание TIFF-файлов с плавающей запятой.Это все еще не супер быстро, потребляя 0,7 мс на iPhone X, но намного быстрее, чем метод PNG.

Наличие текстуры с плавающей точкой также имеет преимущества прямой передачи с плавающей точкой, то есть, отсутствие кодирования для нескольких uint8Значения RGBA в ЦП и восстановление поплавков в ГП.

Вот как:

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

...