using multiple programs in open gl es 2

Hi,

Is there any online sample that shows how to use two or more gles2 programs (using glUseProgram)? I’m getting strange errors when i try to do that here.

thanks in advance,

guich

can you post your code here? and what error are you getting?

At the same time? You can create as much programs as you want. You can have only one active program at a time when using glUseProgram() and since that’s the only way in GLES2/3 you have to stick with that.

Hi,

Here’s the code:


#define TEXTURE_VERTEX_CODE  \
      "uniform vec4 uTextureColor;" \
      "attribute vec4 vertexPoint;" \
      "attribute vec2 aTextureCoord;" \
      "uniform mat4 projectionMatrix; " \
      "varying vec2 vTextureCoord;" \
      "varying vec4 vTextureColor;" \
      "void main()" \
      "{" \
      "    gl_Position = vertexPoint * projectionMatrix;" \
      "    vTextureCoord = aTextureCoord;" \
      "    vTextureColor = uTextureColor;" \
      "}"                         
     
#define TEXTURE_FRAGMENT_CODE \
      "precision mediump float;" \
      "varying vec2 vTextureCoord;" \
      "varying vec4 vTextureColor;" \
      "uniform sampler2D sTexture;" \
      "void main() {gl_FragColor = texture2D(sTexture, vTextureCoord) * vTextureColor;}"

static GLuint textureProgram;
static GLuint textureColor,texturePoint;
static GLuint textureCoord,textureId;

//////////// points (text)

#define POINTS_VERTEX_CODE \
      "attribute vec4 a_Position; attribute vec4 a_Color; varying vec4 v_Color;" \
      "uniform mat4 projectionMatrix;" \
      "void main() {v_Color = a_Color; gl_Position = a_Position * projectionMatrix;}"

#define POINTS_FRAGMENT_CODE \
      "precision mediump float;" \
      "varying vec4 v_Color;" \
      "void main() {gl_FragColor = v_Color;}"

void initTexture()
{  
   GLfloat textureVerts[8] = { 0, 1,  1, 1,  1, 0,  0, 0 };
   debug("init texture");
   
   textureProgram = glCreateProgram();
   glAttachShader(textureProgram, loadShader(GL_VERTEX_SHADER, TEXTURE_VERTEX_CODE));
   glAttachShader(textureProgram, loadShader(GL_FRAGMENT_SHADER, TEXTURE_FRAGMENT_CODE));
   glLinkProgram(textureProgram);
   glUseProgram(textureProgram);
   
   glEnable(GL_TEXTURE_2D);
   glActiveTexture(GL_TEXTURE0);

   textureColor = glGetUniformLocation(textureProgram, "uTextureColor");
   textureId    = glGetUniformLocation(textureProgram, "sTexture");
   texturePoint = glGetAttribLocation(textureProgram, "vertexPoint");
   textureCoord = glGetAttribLocation(textureProgram, "aTextureCoord");

   glEnableVertexAttribArray(textureCoord);
   glVertexAttribPointer(textureCoord, 2, GL_FLOAT, false, 0, textureVerts);

   glEnableVertexAttribArray(texturePoint);
}

void initPoints()
{
   debug("init points");
   pointsProgram = glCreateProgram();
   glAttachShader(pointsProgram, loadShader(GL_VERTEX_SHADER, POINTS_VERTEX_CODE));
   glAttachShader(pointsProgram, loadShader(GL_FRAGMENT_SHADER, POINTS_FRAGMENT_CODE));
   glLinkProgram(pointsProgram);
   glUseProgram(pointsProgram);

   pointsColor    = glGetAttribLocation(pointsProgram, "a_Color");
   pointsPosition = glGetAttribLocation(pointsProgram, "a_Position"); // get handle to vertex shader's vPosition member
   glEnableVertexAttribArray(pointsColor); // Enable a handle to the colors
   glEnableVertexAttribArray(pointsPosition); // Enable a handle to the vertices
}
GLuint loadShader(GLenum shaderType, const char* pSource)
{
   GLuint shader = glCreateShader(shaderType);
   checkGlErrorI("loadShader createShader",shaderType); // ***
   glShaderSource(shader, 1, &pSource, NULL);
   checkGlError("loadShader glShaderSource");
   glCompileShader(shader);
   checkGlError("loadShader glCompileShader");
   return shader;
}


If i call

initTexture();
initPoints();

then i get a GL_INVALID_ENUM when compiling the GL_VERTEX_SHADER of initPoints in line marked with ***. If i call only initPoints(), i don’t get such error.

If i use both codes standalone, they work.

thanks

guich

The GL_INVALID_ENUM error is probably from this line:

glEnable(GL_TEXTURE_2D);

Since enabling/disabling textures is only used by fixed function OpenGL, not while using shaders.

[QUOTE=Dan Bartlett;1243027]The GL_INVALID_ENUM error is probably from this line:

glEnable(GL_TEXTURE_2D);

Since enabling/disabling textures is only used by fixed function OpenGL, not while using shaders.[/QUOTE]

You were right! Removing the line made the code work without such error.

Something i cant understand is about the state changes. What is and what is not stored in the program when you call glUseProgram? For example, are the glEnableVertexAttribArray calls persistent across glUseProgram calls? Is there any document that says what you have to call again after each program change and what is persisted?

From my researches, everyone says that to keep performance a high rate, you have to batch the commands to opengl. I believe that a program change flushes the pipeline. So, would it be faster to add a variable inside a program and a if/else to select the desired program code, or do 3 distinct programs for each situation? I have 3 here: one program to draw point,line,rect; one to draw points; and one to draw textures.

thanks!

guich

What is and what is not stored in the program when you call glUseProgram?

Nothing. Calling glUseProgram does not “store” anything in the program. It makes the state that is already stored in the program available to the context. That state includes:

  • The compiled/linked programs.
  • The uniform values for each non-default block uniform variable.
  • The UBO binding indices for uniform blocks in the programs.
  • Other similar state.

Program state deals with programs and stuff within programs; it has nothing to do (directly of course) with vertex arrays. That state is owned by the Vertex Array Object. You shouldn’t be concerned about glUseProgram smashing some random and arbitrary state. OpenGL’s API may be a bit odd, but it’s not that stupid.

Most of the time…

I believe that a program change flushes the pipeline.

Why? Do you know enough about various OpenGL implementations to know that for a fact? And if you don’t know it, why would you base optimization decisions on it?

Profile first, optimize later.