В Metal каковы правильные коэффициенты смешивания для компоновки «поверх» классического Porter-Duff?

#ios #macos #texture-mapping #metal #porter-duff

#iOS #macos #отображение текстур #Металлические #porter-duff

Вопрос:

В приложении Metal для iOS мне нужно отобразить полупрозрачную текстуру, прикрепленную к простому квадрату. Я не могу определить правильные коэффициенты цветового сочетания rgb и alpha.

Моя настройка:

1) Красное изображение, созданное в Photoshop с 50% непрозрачностью. Сохранено в формате PNG с прозрачностью. Изображение хранится в папке «Мои ресурсы проекта».

введите описание изображения здесь

2) Я создаю текстуру металла, сначала создавая, UIImage затем используя .cgImage — CoreImage — field для извлечения данных изображения. Теперь это изображение в предварительно умноженном формате, поэтому можно применять классические формулы Портера-Даффа. Подробнее об этом позже.

 // load hero texture
do {

    let textureLoader = MTKTextureLoader(device: device)

    guard let image = UIImage(named:"red_translucent") else {
        fatalError("Error: Can not create UIImage")
    }

    if (image.cgImage?.alphaInfo == .premultipliedLast) {
        print("texture uses premultiplied alpha. Rock.")
    }

    heroTexture = try textureLoader.newTexture(with: image.cgImage!, options: nil)
} catch {
    fatalError("Error: Can not load texture")
}
  

3) Вот мой довольно скучный шейдер фрагмента текстуры

 fragment float4 textureFragmentShader(_Vertex_ vert [[ stage_in ]], texture2d<float> texas [[ texture(0) ]]) {

    constexpr sampler defaultSampler;

    float4 rgba = texas.sample(defaultSampler, vert.st).rgba;
    return rgba;
}
  

4) Это мои настройки коэффициента смешивания colorAttachment, которые являются формулой «поверх» Портера-Даффа:

 descriptor.colorAttachments[ 0 ].isBlendingEnabled = true

descriptor.colorAttachments[ 0 ].rgbBlendOperation = .add
descriptor.colorAttachments[ 0 ].alphaBlendOperation = .add

descriptor.colorAttachments[ 0 ].sourceRGBBlendFactor = .one
descriptor.colorAttachments[ 0 ].sourceAlphaBlendFactor = .one

descriptor.colorAttachments[ 0 ].destinationRGBBlendFactor = .oneMinusSourceAlpha
descriptor.colorAttachments[ 0 ].destinationAlphaBlendFactor = .oneMinusSourceAlpha
  

5) Когда я визуализирую квадрат с этой красной полупрозрачной текстурой поверх белого фона, изображение получается слишком темным. Неправильный рендеринг (правильное изображение) равен rgb = (182, 127, 127). Правильное изображение из Photoshop — rgb (255, 127, 127):

введите описание изображения здесь

Каковы правильные функции смешивания?

Обновить

Если люди хотят взглянуть на код, он находится на Github здесь:https://github.com/turner/HelloMetal/tree/2_pass_render

Комментарии:

1. Я не могу воспроизвести это с текстурой, сгенерированной вручную. Вы использовали getBytes для проверки фактических значений пикселей в текстуре? Вы также можете попробовать передать MTKTextureLoaderOptionSRGB (= false ) параметр при загрузке, чтобы убедиться, что вы случайно не получаете текстуру sRGB, которая может казаться темнее, если исходные данные на самом деле не находятся в пространстве sRGB.

2. Привет, Уоррен, я попробую это. Проект находится на Github здесь, если вы хотите взглянуть: github.com/turner/HelloMetal/tree/2_pass_render . Это ветвь с именем 2_pass_render.

3. Бинго! отключение sRGB сделало свое дело. Неплохо. Спасибо, Уоррен,

Ответ №1:

Решением — по предложению Уоррена — было установить MTKTextureLoaderOptionSRGB параметр на false .