Summary
I have found a solution. In the end, it was my mistake. SpriteKit will certainly automatically revert to openGL. The GLES shader language is less simple than metal. This is where the problem arose. In openGL shaders, you MUST set a decimal point in each number. Unfortunately, the shader compiler did not tell me that after compilation. Another problem was that sometimes old shaders build a stick with a package. Perform clean before testing the shader.
So, here's how to deal with both types of shaders and detect Metal / openGL:
Determine if metal is available
This little helper can be placed anywhere in your code. This helps you detect metal upon first use and gives you the ability to execute your own code, depending on your configuration, once.
Headers:
#import SpriteKit #import Metal
code:
var metalAvailable:Bool { get { struct Static { static var metalAvailable : Bool = false static var metalNeedsToBeTested : Bool = true } if Static.metalNeedsToBeTested { Static.metalNeedsToBeTested = false let device = MTLCreateSystemDefaultDevice() Static.metalAvailable = (device != nil) if Static.metalAvailable {
Create a shader in a sprite set
Create a shader, as usual, using a set of sprites.
let shaderContainer = SKSpriteNode() shaderContainer.position = CGPoint(x:self.frame.size.width/2, y:self.frame.size.height/2) shaderContainer.size = CGSize(width:self.frame.size.width, height:self.frame.size.height) self.backgroundNode.addChild(shaderContainer) let bgShader:SKShader
As you can see, depending on the detected configuration, another shader file is loaded. OpenGL shaders require an extra form for size because the v_tex_coord character is not available in openGL. If you are not using the size in the Metal form, you can move the form operator to the if block or simply ignore it. Metal does not complain if you do not use it.
Metal Shader: plasma.fsh
#define M_PI 3.1415926535897932384626433832795 #define frequency 1
In metal shaders, you can simply read the normalized coordinates. You can use the size to restore the coordinates of the image if you want. However, the metal more forgives decimal points. As you can see, some numbers here do not have decimal points.
Open GL shader: plasmaGL.fsh
Outlook
This is a lot of work to test both systems and create two shaders. But as long as we move from GL to Metal, this is a good method for checking which type of shader to use. The iOS simulator also does not support Metal. This means that you can test openGL behavior with the iOS simulator and tvOS.
If you are developing for AppleTV, then this approach is really convenient because openGL shaders always work with Metal. You just need to replace gl_FragCoord.xy / size.xy with v_tex_coord. If you run the code on the simulator, you will see the openGL code; if you run it on the AppleTV target, you will see smooth metal shaders.
And one more hint to all fast developers: never forget the semicolon at the end of the line with shaders; -)
Another trap throws.
Metal: int intVal = (int) uv.x; float a = (float) intVal;
Open GL: int intVal = int (uv.x); float a = float (intVal);
Hope I help someone.
Greetings
Jack