首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >启用混合使renderPipelineState无法在MetalKit MTKView中生成

启用混合使renderPipelineState无法在MetalKit MTKView中生成
EN

Stack Overflow用户
提问于 2017-05-01 22:18:20
回答 1查看 1.6K关注 0票数 2

我正在绘制一个几何图形,在金属套件MTKView中有一些半透明的区域(alpha < 1)。如果isBlendingEnabled在呈现管道状态的描述符中被保留为false,那么所有的东西都会以它应该显示的方式显示(尽管所有的颜色都是实色的)。

我知道绘制半透明的对象取决于绘制顺序。目前,我只想测试alpha混合与渲染缓冲区中已经混合的半透明区域是什么样子,即使它只是混合到背景(此时仍然是清晰的颜色)。

但是,当我试图启用混合时,makeRenderPipelineState会失败,并出现以下错误:

编译器未能生成请求错误Domain=CompilerError Code=1“片段着色器未写入以呈现目标颜色(0)、索引(1),这是混合所需的”

下面是试图在MTKView的委托中构建管道状态的代码。在从MTKView继承属性的地方,我将这些属性的值放在注释中

代码语言:javascript
复制
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]绑定添加到片段着色器的输出中:

代码语言:javascript
复制
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;
};

最后,抽签代码:

代码语言:javascript
复制
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处的颜色附件?为什么错误消息希望在索引1处看到color(0)?混合需要两个颜色附件吗?(它不能只是加在已经渲染的东西上吗?)

谢谢。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-05-02 00:25:24

您似乎无意中调用了双源共混。与其将destinationAlphaBlendFactor设置为oneMinusSource1Alpha,不如尝试oneMinusSourceAlpha (注意缺少的1)。

此外,默认情况下,金属写入第一个颜色附件的直觉是正确的( MTKView将当前可绘制配置为第一个颜色附件的纹理)。与返回带有[[color(0)]]属性的成员的结构不同,您可以从片段函数返回一个float4 (或half4),然后将该颜色写入主颜色附件。但是,在正确配置混合因素之后,编写它的方式应该可以工作。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43727335

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档