rraallvv
rraallvv

Reputation: 2933

Why is SpriteKit not updating the shader’s uniforms?

I added two shaders to my project, one is the same shader from the WWDC 2014 example, and the other has the same code but adding a custom uniform. The problem is that the sprite with the custom uniform is rendered static when the app is running, and with black color on SpriteKit editor in Xcode.

enter image description here

The shader with the custom uniform is below, u_speed is used to control how fast the waves move.

void main()
{
    float currTime = u_time * u_speed;

    vec2 uv = v_tex_coord;
    vec2 circleCenter = vec2(0.5, 0.5);
    vec3 circleColor = vec3(0.8, 0.5, 0.7);
    vec3 posColor = vec3(uv, 0.5 + 0.5 * sin(currTime)) * circleColor;

    float illu = pow(1. - distance(uv, circleCenter), 4.) * 1.2;
    illu *= (2. + abs(0.4 + cos(currTime * -20. + 50. * distance(uv, circleCenter)) / 1.5));

    gl_FragColor = vec4(posColor * illu * 2., illu * 2.) * v_color_mix.a;
}

This is a project I’ve put together with just the shaders and the two sprites showing the problem.

Upvotes: 1

Views: 1203

Answers (2)

rraallvv
rraallvv

Reputation: 2933

Adding something like the code below in didMoveToView: did the trick, somehow the uniforms are there but are not read by the shader, this "refreshing" of the values did make it work normally.

for (SKSpriteNode *sprite in self.children) {
    if ([sprite isKindOfClass:[SKSpriteNode class]]) {
        for (SKUniform *uniform in sprite.shader.uniforms) {
            if (uniform.uniformType == SKUniformTypeFloat) {
                uniform.floatValue = uniform.floatValue;
            }
        }
    }
}

Upvotes: 1

itnAAnti
itnAAnti

Reputation: 654

From what I can tell, there's nothing wrong with your code. There seems to be a bug in how GameScene.sks passes your custom shader uniform into the shader which is causing it to be 0, and the animation to freeze.

If you initialize everything in code rather than in the UI Builder, it works fine. Paste this into your didMoveToView: to see what I mean.

SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithColor:[SKColor whiteColor] size:CGSizeMake(100, 100)];
sprite.position = CGPointMake(self.size.width/2, self.size.height/2);
[self addChild:sprite];
SKShader* spin2x = [SKShader shaderWithFileNamed:@"Shader2"];

spin2x.uniforms = @[
                         [SKUniform uniformWithName:@"u_speed" float:(2.0)],
                         ];
sprite.shader = spin2x;

Upvotes: 2

Related Questions