开发者

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()
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜