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)":
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:
As a final, more rigorous test, I can confirm that all 4 colors "disappear" over an equivalent RGB background, regardless of the texels' opacities:
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
Generate Random Questions in Swift
Error: Missing Return in a Closure Expected to Return 'Uiviewcontroller' (Xcode, Swift, iOS 13)
How to Collect The Return Value of a Function (Swift 3)
What's The How to Access a Swift Package Item from Objective-C
Core Image and Memory Leak, Swift 3.0
Populating Collection View from Array in Document Directory
Combining Scenekit and Spritekit in a Single Screen
Prepareforsegue from a UIbutton in a Custom Prototype Cell
Swift Variable Declaration Meaning
Swift Pattern Match on Array<Any>
How to Programmatically Scroll iOS Wkwebview, Swift 4
Pinterest-iOS 2.3 and Swift: Calling Createpinwithimageurl Results in Exc_Bad_Access
Macos, Swift 3: How to Get Data Back After Segue
Allow Siri Remote Menu Button When Play/Pause Button Is Overridden
How to Change Bordercolor When Button.Ishighlighted
Advantage of Computed Properties (Gettable Ones Only) VS. Stored Properties