[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [pygame] OpenGL and blitting
Here's a suggestion, don't do it that way ;)
You want to make a texture, and blit the texture... Here's a start,
could be done better, but it served my purposes.
###
POWERS = (32, 64, 128, 256, 512, 1024, 2048, 4096)
def nextPower(x):
for y in POWERS:
if y >= x:
return y
def surface_to_opengl_texture(imgsurf, texid=0, scale=0, mipmap=0):
"load and bind an opengl texture"
owidth, oheight = imgsurf.get_size()
width, height = tuple(map(nextPower,imgsurf.get_size()))
imgstring = pygame.image.tostring(imgsurf, "RGBA", 0)
if not texid:
texid = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, texid)
glPixelStorei(GL_PACK_ALIGNMENT, 1)
glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
if mipmap:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR_MIPMAP_LINEAR)
else:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
if owidth == width and oheight == height:
if mipmap:
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, width, height,
GL_RGBA, GL_UNSIGNED_BYTE, imgstring)
else:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, imgstring)
elif scale:
if mipmap:
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, width, height,
GL_RGBA, GL_UNSIGNED_BYTE, gluScaleImage(GL_RGBA, owidth, oheight,
imgstring, width, height, GL_UNSIGNED_BYTE))
else:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, gluScaleImage(GL_RGBA, owidth, oheight,
imgstring, width, height, GL_UNSIGNED_BYTE))
else:
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, None)
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, owidth, oheight, GL_RGBA,
GL_UNSIGNED_BYTE, imgstring)
return (texid, (owidth, oheight), (width, height))
def drawTexture((x, y), texid, (owidth, oheight), (width, height),
(xres, yres)):
wv, hv = float(owidth)/float(width), float(oheight)/float(height)
pMatrix = glGetDoublev( GL_PROJECTION_MATRIX )
mMatrix = glGetDoublev( GL_MODELVIEW_MATRIX )
glMatrixMode( GL_PROJECTION )
glLoadIdentity()
gluOrtho2D(0, xres, yres, 0)
glMatrixMode( GL_MODELVIEW )
glLoadIdentity()
glTranslatef(x, y, 0)
glEnable(GL_TEXTURE_2D)
glBindTexture(GL_TEXTURE_2D, texid)
glBegin(GL_QUADS)
glTexCoord2f(0.0, 0.0)
glVertex2f(0.0, 0.0)
glTexCoord2f(0.0, hv)
glVertex2f(0, oheight)
glTexCoord2f(wv, hv)
glVertex2f(owidth, oheight)
glTexCoord2f(wv, 0.0)
glVertex2f(owidth, 0)
glEnd()
glDisable(GL_TEXTURE_2D)
glMatrixMode( GL_PROJECTION )
glLoadMatrixd( pMatrix )
glMatrixMode( GL_MODELVIEW )
glLoadMatrixd( mMatrix )
class SurfaceTextureClass:
def __init__(self,surface,screenres,pos=(0,0)):
self.surface = surface
self.texinfo = surface_to_opengl_texture(surface)
self.screenres = screenres
self.pos = pos
def delete(self):
glDeleteTextures([self.texinfo[0]])
def setRes(self,res):
self.screenres = screenres
def draw(self):
_texinfo = self.texinfo + (self.screenres,)
drawTexture(self.pos,*_texinfo)
def pickDraw(self):
pass
def moveTo(self,pos):
self.pos = pos
def moveBy(self,pos):
self.pos = (self.pos[0]+pos[0], self.pos[1]+pos[1])
def updateSurface(self,surfRect=None):
if not surfRect:
surfRect = self.surface.get_rect()
x,y,w,h = surfRect
mySurf = self.surface
if not surfRect == self.surface.get_rect():
mySurf = mySurf.subsurface(surfRect)
imgstring = pygame.image.tostring(mySurf, "RGBA", 0)
glBindTexture(GL_TEXTURE_2D, self.texinfo[0])
glPixelStorei(GL_PACK_ALIGNMENT, 1)
glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA,
GL_UNSIGNED_BYTE, imgstring)
On Monday, Nov 4, 2002, at 14:26 America/New_York, Sami Hangaslammi
wrote:
>
> What would be the preferred method of blitting pygame surfaces to an
> opengl screen? I couldn't get OPENGLBLIT to work, so I ended up making
> the
> following function:
>
> def gl_blit(surface, (x,y)):
> sx,sy = surface.get_size()
> glMatrixMode(GL_PROJECTION)
> glPushMatrix()
> glLoadIdentity()
> glMatrixMode(GL_MODELVIEW)
> glPushMatrix()
> glLoadIdentity()
> glRasterPos2f(x,y)
> bytes = pygame.image.tostring(surface,"RGBX",1)
> glDrawPixels(sx,sy,GL_RGBA,GL_UNSIGNED_BYTE,bytes)
> glPopMatrix()
> glMatrixMode(GL_PROJECTION)
> glPopMatrix()
> glMatrixMode(GL_MODELVIEW)
>
> It works, but it is REALLY slow (relatively speaking), even with small
> surfaces. Most of the time is spent in glDrawPixels. Commenting it out
> makes things fast again. I timed it, and glDrawPixels seems to take
> about
> 1.4 ms. Since my game's whole main loop (draw the 3D scene, read user
> input, calculate movement etc.) takes about 1.6 ms (without
> glDrawPixels),
> it effectively halves my frames per second.
>
> Any suggestions?
>
> --
> Sami Hangaslammi
>
> ____________________________________
> pygame mailing list
> pygame-users@seul.org
> http://pygame.seul.org
____________________________________
pygame mailing list
pygame-users@seul.org
http://pygame.seul.org