在Metal中复制OpenGL混合效果

3

我一直在将一个使用固定功能管线编写的开源游戏移植到Metal上。

我已经重新制作了所有投影变换,并且已经用正确的纹理和顶点信息绘制出了应该绘制的内容,但是我在让片段着色器匹配OpenGL混合时遇到了很多麻烦,纹理看起来正确,但是混合和亮度有所偏差。

这是我要匹配的内容:

GoodRender

这是当前的渲染效果:

enter image description here

我能看到控制GL混合的代码如下:

glShadeModel(GL_SMOOTH);

glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.0f);

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 2.0f);

它禁用混合功能绘制主要纹理,然后在它们之间的小三角形上启用混合功能(在我的版本中非常明显)。每个顶点还提供了RGB颜色。

可能还有其他调用会改变状态,但我不确定还有什么需要查找的。

鉴于这一切,我已将其翻译为两个管道状态,一个禁用混合功能,另一个启用混合功能。混合功能被设置为如下:

 pipelineStateDescriptor.fragmentFunction = viewer.library.makeFunction(name: "borderFragment")!
    pipelineStateDescriptor.colorAttachments[0].isBlendingEnabled = true

    pipelineStateDescriptor.colorAttachments[0].rgbBlendOperation = .add
    pipelineStateDescriptor.colorAttachments[0].alphaBlendOperation = .add

    pipelineStateDescriptor.colorAttachments[0].sourceRGBBlendFactor = .sourceAlpha
    pipelineStateDescriptor.colorAttachments[0].sourceAlphaBlendFactor = .sourceAlpha

    pipelineStateDescriptor.colorAttachments[0].destinationRGBBlendFactor = .oneMinusSourceAlpha
    pipelineStateDescriptor.colorAttachments[0].destinationAlphaBlendFactor = .oneMinusSourceAlpha
1个回答

2

我找到了问题所在,它与纹理的创建方式有关,而不是混合设置,后者是正确的。在使用MetalKit创建纹理时,我在一个集合中使用了选项:[MTKTextureLoaderOptionSRGB:NSNumber(value:0)],而在另一个集合中则没有使用。当它们都被设置为相同的值(1或0)时,它们匹配并且混合工作正常。

最终着色器代码如下:

fragment float4 terrainFragment(FragmentIn inFrag [[stage_in]],
                            texture2d<float, access::sample> colorTexture [[ texture(0) ]],
                            sampler colorSampler [[ sampler(0) ]]) {
    float4 color = colorTexture.sample(colorSampler, inFrag.uv * 1.33);
    color *= float4(inFrag.shadow,inFrag.shadow,inFrag.shadow,1);
    return color * 4;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接