В результате MTLTexture светлее, чем CGImage - PullRequest
3 голосов
/ 20 июня 2020

У меня есть удовольствие от ядра c, которое должно преобразовывать текстуры Y и CbCr, созданные из pixelBuffer (ARFrame.capturedImage), в текстуру RGB, как в руководстве по яблоку https://developer.apple.com/documentation/arkit/displaying_an_ar_experience_with_metal Но я перебрал освещенную текстуру

kernel void renderTexture(texture2d<float, access::sample> capturedImageTextureY [[ texture(0) ]],
                          texture2d<float, access::sample> capturedImageTextureCbCr [[ texture(1) ]],
                      
                          texture2d<float, access::read_write> outTextue [[texture(2)]],
                      
                      
                          uint2 size [[threads_per_grid]],
                          uint2 pid [[thread_position_in_grid]]){


constexpr sampler colorSampler(mip_filter::linear,
                               mag_filter::linear,
                               min_filter::linear);


const float4x4 ycbcrToRGBTransform = float4x4(
    float4(+1.0000f, +1.0000f, +1.0000f, +0.0000f),
    float4(+0.0000f, -0.3441f, +1.7720f, +0.0000f),
    float4(+1.4020f, -0.7141f, +0.0000f, +0.0000f),
    float4(-0.7010f, +0.5291f, -0.8860f, +1.0000f)
);

float2 texCoord;
texCoord.x = float(pid.x) / size.x;
texCoord.y = float(pid.y) / size.y;

// Sample Y and CbCr textures to get the YCbCr color at the given texture coordinate
float4 ycbcr = float4(capturedImageTextureY.sample(colorSampler,    texCoord).r,
                      capturedImageTextureCbCr.sample(colorSampler, texCoord).rg, 1.0);

float4 color = ycbcrToRGBTransform * ycbcr;

outTextue.write(color, pid);

}

Я создаю CGImage с помощью этого кода:

var cgImage: CGImage?
VTCreateCGImageFromCVPixelBuffer(pixelBuffer, options: nil, imageOut: &cgImage)

     

cgImage имеет нормальное освещение

, когда я пытаюсь создать текстуру из cgImage с помощью MTKTextureLoader I получить более светлую текстуру

Как получить MTLTexture с нормальным светом, как в cgImage

cgImage: (ожидаемый результат)

enter image description here

kernel func:

create texture with this code:

let descriptor = MTLTextureDescriptor()
descriptor.width = Int(Self.maxTextureSize.width)
descriptor.height = Int(Self.maxTextureSize.height)
descriptor.usage = [.shaderWrite, .shaderRead]
    
let texture = MTLCreateSystemDefaultDevice()?.makeTexture(descriptor: descriptor)

and write pixels with kernel func.

already tried different pixelFormats of MTLTextureDescriptor

enter image description here

textureLoader:

let textureLoader = MTKTextureLoader(device: MTLCreateSystemDefaultDevice()!)
let texturee = try! textureLoader.newTexture(cgImage: cgImage!, options: [.SRGB : (false as NSNumber)])

already tried different MTKTextureLoader.Options

enter image description here

GitHub project demonstrating issue: PixelBufferToMTLTexture

Ответы [ 2 ]

1 голос
/ 28 июня 2020

Проблема была решена Спасибо 0xBFE1A8, добавив гамма-коррекцию

путем замены

outTextue.write(color, pid);

на:

outTextue.write(float4(pow(color.rgb, float3(2,2,2)), color.a), pid);
1 голос
/ 20 июня 2020

когда я пытаюсь создать текстуру из cgImage с помощью MTKTextureLoader, я получаю более светлую текстуру

Это потому, что металл применяет гамма-коррекцию к вашей текстуре.

MTKTextureLoader имеет ключ SRGB , который используется, чтобы указать, будут ли данные текстуры сохранены как данные изображения sRGB.

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

let path = Bundle.main.path(forResource: "yourTexture", ofType: "png")!
let data = NSData(contentsOfFile: path) as! Data
let texture = try! textureLoader.newTexture(with: data, options: [MTKTextureLoaderOptionSRGB : (false as NSNumber)])

Эту проблему также можно решить, добавив в шейдер уравнение коррекции гаммы .

  • Линейно для sRGB и наоборот:

rgb = mix(rgb.0.0774, pow(rgb*0.9479 + 0.05213, 2.4), step(0.04045, rgb))

rgb = mix(rgb12.92, pow(rgb*0.4167) * 1.055 - 0.055, step(0.00313, rgb))

...