Eduardo da Costa Eduardo da Costa - 2 months ago 17
Android Question

Why GLES20.glGetAttribLocation returns different values for different devices?

I'm trying using OpenGL2.0 and create multiple cubes in 3D space, for android devices.

The code it runs perfectly in some devices, but not in others, and i don't know why... (All devices have OpenGL 2.0 supported, and have recent android versions [5.0 or 6.0])

I only know that the problem is in a -1 return value (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 ...


The
cubeNormalParam1 = GLES20.glGetAttribLocation(cubeProgram1, "a_Normal");
returns value 2 in some devices, and -1 in others. Those who have -1 value, give error and doesn't run...

I'm trying see if the vertex_shader have errors but i can'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 this happen? Is the Hardware?

Any Solution to fix this?




To draw Cube i've 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");
}

Answer

The Solution - multiplying with -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;

Is not the best solution, but now it works.