问题
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