Как очистить экран прозрачным слоем вместо сплошного цвета в pyglet / pyopengl - PullRequest
1 голос
/ 03 июня 2019

Я новичок в pyglet, и я пытаюсь нарисовать объект, который движется вокруг.Я хочу показать траекторию движения этого объекта, но постепенно заставлять старые позиции исчезать.Поэтому я пытаюсь очистить экран при каждом рисовании полупрозрачным цветом.

Но по какой-то причине метод очистки окна непрозрачен, даже когда я устанавливаю цвет почти прозрачным.Код работает, если я опускаю очистку и рисую полупрозрачный квадрат размером с окно, но я не понимаю, почему метод clear дает сплошной цвет.

Это мой код:

import pyglet


class GameWindow(pyglet.window.Window):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.px, self.py = 10, 10
        self.vx, self.vy = 15, 60
        self.ax, self.ay = 0, -5

    def update(self, dt):
        self.px, self.py = self.px + self.vx * dt, self.py + self.vy * dt
        self.vx, self.vy = self.vx + self.ax * dt, self.vy + self.ay * dt

    def on_draw(self):
        # clear screen with semitransparent layer
        pyglet.gl.glEnable(pyglet.gl.GL_BLEND)
        pyglet.gl.glBlendFunc(pyglet.gl.GL_SRC_ALPHA, pyglet.gl.GL_ONE_MINUS_SRC_ALPHA)
        pyglet.gl.glClearColor(0, 0, 0, 0.01)  # black and almost transparent
        self.clear()

        # calculate and draw object
        relative_vertices = [[20, 20], [20, -20], [-20, -20], [-20, 20]]
        vertices = []
        for v in relative_vertices:
            vertices.append(self.px + v[0])
            vertices.append(self.py + v[1])
        colors = [255, 0, 0] * len(relative_vertices)
        pyglet.graphics.vertex_list(len(relative_vertices), ("v2f", vertices), ("c3B", colors)).draw(pyglet.gl.GL_POLYGON)


if __name__ == "__main__":
    config = pyglet.gl.Config(double_buffer=False)
    window = GameWindow(400, 400, config=config)
    pyglet.clock.schedule_interval(window.update, 1/120)
    pyglet.app.run()

По какой-то причине я могу рисовать прозрачные объекты, но фон, когда используется очистка, является непрозрачным.Почему это не работает?

Кроме того, я хотел бы знать, есть ли способ сделать все пиксели фона более прозрачными, сохраняя их цвет, вместо того, чтобы рисовать поверх них полупрозрачный черный слой.

1 Ответ

2 голосов
/ 03 июня 2019

PyGlet - это оболочка OpenGL. Метод очистки использует glClear. glClear не делает ничего, кроме как скопировать текущий чистый цвет (который установлен glClearColor ) во все пиксели цветовой плоскости (текущего кадрового буфера). Ничто не смешивается с этими операциями.

Вы должны наложить прямоугольник на всё окно вместо использования clear:

# pyglet.gl.glClearColor(0, 0, 0, 0.01)  # <--- delete
# self.clear()                           # <--- delete
cover_vertices = [0, 0, 400, 0, 400, 400, 0, 400]
cover_colors = [0, 0, 0, 2] * (len(cover_vertices)//2)
pyglet.graphics.vertex_list(len(cover_vertices)//2, ("v2f", cover_vertices), ("c4B", cover_colors)).draw(pyglet.gl.GL_POLYGON)


Есть ли способ сделать это лучше? Я уже пробовал это, но я не был доволен результатом. Я ожидал бы, что темно-красная траектория снова постепенно исчезнет в черном

В этом случае режим наложения должен быть изменен. Нарисуйте прямоугольник, который покрывает экран и вычитается из целевого цвета. Это может быть достигнуто путем установки параметра glBlendEquation на GL_FUNC_REVERSE_SUBTRACT.
Наконец, нарисуйте красный прямоугольник сверху с отключенным режимом наложения:

# subtract [1, 1, 1, 0] from all pixels in the frambuffer
        pyglet.gl.glEnable(pyglet.gl.GL_BLEND)
        pyglet.gl.glBlendEquation(pyglet.gl.GL_FUNC_REVERSE_SUBTRACT)
        pyglet.gl.glBlendFunc(pyglet.gl.GL_ONE, pyglet.gl.GL_ONE)
        cover_vertices = [0, 0, 400, 0, 400, 400, 0, 400]
        cover_colors = [1, 1, 1, 0] * (len(cover_vertices)//2)
        pyglet.graphics.vertex_list(len(cover_vertices)//2, ("v2f", cover_vertices), ("c4B", cover_colors)).draw(pyglet.gl.GL_POLYGON)

        # draw the object on top of the frambuffer
        pyglet.gl.glDisable(pyglet.gl.GL_BLEND)
        relative_vertices = [[20, 20], [20, -20], [-20, -20], [-20, 20]]
        vertices = []
        for v in relative_vertices:
            vertices.append(self.px + v[0])
            vertices.append(self.py + v[1])
        colors = [255, 0, 0] * len(relative_vertices)
        pyglet.graphics.vertex_list(len(relative_vertices), ("v2f", vertices), ("c3B", colors)).draw(pyglet.gl.GL_POLYGON)

...