打开G1 ES 2.0三角形总是黑色

时间:2015-08-19 20:25:59

标签: java android opengl-es

我最近开始使用OpenGL ES 2.0进行编码,然后遇到了一个非常具有挑战性的问题。这是我的第一次尝试,动态地流式传输VBO缓冲区对象(至少这是我认为我正在做的事情)。我的应用程序应该绘制特定颜色的2个三角形,但它们只是黑色。我认为我可能混合了一些GL命令,但我找不到问题。

以下是我的GLRenderer类的片段:

@Override
public void onSurfaceCreated(GL10 unused, EGLConfig config) {



    /* Draw black background */
    GLES20.glClearColor(0.8f, 0.6f, 0.4f, 1.0f);

    {...}

    viewMatrix = camera.getMatrix();

    /* Create and compile shaders */
    int vertexShaderHandle = loadShader(vertexShader, GLES20.GL_VERTEX_SHADER);
    int fragmentShaderHandle = loadShader(fragmentShader, GLES20.GL_FRAGMENT_SHADER);

    /* Create and link program */
    programHandle = loadProgram(vertexShaderHandle, fragmentShaderHandle);

    /* Set references for drawing input */
    mVPMatrixHandle = GLES20.glGetUniformLocation(programHandle, "uMVPMatrix");
    positionHandle = GLES20.glGetAttribLocation(programHandle, "vPosition");
    colorHandle = GLES20.glGetUniformLocation(programHandle, "vColor");
    checkGlError("glGetUniformLocation");

    /* Create 2 Triangles for testing purposes. */
    final float[] triangle1Vertex = { 0.0f,  0.5f, 0.0f,
           -0.5f, -0.5f, 0.0f,
            0.5f, -0.5f, 0.0f,};
    final float[] triangle2Vertex = { -1.0f,  1.0f, 0.0f,
            -1.0f, -0.5f, 0.0f,
            -0.5f, 1.0f, 0.0f};

    /* Color */
    final float[] color = { 0.63671875f, 0.76953125f, 0.22265625f, 0.0f};

    /* Init triangles */
    Triangle triangle1 = new Triangle(triangle1Vertex, color);
    Triangle triangle2 = new Triangle(triangle2Vertex, color);

    /* Add triangles to be drawn */
    TriangleCollection.add(triangle1);
    TriangleCollection.add(triangle2);

    /* Create buffer objects in GPU, 2 buffers are needed */
    final int buffers[] = new int[2];

    GLES20.glGenBuffers(2, buffers, 0); //Generate GPUSide Buffers

    /* Allocate GPU memory space for vertices */
    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, buffers[0]);
    GLES20.glBufferData(
            GLES20.GL_ARRAY_BUFFER,
            TriangleCollection.MAX_NUMBER_OF_VERTICES * TriangleCollection.BYTES_PER_FLOAT,
            TriangleCollection.publishVerticesBuffer(),
            GLES20.GL_STREAM_DRAW);
    checkGlError("glBufferData");


    /* Allocate GPU memory space for color data */
    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, buffers[1]);
    GLES20.glBufferData(
            GLES20.GL_ARRAY_BUFFER,
            TriangleCollection.NUMBER_OF_COLOR_ELEMENTS * TriangleCollection.BYTES_PER_FLOAT,
            TriangleCollection.publishColorBuffer(),
            GLES20.GL_STREAM_DRAW);
    checkGlError("glBufferData");

    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);

    /* Reference the GPU Buffers */
    triangleVerticesIdx = buffers[0];
    triangleColorsIdx = buffers[1];

    GLES20.glFlush();

    startTime = System.nanoTime();
}

@Override
public void onDrawFrame(GL10 unused) {

    FloatBuffer vertices = TriangleCollection.publishVerticesBuffer();
    FloatBuffer colors = TriangleCollection.publishColorBuffer();

    /* Upload triangle data */
    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, triangleVerticesIdx);
    GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER, 0, vertices.capacity() * Triangle.BYTES_PER_FLOAT, vertices);
    checkGlError("glBufferSubData");

    /* Upload color data */
    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, triangleColorsIdx);
    GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER, 0, colors.capacity() * Triangle.BYTES_PER_FLOAT, colors);
    checkGlError("glBufferSubData");

    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);

    /* Clear Screen */
    GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);

    GLES20.glUseProgram(programHandle);

    /*Matrix calculations */
    Matrix.setIdentityM(modelMatrix, 0);
    Matrix.multiplyMM(mvpMatrix, 0, projectionMatrix, 0, viewMatrix, 0);
    GLES20.glUniformMatrix4fv(mVPMatrixHandle, 1, false, mvpMatrix, 0);
    checkGlError("glUniformMatrix4fv");

    /* Pass the position information */

    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, triangleVerticesIdx);
    checkGlError("glBindBuffer");
    GLES20.glEnableVertexAttribArray(positionHandle);
    checkGlError("glEnableVertexAttribArray");
    GLES20.glVertexAttribPointer(positionHandle, Triangle.COORDINATES_PER_VERTEX, GLES20.GL_FLOAT, false, 0, 0);
    checkGlError("glVertexAttribPointer");


    /* Pass the color information */

    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, triangleColorsIdx);
    checkGlError("glBindBuffer");
    GLES20.glEnableVertexAttribArray(colorHandle);
    checkGlError("glEnableVertexAttribArray");
    GLES20.glVertexAttribPointer(colorHandle, TriangleCollection.COLOR_SIZE_FLOAT, GLES20.GL_FLOAT, false, 0, 0);
    checkGlError("glVertexAttribPointer");


    /* Clear currently bound buffer  */
    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
    checkGlError("glBindBuffer");

    //Draw
    GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, TriangleCollection.MAX_NUMBER_OF_VERTICES);
    checkGlError("glDrawArrays");

}

此代码运行没有错误,我已经在调试模式下检查了FloatBuffers。它们包含所需的信息。

我还会对绘图/渲染管道的一般概念提出任何反馈意见。我不确定天气这是一个很好的解决方案,但至少我的Nexus 5上有30个FPS @ 8000三角形。

编辑1

经过一些测试后,我得到了以下结果:

  1. 根据日志我正在使用EGL 1.4。我现在不打算使用OpenGL ES 3.0(只要这是可能的)。
  2. 2.用常量值替换片段着色器的vColor元素。三角形是红色的:

    final String fragmentShader =
    "precision mediump float;" +
    "uniform vec4 vColor;" +
    "void main() {" +
    "  gl_FragColor = vec4(1.0,0.0,0.0,1.0);" +
    "}";
    
    1. 使用普通的非静态片段着色器时,删除这部分代码绝对不会改变:

      / *传递颜色信息* /

      GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, triangleColorsIdx);
      checkGlError("glBindBuffer");
      GLES20.glEnableVertexAttribArray(colorHandle);
      checkGlError("glEnableVertexAttribArray");
      GLES20.glVertexAttribPointer(colorHandle, TriangleCollection.COLOR_SIZE_FLOAT, GLES20.GL_FLOAT, false, 0, 0);
      checkGlError("glVertexAttribPointer");
      
    2. 删除colorHandle = GLES20.glGetUniformLocation(programHandle,“vColor”); from surfaceCreated()照常工作,不绘制三角形。

    3. 编辑2

      我仍然找不到我的错误。虽然使用glGetUniformLocation适用于一个三角形,但对许多人来说并不适用。我将我的项目剥离到一个简单的测试应用程序,以便我可以显示完整的代码:

      public class MainActivity extends Activity {
      
      private MySurfaceView mySurfaceView;
      
      @Override
      protected  void onCreate(Bundle savedInstanceState) {
      
          super.onCreate(savedInstanceState);
      
          /* Create SurfaceView and add it to Activity */
          MySurfaceView = new MySurfaceView(this);
          setContentView(mySurfaceView);
      
      }
      
      
      @Override
      protected void onPause() {
          super.onPause();
          MySurfaceView.onPause();
      }
      
      @Override
      protected void onResume() {
          super.onResume();
          MySurfaceView.onResume();
      }
      }
      
      public class MySurfaceView extends GLSurfaceView {
      
      private final GLRenderer renderer;
      
      /**
       * Creates the SurfaceView
       * @param context Application context
       */
      public MySurfaceView(Context context) {
          super(context);
      
          setEGLConfigChooser(8, 8, 8, 8, 16, 0);
      
          /* OpenGl Version GLES 2.0 min */
          setEGLContextClientVersion(2);
      
          /* Add Renderer for drawing */
          renderer = new GLRenderer();
          setRenderer(renderer);
      
      }
      }
      
      
      
      
      public class GLRenderer implements GLSurfaceView.Renderer {
      
      /* Frame Counter */
      private int nbFrame = 0;
      private long startTime;
      
      /* Vertex Shader */
      final String vertexShader =
              // This matrix member variable provides a hook to manipulate
              // the coordinates of the objects that use this vertex shader
              "uniform mat4 uMVPMatrix;" +
                      "attribute vec4 vPosition;" +
                      "void main() {" +
                      // the matrix must be included as a modifier of gl_Position
                      // Note that the uMVPMatrix factor *must be first* in order
                      // for the matrix multiplication product to be correct.
                      "  gl_Position = uMVPMatrix * vPosition;" +
                      "}";
      /* Fragment Shader*/
      final String fragmentShader =
              "precision mediump float;" +
              "uniform vec4 vColor;" +
              "void main() {" +
              "  gl_FragColor = vColor;" +
              "}";
      /* Reference for the program */
      private int programHandle;
      
      /* References to pass data into shader */
      private int mVPMatrixHandle, positionHandle, colorHandle;
      
      /* Projection matrix, used for projection 3D scene to 2D viewport. */
      private float[] projectionMatrix = new float[16];
      
      /* Model matrix used for moving Models around */
      private float[] modelMatrix = new float[16];
      
      /* Combined Matrix */
      private float[] mvpMatrix = new float[16];
      
      /* Matrix of the camera position and perspective */
      private float[] viewMatrix;
      
      /* Reference to the buffer of the triangle vertices in the GPU DDR */
      private int triangleVerticesIdx;
      
      /* Reference to the buffer of the triangle colors in the GPU DDR */
      private int triangleColorsIdx;
      
      /**
       * Load shader
       */
      static int loadShader(final String shader, int type) {
      
          int shaderHandle = GLES20.glCreateShader(type);
      
          if (shaderHandle != 0) {
              GLES20.glShaderSource(shaderHandle, shader);
              checkGlError("glShaderSource");
      
              GLES20.glCompileShader(shaderHandle);
              checkGlError("glCompileShader");
      
              final int[] compileStatus = new int[1];
              GLES20.glGetShaderiv(shaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
      
              if (compileStatus[0] == 0) {
                  GLES20.glDeleteShader(shaderHandle);
                  shaderHandle = 0;
              }
          }
      
          if (shaderHandle == 0) {
              throw new RuntimeException("Error while creating shader");
          }
      
          return shaderHandle;
      }
      
      /**
       * Loads a OpenGL ES 2.0 program with a vertex and a fragment shader.
       * @param vertexShader
       * @param fragmentShader
       * @return
       */
      public static int loadProgram(int vertexShader, int fragmentShader) {
          int programHandle;
      
          /* Load program */
          programHandle = GLES20.glCreateProgram();
      
          if (programHandle != 0) {
              /* Bind shaders to program */
              GLES20.glAttachShader(programHandle, vertexShader);
              checkGlError("glAttachShader");
              GLES20.glAttachShader(programHandle, fragmentShader);
              checkGlError("glAttachShader");
      
              /* Bind Attributes */
              GLES20.glBindAttribLocation(programHandle, 0, "vPosition");
              checkGlError("glBindAttribLocation");
              GLES20.glBindAttribLocation(programHandle, 1, "vColor");
              checkGlError("glBindAttribLocation");
      
              /* Link shaders */
              GLES20.glLinkProgram(programHandle);
      
              /* Get link status... */
              final int[] linkStatus = new int[1];
              GLES20.glGetProgramiv(programHandle, GLES20.GL_LINK_STATUS, linkStatus, 0);
      
              if (linkStatus[0] == 0) {
                  GLES20.glDeleteProgram(programHandle);
                  programHandle = 0;
              }
          }
          if (programHandle == 0) {
              throw new RuntimeException("Error creating program.");
          }
      
          return programHandle;
      }
      
      @Override
      public void onSurfaceCreated(GL10 unused, EGLConfig config) {
      
      
      
          /* Draw black background */
          GLES20.glClearColor(0.8f, 0.6f, 0.4f, 1.0f);
      
          /* Create Camera and define values -> calculate Matrix */
          Camera camera = new Camera();
          camera.setPosition(0.0f, 0.0f, 1.5f);
          camera.setPerspective(0.0f, 0.0f, -5.0f);
          camera.setUpVector(0.0f, 1.0f, 0.0f);
          camera.setMatrix();
      
          viewMatrix = camera.getMatrix();
      
          /* Create and compile shaders */
          int vertexShaderHandle = loadShader(vertexShader, GLES20.GL_VERTEX_SHADER);
          int fragmentShaderHandle = loadShader(fragmentShader, GLES20.GL_FRAGMENT_SHADER);
      
          /* Create and link program */
          programHandle = loadProgram(vertexShaderHandle, fragmentShaderHandle);
      
          /* Set references for drawing input */
      
          mVPMatrixHandle = GLES20.glGetUniformLocation(programHandle, "uMVPMatrix");
          positionHandle = GLES20.glGetAttribLocation(programHandle, "vPosition");
          colorHandle = GLES20.glGetUniformLocation(programHandle, "vColor");
          checkGlError("glGetUniformLocation");
      
          /* Create 2 Triangles for testing purposes. */
          final float[] triangle1Vertex = { 0.0f,  0.5f, 0.0f,
                 -0.5f, -0.5f, 0.0f,
                  0.5f, -0.5f, 0.0f,};
      
          /* Color */
          final float[] color = { 0.0f, 0.76953125f, 0.22265625f, 1.0f,
                  0.0f, 0.76953125f, 0.22265625f, 1.0f,
                  0.0f, 0.76953125f, 0.22265625f, 1.0f};
      
          /* Create Vertex Buffer */
          ByteBuffer bb = ByteBuffer.allocateDirect(triangle1Vertex.length*4);
      
          bb.order(ByteOrder.nativeOrder());
      
          FloatBuffer vert1 = bb.asFloatBuffer();
      
          vert1.put(triangle1Vertex);
          vert1.position(0);
      
          /* Create Color Buffer */
          ByteBuffer bb1 = ByteBuffer.allocateDirect(color.length*4);
      
          bb1.order(ByteOrder.nativeOrder());
      
          FloatBuffer color1 = bb1.asFloatBuffer();
      
          color1.put(color);
          color1.position(0);
      
          /* Create buffer objects in GPU, 2 buffers are needed */
          final int buffers[] = new int[2];
      
          GLES20.glGenBuffers(2, buffers, 0); //Generate GPUSide Buffers
      
          /* Allocate GPU memory space for vertices */
          GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, buffers[0]);
          GLES20.glBufferData(
                  GLES20.GL_ARRAY_BUFFER,
                  1*9*4,// 9 floats for triangle and 4 bytes per float
                  vert1,
                  GLES20.GL_STATIC_DRAW);
          checkGlError("glBufferData");
      
      
          /* Upload FPU memory space for color data */
          GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, buffers[1]);
          GLES20.glBufferData(
                  GLES20.GL_ARRAY_BUFFER,
                  1*3*4*4,
                  color1,
                  GLES20.GL_STATIC_DRAW);
          checkGlError("glBufferData");
      
          GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
      
          /* Reference the GPU Buffers */
          triangleVerticesIdx = buffers[0];
          triangleColorsIdx = buffers[1];
      
          GLES20.glFlush();
      
          startTime = System.nanoTime();
      }
      
      /**
       * Not needed. Device must be in landscape mode all the time.
       *
       * @param unused -
       */
      @Override
      public void onSurfaceChanged(GL10 unused, int width, int height) {
      
          /* Define Viewport */
          GLES20.glViewport(0, 0, width, height);
      
          /* Create perspective projection */
      
          final float ratio = (float) width / height;
          final float left = -ratio;
          final float right = ratio;
          final float bottom = -1.0f;
          final float top = 1.0f;
          final float near = 1.0f;
          final float far = 10.0f;
      
          Matrix.frustumM(projectionMatrix, 0, left, right, bottom, top, near, far);
      }
      
      @Override
      public void onDrawFrame(GL10 unused) {
      
          /* Measure FPS */
          nbFrame++;
          if(System.nanoTime()-startTime >= 1000000000) {
              Log.d("FPS", Integer.toString(nbFrame));
              nbFrame = 0;
              startTime = System.nanoTime();
          }
      
          /* Clear Screen */
          GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
      
          GLES20.glUseProgram(programHandle);
      
          /*Matrix calculations */
          Matrix.setIdentityM(modelMatrix, 0);
          Matrix.multiplyMM(mvpMatrix, 0, projectionMatrix, 0, viewMatrix, 0);
          GLES20.glUniformMatrix4fv(mVPMatrixHandle, 1, false, mvpMatrix, 0);
          checkGlError("glUniformMatrix4fv");
      
          /* Pass the position information */
      
          GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, triangleVerticesIdx);
          checkGlError("glBindBuffer");
          GLES20.glEnableVertexAttribArray(positionHandle);
          checkGlError("glEnableVertexAttribArray");
          GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 0, 0);
          checkGlError("glVertexAttribPointer");
      
      
          /* Pass the color information */
      
          GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, triangleColorsIdx);
          checkGlError("glBindBuffer");
          GLES20.glEnableVertexAttribArray(colorHandle);
          checkGlError("glEnableVertexAttribArray");
          GLES20.glVertexAttribPointer(colorHandle, 4, GLES20.GL_FLOAT, false, 0, 0);
          checkGlError("glVertexAttribPointer");
      
      
          /* Clear currently bound buffer  */
          GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
          checkGlError("glBindBuffer");
      
          //Draw
          GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 1*9);
          checkGlError("glDrawArrays");
      
      }
      
      /**
       * Utility method for debugging OpenGL calls. Provide the name of the call
       * just after making it:
       *
       * <pre>
       * mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
       * MyGLRenderer.checkGlError("glGetUniformLocation");</pre>
       *
       * If the operation is not successful, the check throws an error.
       *
       * @param glOperation - Name of the OpenGL call to check.
       */
      public static void checkGlError(String glOperation) {
          int error;
          while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
              Log.e("OPEN_GL", glOperation + ": glError " + error);
              throw new RuntimeException(glOperation + ": glError " + error);
          }
      }
      

      }

      解决方案

      最后,我能够解决问题(借助你的线索)。对于有类似问题的所有其他人,请检查您的着色器,而不仅仅是复制&amp;像我一样粘贴它们。 this也帮了我很多。这里还有我现在正在使用的着色器:

      final String vertexShader =
              "uniform mat4 uMVPMatrix;      \n"     
                      + "attribute vec4 aPosition;     \n"   
                      + "attribute vec4 aColor;        \n" 
                      + "varying vec4 vColor;          \n"   
      
                      + "void main()                    \n"     
                      + "{                              \n"
                      + "   vColor = aColor;          \n"
                      + "   gl_Position = uMVPMatrix * aPosition;   \n" 
                      + "}                              \n";
      /* Fragment Shader*/
      final String fragmentShader =
              "precision mediump float;" +
              "varying vec4 vColor;" +
              "void main() {" +
              "  gl_FragColor = vColor;" +
              "}";
      

1 个答案:

答案 0 :(得分:1)

我必须看到你的片段着色器肯定知道,但从这里看起来你的颜色数组中的alpha分量设置为0,这意味着你的颜色不会显示起来。将alpha分量设置为1。

您需要检查并确保片段着色器正在正确编译。 According to the GLSL_ES specification, shaders need to contain a line at the beginning indicating which version you're using. (Section 3.3, page 9)。除非您正在为ESGL1.0构建(在您自由使用顶点缓冲区对象时似乎不太可能),否则该指令必须存在于任何有效的着色器代码中。