androidopengl-es-2.0vertex-shaderphongopengl-es-lighting

Phong Lighting in Vertex Shader


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);
}

Solution

  • 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.