Search code examples
swiftopenglsprite-kitshaderskshapenode

SKShapeNode: Shader transparency is ignored


I want to fill a SKShapeNode with a linear gradient. Being a programming perfectionist I want the solution to be as customizable as possible. So I decided to use a fillShader. Here's the shader:

let shader = SKShader(
    source: "void main() {" +
    "vec4 c1 = vec4(1, 1, 1, 0.25);" +
    "vec4 c2 = vec4(0, 0, 0, 0);" +
    "vec2 p1 = vec2(0, 0);" +
    "vec2 p2 = vec2(1, 1);" +
    "vec2 v0 = p2 - p1;" +
    "vec2 v = v_tex_coord - p1;" +
    "float t = dot(v, v0) / (length(v0) * length(v0));" +
    "t = clamp(t, 0.0, 1.0);" +
    "gl_FragColor = mix(c1, c2, t);" +
    "}")

(c1, c2, p1, p2 should be attributes but here they are constant to isolate the bug)

So the problem is the shader ignores alpha, and instead of transparent color white I see solid white in the corner:

Gradient

If you change c1 and c2 to other colors, the bug will stay there.


Solution

  • Like the comments said, the color value you return should already be premultiplied by the fragment's alpha value.

    From Apple's documentation - Creating a Custom Fragment Shader:

    Typically, the color value you return in this variable should already be premultiplied by the fragment’s alpha value.

    You might also want to use v_color_mix.a if you want your shader to take into account the alpha value set on the node:

    gl_FragColor = col * v_color_mix.a;