python - 我一直在尝试对这个立方体进行纹理处理,它与图像一起纹理化,但方式不正确

标签 python opengl pygame pyopengl opengl-compat

当我运行程序时,立方体上的纹理似乎方向不正确并且不断重复。此外,图像中的白色似乎已被绿色取代。我尝试删除 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 堆栈溢出。

最佳答案

有一些问题。首先,纹理的颜色不对。

如果启用纹理,则默认情况下纹理元素的颜色会乘以当前颜色,因为默认情况下纹理环境模式 (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()
<小时/>

如果您希望立方体靠近相机的侧面覆盖其后面的侧面,那么您必须启用 Depth Test通过 glEnable(GL_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)

请注意,您必须确保绑定(bind)正确的纹理 (glBindTexture(GL_TEXTURE_2D, texid)) 并启用 2 维纹理 (glEnable(GL_TEXTURE_2D))在绘制几何体(立方体)之前。
OpenGL 是一个状态引擎。设置的状态将被保留,直到您再次更改它们,甚至超出框架。

<小时/>

有不同的电流矩阵,可以通过 glMatrixMode 进行切换。顶点坐标通过投影矩阵和模型 View 矩阵进行变换:

pos = projectionMatrix * modelviewMatrix * vertex

因此,投影矩阵应设置为当前投影矩阵, View 相应模型矩阵应设置为模态视图矩阵:

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)

关于python - 我一直在尝试对这个立方体进行纹理处理,它与图像一起纹理化,但方式不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57540156/

相关文章:

python - 如何将圆圈移动到预定的 x,y 坐标?

javascript - 为什么 Bootstrap4 模式不显示我的 Django 模板中的数据?

iphone - OpenGL 或用于为 iphone 或 iPod touch 开发游戏的游戏引擎,哪个是更好的选择?

java - .3ds 与 JOGL?

c++ - OpenGL/GLUT 在 mainEventLoop() 之后创建窗口

python - 在使用 pyinstaller 制作的可执行文件中获取运行时错误

python - 缺少位置参数

python - 在 Python 中使用 LPC 估计共振峰

python - 比较 2 个字符串列表,更新同一索引位置的第三个字符串列表

python - 评估 Python 中的比较运算符的异常行为