Mischen 2d und 3d in OpenGL (mit Pyglet)
Frage
Ich versuche, 2d und 3d in opengl in Pyglet zu mischen, das heißt eine 3D-Szene zu orthographischer Projektion zeichne dann wechseln und so über die Spitze ziehen. Ich ziehe die 3D stuff, schieben die Projektionsmatrix auf die Stapel, tut eine glOrtho Projektionsmatrix, das 2D-Material zeichnen, dann Pop die vorherige Matrix aus dem Stapel. Das 3D-Zeug zieht gut, aber aus irgendeinem Grunde der 2d Teil zieht überhaupt nicht, auch auf seinem eigenen. Hier ist der Code:
class Window(pyglet.window.Window):
# resolution
width, height = 1024, 786
def __init__(self, width, height):
# initialise window
super(Window, self).__init__(width, height)
# set title
self.set_caption("OpenGL Doss")
# call update() at 30fps
pyglet.clock.schedule_interval(self.update, 1 / 30.0)
glEnable(GL_TEXTURE_2D) # enable textures
glShadeModel(GL_SMOOTH) # smooth shading of polygons
glClearColor(0.0, 0.0, 0.0, 0.0)
glClearDepth(1.0)
glDepthFunc(GL_LEQUAL)
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST) # make stuff look nice
self.world = World() # initialise world
self.label = pyglet.text.Label('Hello, world',
font_name='Times New Roman',
font_size=20,
width=10, height=10)
def on_resize(self, width, height):
print 'on resize'
if height == 0:
height = 1
glViewport(0, 0, width, height) # specify viewport
# load perspective projection matrix
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(45, 1.0 * width / height, 0.1, 100.0)
#glLoadIdentity()
def on_draw(self):
self.set3d()
# draw 3d stuff
self.world.draw()
self.set2d()
# draw 2d stuff
self.draw2d()
self.unSet2d()
def update(self, dt):
"called at set interval during runtime"
#maze = self.world.maze
maze_platform = self.world.maze_platform
pacman = maze_platform.maze.pacman
maze_platform.update()
# send it world pointer
pacman.update(self.world)
def on_key_press(self, symbol, modifiers):
control.press(symbol, modifiers)
def on_key_release(self, symbol, modifiers):
control.release(symbol, modifiers)
def set3d(self):
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glEnable(GL_DEPTH_TEST) # enable depth testing
# reset modelview matrix
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
def set2d(self):
glDisable(GL_DEPTH_TEST)
# store the projection matrix to restore later
glMatrixMode(GL_PROJECTION)
glPushMatrix()
# load orthographic projection matrix
glLoadIdentity()
#glOrtho(0, float(self.width),0, float(self.height), 0, 1)
far = 8192
glOrtho(-self.width / 2., self.width / 2., -self.height / 2., self.height / 2., 0, far)
# reset modelview
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
#glClear(GL_COLOR_BUFFER_BIT)
def unSet2d(self):
# load back the projection matrix saved before
glMatrixMode(GL_PROJECTION)
glPopMatrix()
def draw2d(self):
z=-6
n=100
glTranslatef(0, 0.0, -z)
glBegin(GL_TRIANGLES)
glVertex3f(0.0, n, 0.0)
glVertex3f(-n, -n, 0)
glVertex3f(n, -n, 0)
glEnd()
def main():
window = Window(Window.width, Window.height)
pyglet.app.run()
print 'framerate:', pyglet.clock.get_fps(), '(error checking = %s)' % pyglet.options['debug_gl']
if __name__ == '__main__': main()
#command = 'main()'
#cProfile.run(command)
Lösung
Ich würde empfehlen, dass Sie die Model-View und Projektionsmatrizen zurückgesetzt auf jedem machen, und dann nicht Push verwenden / Pop, wenn Sie von 3d gehen bis 2d.
Allerdings vermute ich, dass Sie schlechte Koordinaten verwenden, so dass die Szene außerhalb der Klammerebene zeichnen. In partciular bin ich ein bisschen misstrauisch, die in der Nähe von Clipping-Ebene auf Null setzen. Normalerweise sind 2D-Elemente mit z = 0 gezeichnet.
Versuchen Sie, die in der Nähe von Clip-Ebene zu setzen -1.
Ich bin auch ein bisschen unsicher, warum Sie anrufen glTranslatef (0, 0,0, -Z) in Draw2d, würde ich nicht stören.
Andere Tipps
In draw2d()
Versuch glDisable(GL_TEXTURE_2D)
und glColor3ub(255,255,255)
vor Ihrem Dreieck zeichnen.
Achten Sie darauf, wieder glEnable(GL_TEXTURE_2D)
vor world.draw()
Aufruf wieder, wenn es Geometrie texturierten verwendet.