[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] Bump mapping



On Wed, 30 Jun 2004, Sami Hangaslammi wrote:

> I was bored, so here. ;)
> 
> def shadeMapSurfArray( surface, shadeSurf, elevation=55.0, compensate=False ):
>     array = pygame.surfarray.array3d(surface)
>     shade = pygame.surfarray.array3d(shadeSurf).astype(N.Float64)
>     if compensate:
>         compensation = sin(elevation)
>         shade /= compensation
>     shade /= 255.0
> 
>     # repeat the shade pattern as many times as needed
>     # to cover the whole surface
>     x,y  = surface.get_size()
>     xx,yy = shadeSurf.get_size()
>     mx,my = (x+xx)//xx, (y+yy)//yy
>     shade = N.concatenate((shade,)*mx,0)
>     shade = N.concatenate((shade,)*my,1)
>     shade = shade[:x,:y,...]
>     
>     array = array * shade
>     array = N.where(array > 255, 255, array).astype(N.Int0)
>     return pygame.surfarray.make_surface(array)
> 
> Probably someone more familiar with the surfarray can make it faster,
> but should beat get_at/set_at at least.

Cool, thanks!  This helped quite a bit, as I was fumbling around trying to
find a way to multiply 2 arrays of different sizes, and also didn't know
about N.where().

For 380x360  I got  .35 seconds for a ~3.7x speed improvement.
For 1220x840 I got 1.30 seconds for a ~7.5x speed improvement.
For the next size up (~2000x2000) it appears to suck up memory/cpu and hang!
Not sure what's going on here. :-/


Some comments:
  -You left out the radian conversion for elevation.
  -This requires changing the rest of the code to store shades as
  (shade,shade,shade) instead of (shade,0,0)
  -I upped the speed a bit by doing the N.where() conditionally
  -How is "//" different than "/" ?

-Jasper


PS  Here's my tweaked version:

def shadeMap( surface, shadeSurf, compensate=False, elevation=55.0 ):
    '''Bump map from a pre calculated shade map'''
    array = pygame.surfarray.array3d( surface )
    shade = pygame.surfarray.array3d( shadeSurf ).astype( N.Float64 )

    if compensate:
        elevation     = radians( elevation )
        compensation  = sin( elevation )
        shade        /= compensation
    shade /= 255.0
    shade  = expandShadeMap( shade, shadeSurf.get_size(), surface.get_size() )
    
    array = array * shade
    if compensate:
        array = N.where( array > 255, 255, array )
    array = array.astype( N.Int8 )
    return pygame.surfarray.make_surface( array )

def expandShadeMap( shade, (wOrig,hOrig), (wEnd,hEnd) ):
    '''Tile the shade surfarray up to newSize'''
    xTiles = (wEnd+wOrig)/wOrig
    yTiles = (hEnd+hOrig)/hOrig
    shade  = N.concatenate((shade,)*xTiles,0)
    shade  = N.concatenate((shade,)*yTiles,1)
    return shade[:wEnd,:hEnd,...]