Я использовал MTKTextureLoader для загрузки предоставленных пользователем изображений в текстуры для рендеринга. Я визуализирую эти предоставленные текстуры в промежуточную текстуру, а затем визуализирую промежуточную текстуру в отображаемом MTKView. И промежуточная текстура, и растягиваемая имеют одинаковый цветовой формат.
У меня возникли проблемы с некоторыми изображениями. Все изображения являются файлами PNG, но похоже, что я могу получить различные базовые данные из MTKTextureLoader.
Первый выпуск:
Я загружаю PNG с альфой и без альфы. Кажется, это фактор, но это не на 100% ясно. Оба свойства текстуры кажутся одинаковыми.
PNG с альфа-каналом:
Texture: <BronzeMtlTexture: 0x1015484b0>
label = 512x512.png
textureType = MTLTextureType2D
pixelFormat = MTLPixelFormatBGRA8Unorm_sRGB
width = 512
height = 512
depth = 1
arrayLength = 1
mipmapLevelCount = 10
sampleCount = 1
cpuCacheMode = MTLCPUCacheModeDefaultCache
storageMode = MTLStorageModeManaged
resourceOptions = MTLResourceCPUCacheModeDefaultCache MTLResourceStorageModeManaged
usage = MTLTextureUsageShaderRead
framebufferOnly = 0
purgeableState = MTLPurgeableStateNonVolatile
parentTexture = <null>
parentRelativeLevel = 0
parentRelativeSlice = 0
buffer = <null>
bufferOffset = 0
bufferBytesPerRow = 0
iosurface = 0x0
iosurfacePlane = 0
label = 512x512.png
PNG без альфа:
Texture: <BronzeMtlTexture: 0x10164a9b0>
label = 016 - jKsgTpt.png
textureType = MTLTextureType2D
pixelFormat = MTLPixelFormatBGRA8Unorm_sRGB
width = 1685
height = 815
depth = 1
arrayLength = 1
mipmapLevelCount = 11
sampleCount = 1
cpuCacheMode = MTLCPUCacheModeDefaultCache
storageMode = MTLStorageModeManaged
resourceOptions = MTLResourceCPUCacheModeDefaultCache MTLResourceStorageModeManaged
usage = MTLTextureUsageShaderRead
framebufferOnly = 0
purgeableState = MTLPurgeableStateNonVolatile
parentTexture = <null>
parentRelativeLevel = 0
parentRelativeSlice = 0
buffer = <null>
bufferOffset = 0
bufferBytesPerRow = 0
iosurface = 0x0
iosurfacePlane = 0
label = 016 - jKsgTpt.png
В приведенном выше случае загружается PNG с альфа-каналом с замененными компонентами R&B. Есть ли способ обнаружить это, чтобы я мог правильно настроить шейдер по мере необходимости?
Вторая проблема:
Один из файлов PNG, который я тестировал, закончил загрузку как MTLPixelFormatRGBA16Unorm
. Моя промежуточная текстура и возможность рисования в MTKView обычно MTLPixelFormatBGRA8Unorm
. Это можно обнаружить, но как мне правильно визуализировать эту текстуру для промежуточной текстуры? В этом случае я получаю очень неприятную картину.
Я чувствую, что мне не хватает некоторых нюансов MTKTextureLoader, или что, возможно, он не предназначен для использования так, как я хочу его использовать.
Обновление 1
С загрузчиком текстур ничего особенного не делаю. Настроить особо нечего:
let textureLoader = MTKTextureLoader(device: metalDevice)
let options: [MTKTextureLoader.Option:Any] = [
.generateMipmaps : true,
.SRGB: true
]
textureLoader.newTexture(URL: url, options: options) { (texture, error) in
// Store the texture here
}
Как показано в первом выпуске, я получу две разные текстуры, помеченные как BGRA8, но обычно пиксели с прозрачностью имеют порядок RGBA. Во втором выпуске у меня есть один конкретный PNG, который загружается в RGBA16.
Обновление 2
Настройка трубопровода:
let pipelineDescriptor = MTLRenderPipelineDescriptor()
pipelineDescriptor.vertexFunction = self.library.makeFunction(name: "instance_vertex")
pipelineDescriptor.fragmentFunction = self.library.makeFunction(name: "instance_fragment")
pipelineDescriptor.colorAttachments[0].pixelFormat = newTexture.pixelFormat
pipelineDescriptor.colorAttachments[0].isBlendingEnabled = true
pipelineDescriptor.colorAttachments[0].rgbBlendOperation = .add
pipelineDescriptor.colorAttachments[0].alphaBlendOperation = .add
pipelineDescriptor.colorAttachments[0].sourceRGBBlendFactor = .sourceAlpha
pipelineDescriptor.colorAttachments[0].sourceAlphaBlendFactor = .sourceAlpha
pipelineDescriptor.colorAttachments[0].destinationRGBBlendFactor = .oneMinusSourceAlpha
pipelineDescriptor.colorAttachments[0].destinationAlphaBlendFactor = .oneMinusSourceAlpha
newTexture
в данном случае - это текстура, загруженная из MTKTextureLoader.
Настройка прохода рендеринга:
let renderPassDescriptor = MTLRenderPassDescriptor()
renderPassDescriptor.colorAttachments[0].texture = canvasTexture
renderPassDescriptor.colorAttachments[0].loadAction = .clear
renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColor(
red: Double(red),
green: Double(green),
blue: Double(blue),
alpha: Double(alpha)
)
renderPassDescriptor.colorAttachments[0].storeAction = .store
let encoder = commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDescriptor)!
canvasTexture
был сделан с тем же типом текстуры, что и MTKView. Я пробовал BGRA8 и BGRA8 SRGB, в зависимости от флага загрузчика для SRGB, установленного выше в загрузчике.
Рендеринг:
encoder.setRenderPipelineState(pipelineState)
encoder.setVertexBuffer(vertexBuffer, offset: 0, index: 0)
encoder.setVertexBuffer(uniformBuffer, offset: memorySize * offset, index: 1)
encoder.setFragmentTexture(newTexture, index: 0)
encoder.drawPrimitives(type: .triangleStrip, vertexStart: 0, vertexCount: 4)
Фрагментный шейдер:
fragment half4 face_instance_fragment(VertexOut v [[stage_in]], texture2d<float, access::sample> texture [[ texture(0) ]])
{
constexpr sampler textureSampler(mag_filter::linear,
min_filter::linear,
s_address::clamp_to_edge,
t_address::clamp_to_edge,
r_address::clamp_to_edge);
return (half4)texture.sample(textureSampler, v.texturePosition);
}
Добавление .zyxw
в сэмплер выше исправит цвета одной текстуры, но сломает другую, поэтому я знаю, что цвета правильные, только в неправильном порядке.
.SRGB: true
. Также покажите код, который использует текстуры. - person Ken Thomases   schedule 11.09.2018.SRGB
какtrue
, так иfalse
, при необходимости настраивая вид и целевой формат текстуры. Те же результаты. - person Stephen H. Gerstacker   schedule 11.09.2018.SRGB
. Если вы укажете его (истина или ложь), вы переопределите интерпретацию изображения по умолчанию. Кроме того, можно также объявить параметр текстуры во фрагментном шейдере какtexture2d<half, ...>
, так как в любом случае вы просто выполняете приведение к половине. - person Ken Thomases   schedule 11.09.2018.SRGB
был во всех трех состояниях. Делоhalf
в том, что я просто играл в какой-то момент. - person Stephen H. Gerstacker   schedule 11.09.2018