我试图让 pyglet 在视角围绕精灵旋转时从后面显示精灵。如果运行代码,您将看到精灵消失,因为视角移动的角度足够远,与精灵的法线相差超过 90 度。
我知道一种选择是转换坐标和纹理来模拟旋转,但这变得非常复杂。也许有更简单的方法?请注意,这是使用 pyglet 2.0+,因此透视更容易进行 3D,并且默认使用着色器来渲染精灵。
import sys
from math import cos, sin
import pyglet
from pyglet.math import Mat4, Vec3
if __name__ == "__main__":
if len(sys.argv) == 1:
print(f'Usage: {sys.argv[0]} <image>')
sys.exit(1)
window = pyglet.window.Window(width=964, height=540, resizable=True)
batch = pyglet.graphics.Batch()
initial_z = 300
global time
time = 0
@window.event
def on_draw():
window.clear()
batch.draw()
@window.event
def on_resize(width, height):
window.viewport = (0, 0, width, height)
window.projection = Mat4.perspective_projection(window.aspect_ratio, z_near=0.1, z_far=1000, fov=45)
return pyglet.event.EVENT_HANDLED
@window.event
def on_refresh(dt):
global time
time += dt
x = initial_z * sin(time)
z = initial_z * cos(time)
position = Vec3(x, 0, z)
window.view = Mat4.look_at(position, target, up)
pyglet.graphics.glEnable(pyglet.graphics.GL_DEPTH_TEST)
pyglet.graphics.glEnable(pyglet.graphics.GL_CULL_FACE)
sprites = []
for i in range(1, 3):
img = pyglet.image.load(sys.argv[1])
img.anchor_x = img.width // 2
img.anchor_y = img.height // 2
sprite = pyglet.sprite.Sprite(img, batch=batch)
sprite.scale = 0.01
sprite.x = sprite.width // 2 + i * sprite.width + i * 10
y = i
if i == 2:
y = -i
sprite.y = sprite.width // 2 + y * 20
sprite.z = y * 20
sprites.append(sprite)
position = Vec3(0, 0, initial_z)
target = Vec3(0, 0, -1)
up = Vec3(0, 1, 0)
window.view = Mat4.look_at(position, target, up)
pyglet.app.run()
问题是需要禁用背面剔除,因此执行以下操作可以解决该问题。
pyglet.graphics.glDisable(pyglet.graphics.GL_CULL_FACE)