0

I am having a problem getting an openGL fragment shader .fsh to appear on the texture of my Sprite in Spritekit. I downloaded a second shader file for troubleshooting purposes and it DID work. So what is going wrong with the first shader file?

After adding the file to my project and initializing it like this

class GameScene: SKScene {

    private var leftDoor: SKSpriteNode!
    private var doorShader: SKShader!

override func didMove(to view: SKView) {
    self.initializeDoors()
    self.initializeShader()
}

func initializeShader() {
        // Initialize shaders
        self.doorShader = SKShader(fileNamed: "shader.fsh")
    }
func initializeDoors() {
    // Initializing left door
        self.setDoorAttributes("left")
    leftDoor.position = CGPoint(x:(view!.bounds.size.width/2) - (25 * leftDoor.frame.size
            .width / 20), y: self.view!.bounds.size.height + leftDoor.frame.size.height/2)
        // Specifying zPosition
        leftDoor.zPosition = 1
        // Adding the door to the scene
        addChild(leftDoor)
    }
func setDoorAttributes(_ position: String) {
     switch position {
            case "wrong_left_door", "correct_left_door", "left":
                // Setting the door sprite randomly
            if (arc4random_uniform(2) == 0) {
                    // Initialize the door if null
                    if (leftDoor == nil) {
                        leftDoor = SKSpriteNode(imageNamed: "wrong_door")
                    }
                    // Update texture and name attributes
                    leftDoor.texture = SKTexture(imageNamed: "wrong_door")
                    leftDoor.name = "wrong_left_door"
                    leftDoor.shader = self.doorShader
                } else {
                    // Initialize the door if null
                    if (leftDoor == nil) {
                        leftDoor = SKSpriteNode(imageNamed: "correct_door")
                    }
                    // Update texture and name attributes
                    leftDoor.texture = SKTexture(imageNamed: "correct_door")
                    leftDoor.name = "correct_left_door"
                    // Remove shader
                    leftDoor.shader = nil
                }
    }

The door shader never appears on any door. I suspect either the code for the shader might be written in an old and outdated fashion or I made some error in adding the file to my project. So if anyone can take a look at the following shader code and give me some advice how to update or fix it, it would be appreciated. Here is the contents of the shader file ->

float M_PI  = 3.141592653589793;
float M_2PI =  6.283185307179586;

vec3 c1a = vec3(0.0, 0.0, 0.0);
vec3 c1b = vec3(0.9, 0.0, 0.4);
vec3 c2a = vec3(0.0, 0.5, 0.9);
vec3 c2b = vec3(0.0, 0.0, 0.0);

void main() {
    vec2 point = (0.5 * u_sprite_size - gl_FragCoord.xy) / u_sprite_size;
    float angle = atan(point.y, point.x);
    float turn = (angle + M_PI) / M_2PI;
    float radius = sqrt(point.x * point.x + point.y * point.y);
    
    float sine_kf = 19.0;
    float ka_wave_rate = 0.94;
    float ka_wave = sin(ka_wave_rate * u_time);
    float sine_ka = 0.35 * ka_wave;
    float sine2_ka = 0.47 * sin(0.87 * u_time);
    float turn_t = turn + -0.0 * u_time + sine_ka * sin(sine_kf * radius) + sine2_ka * sin(8.0 * angle);
    bool turn_bit = mod(10.0 * turn_t, 2.0) < 1.0;
    
    float blend_k = pow((ka_wave + 1.0) * 0.5, 1.0);
    vec3 c;
    if(turn_bit) {
        c = blend_k * c1a + (1.0 -blend_k) * c1b;
    } else {
        c = blend_k * c2a + (1.0 -blend_k) * c2b;
    }
    c *= 1.0 + 1.0 * radius;
    
    gl_FragColor = vec4(c, 1.0);
}
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
quickj
  • 25
  • 5

1 Answers1

0

there are two errors in your code. first, you are initializing your sprite before initializing your shader. thus when you assign the shader to the sprite the shader is still null. this also means the shader isn't compiled and isn't giving error messages. here's a minimal reproducible example that works better for debugging

override func didMove(to view: SKView) {
    doorShader = SKShader(fileNamed: "shader.fsh")
    leftDoor = SKSpriteNode(imageNamed: "wrong_door")
    leftDoor.shader = doorShader //<-- shader is non-null at assignment
    addChild(leftDoor)
}

second, the global variables in the shader need to be marked constant as explained here

constant float M_PI  = 3.141592653589793;
constant float M_2PI =  6.283185307179586;

constant vec3 c1a = vec3(0.0, 0.0, 0.0);
constant vec3 c1b = vec3(0.9, 0.0, 0.4);
constant vec3 c2a = vec3(0.0, 0.5, 0.9);
constant vec3 c2b = vec3(0.0, 0.0, 0.0);
Fault
  • 1,115
  • 1
  • 7
  • 11