Освещение Фонга в вершинном шейдере

Я пытаюсь использовать OpenGL ES 2.0 для Android для отображения простого куба с нормалями и цветами. Для этого я создаю шейдерную программу, присоединяю свои вершинные и фрагментные шейдеры и связываю свою программу следующим образом:

// 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");

И он тут же вылетает в конце, печатая в LogCat: glUseProgram: glError 1281 и я проверил документацию, и генерируется glError 1281, т.е. GL_INVALID_VALUE, если программа не является ни 0, ни значением, сгенерированным OpenGL.

Погуглив это уже около 10 часов, я решил обратиться за помощью к StackOverflow. Есть идеи, что может быть не так с моим кодом вершинного шейдера, чтобы заставить glUseProgram вести себя таким образом?

Вот мой код вершинного шейдера, моя попытка реализовать фонговское освещение:

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

person Luke    schedule 13.02.2014    source источник
comment
Вы проверили, поддерживает ли аппаратное обеспечение необходимое количество атрибутов, используя что-то вроде ›› getIntegerv(MAX_VERTEX_ATTRIBS, &n)   -  person Prabindh    schedule 13.02.2014
comment
Спасибо за быстрый ответ. Да, я проверил это, распечатав это в LogCat. MAX_VERTEX_ATTRIBS на моем планшете Nexus 7 – 16.   -  person Luke    schedule 13.02.2014
comment
Вы пытались проверить LINK_STATUS и журнал информации о шейдерах?   -  person rotoglup    schedule 13.02.2014


Ответы (2)


Спасибо за помощь, ребята! Я наконец-то понял. Проблема заключалась в том, что в моем вершинном шейдере я объявил "attribute vec4 aColor;" а затем позже в моем коде я попытался сделать это:

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

Однако на самом деле aColor никогда не используется в коде вершинного шейдера и был оптимизирован из скомпилированного шейдера, поэтому, когда я пытался получить его дескриптор и заполнить его, это приводило к сбою остальной части моей программы.

person Luke    schedule 14.02.2014

Я вижу потенциальную проблему в использовании вами checkGLError. Нет проверки на ошибку, после MyGLRenderer.loadShader. Можете ли вы добавить туда проверку и посмотреть, действительно ли он скомпилировался правильно (до следующей проверки ошибки после glAttachShader)? Обратите внимание, что внутри вызова loadShader есть 2 вызова GL — один для загрузки строки и один для компиляции самого шейдера.

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

person Prabindh    schedule 13.02.2014