我一直在尝试纹理这个立方体,它与图像一起纹理但不是以正确的方式
Posted
技术标签:
【中文标题】我一直在尝试纹理这个立方体,它与图像一起纹理但不是以正确的方式【英文标题】:I've been trying to texture this cube, it is textured with the image but not in the right way 【发布时间】:2019-08-17 21:48:31 【问题描述】:当我运行我的程序时,立方体上的纹理似乎方向不正确并重复出现。图像中的白色似乎也被绿色取代了。我曾尝试删除 glColor 标签,但这只会引发错误。如果有人也知道如何让它只显示原始图像,那就太好了,但如果没有人可以,这不是世界末日。
看起来像这样
纹理是这样的
这是我的代码:
import pygame
import sys
from OpenGL.GL import *
from OpenGL.GLU import *
from pygame.locals import *
verticies = (
(1, 1, 1), #0
(1, 1, -1), #1
(1, -1, 1), #2
(1, -1, -1), #3
(-1, 1, 1), #4
(-1, 1, -1), #5
(-1, -1, 1), #6
(-1, -1, -1), #7
)
# (<node1>, <node2>)
edges = (
(0, 1), #0
(0, 2), #1
(0, 4), #2
(1, 3), #3
(1, 5), #4
(2, 3), #5
(2, 6), #6
(3, 7), #7
(4, 5), #8
(4, 6), #9
(5, 7), #10
(6, 7), #11
)
# (<node1>, <node2>, <node3>, <node4>)
faces = (
(0, 1, 3, 2), #0
(0, 1, 5, 4), #1
(0, 2, 6, 4), #2
(1, 3, 7, 5), #3
(2, 3, 7, 6), #4
(4, 5, 7, 6), #5
)
def cube():
glBegin(GL_QUADS)
for face in faces:
for vertex in face:
glColor3fv((0, 1, 0))
glTexCoord2fv(edges[vertex])
glVertex3fv(verticies[vertex])
glEnd()
glBegin(GL_LINES)
for edge in edges:
for vertex in edge:
glColor3fv((0, 0, 0))
glVertex3fv(verticies[vertex])
glEnd()
def loadTexture():
textureSurface = pygame.image.load('test_image.png')
textureData = pygame.image.tostring(textureSurface, "RGBA", 1)
width = textureSurface.get_width()
height = textureSurface.get_height()
glEnable(GL_TEXTURE_2D)
texid = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, texid)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height,
0, GL_RGBA, GL_UNSIGNED_BYTE, textureData)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
def main():
pygame.init()
display = (800, 600)
pygame.display.set_mode(display, DOUBLEBUF|OPENGL)
## loadTexture()
gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)
glTranslatef(0.0, 0.0, -5)
glRotatef(0, 0, 0, 0)
shiftActive = 0
ctrlActive = 0
while 1:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
glTranslatef(0.03, 0, 0)
if event.key == pygame.K_RIGHT:
glTranslatef(-0.03, 0, 0)
if event.key == pygame.K_UP:
glTranslatef(0, -0.03, 0)
if event.key == pygame.K_DOWN:
glTranslatef(0, 0.03, 0)
if event.key == pygame.K_LSHIFT:
shiftActive = 1
if event.key == pygame.K_LCTRL:
ctrlActive = 1
if event.type == pygame.KEYUP:
if event.key == pygame.K_LSHIFT:
shiftActive = 0
if event.key == pygame.K_LCTRL:
ctrlActive = 0
# scroll controls !CURRENTLY IN CLIK MODE BECAUSE OF MOUSE ISSUES!
if shiftActive:
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
glTranslatef(-0.03, 0, 0)
if event.button == 3:
glTranslatef(0.03, 0, 0)
elif ctrlActive:
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
glTranslatef(0, 0, 0.03)
if event.button == 3:
glTranslatef(0, 0, -0.03)
else:
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
glTranslatef(0, -0.03, 0)
if event.button == 3:
glTranslatef(0, 0.03, 0)
## glRotatef(1, 1, 1, 1)
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
cube()
loadTexture()
pygame.display.flip()
pygame.time.wait(10)
main()
有人知道我做错了什么吗?
再次,堆栈溢出不喜欢我的代码与描述的比率,所以我必须在问题的末尾添加随机句子让我发布它。我希望这被删除或只是一个可选的警告。我不认为深入讨论图像的角度以及图像的百分比大小应该与每个面的当前大小进行比较并给出覆盖纹理中白色的绿色的确切十六进制值将帮助任何人回答这个问题。 FFS 堆栈溢出。
【问题讨论】:
【参考方案1】:有一些问题。一是贴图颜色不对。
如果启用纹理,则默认情况下纹理元素的颜色乘以当前颜色,因为默认情况下纹理环境模式 (GL_TEXTURE_ENV_MODE
) 为GL_MODULATE
。见glTexEnv
。
这会导致纹理纹素的颜色与您在glColor3f
设置的最后一种颜色“混合”。
在渲染纹理之前设置“白色”颜色,以解决您的问题:
glColor3f(1, 1, 1)
同样,您可以将环境模式更改为GL_REPLACE
,而不是:
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE)
此外,纹理未按预期包裹到几何体。这是因为纹理坐标错误。阅读How do opengl texture coordinates work?。
如果您想将整个纹理放在立方体的每一侧,那么您必须为四边形的每个角定义一个纹理坐标,从而形成立方体的一侧。最小纹理坐标为 (0, 0),最大值为 (1, 1)。例如:
(0, 1) (1, 1)
+------+
| |
| |
+------+
(0, 0) (1, 0)
修改代码如下绘制一个合适的立方体:
uv = ((1, 1), (1, 0), (0, 0), (0, 1))
def cube():
glColor3f(1, 1, 1)
glBegin(GL_QUADS)
for face in faces:
for i, vertex in enumerate(face):
glTexCoord2fv(uv[i])
glVertex3fv(verticies[vertex])
glEnd()
如果您希望立方体靠近相机的侧面覆盖它们后面的侧面,那么您必须通过glEnable(GL_DEPTH_TEST)
启用Depth Test。
在每一帧中重新加载纹理是浪费时间。在主循环之前加载一次纹理就足够了。:
# load texture
loadTexture()
# enable the depth test
glEnable(GL_DEPTH_TEST)
while 1:
# [...]
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
cube()
pygame.display.flip()
pygame.time.wait(10)
请注意,在绘制几何体(立方体)之前,您必须确保绑定了正确的纹理 (glBindTexture(GL_TEXTURE_2D, texid)
) 并启用了二维纹理 (glEnable(GL_TEXTURE_2D)
)。
OpenGL 是一个状态引擎。设置的状态会被保留,直到您再次更改它们,甚至超出框架。
有不同的电流矩阵,可以通过glMatrixMode
切换。顶点坐标通过投影矩阵和模型视图矩阵进行变换:
pos = projectionMatrix * modelviewMatrix * vertex
因此应该将投影矩阵设置为当前投影矩阵,并将视图模型矩阵分别设置为模式视图矩阵:
glMatrixMode(GL_PROJECTION)
gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)
glMatrixMode(GL_MODELVIEW)
glTranslatef(0.0, 0.0, -5)
glRotatef(0, 0, 0, 0)
当前的矩阵被组织在一个堆栈上,可以被glPushMatrix()
/glPopMatrix
保存和恢复
请参阅以下main()
的示例代码:
def main():
pygame.init()
display = (800, 600)
pygame.display.set_mode(display, DOUBLEBUF|OPENGL)
glMatrixMode(GL_PROJECTION)
gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)
glMatrixMode(GL_MODELVIEW)
glTranslatef(0.0, 0.0, -5)
loadTexture()
glEnable(GL_DEPTH_TEST)
shiftActive, ctrlActive = 0, 0
anglex, angley = 0, 0
while 1:
for event in pygame.event.get():
# [...]
# [...]
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
glPushMatrix()
glRotate(anglex, 1, 0, 0)
glRotate(angley, 0, 1, 0)
anglex += 2
angley += 1
cube()
glPopMatrix()
pygame.display.flip()
pygame.time.wait(10)
【讨论】:
【参考方案2】:试试这个(注意 glColor3fv((1, 1, 1)) 和“textcoords”):
import pygame
import sys
from OpenGL.GL import *
from OpenGL.GLU import *
from pygame.locals import *
verticies = (
(1, 1, 1), #0
(1, 1, -1), #1
(1, -1, 1), #2
(1, -1, -1), #3
(-1, 1, 1), #4
(-1, 1, -1), #5
(-1, -1, 1), #6
(-1, -1, -1), #7
)
# (<node1>, <node2>)
edges = (
(0, 1), #0
(0, 2), #1
(0, 4), #2
(1, 3), #3
(1, 5), #4
(2, 3), #5
(2, 6), #6
(3, 7), #7
(4, 5), #8
(4, 6), #9
(5, 7), #10
(6, 7), #11
)
textcoords = (
(1, 1),
(1, 0),
(0, 0),
(0, 1)
)
# (<node1>, <node2>, <node3>, <node4>)
faces = (
(0, 1, 3, 2), #0
(0, 1, 5, 4), #1
(0, 2, 6, 4), #2
(1, 3, 7, 5), #3
(2, 3, 7, 6), #4
(4, 5, 7, 6), #5
)
def cube():
glBegin(GL_QUADS)
for face in faces:
for vertex, id in zip(face, range(0, 4)):
glColor3fv((1, 1, 1))
glTexCoord2fv(textcoords[id])
glVertex3fv(verticies[vertex])
glEnd()
glBegin(GL_LINES)
for edge in edges:
for vertex in edge:
glColor3fv((0, 0, 0))
glVertex3fv(verticies[vertex])
glEnd()
def loadTexture():
textureSurface = pygame.image.load('BkHwp.png')
textureData = pygame.image.tostring(textureSurface, "RGBA", 1)
width = textureSurface.get_width()
height = textureSurface.get_height()
glEnable(GL_TEXTURE_2D)
texid = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, texid)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height,
0, GL_RGBA, GL_UNSIGNED_BYTE, textureData)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
#glGenerateMipmap(GL_TEXTURE_2D)
def main():
pygame.init()
display = (800, 600)
pygame.display.set_mode(display, DOUBLEBUF|OPENGL)
gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)
glTranslatef(0.0, 0.0, -5)
glRotatef(0, 0, 0, 0)
shiftActive = 0
ctrlActive = 0
while 1:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
glTranslatef(0.03, 0, 0)
if event.key == pygame.K_RIGHT:
glTranslatef(-0.03, 0, 0)
if event.key == pygame.K_UP:
glTranslatef(0, -0.03, 0)
if event.key == pygame.K_DOWN:
glTranslatef(0, 0.03, 0)
if event.key == pygame.K_LSHIFT:
shiftActive = 1
if event.key == pygame.K_LCTRL:
ctrlActive = 1
if event.type == pygame.KEYUP:
if event.key == pygame.K_LSHIFT:
shiftActive = 0
if event.key == pygame.K_LCTRL:
ctrlActive = 0
# scroll controls !CURRENTLY IN CLIK MODE BECAUSE OF MOUSE ISSUES!
if shiftActive:
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
glTranslatef(-0.03, 0, 0)
if event.button == 3:
glTranslatef(0.03, 0, 0)
elif ctrlActive:
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
glTranslatef(0, 0, 0.03)
if event.button == 3:
glTranslatef(0, 0, -0.03)
else:
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
glTranslatef(0, -0.03, 0)
if event.button == 3:
glTranslatef(0, 0.03, 0)
## glRotatef(1, 1, 1, 1)
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
cube()
loadTexture()
pygame.display.flip()
pygame.time.wait(10)
main()
【讨论】:
> “试试这个 [...]”以上是关于我一直在尝试纹理这个立方体,它与图像一起纹理但不是以正确的方式的主要内容,如果未能解决你的问题,请参考以下文章