# Controlling Shape Drawing with Shaders ------------------------- Change a shape node's appearance by supplying custom shader code. ### Overview When you want to go beyond the effects provided by a shape node's properties, you can take full control of its stroking or filling by using the `strokeShader` and `fillShader` properties, respectively. To do that, you supply custom OpenGL ES shader code embedded within a `SKShader` object. Custom shaders allow you to create custom effects, such as dashed lines and gradient strokes, and custom fills, such as checkerboards and random patterns. ### Customize a Shape Node's Stroke Shape nodes have two additional stroke-related properties that extend the properties defined by `SKShader`: |Symbol declaration|Type|Description| |------------------|----|-----------| |float u_path_length;|Uniform|The total length of the path, in points.| |float v_path_distance;|Varying|The distance along the path, in points.| By dividing the distance along the path by the total length of the path, you get the normalized position (between 0 and 1) of each point along a shape node's path and use it to construct the color of each pixel along the shape node's stroke. The following code shows how you create a custom shader to do this: ```swift let gradientShader = SKShader(source: "void main() {" + "float normalisedPosition = v_path_distance / u_path_length;" + "gl_FragColor = vec4(normalisedPosition, normalisedPosition, 0.0, 1.0);" + "}") let squareShapeNode = SKShapeNode(rectOf: CGSize(width: 610, height: 200), cornerRadius: 25) squareShapeNode.fillColor = .clear squareShapeNode.lineWidth = 20 squareShapeNode.strokeShader = gradientShader ``` The generated shape node looks like this: ![controlling-shape-drawing-with-shaders-001](/images/035-skshapenode-controlling-shape-drawing-with-shaders-001.png) Alternatively, by casting both symbols to integers and using the modulo operator, you get the same shape node with a shader that generates a dashed line, as shown in the following code: ```swift let dashedShader = SKShader(source: "void main() {" + "int stripe = int(u_path_length) / 150;" + "int h = int(v_path_distance) / stripe % 2;" + "gl_FragColor = float4(h);" + "}") ``` The generated shape node looks like this: ![controlling-shape-drawing-with-shaders-002](/images/035-skshapenode-controlling-shape-drawing-with-shaders-002.png) ### Customize a Shape Node's Fill You create a custom fill for a shape node by writing shader code and embedding it within an `SKShader` object. Assigning the shader to the `fillShader` property overrides the appearance that would otherwise be defined by `fillColor` and `fillTexture`. The following shader code demonstrates filling a shape node with a simple checkerboard texture. Inside the shader, the variables h and v would, on their own, form horizontal and vertical stripes. The exclusive or operator, ^, creates the checkerboard pattern from those stripes. ```swift let checkerboardShader = SKShader(source: "void main() {" + "int size = 20;" + "int h = int(v_tex_coord.x * u_texture_size.x) / size % 2;" + "int v = int(v_tex_coord.y * u_texture_size.y) / size % 2;" + "gl_FragColor = float4(v ^ h, v ^ h, v ^ h, 1.0);" + "}") let size = CGSize(width: 610, height: 200) checkerboardShader.uniforms = [ SKUniform(name: "u_texture_size", vectorFloat2: vector_float2(Float(size.width), Float(size.height))) ] let squareShapeNode = SKShapeNode(rectOf: size, cornerRadius: 25) squareShapeNode.fillShader = checkerboardShader ``` The generated shape node looks like this: ![controlling-shape-drawing-with-shaders-002](/images/035-skshapenode-controlling-shape-drawing-with-shaders-003.png) -------------------------------- [download this page as .md](https://raw.githubusercontent.com/retrokid/retrokid.github.io/master/tech_notes/spritekit_documentation/035-skshapenode-controlling-shape-drawing-with-shaders.md) [download this page as .pdf](https://github.com/retrokid/retrokid.github.io/raw/master/tech_notes/spritekit_documentation/035-skshapenode-controlling-shape-drawing-with-shaders.pdf) [back to SpriteKit documentation](./spritekit-documentation)