0
votes

I'm trying to use OpenGL ES 2.0 for Android to display a simple cube with normals and colors. To do so, I create a shader program, attach my vertex and fragment shaders, and link my program, as follows:

// Create empty OpenGL ES Program
mProgram = GLES20.glCreateProgram();
MyGLRenderer.checkGlError("glCreateProgram");

// Add the vertex shader to program
vertexShaderCode = Utilities.convertResourceToString(context, R.raw.vert_shader_hw3);
int vertexShader = MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
GLES20.glAttachShader(mProgram, vertexShader);
MyGLRenderer.checkGlError("glAttachShader");

// Add the fragment shader to program
fragmentShaderCode = Utilities.convertResourceToString(context, R.raw.frag_shader_hw3);
int fragmentShader = MyGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
GLES20.glAttachShader(mProgram, fragmentShader);
MyGLRenderer.checkGlError("glAttachShader");

// Bind attributes
GLES20.glBindAttribLocation(mProgram, 0, "aPosition");
MyGLRenderer.checkGlError("glBindAttribLocation");

GLES20.glBindAttribLocation(mProgram, 1, "aNormal");
MyGLRenderer.checkGlError("glBindAttribLocation");

GLES20.glBindAttribLocation(mProgram, 2, "aColor");
MyGLRenderer.checkGlError("glBindAttribLocation");

// Create OpenGL program executables
GLES20.glLinkProgram(mProgram);
MyGLRenderer.checkGlError("glLinkProgram");

// Add program to OpenGL ES environment
GLES20.glUseProgram(mProgram);
MyGLRenderer.checkGlError("glUseProgram");

And it crashes right there at the end, printing to the LogCat: glUseProgram: glError 1281 and I checked the documentation, and glError 1281, i.e. GL_INVALID_VALUE is generated if program is neither 0 nor a value generated by OpenGL.

After Googling this for ~10 hours now, I've decided to turn to StackOverflow for assistance. Any idea what could be wrong with my vertex shader code to make glUseProgram behave this way?

Here is my vertex shader code, my attempt to implement phong lighting:

uniform mat4 uMVPMatrix;
uniform mat4 uMVMatrix;
uniform vec3 uLightPosition;
uniform vec4 uAmbient;
uniform vec4 uDiffuse;
uniform vec4 uSpecular;
uniform vec4 uEmission;
uniform float uShininess;

attribute vec4 aPosition;
attribute vec3 aNormal;
attribute vec4 aColor;

varying vec4 vColor;

vec4 phong()
{
    //  P is the vertex coordinate on body
    vec3 P = vec3(uMVMatrix * aPosition);

    //  N is the object normal at P
    vec3 N = vec3(uMVMatrix * vec4(aNormal, 0.0)); 

    //  Light Position for light 0
    vec3 LightPos = uLightPosition;

    //  L is the light vector
    vec3 L = normalize(LightPos - P);

    //  R is the reflected light vector R = 2(L.N)N - L
    vec3 R = reflect(-L, N);

    //  V is the view vector (eye at the origin)
    vec3 V = normalize(-P);

    //  Diffuse light intensity is cosine of light and normal vectors
    float Id = max(dot(L,N) , 0.0);

    //  Shininess intensity is cosine of light and reflection vectors to a power
    float Is = (Id>0.0) ? pow(max(dot(R,V) , 0.0) , uShininess) : 0.0;

    //  Vertex color
    return uEmission + uAmbient + Id*uDiffuse + Is*uSpecular;
}

void main()
{
    gl_Position = uMVPMatrix * aPosition;
    vColor = phong() * 0.5*(gl_Position/gl_Position.w + 1.0);
}
2
Have you checked to confirm that the HW supports the required number of attributes, using something like >> getIntegerv(MAX_VERTEX_ATTRIBS, &n)Prabindh
Thanks for the swift response. Yes, I checked this by printing it to the LogCat. MAX_VERTEX_ATTRIBS on my Nexus 7 tablet is 16.Luke
Did you try to check the LINK_STATUS and the shader info log ?rotoglup

2 Answers

2
votes

Thanks for the help guys. I finally figured it out. The problem was that in my vertex shader, I declared "attribute vec4 aColor;" and then later in my code, I tried doing this:

mColorHandle = GLES20.glGetAttribLocation(mProgram, "aColor");
GLES20.glEnableVertexAttribArray(mColorHandle);
GLES20.glVertexAttribPointer(mColorHandle, 4, GLES20.GL_FLOAT, false, 16, colorsBuffer);

However, aColor is never actually used in the vertex shader code, and was optimized out of the compiled shader, so that when I tried to get had a handle to it and fill it up, it was causing the rest of my program to fail.

0
votes

I see a potential problem in your usage of checkGLError. There is no check for error, after MyGLRenderer.loadShader. Can you add a check there and see if it really has compiled correctly (before the next check of error after glAttachShader) ? Note that the loadShader call has 2 GL calls inside - one for loading the string, and one for compiling the shader itself.

vertexShaderCode = Utilities.convertResourceToString(context, R.raw.vert_shader_hw3);

int vertexShader = MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);

GLES20.glAttachShader(mProgram, vertexShader); MyGLRenderer.checkGlError("glAttachShader");