Как указать формат текстуры металла, совместимый с симулятором iOS, из файла на диске?

Работая с другим сообщением здесь в качестве отправной точки, я пытаюсь сделать что-то подобное. Взяв текстуру .jpg из этого поста, мой код отлично работает на реальном устройстве, но не работает в симуляторе. Причина, по всей видимости, в формате изображения.

Как упоминалось в документации Apple здесь, вы не можете использовать формат MTLPixelFormat.r8Unorm_srgb, который я считаю во что закодирована эта текстура, на основе следующей ошибки:

failed assertion `pixelFormat (11) is not a valid MTLPixelFormat.'

Пытаюсь понять, как изменить формат, но не знаю, как это сделать. Я не знаю, можно ли его загрузить в определенное цветовое пространство во время создания, или мне нужно сделать что-то конкретное в Photoshop, возможно, даже полностью изменить тип файла, но даже там я не вижу, как включить с цветовых профилей, просто замените их на что-нибудь другое.

Итак, есть ли у кого-нибудь информация о том, как можно создать / загрузить текстуру, которая также совместима с симулятором?

Обновлять

Кто-то спрашивает, вот как я настраиваю текстуру.

let noiseImage = UIImage(resourceName: "Noise", extension: "jpg")!
myMaterial.setValue(SCNMaterialProperty(contents: noiseImage), forKey: "noiseTexture")

Вот инициализатор удобства, который используется выше ...

extension UIImage {

    convenience init?(resourceName:String, extension:String? = nil, bundle:Bundle? = nil) {

        let bundle = bundle ?? Bundle.main

        guard let resourceFileName = bundle.path(forResource: resourceName, ofType: `extension`) else {
            return nil
        }

        self.init(contentsOfFile: resourceFileName)
    }
}

person Mark A. Donohoe    schedule 20.06.2020    source источник
comment
Вы можете показать нам, как именно вы создаете текстуру?   -  person warrenm    schedule 21.06.2020
comment
Смотрите обновление. Совершенно уверен, что это не имеет ничего общего с кодом, опять же, он отлично работает на симуляторе. Я думаю, что это jpg не в формате, который работает с симулятором.   -  person Mark A. Donohoe    schedule 21.06.2020
comment
Формат файла JPEG не может быть несовместим с Симулятором. Это связано с тем, как текстура создается и загружается, и в данном случае это похоже на ошибку в SceneKit.   -  person warrenm    schedule 21.06.2020
comment
Не понимаю, как вы говорите, это ошибка, если изображение явно в формате MTLPixelFormat.r8Unorm_srgb, а в документации конкретно указано, что этот формат не поддерживается в симуляторе. С тех пор я преобразовал его в PNG с цветовым пространством «Apple RGB» в Photoshop, и теперь точный код работает и в симуляторе, подтверждая, что это проблема с цветовым форматом. Тем не менее, я также хочу попробовать ваш код ниже, поскольку я предпочитаю использовать Metal непосредственно вместо UIKit для таких вещей.   -  person Mark A. Donohoe    schedule 21.06.2020
comment
Изображение JPEG (или PNG) явно не содержит указания, в какой формат пикселей Metal должно быть загружено его содержимое. Возможно, он содержит цветовой профиль, который заставляет внутренний загрузчик текстуры (например, в SceneKit) предпочитать определенный формат пикселей, после чего выбор загрузчика для выбора формата пикселей, который не поддерживается, становится Жук. В любом случае, я рад за вас, что перекодирование изображения работает.   -  person warrenm    schedule 21.06.2020
comment
Думаю, проблема в цветовом профиле. НО ... тот же файл работает с вашим кодом, поэтому теперь есть два решения. Тем не менее, я отмечаю ваш как ответ. Спасибо! :)   -  person Mark A. Donohoe    schedule 21.06.2020


Ответы (1)


Похоже, это ошибка в SceneKit, которая не учитывает тот факт, что определенные форматы пикселей не поддерживаются в iOS Simulator. Вы можете обойти это, вручную создав текстуру металла с помощью MetalKit:

let textureLoader = MTKTextureLoader(device: scnView.device!)

let noiseImage = UIImage(resourceName: "Noise", extension: "jpg")?.cgImage
let texture = try! textureLoader.newTexture(cgImage: noiseImage!, options: [:])
myMaterial.setValue(SCNMaterialProperty(contents: texture), forKey: "noiseTexture")
person warrenm    schedule 21.06.2020