Skip to content

(RGB split, Chromatic aberration, Water ripple effect, heatmap)

Yoann Berenguer edited this page May 20, 2023 · 4 revisions

RGB SPLIT & CHROMATIC ABBERATION

chromatic(
        surface_,
        unsigned int delta_x,
        unsigned int delta_y,
        float zoom=0.9999,
        float fx=0.02
)
    """
    CHROMATIC ABERRATION 
    
    Create a chromatic aberration with an amplitude proportional to the 
    distance from the centre of the effect
    
    :param surface_ : pygame.Surface
    :param delta_x  : int; chromatic centre effect coordinate X, must be in range [0 ... w]
    :param delta_y  : int; chromatic centre effect coordinate Y, must be in range [0 ... h]
    :param zoom     : float; zoom factor 0.9999 (no zoom, full image), < 1.0 zoom-in. Must 
        be in range [0.0 ... 0.9999] 
    :param fx       : channel rgb layer offset default 0.02. Must be in range [0.0 ... 0.2]
    :return         : a chromatic aberration effect
    """

alt text alt text

example :

# Offset between layers 0.02
IMAGE = chromatic(IMAGE, 400, 300, 0.9999, fx=0.02)

rgb_split(object surface_, int offset_=10)
    """
    
    THIS SHADER CREATE AN RGB SPLIT EFFECT (SUPERPOSED CHANNEL R, G, B WITH GIVEN OFFSET)
    The transformation apply inplace

    The original surface will be used for the subsurface blit operation.
    Each channels will be blit sequentially in the following order RGB
    Note that channel green and blue will be blit with an additional flag BLEND_RGB_ADD, to mix
    the channel with the lower layers.


    :param surface_ : pygame Surface to process (24bit format)
    :param offset_  : integer; offset for (x, y) to add to each channels RGB
    :return         : void
    
    """

alt text alt text


rgb_split_clean(object surface_, int offset_=10)
    """

    THIS SHADER CREATE AN RGB SPLIT EFFECT (SUPERPOSED CHANNEL R, G, B WITH GIVEN OFFSET)
    The final image has a different width and height since the offset value is removed to keep only 
    the overlapping R, G, B channels 
    Setting the Offset_ to zero will have no effect to the original image.

    :param surface_ : pygame Surface to process (24bit format)
    :param offset_  : integer; offset for (x, y) to add to each channels RGB
    :return         : pygame.Surface

    """

alt text alt text
alt text


WATER RIPPLE EFFECT

ripple(
        int rows_,
        int cols_,
        float [:, ::1] previous_,
        float [:, ::1] current_,
        unsigned char [:, :, ::1] array_
)
    """
    
    THIS SHADER CREATE A WATER EFFECT ON A PYGAME SURFACE
    This version does not include any background deformation to keep a reasonable FPS rate

    * NOTE this shader cannot be apply to the screen directly 

    :param rows_        : integer; Array width
    :param cols_        : integer; Array height
    :param previous_    : numpy.ndarray type (w, h) type float; array use for the transformation
    :param current_     : numpy.ndarray type (w, h) type float; array use for the transformation
    :param array_       : numpy.ndarray type (w, h, 3) type unsigned char
    :return             : void
    
    """

e.g:

WIDTH = 1024
HEIGHT = 768

SCREEN = pygame.display.set_mode((WIDTH, HEIGHT), vsync=True)
SCREEN.convert(32, RLEACCEL)
SCREEN.set_alpha(None)

BACKGROUND = pygame.image.load("../Assets/space2.jpg").convert()
BACKGROUND = pygame.transform.smoothscale(BACKGROUND, (WIDTH, HEIGHT))
FRAME = 0
CLOCK = pygame.time.Clock()
GAME = True

W2 = WIDTH >> 1
H2 = HEIGHT >> 1

current = numpy.zeros((W2, H2), dtype=numpy.float32)
previous = numpy.zeros((W2, H2), dtype=numpy.float32)
array_ = numpy.full((W2, H2, 3), 0, numpy.uint8)

image = BACKGROUND.copy()
t = time.time()

while GAME:

            pygame.event.pump()
            for event in pygame.event.get():

                keys = pygame.key.get_pressed()

                if keys[pygame.K_ESCAPE]:
                    GAME = False
                    break

            SCREEN.blit(BACKGROUND, (0, 0))

            rnd = randint(0, 1000)

            if rnd > 900:
                m = randint(1000, 10000)
                previous[randint(0, W2 - 1), randint(0, H2 - 1)] = m

            previous, current, array_ = ripple(W2, H2, previous, current, array_)

            surf = make_surface(asarray(array_, dtype=uint8))
            surf = smoothscale(surf, (WIDTH, HEIGHT))
            image.blit(surf, (0, 0), special_flags=pygame.BLEND_RGBA_ADD)

            SCREEN.blit(image, (0, 0))

            pygame.display.flip()
            CLOCK.tick()
            FRAME += 1

            pygame.display.set_caption(
                "Test ripple rain drop effect %s fps "
                "(%sx%s)" % (round(CLOCK.get_fps(), 2), WIDTH, HEIGHT))

            image = BACKGROUND.copy()

            if time.time() - t > 5:
                break

demo https://www.youtube.com/watch?v=XgLF2BWP0Rs#t=2m42s --> 2 mins 42 secs


HEATMAP

cpdef inline void heatmap(object surface_, bint rgb_=True)
    """
    TRANSFORM AN IMAGE INTO A HEATMAP EQUIVALENT

    :param surface_ : pygame.Surface
    :param rgb_     : boolean; True transformed the image into a RGB heatmap model of False (BGR)
    :return         : void
    """
    

e.g:

heatmap_convert(surface_, False)
heatmap_convert(surface_, True)

alt text alt text
alt text

Clone this wiki locally