My goal is to display a static triangle over a rotated cube using PyOpenGL. However, I had no luck in achieving the result I wanted; instead, I am left with a blank screen. I had tested both the cube and triangle with their corresponding matrix projections on separate files to make sure that the scene itself wasn't the problem. And sure enough, it wasn't.
Displays a triangle at the bottom left corner of the screen.
def reshape(width, height):
glViewport(0, 0, width, height)
glClearColor(0.0, 0.0, 0.0, 0.0)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(0, width, 0, height, 0, 0.1)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
#--- func for defining triangle
def drawTriangle():
### clear color and depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glLoadIdentity()
### draw triangle
glBegin(GL_TRIANGLES)
glColor3f(0.0, 1.0, 0.0)
glVertex2f(0, 0)
glVertex2f(100, 0)
glVertex2f(0, 100)
glEnd()
glutSwapBuffers()
#--- func for main loop
def main():
window = 0
glutInit(sys.argv)
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE)
glutInitWindowSize(640, 480)
glutInitWindowPosition(200, 200)
window = glutCreateWindow(b'OpenGL Python Triangle')
glutReshapeFunc(reshape)
glutDisplayFunc(drawTriangle)
glutIdleFunc(drawTriangle)
glutMainLoop()
if __name__ == '__main__':
main()
Displays a cube at the center of the screen.
def reshape(width, height):
glClearColor(0.0, 0.0, 0.0, 0.0)
glClearDepth(1.0)
glDepthMask(GL_TRUE)
glDepthFunc(GL_LESS)
glEnable(GL_DEPTH_TEST)
glShadeModel(GL_SMOOTH)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(45.0, float(width)/float(height), 0.1, 100.0)
glMatrixMode(GL_MODELVIEW)
#--- func for defining cube
def drawCube():
### clear color and depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
### set position and rotation
glLoadIdentity()
glTranslatef(0.0,0.0,-6.0)
glRotatef(30,1.0,0.0,0.0)
glRotatef(0,0.0,1.0,0.0)
glRotatef(30,0.0,0.0,1.0)
### draw cube
glBegin(GL_QUADS)
#/* Long list of vertices
glEnd()
glutSwapBuffers()
#--- func for main loop
def main():
window = 0
glutInit(sys.argv)
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH)
glutInitWindowSize(640,480)
glutInitWindowPosition(200,200)
window = glutCreateWindow(b'OpenGL Python Cube')
glutReshapeFunc(reshape)
glutDisplayFunc(drawCube)
glutIdleFunc(drawCube)
glutMainLoop()
if __name__ == "__main__":
main()
I believe the problem might be occurring with the depth test but I was unsuccessful in providing any results that proved the idea right. Instead, it might be with organizing the matrix projections. I ordered it so that the 3d scene would render first and then the 2d scene would overlay it.
#--- 3D projection function
def render3d():
global width, height
### clear buffers
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glViewport(0, 0, width, height)
### projection mode
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(45.0, float(width)/float(height), 0.1, 100.0)
### modelview mode
glMatrixMode(GL_MODELVIEW)
### setup 3d shader
glDepthFunc(GL_LESS)
glEnable(GL_DEPTH_TEST)
glShadeModel(GL_SMOOTH)
#--- 2D projection function
def render2d():
global width, height
### projection mode
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluOrtho2D(0.0, width, height, 0.0)
### modelview mode
glMatrixMode(GL_MODELVIEW)
### setup 2d shader
glDisable(GL_DEPTH_TEST)
#--- reshape function
def reshape(new_width, new_height):
global width, height
### apply new window size
width = new_width
height = new_height
#--- 3D cube function
def scene3d():
### setup polygon location & orientation
glTranslatef(0.0, 0.0, -6.0)
glRotatef(30, 1.0, 0.0, 0.0)
glRotatef(0, 1.0, 1.0, 0.0)
glRotatef(30, 0.0, 0.0, 1.0)
### draw cube
glBegin(GL_QUADS)
glColor3f(0.0,1.0,0.0)
glVertex3f( 1.0, 1.0,-1.0)
glVertex3f(-1.0, 1.0,-1.0)
glVertex3f(-1.0, 1.0, 1.0)
glVertex3f( 1.0, 1.0, 1.0)
glColor3f(1.0,0.0,0.0)
glVertex3f( 1.0,-1.0, 1.0)
glVertex3f(-1.0,-1.0, 1.0)
glVertex3f(-1.0,-1.0,-1.0)
glVertex3f( 1.0,-1.0,-1.0)
glColor3f(0.0,1.0,1.0)
glVertex3f( 1.0, 1.0, 1.0)
glVertex3f(-1.0, 1.0, 1.0)
glVertex3f(-1.0,-1.0, 1.0)
glVertex3f( 1.0,-1.0, 1.0)
glColor3f(1.0,1.0,0.0)
glVertex3f( 1.0,-1.0,-1.0)
glVertex3f(-1.0,-1.0,-1.0)
glVertex3f(-1.0, 1.0,-1.0)
glVertex3f( 1.0, 1.0,-1.0)
glColor3f(0.0,0.0,1.0)
glVertex3f(-1.0, 1.0, 1.0)
glVertex3f(-1.0, 1.0,-1.0)
glVertex3f(-1.0,-1.0,-1.0)
glVertex3f(-1.0,-1.0, 1.0)
glColor3f(1.0,0.0,1.0)
glVertex3f( 1.0, 1.0,-1.0)
glVertex3f( 1.0, 1.0, 1.0)
glVertex3f( 1.0,-1.0, 1.0)
glVertex3f( 1.0,-1.0,-1.0)
glEnd()
#--- 2D triangle function
def scene2d():
### draw triangle
glBegin(GL_TRIANGLES)
glColor3f(0.0, 1.0, 0.0)
glVertex2f(0, 0)
glVertex2f(100, 0)
glVertex2f(0, 100)
glEnd()
#--- draw function
def draw():
### 3D scene
render3d()
scene3d()
### 2D scene
glPushMatrix()
render2d()
scene2d()
glPopMatrix()
### swap buffers
glutSwapBuffers()
#--- main loop function
def main():
window = 0
glutInit(sys.argv)
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH)
glutInitWindowSize(640,480)
glutInitWindowPosition(200,200)
window = glutCreateWindow(b'OpenGL Python HUD')
glutReshapeFunc(reshape)
glutDisplayFunc(draw)
glutIdleFunc(draw)
glutMainLoop()
#--- only run if this is the main module
if __name__ == "__main__":
main()
To explain, I defined two matrix projection functions: one for the 3d scene (render3d) and the other for the 2d scene (render2d). The next function (reshape) is to obtain the current window size so that I can input it into the proportions for the matrix projections. The following function (scene3d) creates the cube and sets it at the center of the scene while (scene2d) creates the triangle and sets it at the bottom left corner of the scene. The (draw) function puts everything in order in which the 3d scene is rendered first and then the 2d scene [which I nested under a push and pop matrix]. Finally, the main function creates the window and starts the loop.
Feedback would be greatly appreciated. Thank you and have a nice day!
Inside draw()
consider this for a second:
def draw():
render3d()
scene3d()
glPushMatrix()
render2d()
scene2d()
glPopMatrix()
Noticing anything missing?
There should be a glPushMatrix()
and glPopMatrix()
around the other part as well:
def draw():
glPushMatrix()
render3d()
scene3d()
glPopMatrix()
glPushMatrix()
render2d()
scene2d()
glPopMatrix()
The reason you're seeing a black screen is because within scene3d()
you're calling glTranslatef()
. So everything within milliseconds of starting the application gets translated off-screen.
Adding the missing glPushMatrix()
and glPopMatrix()
and you should see this: