Pyglet 纹理搞砸了
Pyglet textures are messed up
我一直在关注 Youtube 上的 Pyglet OpenGL 教程 here,大约一两年前我关注了它。它工作得很好,我设法制作了一个包含简单物理的 Minecraft 克隆。现在,我丢失了代码,我试图重新创建它。我关注了视频,但是时间太长了,所以我只是从 link 下载了它。然后,我唯一替换的是 tex = pyglet.image.load(file).texture
,因为显然我应该使用 tex = pyglet.image.load(file).get_texture()
。然后,当我 运行 它时,立方体看起来非常扭曲,纹理都在错误的位置。以下是 link 的立方体图片:
代码在这里:
from pyglet.gl import *
from pyglet.window import key
import math
class Model:
def get_tex(self,file):
tex = pyglet.image.load(file).get_texture()
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST)
return pyglet.graphics.TextureGroup(tex)
def __init__(self):
self.top = self.get_tex('grass_top.png')
self.side = self.get_tex('grass_side.png')
self.bottom = self.get_tex('dirt.png')
self.batch = pyglet.graphics.Batch()
tex_coords = ('t2f',(0,0, 1,0, 1,1, 0,1, ))
x,y,z = -1,-1,-1
X,Y,Z = x+2,y+2,z+2
self.batch.add(4, GL_QUADS, self.side, ('v3f',(x,y,z, x,y,Z, x,Y,Z, x,Y,z)), tex_coords)
self.batch.add(4, GL_QUADS, self.side, ('v3f',(X,y,Z, X,y,z, X,Y,z, X,Y,Z)), tex_coords)
self.batch.add(4, GL_QUADS, self.bottom, ('v3f',(x,y,z, X,y,z, X,y,Z, x,y,Z)), tex_coords)
self.batch.add(4, GL_QUADS, self.top, ('v3f',(x,Y,Z, X,Y,Z, X,Y,z, x,Y,z)), tex_coords)
self.batch.add(4, GL_QUADS, self.side, ('v3f',(X,y,z, x,y,z, x,Y,z, X,Y,z)), tex_coords)
self.batch.add(4, GL_QUADS, self.side, ('v3f',(x,y,Z, X,y,Z, X,Y,Z, x,Y,Z)), tex_coords)
def draw(self):
self.batch.draw()
class Player:
def __init__(self,pos=(0,0,0),rot=(0,0)):
self.pos = list(pos)
self.rot = list(rot)
def mouse_motion(self,dx,dy):
dx/=8; dy/=8; self.rot[0]+=dy; self.rot[1]-=dx
if self.rot[0]>90: self.rot[0] = 90
elif self.rot[0]<-90: self.rot[0] = -90
def update(self,dt,keys):
s = dt*10
rotY = -self.rot[1]/180*math.pi
dx,dz = s*math.sin(rotY),s*math.cos(rotY)
if keys[key.W]: self.pos[0]+=dx; self.pos[2]-=dz
if keys[key.S]: self.pos[0]-=dx; self.pos[2]+=dz
if keys[key.A]: self.pos[0]-=dz; self.pos[2]-=dx
if keys[key.D]: self.pos[0]+=dz; self.pos[2]+=dx
if keys[key.SPACE]: self.pos[1]+=s
if keys[key.LSHIFT]: self.pos[1]-=s
class Window(pyglet.window.Window):
def push(self,pos,rot): glPushMatrix(); glRotatef(-rot[0],1,0,0); glRotatef(-rot[1],0,1,0); glTranslatef(-pos[0],-pos[1],-pos[2],)
def Projection(self): glMatrixMode(GL_PROJECTION); glLoadIdentity()
def Model(self): glMatrixMode(GL_MODELVIEW); glLoadIdentity()
def set2d(self): self.Projection(); gluOrtho2D(0,self.width,0,self.height); self.Model()
def set3d(self): self.Projection(); gluPerspective(90,self.width/self.height,0.05,1000); self.Model()
def setLock(self,state): self.lock = state; self.set_exclusive_mouse(state)
lock = False; mouse_lock = property(lambda self:self.lock,setLock)
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
self.set_minimum_size(300, 200)
self.keys = key.KeyStateHandler()
self.push_handlers(self.keys)
pyglet.clock.schedule(self.update)
self.model = Model()
self.player = Player((0,0,5),(0,0))
def on_mouse_motion(self,x,y,dx,dy):
if self.mouse_lock: self.player.mouse_motion(dx,dy)
def on_key_press(self,KEY,MOD):
if KEY == key.ESCAPE: self.close()
elif KEY == key.E: self.mouse_lock = not self.mouse_lock
def update(self,dt):
self.player.update(dt,self.keys)
def on_draw(self):
self.clear()
self.set3d()
self.push(self.player.pos,self.player.rot)
self.model.draw()
glPopMatrix()
if __name__ == '__main__':
window = Window(width=854,height=480,caption='Minecraft',resizable=True)
glClearColor(0.5,0.7,1,1)
glEnable(GL_DEPTH_TEST)
# glEnable(GL_CULL_FACE)
pyglet.app.run()
注意:我摆弄了纹理,当我替换批次时添加了这个:
self.batch.add(4, GL_QUADS, self.top, ('v3f',(x,y,z, x,y,Z, x,Y,Z, x,Y,z)), tex_coords)
self.batch.add(4, GL_QUADS, self.top, ('v3f',(X,y,Z, X,y,z, X,Y,z, X,Y,Z)), tex_coords)
self.batch.add(4, GL_QUADS, self.side, ('v3f',(x,y,z, X,y,z, X,y,Z, x,y,Z)), tex_coords)
self.batch.add(4, GL_QUADS, self.bottom, ('v3f',(x,Y,Z, X,Y,Z, X,Y,z, x,Y,z)), tex_coords)
self.batch.add(4, GL_QUADS, self.top, ('v3f',(X,y,z, x,y,z, x,Y,z, X,Y,z)), tex_coords)
self.batch.add(4, GL_QUADS, self.top, ('v3f',(x,y,Z, X,y,Z, X,Y,Z, x,Y,Z)), tex_coords)
立方体纹理正确。有什么想法吗?
另外,当我只画一侧时,它在正确的位置,但纹理在脸上弯曲,好像是两个三角形。
您必须启用 Depth Test:
if __name__ == "__main__":
window = Window(width = 400, height = 300, caption = "Minecraft", resizable = True)
glClearColor(0.5, 0.7, 1, 1)
glEnable(GL_DEPTH_TEST) # <----
pyglet.app.run()
请注意,立方体似乎被搞砸了,因为立方体的正面没有覆盖背面。深度测试确保已经绘制的几何图形不会被后面的新几何图形覆盖。
我找到了答案。在较新的 PC 上测试完全相同的代码后,它起作用了。好像我有一个过时的 GPU 或图形驱动程序,就像 Rabbid76 说的那样。
我一直在关注 Youtube 上的 Pyglet OpenGL 教程 here,大约一两年前我关注了它。它工作得很好,我设法制作了一个包含简单物理的 Minecraft 克隆。现在,我丢失了代码,我试图重新创建它。我关注了视频,但是时间太长了,所以我只是从 link 下载了它。然后,我唯一替换的是 tex = pyglet.image.load(file).texture
,因为显然我应该使用 tex = pyglet.image.load(file).get_texture()
。然后,当我 运行 它时,立方体看起来非常扭曲,纹理都在错误的位置。以下是 link 的立方体图片:
代码在这里:
from pyglet.gl import *
from pyglet.window import key
import math
class Model:
def get_tex(self,file):
tex = pyglet.image.load(file).get_texture()
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST)
return pyglet.graphics.TextureGroup(tex)
def __init__(self):
self.top = self.get_tex('grass_top.png')
self.side = self.get_tex('grass_side.png')
self.bottom = self.get_tex('dirt.png')
self.batch = pyglet.graphics.Batch()
tex_coords = ('t2f',(0,0, 1,0, 1,1, 0,1, ))
x,y,z = -1,-1,-1
X,Y,Z = x+2,y+2,z+2
self.batch.add(4, GL_QUADS, self.side, ('v3f',(x,y,z, x,y,Z, x,Y,Z, x,Y,z)), tex_coords)
self.batch.add(4, GL_QUADS, self.side, ('v3f',(X,y,Z, X,y,z, X,Y,z, X,Y,Z)), tex_coords)
self.batch.add(4, GL_QUADS, self.bottom, ('v3f',(x,y,z, X,y,z, X,y,Z, x,y,Z)), tex_coords)
self.batch.add(4, GL_QUADS, self.top, ('v3f',(x,Y,Z, X,Y,Z, X,Y,z, x,Y,z)), tex_coords)
self.batch.add(4, GL_QUADS, self.side, ('v3f',(X,y,z, x,y,z, x,Y,z, X,Y,z)), tex_coords)
self.batch.add(4, GL_QUADS, self.side, ('v3f',(x,y,Z, X,y,Z, X,Y,Z, x,Y,Z)), tex_coords)
def draw(self):
self.batch.draw()
class Player:
def __init__(self,pos=(0,0,0),rot=(0,0)):
self.pos = list(pos)
self.rot = list(rot)
def mouse_motion(self,dx,dy):
dx/=8; dy/=8; self.rot[0]+=dy; self.rot[1]-=dx
if self.rot[0]>90: self.rot[0] = 90
elif self.rot[0]<-90: self.rot[0] = -90
def update(self,dt,keys):
s = dt*10
rotY = -self.rot[1]/180*math.pi
dx,dz = s*math.sin(rotY),s*math.cos(rotY)
if keys[key.W]: self.pos[0]+=dx; self.pos[2]-=dz
if keys[key.S]: self.pos[0]-=dx; self.pos[2]+=dz
if keys[key.A]: self.pos[0]-=dz; self.pos[2]-=dx
if keys[key.D]: self.pos[0]+=dz; self.pos[2]+=dx
if keys[key.SPACE]: self.pos[1]+=s
if keys[key.LSHIFT]: self.pos[1]-=s
class Window(pyglet.window.Window):
def push(self,pos,rot): glPushMatrix(); glRotatef(-rot[0],1,0,0); glRotatef(-rot[1],0,1,0); glTranslatef(-pos[0],-pos[1],-pos[2],)
def Projection(self): glMatrixMode(GL_PROJECTION); glLoadIdentity()
def Model(self): glMatrixMode(GL_MODELVIEW); glLoadIdentity()
def set2d(self): self.Projection(); gluOrtho2D(0,self.width,0,self.height); self.Model()
def set3d(self): self.Projection(); gluPerspective(90,self.width/self.height,0.05,1000); self.Model()
def setLock(self,state): self.lock = state; self.set_exclusive_mouse(state)
lock = False; mouse_lock = property(lambda self:self.lock,setLock)
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
self.set_minimum_size(300, 200)
self.keys = key.KeyStateHandler()
self.push_handlers(self.keys)
pyglet.clock.schedule(self.update)
self.model = Model()
self.player = Player((0,0,5),(0,0))
def on_mouse_motion(self,x,y,dx,dy):
if self.mouse_lock: self.player.mouse_motion(dx,dy)
def on_key_press(self,KEY,MOD):
if KEY == key.ESCAPE: self.close()
elif KEY == key.E: self.mouse_lock = not self.mouse_lock
def update(self,dt):
self.player.update(dt,self.keys)
def on_draw(self):
self.clear()
self.set3d()
self.push(self.player.pos,self.player.rot)
self.model.draw()
glPopMatrix()
if __name__ == '__main__':
window = Window(width=854,height=480,caption='Minecraft',resizable=True)
glClearColor(0.5,0.7,1,1)
glEnable(GL_DEPTH_TEST)
# glEnable(GL_CULL_FACE)
pyglet.app.run()
注意:我摆弄了纹理,当我替换批次时添加了这个:
self.batch.add(4, GL_QUADS, self.top, ('v3f',(x,y,z, x,y,Z, x,Y,Z, x,Y,z)), tex_coords)
self.batch.add(4, GL_QUADS, self.top, ('v3f',(X,y,Z, X,y,z, X,Y,z, X,Y,Z)), tex_coords)
self.batch.add(4, GL_QUADS, self.side, ('v3f',(x,y,z, X,y,z, X,y,Z, x,y,Z)), tex_coords)
self.batch.add(4, GL_QUADS, self.bottom, ('v3f',(x,Y,Z, X,Y,Z, X,Y,z, x,Y,z)), tex_coords)
self.batch.add(4, GL_QUADS, self.top, ('v3f',(X,y,z, x,y,z, x,Y,z, X,Y,z)), tex_coords)
self.batch.add(4, GL_QUADS, self.top, ('v3f',(x,y,Z, X,y,Z, X,Y,Z, x,Y,Z)), tex_coords)
立方体纹理正确。有什么想法吗?
另外,当我只画一侧时,它在正确的位置,但纹理在脸上弯曲,好像是两个三角形。
您必须启用 Depth Test:
if __name__ == "__main__":
window = Window(width = 400, height = 300, caption = "Minecraft", resizable = True)
glClearColor(0.5, 0.7, 1, 1)
glEnable(GL_DEPTH_TEST) # <----
pyglet.app.run()
请注意,立方体似乎被搞砸了,因为立方体的正面没有覆盖背面。深度测试确保已经绘制的几何图形不会被后面的新几何图形覆盖。
我找到了答案。在较新的 PC 上测试完全相同的代码后,它起作用了。好像我有一个过时的 GPU 或图形驱动程序,就像 Rabbid76 说的那样。