pygame is
Python
Simple DirectMedia Layer
 
 
pygame.org is
Site Swing
Wiki

SimpleOpenGL2dClasses

      
Search:  
 
 
This code makes OpenGL simpler to get started with. It provides these classes:

GL_Texture - Loads texture data and provides a draw function
Textureset - Container for textures
GL_Image - Bootstraps off of Textureset; it provides a more sophisticated draw method and contains default values for said method
CImage - Multiple GLImages cached together, for ex. a tiled landscape
DCImage - Dynamic version of Cimage; much lower performance
LDCImage - Simplified version of DCImage with midrange performance but no special drawing arguments

The test code will run if you add a 32x32 .bmp image to "/data". It demos all of the featured classes and functions, but not every included method

import pygame
import os
 
from OpenGL.GL import *
from OpenGL.GLU import *
 
def initializeDisplay(w, h):
    pygame.display.set_mode((w,h), pygame.OPENGL|pygame.DOUBLEBUF)
 
    glClearColor(0.0, 0.0, 0.0, 1.0)
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
 
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity();
    # this puts us in quadrant 1, rather than quadrant 4
    gluOrtho2D(0, w, h, 0)
    glMatrixMode(GL_MODELVIEW)
 
    # set up texturing
    glEnable(GL_TEXTURE_2D)
    glEnable(GL_BLEND)
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
 
 
def render_init(w,h):
    """Finds the smallest available resolution that fits the desired
    viewfield."""
    pygame.init()
    modelist = pygame.display.list_modes()
    nextmode = [l for l in modelist if l[0]>=w and l[1]>=h]
    bestx, besty = -1,-1
    for l in nextmode:
        if (bestx==-1 or bestx>=l[0]) and (besty==-1 or besty>=l[1]):
            bestx, besty = l[0],l[1]
 
    print "resolution: ",bestx, besty
 
    initializeDisplay(bestx, besty)
 
def loadImage(image):
    textureSurface = pygame.image.load(image)
 
    textureData = pygame.image.tostring(textureSurface, "RGBA", 1)
 
    width = textureSurface.get_width()
    height = textureSurface.get_height()
 
    texture = glGenTextures(1)
    glBindTexture(GL_TEXTURE_2D, texture)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
        GL_UNSIGNED_BYTE, textureData)
 
    return texture, width, height
 
def SurfaceClip(surface, rect):
    textureSurface = surface.subsurface(rect)
 
    textureData = pygame.image.tostring(textureSurface, "RGBA", 1)
 
    width = textureSurface.get_width()
    height = textureSurface.get_height()
 
    texture = glGenTextures(1)
    glBindTexture(GL_TEXTURE_2D, texture)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
        GL_UNSIGNED_BYTE, textureData)
 
    return texture, width, height
 
 
def delTexture(texture):
    glDeleteTextures(texture)
 
 
def createTexDL(texture, width, height):
    newList = glGenLists(1)
    glNewList(newList,GL_COMPILE);
    glBindTexture(GL_TEXTURE_2D, texture)
    glBegin(GL_QUADS)
 
    # Bottom Left Of The Texture and Quad
    glTexCoord2f(0, 0); glVertex2f(0, 0)
 
    # Top Left Of The Texture and Quad
    glTexCoord2f(0, 1); glVertex2f(0, height)
 
    # Top Right Of The Texture and Quad
    glTexCoord2f(1, 1); glVertex2f( width,  height)
 
    # Bottom Right Of The Texture and Quad
    glTexCoord2f(1, 0); glVertex2f(width, 0)
    glEnd()
    glEndList()
 
    return newList
 
 
def delDL(list):
    glDeleteLists(list, 1)
 
def render(layers):
    for l in layers:
        l.render()
 
class GL_Texture:
    def __init__(s, texname=None, texappend=".png"):
        filename = os.path.join('data', texname)
        filename += texappend
       
        s.texture, s.width, s.height = loadImage(filename)
        s.displaylist = createTexDL(s.texture, s.width, s.height)       
 
    def __del__(self):
        if self.texture != None:
            delTexture(self.texture)
            self.texture = None
        if self.displaylist != None:
            delDL(self.displaylist)
            self.displaylist = None
 
    def __repr__(s):
        return s.texture.__repr__()
 
class Textureset:
    """Texturesets contain and name textures."""
 
    def __init__(s):
        s.textures = {}
    def load(s, texname=None, texappend=".png"):
        s.textures[texname] = GL_Texture(texname, texappend)
    def set(s, texname, data):
        s.textures[texname] = data
    def delete(s, texname):
        del s.textures[texname]
    def __del__(s):
        s.textures.clear()
        del s.textures
    def get(s, name):
        return s.textures[name]
 
class GL_Image:
    def __init__(self, texset, texname):
        self.texture = texset.get(texname)
        self.width = self.texture.width
        self.height = self.texture.height
        self.abspos=None
        self.relpos=None
        self.color=(1,1,1,1)
        self.rotation=0
        self.rotationCenter=None
 
    def draw(self, abspos=None, relpos=None, width=None, height=None,
            color=None, rotation=None, rotationCenter=None):
        if color==None:
            color = self.color
 
        glColor4fv(color)
 
        if abspos:
            glLoadIdentity()
            glTranslate(abspos[0],abspos[1],0)
        elif relpos:
            glTranslate(relpos[0],relpos[1],0)
 
        if rotation==None:
            rotation=self.rotation
 
        if rotation != 0:
                if rotationCenter == None:
                    rotationCenter = (self.width / 2, self.height / 2)
                # (w,h) = rotationCenter
                glTranslate(rotationCenter[0],rotationCenter[1],0)
                glRotate(rotation,0,0,-1)
                glTranslate(-rotationCenter[0],-rotationCenter[1],0)
 
        if width or height:
            if not width:
                width = self.width
            elif not height:
                height = self.height
 
            glScalef(width/(self.width*1.0), height/(self.height*1.0), 1.0)
                
 
        glCallList(self.texture.displaylist)
 
        if rotation != 0: # reverse
            glTranslate(rotationCenter[0],rotationCenter[1],0)
            glRotate(-rotation,0,0,-1)
            glTranslate(-rotationCenter[0],-rotationCenter[1],0)
 
class CImage:
    """CImage is a "composed image" that refs multiple GLImages.
    format is [(GLImage,argstoimage)...()..()]
    Cimage is fast but immutable - it has to recreate
    the display list to be changed."""
    
    def __init__(s, ilist):
        newlist = glGenLists(1)
        glNewList(newlist,GL_COMPILE)
 
        # see GL_Image.draw
        for i in ilist:
            if i[1][0] == None:
                i[0].draw(i[1][0], i[1][1], i[1][2], i[1][3], i[1][4],
                    i[1][5], i[1][6])
            else: # absolute positioning normally resets the identity
                i[0].draw(None,i[1][0], i[1][2], i[1][3], i[1][4], i[1][5],
                    i[1][6])
                glTranslate(-i[1][0][0], -i[1][0][1],0)               
 
        glEndList()
        s.displaylist = newlist
 
    def __del__(s):
        if s.displaylist != None:
            delDL(s.displaylist)
            s.displaylist = None
 
    def draw(s, abspos=None,relpos=None):
        if abspos:
            glLoadIdentity()
            glTranslate(abspos[0],abspos[1],0)
        elif relpos:
            glTranslate(relpos[0],relpos[1],0)
 
        glCallList(s.displaylist)
 
class DCImage:
    """Dynamic Composite Image - elements are mutable, at the caveat of
    runtime performance."""
    def __init__(s, ilist):      
        s.ilist = ilist
    def draw(s, abspos):
        glLoadIdentity()
        glTranslate(abspos[0],abspos[1],0)
 
        for i in s.ilist:
            i[0].draw(i[1])
 
class LDCImage:
    """Limited Dynamic Composite Image. LDCImage uses only the
    texture display lists for drawing, which makes it useful for simpler
    applications like text and tiles that don't need the features of DCImage.
    
    Remember not to mistake this for *LCD* Image!"""
    def __init__(s, cache):
        """cache format is: (texture ref, (absx, absy))"""
        s.cache = cache
    def draw(s, abspos):
 
        glLoadIdentity()
        glTranslate(abspos[0],abspos[1],0)
 
        for c in s.cache:
            glTranslate(c[1][0], c[1][1],0)
            glCallList(c[0].displaylist)
            glTranslate(-c[1][0], -c[1][1],0)
 
def main():
    render_init(640,480)
    tset = Textureset()
    tset.load('foo','.bmp')
    fooimage = GL_Image(tset, 'foo')
    rawfootex = tset.get('foo')
 
    compositelist = []
    examplegrid = []
 
    for x in xrange(4):
        for y in xrange(4):
            examplegrid.append((rawfootex,(x*32,y*32)))
            compositelist.append((fooimage, ((x*32,y*32), None, None,
                None, (1,1,1,1), 1, None)))
   
    ldcimg = LDCImage(examplegrid)
    foocomposite = CImage(compositelist)
    
    clock = pygame.time.Clock()
    t = 0
    glLoadIdentity()
    for count in range(100):
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
        if t==0:
            ldcimg.draw((10,10))
            fooimage.draw((0,0))
            t=1
        else:
            t=0
            foocomposite.draw((320,200))   
        clock.tick()
        pygame.display.flip()
        pygame.event.pump()
    print "result: "+str(clock.get_fps())+" FPS"
    
 
if __name__=="__main__":
    main()

spotlight

 
our projects
pygame.org welcomes all python game, art, music, sound, video and multimedia projects. If they use pygame or not.
 
recent releases
Aug 26, 2014

Aug 22, 2014

Aug 21, 2014


Aug 19, 2014

Aug 18, 2014

Aug 2, 2014


Jul 28, 2014

Jul 22, 2014

Jul 21, 2014

Jul 20, 2014

... more!
 
for pygame related questions, comments, and suggestions, please see help (lists, irc)