【问题标题】:PyOpenGL texture isn't displaying correctlyPyOpenGL 纹理未正确显示
【发布时间】:2021-09-28 17:54:32
【问题描述】:

我试图用这段代码将纹理放到四边形上:

import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
from PIL import Image
from numpy import array

def loadTexture(texture):
    try:
        text = Image.open(texture)
    except IOError as ex:
        print("Failed to open texture file: ", texture)
        text = Image.open("0.png")

    textData = array(list(text.getdata()))
    textID = glGenTextures(1)
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
    glBindTexture(GL_TEXTURE_2D, textID)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0)
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, text.size[0], text.size[1], 0, GL_RGB, GL_UNSIGNED_BYTE, textData)
    text.close()
    return textID

def drawQuad(centerX, centerY, textureID):
    verts = (
        (centerX+1,centerY+1),
        (centerX+1,centerY-1),
        (centerX-1,centerY-1),
        (centerX-1,centerY+1)
    )

    surf = (0, 1, 2, 3)

    glEnable(GL_TEXTURE_2D)
    glBindTexture(GL_TEXTURE_2D, textureID)

    glBegin(GL_QUADS)
    for vert in surf:
        glVertex2f(verts[vert][0],verts[vert][1])
        glTexCoord2f(verts[vert][0],verts[vert][1])
    glEnd()
    glDisable(GL_TEXTURE_2D)

def main():
    pygame.init()
    disp = (800,800)
    pygame.display.set_mode(disp, DOUBLEBUF|OPENGL)
    gluPerspective(45, (disp[0] / disp[1]), 0.1, 50.0)
    glTranslatef(0.0, 0.0, -5)
    textID = loadTexture("0.png")

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        drawQuad(0, 0, textID)
        pygame.display.flip()
        pygame.time.wait(10)

但是在加载纹理并循环运行drawQuad() 之后,我的屏幕上出现了这个混乱:

https://i.stack.imgur.com/5UMCf.png(由于愚蠢的信誉系统,无法直接嵌入图像)

如果这很重要,纹理文件格式为 .png,大小为 32x32

【问题讨论】:

  • 在 drawQuad() 中(glVertex2f() 和 glTexCoord2f() )

标签: python opengl pygame pyopengl


【解决方案1】:

glVertex:

[...] 调用glVertex 时,当前颜色、法线、纹理坐标和雾坐标与顶点相关联。

因此,需要在指定顶点坐标之前指定纹理坐标。
纹理坐标必须在 [0.0, 1.0] 范围内(参见How do opengl texture coordinates work?):

def drawQuad(centerX, centerY, textureID):
    verts = (
        (centerX+1,centerY+1),
        (centerX+1,centerY-1),
        (centerX-1,centerY-1),
        (centerX-1,centerY+1)
    )
    texts = ((1, 0), (1, 1), (0, 1), (0, 0))
    surf = (0, 1, 2, 3)

    glEnable(GL_TEXTURE_2D)
    glBindTexture(GL_TEXTURE_2D, textureID)

    glBegin(GL_QUADS)
    for i in surf:
        glTexCoord2f(texts[i][0], texts[i][1])
        glVertex2f(centerX + verts[i][0], centerY + verts[i][1])
    glEnd()
    
    glDisable(GL_TEXTURE_2D)

PNG (Portable Network Graphics) 图像由 4 个通道、3 个颜色通道和 Alpha 通道组成。图像格式需要为GL_RGBA 而不是GL_RGB

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, text.size[0], text.size[1], 0, GL_RGB, GL_UNSIGNED_BYTE, textData)

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, text.size[0], text.size[1], 0, GL_RGBA, GL_UNSIGNED_BYTE, textData)

完整的例子如下图

import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
from PIL import Image
from numpy import array

def loadTexture(texture):
    try:
        text = Image.open(texture)
    except IOError as ex:
        print("Failed to open texture file: ", texture)
        text = Image.open("0.png")

    textData = array(list(text.getdata()))
    textID = glGenTextures(1)
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
    glBindTexture(GL_TEXTURE_2D, textID)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0)
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, text.size[0], text.size[1], 0, GL_RGBA, GL_UNSIGNED_BYTE, textData)
    text.close()
    return textID

def drawQuad(centerX, centerY, textureID):
    verts = (
        (centerX+1,centerY+1),
        (centerX+1,centerY-1),
        (centerX-1,centerY-1),
        (centerX-1,centerY+1)
    )
    texts = ((1, 0), (1, 1), (0, 1), (0, 0))
    surf = (0, 1, 2, 3)

    glEnable(GL_TEXTURE_2D)
    glBindTexture(GL_TEXTURE_2D, textureID)

    glBegin(GL_QUADS)
    for i in surf:
        glTexCoord2f(texts[i][0], texts[i][1])
        glVertex2f(centerX + verts[i][0], centerY + verts[i][1])
    glEnd()
    
    glDisable(GL_TEXTURE_2D)

def main():
    pygame.init()
    disp = (200, 200)
    pygame.display.set_mode(disp, DOUBLEBUF|OPENGL)
    gluPerspective(45, (disp[0] / disp[1]), 0.1, 50.0)
    glTranslatef(0.0, 0.0, -5)
    textID = loadTexture("0.png")

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        drawQuad(0, 0, textID)
        pygame.display.flip()
        pygame.time.wait(10)
        
main()

【讨论】:

  • @ilinm 我已经扩展了答案。
  • 仍然画出彩虹般的混乱。
  • @ilinm 否。事实并非如此,您可以在我的示例中清楚地看到。您需要做的就是复制/粘贴代码。
  • @ilinm 它对我来说很好用。我不知道你做错了什么。请注意,有内部格式和格式参数。第二个是最重要的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-12-29
  • 2021-09-30
  • 2011-08-06
  • 2014-08-18
  • 1970-01-01
  • 2021-07-17
  • 2023-02-03
相关资源
最近更新 更多