Problem getting shaders to work on iOS

Hi everybody, I’m trying to go through this tutorial applying it to iOS but I’m blocked at the first example:

http://openframeworks.cc/tutorials/graphics/shaders.html

Here’s my code from main.mm:

ofSetCurrentRenderer(ofGLProgrammableRenderer::TYPE);

ofSetupOpenGL( 1024, 768, OF_FULLSCREEN ); // <-------- setup the GL context
ofRunApp( new ofApp() );

And here’s the setup function from ofApp.mm:

shader.load( "tutorial.vs", "tutorial.fs" );
xRes = 768;
yRes = 1024;
ofSetFrameRate( 60 );

And this is the draw function from ofApp.mm:

ofSetColor( ofColor::white );
shader.begin();
ofRect( 0, 0, 100, 100 ); 
shader.end();

Vertex shader:

precision highp float;

uniform mat4 modelViewProjectionMatrix;
varying vec4 position;

void main() {
    gl_Position = modelViewProjectionMatrix * position;
}

Fragment shader:

precision highp float;

void main() {

    float windowWidth = 768.0;
    float windowHeight = 1024.0;

    float r = gl_FragCoord.x / windowWidth;
    float g = gl_FragCoord.y / windowHeight;
    float b = 1.0;
    float a = 1.0;

    gl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );
}

My console says:

trying to lauunch delegate ofxiOSAppDelegate
2015-03-21 09:39:54.232 emptyExample[3072:60b] Creating OpenGL ES2 Renderer

And the output is a white screen, as if the rect is being drawn without the shader applied.
I’m pretty sure the shaders are being compiled, because I had to go through a few steps fixing syntax errors in them. I’m not sure what is going on here, I expect the rect to be filled red. Is there anything else I need to do to turn on shaders?

Thank you!

Same problem here, any updates on this?

Hey there,

I spent all day looking at this, but unfortunately I am even more confused. Since capturing an OpenGL ES frame doesn’t seem to work in XCode for me I had to investigate with print statements. Also, after the first draw call I am not able to place a breakpoint anymore – not sure if you are seeing the same behavior.

Anyways, this post really helped me out:

I realized that even when my shaders aren’t working, some other shaders are (the ones in ofGLProgrammableRenderer are used if you don’t specify your own shaders). So at the least I can get shaders to run on iOS by overwriting the default shaders in ofGLProgrammableRenderer.

It seems like no matter what, if I place any visual calls between shader.begin() and shader.end() nothing draws to the screen and the program gets into a very bad state. Even if the shaders are exact duplicates of the default shaders!

Leaving an empty shader.begin() and shader.end() pair seems to be fine and doesn’t adversely affect anything.

I went through lacing the program up with calls to glError() but didn’t find anything yet.

Maybe this will provide some clues to somebody? It sounds like maybe something is missing in terms of hooking up uniforms or attibutes when ofShader is used?

Also, just went to see if anything about this problem was mentioned in the changelog here:

https://github.com/openframeworks/openFrameworks/commits/master/libs/openFrameworks/gl/ofGLProgrammableRenderer.cpp

And realized I am running 0.8.0… going to update to 0.8.4 later tonight and see what happens.

Okay, so it was something with those sample shaders. When I run examples/iosES2ShaderExample everything works fine.

I guess I just have to make those sample shaders look like these sample shaders.

Here they are fixed up, the vertex shader:

attribute vec4 position;
attribute vec4 color;
attribute vec4 normal;
attribute vec2 texcoord;

uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;

varying vec4 colorVarying;
varying vec2 texCoordVarying;

void main() {
	vec4 pos = projectionMatrix * modelViewMatrix * position;
    gl_Position = pos;
}

And the fragment shader:

precision highp float;

uniform sampler2D src_tex_unit0;
uniform float useTexture;
uniform float useColors;
uniform vec4 globalColor;

varying float depth;
varying vec4 colorVarying;
varying vec2 texCoordVarying;

void main() {
    // gl_FragCoord contains the window relative coordinate for the fragment.
    // we use gl_FragCoord.x position to control the red color value
    // we use gl_FragCoord.y position to control the green color value
    // please note that all r, g, b, a values are between 0 and 1

    float windowWidth = 768.0;
    float windowHeight = 1024.0;

    float r = gl_FragCoord.x / windowWidth;
    float g = gl_FragCoord.y / windowHeight;
    float b = 1.0;
    float a = 1.0;

    gl_FragColor = vec4( r, g, b, a );
}

I guess the lesson is unused attributes and varyings are important and even if the GLSL compiler says everything is okay maybe sometimes it isn’t.