2

I am trying to draw a centered circle to fill in image with a shader in SpriteKit using Swift. I am using this link to learn about shaders, and the section I'm using for this looks like this:

vec2 center = vec2(uResolution.x/2., uResolution.y/2.);

float radius = uResolution.x/2.;

vec2 position = gl_FragCoord.xy - center;

if (length(position) > radius) {
    gl_FragColor = vec4(vec3(0.), 1.);
} else {
    gl_FragColor = vec4(vec3(1.), 1.);
}

But I wanted to use this with SpriteKit so I rewrote it as this:

void main() {

    vec2 center = u_sprite_size / 2.0;
    float radius = center.x;
    vec2 position = v_tex_coord - center;

    if (length(position) > radius) {
        gl_FragColor = vec4(vec3(0.0), 1.0);
    } else {
        gl_FragColor = vec4(vec3(1.0), 1.0);
    }

}

This is how I am loading the shader:

let node = SKSpriteNode(imageNamed: "napolean.png")
node.position = CGPoint(x: size.width / 2, y: size.height / 2)
node.shader = SKShader(fileNamed: "circle.fsh")
addChild(node)

When I run the image is always black, and gl_FragColor = vec4(vec3(1.0), 1.0); is never run, and there are no errors in the console. Could someone explain what is going wrong? Thanks

Update

Okapi pointed out that u_tex_coord is normalized, so I normalized the center then divided it in half like this: vec2 center = (u_sprite_size) / length(u_sprite_size) / 2.0;. After I do that I can the the circle, but it is too small and off center

Community
  • 1
  • 1
Addison
  • 3,791
  • 3
  • 28
  • 48
  • I think `v_tex_coord` is in unit coordinates `[0-1]` so centre should be `vec2(0.5,0.5)` and radius should be `1.0` –  Mar 21 '15 at 13:47
  • Ok, I just tried that and now the whole screen is white instead of black. – Addison Mar 21 '15 at 13:52
  • Oh wait, If I normalize u_sprite_size like this: `center = (u_sprite_size / 2.0) / length(u_sprite_size / 2.0);` then I can see the circle is working, but its too big and off center. – Addison Mar 21 '15 at 13:58
  • Actually I think `vec2 center = (u_sprite_size) / length(u_sprite_size) / 2.0;` would normalize it, then get half, but its to small and off center when I do that. – Addison Mar 21 '15 at 14:05

1 Answers1

1

Since v_tex_coord is normalized, you don’t have to use u_sprite_size at all—the texture coordinate will always be in the (0,0)–(1,1) range, which means your center and radius are always (0.5, 0.5) and 0.5 respectively. Your shader code can just be this:

void main() {
    const float radius = 0.5;
    vec2 position = v_tex_coord - vec2(0.5, 0.5);

    if (length(position) > radius) {
        gl_FragColor = vec4(vec3(0.0), 1.0);
    } else {
        gl_FragColor = vec4(vec3(1.0), 1.0);
    }
}
Noah Witherspoon
  • 57,021
  • 16
  • 130
  • 131