Search code examples
iosxcodeglslnsbundlevertex-shader

Why doesn't Xcode recognize these shaders?


I'm trying to teach myself Xcode, Objective-C, iOS app development, and GLSL all at once. (Probably not advisable, I know. ;-) I've been modifying the GLCameraRipple example, and had a lot of success so far! But I got stumped today when I tried to create some new vertex and fragment shaders.

The example comes with shaders called "Shader.vsh" and "Shader.fsh". I used File->Duplicate to make copies of them, which I called "Reflection.vsh" and "Reflection.fsh" respectively. The problem is that I can't get Xcode to recognize the new shaders. This code, which loads up the original vertex shader, works just fine:

vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"];
NSLog(@"Original vertex shader should be here: %@", vertShaderPathname);
if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) {
    NSLog(@"Failed to compile original vertex shader");
    return NO;
}

But this code, which tries to load my new "Reflection.vsh" shader, fails. Specifically, the reflectVertShaderPathname string comes back with a value of (null).

reflectVertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Reflection" ofType:@"vsh"];
NSLog(@"Reflection vertex shader should be here: %@", reflectVertShaderPathname);
if (![self compileShader:&reflectVertShader type:GL_VERTEX_SHADER file:reflectVertShaderPathname]) {
    NSLog(@"Failed to compile reflection vertex shader");
    return NO;
}

What do I have to do to make this work? I can't even tell where to start: is Xcode failing to include my new shaders in the NSBundle it makes when compiling this for the iPad? What magic voodoo do I have to invoke to convince Xcode to load up my new shaders? (Or am I looking for answers in the wrong place entirely?) Has anyone else run into a similar problem before?

Inspecting the "project.pbxproj" file in a text editor, I noticed a section where the shaders are being treated differently:

/* Begin PBXResourcesBuildPhase section */
            B66E3E2C13E9E79C00D2ACF0 /* Resources */ = {
                    isa = PBXResourcesBuildPhase;
                    buildActionMask = 2147483647;
                    files = (
                            B66E3E4713E9E79C00D2ACF0 /* Shader.fsh in Resources */,
                            B66E3E4913E9E79C00D2ACF0 /* Shader.vsh in Resources */,
                            B66E3E4F13E9E79C00D2ACF0 /* RippleViewController_iPhone.xib in Resources */,
                            B66E3E5213E9E79C00D2ACF0 /* RippleViewController_iPad.xib in Resources */,
                            B6388B2C141AB58300DA02FB /* Icon-72.png in Resources */,
                            B6388B2D141AB58300DA02FB /* Icon-Small-50.png in Resources */,
                            B6388B2E141AB58300DA02FB /* Icon-Small.png in Resources */,
                            B6388B2F141AB58300DA02FB /* Icon-Small@2x.png in Resources */,
                            B6388B30141AB58300DA02FB /* Icon.png in Resources */,
                            B6388B31141AB58300DA02FB /* Icon@2x.png in Resources */,
                            C3E55C21175C49F9007C299D /* Default-568h@2x.png in Resources */,
                    );
                    runOnlyForDeploymentPostprocessing = 0;
            };
/* End PBXResourcesBuildPhase section */

/* Begin PBXSourcesBuildPhase section */
            B66E3E2A13E9E79C00D2ACF0 /* Sources */ = {
                    isa = PBXSourcesBuildPhase;
                    buildActionMask = 2147483647;
                    files = (
                            B66E3E4113E9E79C00D2ACF0 /* main.m in Sources */,
                            B66E3E4513E9E79C00D2ACF0 /* AppDelegate.m in Sources */,
                            B66E3E4C13E9E79C00D2ACF0 /* RippleViewController.m in Sources */,
                            B6670DB413E9FD9F00AEF9EC /* RippleModel.m in Sources */,
                            C359BF4D175EA71C00D801B9 /* Reflection.fsh in Sources */,
                            C359BF4F175EA72A00D801B9 /* Reflection.vsh in Sources */,
                    );
                    runOnlyForDeploymentPostprocessing = 0;
            };
/* End PBXSourcesBuildPhase section */

So it looks like "Shader.vsh" is in something called "Resources", and "Reflection.vsh" is in something called "Sources". I assume that's part of the problem. But (a) what does that even mean, and (b) how should I fix it? Is it safe to just edit project.pbxproj in a text editor???


Solution

  • You've almost got it - xcode needs to know these are resources that need to be copied over, not source. No need to edit project files by hand, it's easy to fix in xcode:

    • Select your project (from the column on the left)
    • Select your target
    • Select the build phases tab
    • If the shaders appear in "compile sources", remove them
    • Add your shaders to "copy bundle resources"

    That's it! Keep in mind, you'll have to do this for every new shader you add.