Я визуализирую геометрию с некоторыми полупрозрачными областями (альфа ‹1) в металлическом метале MTKView
. Если isBlendingEnabled
в дескрипторе состояния конвейера рендеринга оставлено как false, тогда все будет отображаться так, как должно (хотя и сплошным цветом).
Я знаю, что рендеринг полупрозрачных объектов зависит от порядка рисования. На данный момент я просто хочу проверить, как выглядит альфа-смешение с полупрозрачными областями, смешанными с тем, что уже находится в буфере рендеринга, даже если оно просто сливается с фоном (на данный момент все еще только чистый цвет).
Однако, когда я пытаюсь включить смешивание, makeRenderPipelineState
выходит из строя со следующей ошибкой:
Компилятору не удалось создать запрос Error Domain = CompilerError Code = 1 «Фрагментный шейдер не записывает для рендеринга целевой цвет (0), индекс (1), необходимый для смешивания»
Вот код, который пытается построить состояние конвейера в делегате MTKView. Если он наследует свойства от MTKView, я поместил значение этих свойств в комментарии.
do {
let descriptor = MTLRenderPipelineDescriptor()
descriptor.vertexFunction = vertex
descriptor.fragmentFunction = fragment
descriptor.sampleCount = view.sampleCount // 4
descriptor.depthAttachmentPixelFormat = view.depthStencilPixelFormat //.depth32Float
let renderAttachment = descriptor.colorAttachments[0]
renderAttachment?.pixelFormat = view.colorPixelFormat //.bgra8Unorm
// following 7 lines cause makeRenderPipelineState to fail
renderAttachment?.isBlendingEnabled = true
renderAttachment?.alphaBlendOperation = .add
renderAttachment?.rgbBlendOperation = .add
renderAttachment?.sourceRGBBlendFactor = .sourceAlpha
renderAttachment?.sourceAlphaBlendFactor = .sourceAlpha
renderAttachment?.destinationRGBBlendFactor = .oneMinusSourceAlpha
renderAttachment?.destinationAlphaBlendFactor = .oneMinusSource1Alpha
computePipelineState = try device.makeComputePipelineState(function: kernel)
renderPipelineState = try device.makeRenderPipelineState(descriptor: descriptor)
} catch {
print(error)
}
Учитывая, что ошибка связана с color(0)
, я добавил привязку color[0]
к выводу фрагментного шейдера:
constant float3 directionalLight = float3(-50, -30, 80);
struct FragOut {
float4 solidColor [[ color(0) ]];
};
fragment FragOut passThroughFragment(Vertex fragIn [[ stage_in ]]) {
FragOut fragOut;
fragOut.solidColor = fragIn.color;
fragOut.solidColor.rgb *= max(0.4, dot(fragIn.normal, normalize(directionalLight)));
return fragOut;
};
И, наконец, код отрисовки:
if let renderPassDescriptor = view.currentRenderPassDescriptor,
let drawable = view.currentDrawable {
let commandBuffer = queue.makeCommandBuffer()
renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColor(red: 0.8, green: 0.8, blue: 1, alpha: 1)
let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDescriptor)
renderEncoder.setDepthStencilState(depthStencilState)
renderEncoder.setRenderPipelineState(renderPipelineState)
//renderEncoder.setTriangleFillMode(.lines)
renderEncoder.setVertexBuffer(sceneBuffer, offset: 0, at: 0)
renderEncoder.setVertexBuffer(vertexBuffer, offset: 0, at: 1)
renderEncoder.drawPrimitives(type: .triangle, vertexStart: 0, vertexCount: Int(vertexCount) )
renderEncoder.endEncoding()
commandBuffer.present(drawable)
commandBuffer.commit()
}
Я не устанавливаю явно какие-либо текстуры во фрагментном шейдере. Означает ли это, что currentDrawable неявно является прикреплением цвета с индексом 0? Почему в сообщении об ошибке нужно видеть color(0)
в индексе 1? Требуется ли для смешивания двухцветная насадка? (он не может просто аддитивно смешиваться с тем, что уже было визуализировано?)
Спасибо.