0

我正在尝试使用Android的OpenGL ES 2.0来显示具有法线和颜色的简单立方体。要做到这一点,我创建了一个着色器程序,附上我的顶点和片段着色器和链接我的程序,具体如下:顶点着色器中的Phong照明

// 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我查如果程序既不是0也不是由OpenGL生成的值,则生成glError 1281,即GL_INVALID_VALUE

现在谷歌搜索了大约10个小时之后,我决定转向StackOverflow寻求帮助。任何想法是什么可能是我的顶点着色器代码错误,使glUseProgram这样的行为?

这里是我的顶点着色器的代码,我尝试实现Phong光照:

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

您是否检查过硬件是否支持所需数量的属性,使用类似 >> getIntegerv(MAX_VERTEX_ATTRIBS,&n) – prabindh

+0

感谢您的迅速响应。是的,我通过将它打印到LogCat来检查它。我的Nexus 7平板电脑上的MAX_VERTEX_ATTRIBS是16. – Luke

+1

您是否尝试检查LINK_STATUS和着色器信息日志? – rotoglup

回答

2

感谢您的帮助球员。我终于弄明白了。问题是,在我的顶点着色器中,我声明“属性vec4 aColor;”然后在我的代码后,我试着这样做:

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

然而,aColor是从来没有真正的顶点着色器代码中使用,并优化了编译着色器,这样当我试图得到了处理它并填充它,这导致我的程序的其余部分失败。

0

我看到一个潜在的问题,在你checkGLError的使用。 MyGLRenderer.loadShader之后没有检查错误。你可以在那里添加一个检查,看看它是否真的编译正确(在glAttachShader之后的错误检查之前)?请注意,loadShader调用内部有2个GL调用 - 一个用于加载字符串,另一个用于编译着色器本身。

vertexShaderCode = Utilities.convertResourceToString(上下文,R.raw.vert_shader_hw3);

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

GLES20.glAttachShader(mProgram,vertexShader); MyGLRenderer.checkGlError(“glAttachShader”);