我是pyglet的新手,我试图绘制一个可移动的对象。我想显示该对象的轨迹,但使较旧的位置逐渐消失。因此,我试图用半透明的颜色在每次绘制中清除屏幕。
但是,由于某种原因,即使将颜色设置为几乎透明,窗口清除方法也是不透明的。如果我省略clear并绘制与窗口一样大的半透明正方形,则代码可以工作,但是我不明白为什么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()
由于某种原因,我可以绘制透明对象,但是使用clear时的背景是不透明的。为什么这不起作用?
此外,我想知道是否有一种方法可以使所有背景像素保持其颜色更透明,而不必在它们的顶部绘制半透明的黑色层。
答案 0 :(得分:2)
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)