как отобразить MTKView с помощью rgba16Float MTLPixelFormat - PullRequest
1 голос
/ 27 марта 2019

У меня установлен MTKView для использования MTLPixelFormat.rgba16Float.У меня проблемы с отображением, которые лучше всего описать с помощью следующего рисунка:

enter image description here

Таким образом, предполагаемый UIColor становится размытым, но только пока онотображается в MTKView.Когда я преобразую нарисованную текстуру обратно в изображение для отображения в UIView через CIIMage, я возвращаю исходный цвет.Вот как я создаю этот вывод:

let colorSpace = CGColorSpaceCreateDeviceRGB()
let kciOptions = [kCIImageColorSpace: colorSpace,
                  kCIContextOutputPremultiplied: true,
                  kCIContextUseSoftwareRenderer: false] as [String : Any]  
let strokeCIImage = CIImage(mtlTexture: metalTextureComposite, options: kciOptions)!.oriented(CGImagePropertyOrientation.downMirrored)
let imageCropCG = cicontext.createCGImage(strokeCIImage, from: bbox, format: kCIFormatABGR8, colorSpace: colorSpace) 

Другие подходящие настройки:

uiColorBrushDefault: UIColor = UIColor(red: 0.92, green: 0.79, blue: 0.18, alpha: 1.0)
self.colorPixelFormat = MTLPixelFormat.rgba16Float
renderPipelineDescriptor.colorAttachments[0].pixelFormat = self.colorPixelFormat

// below is the colorspace for the texture which is tinted with UIColor
let colorSpace = CGColorSpaceCreateDeviceRGB()
let texDescriptor = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: MTLPixelFormat.rgba8Unorm, width: Int(width), height: Int(height), mipmapped: isMipmaped)
target = texDescriptor.textureType
texture = device.makeTexture(descriptor: texDescriptor)

В некоторых сообщениях намекают на то, что sRGB где-то предполагается, но нет никаких подробностей относительно того, как я могу его отключить,

Мне бы хотелось, чтобы цвет, отображаемый в MTKView, соответствовал входным данным (как можно ближе к нему в любом случае), и я все еще мог преобразовать эту текстуру во что-то, что я могу отобразить в ImageView.Я проверил это на iPad Air и новом iPad Pro.Такое же поведениеЛюбая помощь будет оценена.

Ответы [ 2 ]

1 голос
/ 30 марта 2019

Итак, похоже, вы очень близки к полному решению. Но то, что у вас есть, не совсем правильно. Вот функция Metal, которая преобразует из sRGB в линейное значение, которое вы затем можете записать в свой шейдер Metal (я все же предлагаю вам записать в текстуру sRGB, но вы также можете записать в 16-битную текстуру). Обратите внимание, что sRGB не является простой кривой гаммы 2.2.

// Convert a non-linear log value to a linear value.
// Note that normV must be normalized in the range [0.0 1.0].

static inline
float sRGB_nonLinearNormToLinear(float normV)
{
  if (normV <= 0.04045f) {
    normV *= (1.0f / 12.92f);
  } else {
    const float a = 0.055f;
    const float gamma = 2.4f;
    //const float gamma = 1.0f / (1.0f / 2.4f);
    normV = (normV + a) * (1.0f / (1.0f + a));
    normV = pow(normV, gamma);
  }

  return normV;
}
0 голосов
/ 29 марта 2019

Ключ оказался в отмене гамма-коррекции, встроенной в UIColor

let colorSRGB = UIColor(red: 0.92, green: 0.79, blue: 0.18, alpha: 1.0)
let rgbaSRGB = colorSRGB.getRGBAComponents()!
let gammapower : CGFloat = 2.2

let r = pow(rgbaSRGB.red, gammapower)
let g = pow(rgbaSRGB.green, gammapower)
let b = pow(rgbaSRGB.blue, gammapower)
let a = pow(rgbaSRGB.alpha, gammapower)

let colorNoGamma: UIColor = UIColor(red: CGFloat(r), green: CGFloat(g), blue: CGFloat(b), alpha: CGFloat(a))

Как только я передам colorNoGamma для применения в MKTView с MTLPixelFormat.rgba16Float, результаты будут соответствовать UIView с отображением colorSRGB. Это имеет смысл, как только вы обдумаете это ... Спасибо @MoDJ за то, что вы ввели меня на правильный путь.

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

let texDescriptor = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: MTLPixelFormat.rgba8Unorm, width: Int(width), height: Int(height), mipmapped: isMipmaped)
target = texDescriptor.textureType

И, если я хочу преобразовать currentDrawable в текстуру, которая будет отображаться в UIImageView, то я хочу убедиться, что я не применяю ЛЮБЫЕ настройки цветового пространства. То есть:

let strokeCIImage = CIImage(mtlTexture: metalTextureComposite, options: [:])!.oriented(CGImagePropertyOrientation.downMirrored)
let imageCropCG = cicontext.createCGImage(strokeCIImage, from: box, format: kCIFormatABGR8, colorSpace: colorSpace)  // kCIFormatRGBA8 gives same result. Not sure what's proper
let layerStroke = CALayer()
layerStroke.frame = bbox
layerStroke.contents = imageCropCG

Обратите внимание на аргумент options: [:] означает, что я не передаю настройки цветового пространства / предварительного умножения / рендеринга, как я делал в оригинальном посте, где я определил kciOptions

...