【问题标题】:Why GLES20.glGetAttribLocation returns different values for different devices?为什么 GLES20.glGetAttribLocation 为不同的设备返回不同的值?
【发布时间】:2023-04-01 05:44:01
【问题描述】:

我正在尝试使用 OpenGL2.0 并在 3D 空间中为 Android 设备创建多个立方体。

它的代码在某些设备上可以完美运行,但在其他设备上却不能,我不知道为什么...(所有设备都支持 OpenGL 2.0,并且具有最新的 android 版本 [5.0 或 6.0])

我只知道问题出在一个-1的返回值上(往下看)

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"); 在某些设备中返回值 2,在其他设备中返回 -1。那些有-1值的,给出错误并且不运行......

我正在尝试查看 vertex_shader 是否有错误,但我看不到任何问题...

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

为什么会这样?是硬件吗?

任何解决方案来解决这个问题?


要画立方体,我有这个:

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

【问题讨论】:

  • “不同的设备”是什么意思?不同的 GPU?
  • 不同的 Android 手机和 VR 眼镜,例如。它适用于眼镜和某些手机,但在其他手机中不起作用(例如 S7 Edge)。所有的GPU,支持OpenGL 1.0、2.0、3.0。
  • 错误是 E/Menu: Drawing cube: glError 1281.
  • 关联的片段着色器是什么样的?如果它不使用 v_Color,那么实现可能会随意优化整个计算负载,甚至 a_Color 和 a_Normal 属性。
  • 我的想法与@Columbo 在这里提到的一样。如果您不使用 v_Color,着色器可能会被优化并完全删除此属性。所以发布你的片段着色器也会有所帮助

标签: android opengl-es opengl-es-2.0 vertex-shader


【解决方案1】:
Why GLES20.glGetAttribLocation returns different values for different devices?

... 因为不同的设备会有不同的硬件来设置绑定表,并且在某些情况下可能会完全优化冗余计算并重新打包使用的属性以节省空间。这正是为什么 API 有一个函数调用来在运行时获取设备上的绑定位置;如果它们是确定性常量,则根本不需要运行时调用...

它返回 -1 的事实不是错误;它只是表明不需要该属性(例如已定义,但可以优化,因为它不会影响片段像素颜色),所以这不会导致任何问题。

但这确实意味着您不能安全地假设(例如)a_Position 始终为属性 0,a_Color 始终为 1,a_Normal 始终为 2,等等。如果您已将其硬编码为您的代码,那么您完全有可能将错误的数据上传到每个属性。您必须查询绑定位置以获取要使用的绑定编号(或使用 OpenGL ES 3.x 中添加的着色器端静态绑定)。

哪个实际的 GL API 调用设置了 GL 错误状态?

【讨论】:

  • 我正在使用 openGL2.0。错误不断出现多次就是这个。 10301-10382/com.google.vrtoolkit.cardboard.samples.treasurehunt E/Menu:绘图立方体:glError 1281
  • ... 是的,它告诉你错误是什么,但不是哪个函数调用导致它被设置。如果没有更多关于哪个函数调用出错的详细信息,就无法提供帮助。在每次调用 API 后调用 checkError 函数,并报告设置错误的特定函数 - 仅在最后报告“出现问题”对调试没有特别的帮助......
  • 谢谢,我这样做了,问题是,现在应用程序运行并且不显示任何内容,保持黑色。我将 drawCube 函数放在 update 的问题中。也许错误在那里......但我找不到它,因为应用程序运行并且没有中断。最初,错误在这里: GLES20.glEnableVertexAttribArray(cubeNormalParam1);它位于 onSurfaceCreated(EGLConfig config){... (它返回 -1 ,这就是我认为问题存在的原因)我已经为 cubeDraw() 更改了它,现在它运行了(错误 1281),但不会在屏幕上出现任何内容。
  • 你能帮我解决这个问题吗,@Isogen74?
  • 真的没有什么可以“修复”的——你只是做了太多的一件事。只需停止为返回 -1 绑定索引的属性调用 glEnableVertexAttribArray()。 -1 位置表示它们未使用,因此您根本不需要调用glEnableVertexAttribArray()。一些驱动程序返回 2 和一些返回 -1 的原因只是因为一些缺少删除未使用的优化通道。
【解决方案2】:

解决方案 - 乘以 -1 值

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

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

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

不是最好的解决方案,但现在可以了。

【讨论】:

  • 这不起作用 - 您只是隐藏错误,而不是实际修复它。您正在将 -1(未使用的属性)转换为 +1(这是完全不同属性的绑定位置)。
  • 没错,我隐藏了错误,而不是修复它。但这是我能找到的唯一解决方案,可以让它在设备中运行,并且可以运行。我找不到其他解决方案:\
  • 如果从GLES20.glGetAttribLocation() 返回的位置为-1,则解决方法是停止调用GLES20.glEnableVertexAttribArray(cubeNormalParam1)。也跳过GLES20.glVertexAttibPointer
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-10
  • 2013-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多