3

I'm writing an App for iPad and iOS 10. I'm using Objective-C and SpriteKit.

I need to draw a line that starts in one color and ends in another color (eg. red to green).

This is my Objective-C code:

CGPoint points[2];
points[0] = CGPointMake(100, 100);
points[1] = CGPointMake(160, 110);

SKShapeNode *line1=[SKShapeNode shapeNodeWithPoints:points count:2];
line1.lineWidth = 2.0;
line1.zPosition = -1;
line1.name=@"line";
SKShader *myShader=[SKShader shaderWithFileNamed:@"shader1.fsh"];
line1.strokeShader=myShader;
[self addChild:line1];

And this is the shader:

void main(){

float length = u_path_length;
float distance = v_path_distance;


gl_FragColor = vec4(1.0*(1-(distance/length)), 1.0*(distance/length), 0., 1.);
}

When I run the App I get the error (related to Metal): failed assertion 'missing buffer binding at index 1 for u_path_length[0].'

It looks like u_path_length and v_path_distance don't work in iOS 10.

Can you help solve this problem? Or can you suggest a different solution to the problem?

danyadd
  • 119
  • 1
  • 2
  • 8
  • Don't know if this can help in some way, or will it affect on performance in your case : http://stackoverflow.com/q/34422374. Or you can look this one : http://stackoverflow.com/a/36261550/3402095 – Whirlwind Nov 05 '16 at 20:18
  • @Whirlwind Thank you for your suggestion, but the solutions that you link will create an image that then can be used as a texture. The problem is that SKShapeNode doesn't work very well with textures (can't control texture size) that's why I'd like to use a shader. I need to draw many of these lines on the screen (at least 100). At the moment I'm thinking about using SKShapeNode with a shader (best solution in my opinion) or SKSpriteNode with an image from assets (which I already have working code for). – danyadd Nov 06 '16 at 08:18
  • Well ideally you shouldn't use SKShapeNode at all because one SKShapeNode requires one draw call. Means, you might very quickly run into performance issues. Unlike SKSpriteNode which can be drawn in batches, SKShapeNodes can't, and are meant to be used sparingly, like pointed in the docs. So I would personally avoid it if there can be more than 10-15 instances of them at the same time on the screen. – Whirlwind Nov 06 '16 at 08:24

1 Answers1

2

If I add the PrefersOpenGL key with a bool value of YES in the Info.plist file, the error (related to Metal) disappears. Of course this means that my App will not use Metal. I suppose this is a bug in iOS 10.

I faced another problem: v_path_distance works as expect but u_path_length doesn't. u_path_length is always = 0.

To solve the problem I had to modify my code.

This is my Objective-C code:

CGPoint points[2]; 
points[0] = CGPointMake(100, 100); 
points[1] =  CGPointMake(160, 110);

SKShapeNode *line1=[SKShapeNode shapeNodeWithPoints:points count:2];
line1.lineWidth = 2.0; 
line1.zPosition = -1; 
line1.name=@"line"; 
SKShader *myShader=[SKShader shaderWithFileNamed:@"shader1.fsh"];   
float my_length=hypotf(points[1].x-points[0].x, points[1].y-points[0].y); 
myShader.uniforms=@[[SKUniform uniformWithName:@"u_my_length" float:my_length]];
line1.strokeShader=myShader; 
[self addChild:line1];

And this is the shader:

void main(){    

gl_FragColor=vec4(1.0*(1.0-(v_path_distance/u_my_length)),1.0*(v_path_distance/u_my_length),0.,1.0);

}
danyadd
  • 119
  • 1
  • 2
  • 8