ScriptLineStudios / pygame_shaders

a library to easily integrate shaders into your new or existing pygame projects
https://pygame-shaders.readthedocs.io/en/latest/
MIT License
49 stars 4 forks source link

[bug]the surface read from Shader.render lost its alpha value[solution provided] #11

Open MeteorShower2004 opened 5 months ago

MeteorShower2004 commented 5 months ago

Describe the bug the surface returned by Shader.render method is always opaque (all pixels' alpha value are always 255)

To Reproduce 1.copy the code provided below, paste it into a file 2.put an image file with alpha values next to your source file 3.replace "{your_image}" in the provided source with the name of your image 4.run the source

(you can also try to change the alpha value of target_surface in glsl source, this bug also happens)

the source code is borrowed from file examples/water/main.py

import pygame
import pygame_shaders

pygame.init()
clock = pygame.time.Clock()
pygame.display.set_mode((600, 600), pygame.OPENGL | pygame.DOUBLEBUF)

display = pygame.Surface((600, 600))

screen_shader = pygame_shaders.DefaultScreenShader(display) # <- Here we supply our default display, it's this display which will be displayed onto the opengl context via the screen_shader

target_surface = pygame.image.load({your_image}), (0, 0))
shader = pygame_shaders.Shader(
    pygame_shaders.DEFAULT_VERTEX_SHADER, 
    pygame_shaders.DEFAULT_FRAGMENT_SHADER, 
    target_surface
) #<- give it to our shader

while True:
    display.fill((0, 255, 255))

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()

    #our tested code
    display.blit(shader.render(), (0, 0))

    screen_shader.render() 

    pygame.display.flip()
    clock.tick(30)

Expected behavior Assume the 1x1 image have a pixel with alpha 140, if you didn't modify its alpha in shader, the alpha of returned pixel should also be 140.

solution In file pygame_shaders.py line 160, just replace self.framebuffer.read() with self.framebuffer.read(components=4) and then add an 'A' to the end of the string "RGB". at last it looks like this:

surf​ ​=​ ​pygame​.​image​.​frombuffer​(​self​.​framebuffer​.​read​(components=4), ​self​.​target_surface​.​get_size​(), ​"RGBA"​)

(I edit this issues in my phone, so I'm sorry that if there's any issue)