Render a textured rectangle with PyOpenGL
I'm working on a project using PyOpenGL, and I'm currently attempting to get OpenGL to render a kind of splash screen. My decided solution to this is to draw a textured 2D rectangle. Unfortunately, it appears that no matter what I do, nothing is ever drawn, I just get a black screen (So I guess something is drawn, otherwise it would be a transparent window, but it's definitely not what I want). Here is the pertinent code for my class:
class ClassThing:
def __init__(self):
self.Splash = True
glutInit(sys.argv)
def TexFromPNG(self, filename):
img = Image.open(filename)
img_data = numpy.array(list(img.getdata()), numpy.uint8)
texture = glGenTextures(1)
glPixelStorei(GL_UNPACK_ALIGNMENT,1)
glBindTexture(GL_TEXTURE_2D, texture)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img.size[0], img.size[1], 0, GL_RGB, GL_UNSIGNED_BYTE, img_data)
return texture
def run(self):
glutInitDisplayMode(GLUT_RGBA)
glutInitWindowSize(256,224)
self.window = glutCreateWindow("GL")
glutDisplayFunc(self.draw)
glClearColor(0,0,0,0)
glEnable(GL_TEXTURE_2D)
glEnable(GL_VERTEX_ARRAY)
self.MainTex = glGenTextures(1)
self.SplashTex = self.TexFromPNG("Resources/Splash.png")
glutMainLoop()
def draw(self):
glClear(GL_COLOR_BUFFER_BIT)
glLoadIdentity()
if self.Splash:
glBindTexture(GL_TEXTURE_2D, self.SplashTex)
else:
gl开发者_开发问答BindTexture(GL_TEXTURE_2D, self.MainTex)
glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER)
Varray = numpy.array([[0,0],[0,256],[224,256],[224,0]],numpy.uint16)
glVertexPointer(2,GL_SHORT,0,Varray)
indices = [0,1,2,3]
glDrawElements(GL_QUADS,1,GL_UNSIGNED_SHORT,indices)
glFlush()
thing = ClassThing()
thing.run()
As I said, just that nets me with a totally black screen. It feels like I may be missing some kind of initialization or enabling, but I don't know what else I would need to enable.
As an aside, apparently glVertexPointer is deprecated, how would I run glDrawElements without it? Is there some kind of vertex generation you can do similar to texture generation or what?
Could it be because you called glGenTextures(1)
twice? You assigned it to texture in TexFromPNG and assigned it to self.MainTex in run.
You need to supply texture coordinates as well, otherwise OpenGL doesn't know how to map the texture to your quad — you also could use automatic texture coordinate generation, but in your case just specifying coordinates is simpler. In addition you also need to specify viewport and projection
class ClassThing:
def __init__(self):
self.Splash = True
def TexFromPNG(self, filename):
img = Image.open(filename)
img_data = numpy.array(list(img.getdata()), numpy.uint8)
texture = glGenTextures(1)
glPixelStorei(GL_UNPACK_ALIGNMENT,1)
glBindTexture(GL_TEXTURE_2D, texture)
# Texture parameters are part of the texture object, so you need to
# specify them only once for a given texture object.
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img.size[0], img.size[1], 0, GL_RGB, GL_UNSIGNED_BYTE, img_data)
return texture
def run(self):
glutInitDisplayMode(GLUT_RGBA)
glutInitWindowSize(256,224)
self.window = glutCreateWindow("GL")
glutReshapeFunc(self.reshape)
glutDisplayFunc(self.draw)
self.MainTex = glGenTextures(1)
self.SplashTex = self.TexFromPNG("Resources/Splash.png")
glutMainLoop()
def reshape(self, width, height):
self.width = width
self.height = height
glutPostRedisplay();
def draw(self):
glViewport(0, 0, self.width, self.height)
glClearDepth(1) # just for completeness
glClearColor(0,0,0,0)
glClear(GL_COLOR_BUFFER_BIT)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(0, 1, 0, 1, -1, 1)
glMatrixMode(GL_MODELVIEW);
glLoadIdentity()
if self.Splash:
glBindTexture(GL_TEXTURE_2D, self.SplashTex)
else:
glBindTexture(GL_TEXTURE_2D, self.MainTex)
# it's a good idea to enable state right before you need it
# there's no such thing like global state intialization in
# OpenGL
glEnable(GL_TEXTURE_2D)
# vertex arrays must be enabled using glEnableClientState
glEnableClientState(GL_VERTEX_ARRAY)
glEnableClientState(GL_TEXTURE_COORD_ARRAY)
Varray = numpy.array([[0,0],[0,1],[1,1],[1,0]],numpy.float)
glVertexPointer(2,GL_FLOAT,0,Varray)
glTexCoordPointer(2,GL_FLOAT,0,Varray)
indices = [0,1,2,3]
glDrawElements(GL_QUADS,1,GL_UNSIGNED_SHORT,indices)
# This implies a glFinish, which includes a glFlush
glutSwapBuffers()
# GLUT initialization in program global, so initialize it on
# the process level. It might be
glutInit(sys.argv)
thing = ClassThing()
thing.run()
精彩评论