Search code examples
pythonopenglglslshaderpyopengl

Drawing a crosshair in PyOpenGL


I have a working camera in a 3D scene in OpenGL, and I decided I want to draw a crosshair in the middle. To do that, I want to use a separate shader for the crosshair (and eventually, HUD) and the 3D scene. I managed to make something work using glDrawArrays and a VBO with the line vertices in it.

The problem with this setup is that the cross extends all the way to the borders of the window, even though I specified small coordinates so that it is just in the center of the screen.

Here are my shaders (in order, vertex shader and fragment shader):

#version 450 core

layout (location = 0) in vec2 aPos;

void main() {
    gl_Position = vec4(aPos, 0, 0);
}
#version 450 core

out vec4 FragColor;

void main() {
    FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}

As you can see, they are extremely simple and do literally nothing with the coordinates. The drawing process looks something like this:

crosshair = np.array([
  -0.02, 0,
   0.02, 0,
   0, -0.02,
   0,  0.02], dtype = 'float32')
vbo_2d, vao_2d = glGenBuffers(1), glGenVertexArrays(1)

glBindVertexArray(vao_2d)
glBindBuffer(GL_ARRAY_BUFFER, vbo_2d)
glBufferData(GL_ARRAY_BUFFER, crosshair, GL_STATIC_DRAW)

glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 8, ctypes.c_void_p(0))
glEnableVertexAttribArray(0)

while not window.check_if_closed():
    #render 3d stuff with another shader program and other vbos ad vaos

    glBindVertexArray(0)

    shader_program_2d.use()
    glBindVertexArray(vao_2d)
    glDrawArrays(GL_LINES, 0, 4)

    #swap buffers etc.

This is what my window looks like:

OpenGL Screenshot

Thanks in advance!


Solution

  • The issue is the computation of the Homogeneous clip space coordinate in the vertex shader. The normalized device space coordinate is computed by dividing the .xyz components of gl_Position by it's .w component (Perspective divide).
    Since the .w component is 0, the resulting coordinates become infinite (except the coordinate itself is 0).

    gl_Position = vec4(aPos, 0, 0);

    gl_Position = vec4(aPos, 0, 1.0);