Replicate Opengl Blending in Metal

Replicate OpenGL Blending in Metal

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

Blending operations in Metal

It's the original source alpha. You can think of these two calculations (MTLBlendOperationAdd) as occurring concurrently.

RGB = Source.rgb * SBF + Dest.rgb * DBF
A = Source.a * SBF + Dest.a * DBF

Blending in Metal: alpha set to 0 is still opaque

sourceAlphaBlendFactor and destinationAlphaBlendFactor are to do with constructing a blend for the alpha channel. i.e. they control the alpha that will be written into your destination buffer, which will not really be visible to you. You are probably more interested in the RGB that is written into the frame buffer.

Try setting values for sourceRGBBlendFactor and destinationRGBBlendFactor instead. For traditional alpha blending set sourceRGBBlendFactor to MTLBlendFactorSourceAlpha and set destinationRGBBlendFactor to MTLBlendFactorOneMinusSourceAlpha

Alpha Blending in Metal Not Giving The Expected Results

Well, it turns out the problem was indeed in the texture loading stage, but not in any piece of code that I could possibly tweak (at least not if sticking to MTKTextureLoader).

It seems that I needed to introduce some changes to the Attributes Inspector of my asset catalog in Xcode (But at least now I get to tag my original question with Xcode: One step closer to the bronze badge!).

Specifically, I had to change the texture set's Interpretation attribute from the default option of "Colors" to "Colors (non-premultiplied)":

Sample Image

Cleary, these asset catalog texture sets where designed with more traditional texture image formats in mind such as e.g. TGA, an not PNG (which is officially non-premultiplied, as per the specification).

I somehow expected that MTKTextureLoader would be smart enough to do this for me at load time. Evidently, it is not a piece of information that can be reliably read from (e.g.) a PNG file's metadata/header.


Now, my reference texture is rendered in all its bright glory:

Sample Image

As a final, more rigorous test, I can confirm that all 4 colors "disappear" over an equivalent RGB background, regardless of the texels' opacities:

Sample Image

Explicitly Release Metal Texture

MTLTexture lifetimes are managed exactly like other objects: they are dealloc'ed when their refcount reaches 0 (whether that happens automatically with ARC/Swift or MRR under Obj-C). Objects that use textures, like command buffers, may retain textures while they are in use, affecting their lifetime, but most applications can happily ignore this.



Related Topics



Leave a reply



Submit