编辑 2:查看此 GitHub 项目的Triangle2d 示例以获得完整的工作示例。
编辑:有关正交矩阵如何工作的很好解释的链接,请参阅接受的答案。最后,我稍微调整了提供的代码:
  float[] mvp = {
     2f/width,   0f,         0f, 0f,
     0f,        -2f/height,  0f, 0f,
     0f,         0f,         0f, 0f,
    -1f,         1f,         0f, 1f
   };
请注意,我的 z 固定为 0,w 固定为 1。这个矩阵使原点 (0,0) 位于屏幕的左下角;如果您希望原点位于左上角,请尝试:
  float[] mvp = {
     2f/width,   0f,         0f, 0f,
     0f,         2f/height,  0f, 0f,
     0f,         0f,         0f, 0f,
    -1f,        -1f,         0f, 1f
   };
另一个问题是GLES20.glUniformMatrix4fv我改成的电话:
FloatBuffer b = ByteBuffer.allocateDirect(mvp.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
b.put(mvp).position(0);
GLES20.glUniformMatrix4fv(uMvpPos, b.limit() / mvp.length, false, b);
如果你想弄乱这个,试试这个在线计算器。请记住,您的 sorce 文件中的行将是计算器中的列。
原始问题: 我正在尝试在 android 上使用 OpenGLES 2.0 绘制 2d 三角形,但到目前为止,并没有多大成功。这些是我的着色器:
(Vertex shader)
uniform mat4    uMvp;
attribute vec3 aPosition;
attribute vec3 aColor;
varying vec4 vColor;
void main() {
  vColor = vec4(aColor.xyz, 1.0);
  vec4 position = vec4(aPosition.xyz, 1.0);
  gl_Position = uMvp * position;
};
(Fragment shader)
precision mediump float;
varying vec4 vColor;
void main(void)
{
  gl_FragColor = vColor;
};
然后,在 GLSurfaceView.Renderer 的 onSurfaceChanged 方法中,我放了以下内容:
public void onSurfaceChanged(GL10 gl, int width, int height)
{
  // here I load and compile the shaders and link the program.
  // in the end, I use GLES20.glUseProgram(programHandle);
  // (code omitted)
  // create the matrix for the uniform
  int uMvpPos = GLES20.glGetUniformLocation(programHandle, "uMvp");
  float[] mvp = {width, 0f, 0f, 0f,
                 0f, -height, 0f, 0f,
                 0f, 0f, -2f, 0f,
                 -1f, 1, -1f, 1};
  GLES20.glUniformMatrix4fv(uMvpPos, mvp.length * 4, false, mvp, 0);
  // set viewport and clear color to white
  GLES20.glViewport(0, 0, width, height);
  GLES20.glClearColor(1f, 1f, 1f,1.0f);
}
我使用了这个问题上显示的矩阵值。我的意图是以与画布相同的方式使用坐标:屏幕左上角的 (0,0) 和右下角的 (width, height)。
最后但同样重要的是,这是 onDrawFrame 的代码:
public void onDrawFrame(GL10 gl)
{
  int aPos = GLES20.glGetAttribLocation(programHandle,"aPosition");
  int aColor = GLES20.glGetAttribLocation(programHandle,"aColor");
  // assuming I correctly set up my coordinate system,
  // these are the triangle coordinates and color
  float[] data =
      {
        // XYZ, RGB
        100f, 100f, 0f,
        1f, 0f, 0f,
        50f, 50f, 0f,
        1f, 0f, 0f,
        150f, 50f, 0f,
        1f, 0f, 0f,
      };
  // put all my data into a float buffer
  // the '* 4' is because a float has 4 bytes
  FloatBuffer dataVertex = ByteBuffer.allocateDirect(data.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
  dataVertex.put(data).position(0);
  // set the POSITION values
  // attribute, dataSize(number of elements), data type, normalized?, size(bytes), data
  GLES20.glEnableVertexAttribArray(aPos);
  GLES20.glVertexAttribPointer(aPos, 3, GLES20.GL_FLOAT, false, 6 * 4, dataVertex);
  // set the COLOR values
  dataVertex.position(3); // offset
  GLES20.glEnableVertexAttribArray(aColor);
  GLES20.glVertexAttribPointer(aColor, 3, GLES20.GL_FLOAT, false, 6 * 4, dataVertex);
  // put a white background
  GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
  // and finally draw the triangle!
  GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);
}
最终结果是......一个无聊的白色屏幕,没有三角形。我想我犯了一个非常简单的错误,但我无法发现它。有什么想法吗?