打开Gl ES 2.0三角形总是黑色的



我最近开始用OpenGL ES 2.0编码,并遇到了一个(对我来说)相当具有挑战性的问题。这是我的第一次尝试,流式VBO缓冲对象动态(至少这是我认为我正在做的)。我的应用程序应该用特定的颜色画两个三角形,但它们只是黑色的。我想可能是我混淆了一些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。用一个常量替换碎片着色器的vColor元素是有效的。三角形为红色:

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

    /*传递颜色信息*/

    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");
    
  • 移除colorHandle = GLES20。glGetUniformLocation (programHandle"vColor");from surfaceCreated()正常工作,不绘制三角形

  • 编辑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);
        }
    }
    

    }

    解决方案

    最后我能够解决这个问题(借助你的线索)。对于所有其他有类似问题的人,检查你的着色器,不要只是复制&像我一样粘贴它们。这也帮助了我很多。这里还有我现在工作的着色器:

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

    我必须看到你的片段着色器知道肯定,但从这里,它看起来像你设置alpha组件为0在你的颜色数组,这意味着你的颜色不会出现。设置alpha分量为1

    你需要检查并确保你的片段着色器正确编译。根据GLSL_ES规范,着色器需要在开始处包含一行,指示您使用的是哪个版本。(第3.3节,第9页).除非你是为ESGL1.0(这似乎不太可能给你自由使用顶点缓冲对象),指令必须出现在任何有效的着色器代码。

    相关内容

    • 没有找到相关文章

    最新更新