Replicate OpenGL Blending in Metal

瘦欲@ 提交于 2019-12-22 12:22:56

问题


I have been working on porting an open source game written using a fixed function pipeline to Metal.

I have been able to redo all the projection transformation and have things being drawn where they should be drawn with the correct texture and vertex information but I'm having lots of trouble getting the fragment shader to match the OpenGL blending, the textures look correct but the blending and brightness are off.

Here is what I'm trying to match:

here is how it is currently rendering:

The code I can see controlling the GL Blending looks like:

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);

It draws the main textures with blending disabled then enables it on little triangles (quite visible on my version) between them. There are RGB colors provided for each vertex as well.

There may be other calls altering state but I am not sure what else to look for.

Given all of this I have translated it into two pipeline states one with blending disabled and the other with it enabled. the blending one is set up to look like:

 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:


I found the problem, it was with how the textures were created, not how the blending was set up which was correct. When creating the textures with MetalKit on one set I used the option: [MTKTextureLoaderOptionSRGB: NSNumber(value:0)] and didn't on the other. When they both were set to be the same (either 1 or 0) they matched and blending worked correctly.

Shader ended up being:

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;
}


来源:https://stackoverflow.com/questions/41981825/replicate-opengl-blending-in-metal

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!