Hello, I’m Kenney, a programmer, and today I’m going to analyze the common reasons why OpenGL has black screens and doesn’t render.

For those of you who are new to OpenGL, the problem of black screens can be quite a headache, because it is not as easy to check errors in OpenGL as it is in general programming. We usually use the glGetError() API to get error codes. But this method gets errors that were already generated when the method was called, probably a long time ago, which is still a bit inconvenient, and glGetError() will not report any errors if the screen is black and the render won’t come out.

Before summarizing the common causes of black screen, let’s lay down some basic knowledge. Actually, the screen is also a frame buffer, but it is a special frame buffer with a size 0. If we apply for a frame buffer by ourselves, the ID we get is greater than 0. The frame buffer will have its own color, and if it’s not deliberately set, it will be black, so if we don’t render properly and nothing is rendered, we will see the background color as black.

We can also clear a frame buffer to a certain color by using glClearColor()+glClear() to set the elimination color and perform the elimination operation. Therefore, if you clear the frame buffer to a different color, but the other render operations are not performed correctly, you may not have a black screen, but the elimination color that you set, which is summarized here as a black screen, as well as other incorrect conditions.

If you render to an off-screen frame buffer instead of on-screen, you will also encounter various black or non-rendering situations, some of which will cause both on-screen and off-screen black, some of which will affect only one of them.

Here is a summary for you:

  • Incorrect Context for calling thread

    OpenGL API needs to be called with the correct Context, which is called EGL Context in Android, EAGL Context in IOS, other platforms have other names, but the principle is similar. A thread needs to be bound to an EGL Context in order to use the OpenGL API properly, otherwise the call will have no effect. See my article “OpenGL ES Advanced: EGL and GL Threads”.

  • GL Program is incorrect

    OpenGL rendering needs to go through GL Program, it is a Program, just like our normal Program, but it is running on GPU, if it is incorrect, it will not render the correct result, the common reason for the incorrect is shader compilation failure, usually due to syntax errors, GlGetShaderInfoLog () can be used to view shader information after compilation, and glGetProgramInfoLog() can be used to view program information after Link. If the information is empty, there is no error.

  • Don’t use the program

    Before rendering, the program used for this rendering should be set through glUseProgran. If it is not set, the corresponding shader cannot be executed, so it cannot be rendered naturally.

  • Not call glDrawXXX ()

    To render something out, you must call glDrawXXX(). Generally, there are very few cases where the tone is not tuned. Generally, it is a low-level error, and it is best to check.

  • For surface with multiple buffer implementation at the bottom, swap buffer is not performed after rendering

    There is a back buffer and a front buffer. The front buffer is the one being displayed, and the back buffer is being rendered. If there is no swap buffer after the draw call, The back buffer will not render, so it will not render. Here is a specific screen, if the render is not going to screen, you don’t need to worry about this.

  • The attachment of frame buffer is incorrect

    In the case of off-screen rendering, when we want to render to a frame buffer, the frame buffer must be properly bound with the attachment, otherwise it is equivalent to the frame buffer is an empty shell, it does not have any space to carry the rendering results.

  • The vertex attribute value is incorrectly set

    Vertices are related to where to render, if the Settings are wrong so that the render position is out of visual range, you can’t see it, what is the range here? If you directly use NDC coordinate rendering, that is -1~1. If you use world coordinates to render, you need to see the projection matrix of specific Settings. For details, please refer to my other article “OpenGL 3D Rendering Technology: Coordinate system and matrix Transformation”.

  • The attribute is not enabled

    If we want to set the value of an attribute, we need to get the location of the attribute and set it with glVertexAttribPointer(), But don’t forget to use glGetAttribLocation() to enable this location, otherwise it won’t work, it’s not enabled by default.

  • VAO/VBO is not bound or is incorrectly bound

    If VAO/VBO is used for rendering, the correct VAO/VBO must be bound before rendering, otherwise there is no specified or wrong vertex, rendering will not be done.

  • Render in VAO/VBO mode without reset, then render in non-VAO /VBO mode

    If the vertex is not reset after rendering with VAO/VBO, the vertex is bound to the vertex specified by VAO/VBO. If you use glVertexAttribPointer() to render with VAO/VBO, the usage conflicts. Since VAO/VBO requires glVertexAttribPointer() to specify no vertex data, and glVertexAttribPointer() to specify vertex data, it is easy to create vertex chaos and render incorrect results.

  • The View Port is incorrectly set

    A View Port is a window through which we can see scenes rendered in the OpenGL world coordinate system, just as we can see outdoor scenes through a window. If the window is not set or not set correctly, we will not see anything. In general, we will set it to the size of surface. This renders just enough to fill the surface.

  • Frame Buffer 0 is not rendered

    Sometimes there are many steps in the rendering operation. In order to display the results on the screen after these steps, some frame Buffer will be used for off-screen rendering. However, when the last step is rendered on the screen, the frame buffer needs to be bound back to 0 before the screen can be displayed.

  • Rendered an incorrect texture

    For example, we want to render a texture with some processing, but if the texture itself is not correct, for example, the previous step made some errors, resulting in the texture ID is not correct, such as 0, or the texture ID is correct, but the texture is all black or empty, it will also result in a black screen.

  • The glDrawXXX() method passed an incorrect number of vertices

    When we call glDrawXXX(), we will set the starting position and number of vertices in the array. If this is set incorrectly, zero vertices will be passed and nothing will be rendered.

  • The vertex buffer position is incorrect

    Kotlin glVertexAttribPointer() receives data from a buffer. When we put data to a buffer, the position of the buffer moves back accordingly. So before you call glVertexAttribPointer(), remember to set position back to 0, otherwise it will fetch data from the end, which of course it won’t.

  • Reasons for surface culling

    If Cull Face is enabled, triangles in the rotation order of the vertices will be culled in the cull mode specified by you. If the triangles in the eye direction are culled, they will be invisible.

  • Unturned color blending renders a texture with transparency

    OpenGL does not turn color blending on by default. As a result, transparent parts will often be rendered black instead of showing the colors below.

Ok, first sum up to this, these are more common, also welcome to give me attention to add discussion ~

Thanks for reading!