Why does GLES20.glGetAttribLocation return different values ​​for different devices?

I am trying to use OpenGL2.0 and create multiple cubes in 3D space for Android devices.

This code works fine on some devices, but not on others, and I don’t know why ... (All devices support OpenGL 2.0 and have the latest versions for Android [5.0 or 6.0])

I only know that the problem is in the return value of -1 (see down)

int vertexShader = loadGLShader(GLES20.GL_VERTEX_SHADER, R.raw.vertex); int gridShader = loadGLShader(GLES20.GL_FRAGMENT_SHADER, R.raw.grid_fragment); int passthroughShader = loadGLShader(GLES20.GL_FRAGMENT_SHADER, R.raw.fragment_color); cubeProgram1 = GLES20.glCreateProgram(); GLES20.glAttachShader(cubeProgram1, vertexShader); GLES20.glAttachShader(cubeProgram1, passthroughShader); GLES20.glLinkProgram(cubeProgram1); GLES20.glUseProgram(cubeProgram1); cubePositionParam1 = GLES20.glGetAttribLocation(cubeProgram1, "a_Position"); cubeNormalParam1 = GLES20.glGetAttribLocation(cubeProgram1, "a_Normal"); ----> Returns -1 Value cubeLightPosParam1 = GLES20.glGetUniformLocation(cubeProgram1, "u_LightPos"); cubeModelParam1 = GLES20.glGetUniformLocation(cubeProgram1, "u_Model") cubeModelViewParam1 = GLES20.glGetUniformLocation(cubeProgram1, "u_MVMatrix"); cubeModelViewProjectionParam1 = GLES20.glGetUniformLocation(cubeProgram1, "u_MVP"); 

....

  GLES20.glEnableVertexAttribArray(cubeNormalParam1); ---> Returns -1 ... 

cubeNormalParam1 = GLES20.glGetAttribLocation(cubeProgram1, "a_Normal"); returns 2 on some devices and -1 on others. Those who have a value of -1 give an error and do not start ...

I am trying to see if vertex_shader has errors, but I don't see any problems ...

 uniform mat4 u_Model; uniform mat4 u_MVP; uniform mat4 u_MVMatrix; uniform vec3 u_LightPos; attribute vec4 a_Position; attribute vec4 a_Color; attribute vec3 a_Normal; attribute vec2 a_TexCoordinate; varying vec4 v_Color; varying vec3 v_Grid; varying vec2 v_TexCoordinate; void main() { v_Grid = vec3(u_Model * a_Position); vec3 modelViewVertex = vec3(u_MVMatrix * a_Position); vec3 modelViewNormal = vec3(u_MVMatrix * vec4(a_Normal, 0.0)); float distance = length(u_LightPos - modelViewVertex); vec3 lightVector = normalize(u_LightPos - modelViewVertex); float diffuse = max(dot(modelViewNormal, lightVector), 0.5); diffuse = diffuse * (1.0 / (1.0 + (0.00001 * distance * distance))); v_Color = a_Color * diffuse; v_TexCoordinate = a_TexCoordinate; gl_Position = u_MVP * a_Position; } 

Why is this happening? Hardware?

Any solution to fix this?


To draw a cube, I have this:

 public void drawCube1() { cubeNumber = 1; GLES20.glUseProgram(cubeProgram1); GLES20.glUniform3fv(cubeLightPosParam1, 1, lightPosInEyeSpace, 0); // Set the Model in the shader, used to calculate lighting GLES20.glUniformMatrix4fv(cubeModelParam1, 1, false, modelCube, 0); // Set the ModelView in the shader, used to calculate lighting GLES20.glUniformMatrix4fv(cubeModelViewParam1, 1, false, modelView, 0); // Set the ModelViewProjection matrix in the shader. GLES20.glUniformMatrix4fv(cubeModelViewProjectionParam1, 1, false, modelViewProjection1, 0); // Set the position of the cube GLES20.glVertexAttribPointer( cubePositionParam1, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, 0, cubeVertices); // Set the normal positions of the cube, again for shading GLES20.glVertexAttribPointer(cubeNormalParam1, 3, GLES20.GL_FLOAT, false, 0, cubeNormals); // Set the active texture unit to texture unit 0. GLES20.glActiveTexture(GLES20.GL_TEXTURE0); // Bind the texture to this unit. GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextura1); isLookingAtObject_Number(cubeNumber); // Tell the texture uniform sampler to use this texture in the shader by binding to texture unit 0. GLES20.glUniform1i(mTextureUniform, 0); GLES20.glVertexAttribPointer(mTextureCoordinate, 2, GLES20.GL_FLOAT, false, 0, cubeTexture); GLES20.glEnableVertexAttribArray(mTextureCoordinate); GLES20.glEnableVertexAttribArray(cubePositionParam1); GLES20.glEnableVertexAttribArray(cubeNormalParam1); GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 36); checkGLError("Drawing cube"); } 
+1
source share
2 answers

The solution is multiplying by -1-value

  ... = GLES20.glGetAttribLocation(cubeProgram1, "a_Normal") * -1; 

or

 int value; if( GLES20.glGetAttribLocation(cubeProgram1, "a_Normal") < 0){ value = -1; } else { value = 1; } ... = GLES20.glGetAttribLocation(cubeProgram1, "a_Normal") * value; 

Not the best solution, but now it works.

-1
source
 Why GLES20.glGetAttribLocation returns different values for different devices? 

... because different devices will have different equipment for setting up the binding tables and in some cases can fully optimize redundant calculations and repackage the used attributes to save space. That is why the API has a function call to get location bindings on the device at runtime; if they were deterministic constants, you wouldn't need a call at run time at all ...

The fact that it returns -1 is not an error; it just shows that the attribute is not needed (for example, a specific one, but can be optimized because it does not contribute to the color of the fragment pixel), so this should not cause any problems.

However, this means that you cannot safely assume (for example) that a_Position always attribute 0, a_Color always 1, a_Normal always 2, etc. If you are hardcoded that into your code, then it is entirely possible that you are loading the wrong data into each attribute. You must query the binding locations to get the binding numbers to use (or use the static shader-side binding added in OpenGL ES 3.x).

What actual GL API call sets the GL error state?

+5
source

All Articles