我一直在努力将使用固定功能管道编写的开源游戏移植到Metal。
我已经能够重做所有的投影变换,并使用正确的纹理和顶点信息在需要绘制的地方进行绘制,但是在获取片段着色器以匹配OpenGL混合时遇到了很多麻烦,纹理看起来很正确,但是混合和亮度关闭。
这是我要匹配的内容:
这是当前渲染的方式:
我可以看到控制GL Blending的代码如下:
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
我发现了问题所在,在于纹理的创建方式,而不是正确的混合设置方式。当用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;
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句