我一直在努力将使用固定功能管道编写的开源游戏移植到Metal。
我已经能够重做所有的投影变换,并且正在绘制的地方它们应该使用正确的纹理和顶点信息绘制但是我在使用片段着色器时遇到了很多麻烦匹配OpenGL混合,纹理看起来正确但混合和亮度关闭。
这是我想要匹配的内容:
以下是当前呈现的方式:
我可以看到控制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
答案 0 :(得分:1)
我发现了问题,它是如何创建纹理的,而不是如何设置正确的混合。在一组上使用MetalKit创建纹理时,我使用了以下选项:
[MTKTextureLoaderOptionSRGB: NSNumber(value:0)]
而另一方则没有。当两者都设置为相同(1或0)时,它们匹配并且混合正常工作。
Shader最终成为:
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;
}