带纹理的 PyOpenGL 球体

PyOpenGL sphere with texture

我想使用 Python PyOpenGL 生成三个球体的场景。两个在有颜色的一侧(红色和绿色)。中间一个上面有任何纹理(砖块纹理实际上是与代码位于同一目录中的方形 jpg 文件)。

到目前为止我已经做了:

由于某些原因,gluSphere() 生成的中间球体中的纹理有奇怪的行为。有一些小的绿色三角形而不是我的纹理文件。

这是我的纹理文件:

我试图将此文件映射为表面,例如中间球体上的纹理。不知道问题出在哪里

这是我的代码,我不知道我错过了什么或者在中间球体上获得正确的纹理映射有什么问题:

from OpenGL.GLUT import *
from OpenGL.GLU import *
from OpenGL.GL import *
import sys
from PIL import Image as Image
import numpy

name = 'Navigation paradigm'

def main():
    glutInit(sys.argv)
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH)
    glutInitWindowSize(800, 800)
    glutInitWindowPosition(350, 200)
    glutCreateWindow(name)
    glClearColor(0., 0., 0., 1.)
    glShadeModel(GL_SMOOTH)
    glEnable(GL_CULL_FACE)
    glEnable(GL_DEPTH_TEST)
    glEnable(GL_LIGHTING)
    lightZeroPosition = [10., 4., 10., 1.]
    lightZeroColor = [0.8, 1.0, 0.8, 1.0]
    glLightfv(GL_LIGHT0, GL_POSITION, lightZeroPosition)
    glLightfv(GL_LIGHT0, GL_DIFFUSE, lightZeroColor)
    glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0.1)
    glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.05)
    glEnable(GL_LIGHT0)
    glutDisplayFunc(display_scene)
    glMatrixMode(GL_PROJECTION)
    gluPerspective(40., 1., 1., 40.)
    glMatrixMode(GL_MODELVIEW)
    gluLookAt(0, 0, 10,
              0, 0, 0,
              0, 1, 0)
    glPushMatrix()
    glutMainLoop()
    return

def display_scene():
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glPushMatrix()
    # Textured thing 
    tex = read_texture('brick.jpg')
    qobj = gluNewQuadric()
    gluQuadricTexture(qobj, GL_TRUE)
    glEnable(GL_TEXTURE_2D)
    glBindTexture(GL_TEXTURE_2D, tex)
    glBegin(GL_TRIANGLES)
    gluSphere(qobj, 1, 50, 50)
    gluDeleteQuadric(qobj)
    glDisable(GL_TEXTURE_2D)
    # Left sphere
    color = [1.0, 0.0, 0.0, 1.0]
    glMaterialfv(GL_FRONT, GL_DIFFUSE, color)
    glTranslatef(-2, 0, 0)
    glutSolidSphere(1, 100, 20)
    # Right sphere
    color = [0.0, 1.0, 0.0, 1.0]
    glMaterialfv(GL_FRONT, GL_DIFFUSE, color)
    glTranslatef(4, 0, 0)
    glutSolidSphere(1, 100, 20)
    glPopMatrix()
    glutSwapBuffers()
    return

def read_texture(filename):
    img = Image.open(filename)
    img_data = numpy.array(list(img.getdata()), numpy.int8)
    textID = glGenTextures(1)
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)
    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)
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL)
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img.size[0], img.size[1], 0, GL_RGB, GL_UNSIGNED_BYTE, img_data)
    return textID

if __name__ == '__main__':
    main()

但是手头有一个稍微不同的"problem"。所以以防万一其他人有同样的问题,我会回答它。

首先,如评论中所述,您不需要调用 glBegin()。因为 gluSphere() 已经做到了。此外,如果您要调用 glBegin(),您还需要调用 glEnd()。所以你看到某些东西的原因,基本上是因为你混淆了你的驱动程序,然后它做了一些它不应该做的事情。

In read_texture() after you generate a texture name you don't bind it. So the subsequent texture related calls are going to the default texture and not your newly created texture.

textID  = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, textID) # This is what's missing

添加缺失的 glBindTexture() 调用后,您将得到如下所示的结果。

现在看起来可能有点奇怪,而且看起来有些不对劲。但事实是一切都在按预期进行。问题在于纹理本身。

"problem" 是您的砖块纹理不是球形贴图纹理。如果我们现在只用球形映射纹理替换您的砖块纹理,那么我们将得到以下结果。

这是上面使用的球形映射纹理: