pygame-ce icon indicating copy to clipboard operation
pygame-ce copied to clipboard

sdl2_video with blendmode_blend displays half transparent pixels incorrectly

Open BootsManOut opened this issue 1 year ago • 0 comments
trafficstars

When drawing textures unto other textures using the blend mode "blendmode_blend", it strongly reduces the opacity of half transparent pixels, instead of displaying them accurately.

I use pygame-ce 2.4.0 with python 3.10.

Here's a demonstration: The rotated space ship is glowing, because I drew it without any blendmode active. The upright space ship has lost it's glow because I drew it's texture on top of the first texture using pygame.Blendmode_blend

https://imgur.com/L8kOnkw

Sample code

import pygame, io, base64
from pygame._sdl2 import Renderer, Texture, Image, Window, messagebox
from time import perf_counter as get_ticks
import sys

tmp_image = pygame.image.load("Graphics/spaceship.png")

current = 0
def main():
    global current
    global fontsize
    global font
    pygame.init()

    # We need a Window object and a Renderer
    window = Window("SDL2", size=(1280, 720))
    renderer = Renderer(window)

    font = pygame.font.SysFont('Arial', 10)

    fps = 0
    fps_timestamp = get_ticks()
    fps_t = Texture.from_surface(renderer, font.render('XXX', True, 'white'))

    # ...converted into a Texure
    img = Image(Texture.from_surface(renderer, tmp_image))
    tex = Texture.from_surface(renderer, tmp_image)
    img2 = Image(Texture.from_surface(renderer, tmp_image))

    # Just some variables to let the image move around
    scale = 1
    scale_d = 0.0005
    rotation = 0
    # target = True allows us to render all stuff into this Texture before rendering it to the window
    layer1 = Texture(renderer, (1280, 720), target=True)
    layer2 = Texture(renderer, (1280, 720), target= True)
    x2 = 100
    y2 = 100

    # keep track of the zoom level
    zoom = 1
    fade = 90
    factor = 1

    font = pygame.font.SysFont('Arial', round(30))

    while True:
        events = pygame.event.get()
        for e in events:
            if e.type == pygame.QUIT or e.type == pygame.KEYDOWN and e.key == pygame.K_ESCAPE:
                return
            if e.type == pygame.MOUSEWHEEL:
                if e.y > 0:
                    zoom += 0.1
                else:
                    zoom -= 0.1

        # Count the FPS
        fps += 1
        if get_ticks() - fps_timestamp > 1:
            fps_timestamp = get_ticks()
            fps_t = Texture.from_surface(renderer, font.render(str(fps) + ' FPS', True, 'white'))
            fps = 0

        # start rendering onto the buffer texture
        # everything we do now with the renderer happens on that texture
        renderer.target = layer1
        renderer.clear()
        scale = 1
        img.angle=rotation%40 + 245
        img.angle=265
        img.origin = (520,130)

        img.draw(dstrect=(50, 50, 247 * scale, 247 * scale))


        renderer.target = layer2
        renderer.clear()
        scale = 1
        img2.draw(dstrect=(450, 450, 247 * scale, 247 * scale))


        # clear the screen
        renderer.target = None
        renderer.draw_color = "purple"
        renderer.clear()

        # draw the buffer Texure on the screen
        renderer.draw_color = (0,0,0,0)

        layer1.draw(dstrect=((1280 - 1280 * zoom) / 2, (720 - 720 * zoom) / 2, 1280 * zoom, 720 * zoom))
        x, y = 1280,720

        layer2.blend_mode = pygame.BLENDMODE_BLEND
        layer2.draw(srcrect= (0,0, 1280, 720), dstrect=((1280 - 1280 * zoom) / 2, (720 - 720 * zoom) / 2, 1280 * zoom, 720 * zoom))


        # print some stuff
        zoom_t = Texture.from_surface(renderer, font.render(f'Zoom: {zoom:10.2f}', True, 'white'))
        zoom_t.draw(dstrect=(520, 450, 100, 50))
        # fps_t.draw()
        fps_t.draw(dstrect=(10, 10, fps_t.width, fps_t.height))

        # update the window, like pygame.display.flip() does
        renderer.present()


main()

BootsManOut avatar Feb 24 '24 18:02 BootsManOut