问题描述
我尝试了一切,但仍然没有得到我的错误.我正在尝试在球体对象上放置纹理.
I tried everything but still I don't get my error. I am trying to put a texture on my sphere object.
"""
Minimal texture on sphere demo
This is demo for showing how to put image
on sphere as texture in PyOpenGL.
"""
from OpenGL.GLUT import *
from OpenGL.GLU import *
from OpenGL.GL import *
from PIL import Image
import numpy
def run_scene():
glutInit()
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH)
glutCreateWindow("Minimal sphere OpenGL")
lightning()
glutDisplayFunc(draw_sphere)
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 lightning():
glEnable(GL_DEPTH_TEST)
glEnable(GL_LIGHTING)
glEnable(GL_BLEND)
glLightfv(GL_LIGHT0, GL_POSITION, [10, 4, 10, 1])
glLightfv(GL_LIGHT0, GL_DIFFUSE, [0.8, 1, 0.8, 1])
glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0.1)
glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.05)
glEnable(GL_LIGHT0)
return
def draw_sphere():
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glPushMatrix()
texture_id = read_texture('mars.png')
glEnable(GL_TEXTURE_2D)
glBindTexture(GL_TEXTURE_2D, texture_id)
glEnable(GL_TEXTURE_GEN_S)
glEnable(GL_TEXTURE_GEN_T)
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP)
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP)
glutSolidSphere(1, 50, 50)
glDisable(GL_TEXTURE_2D)
glPopMatrix()
glutSwapBuffers()
return
def read_texture(filename):
img = Image.open(filename)
img_data = numpy.array(list(img.getdata()), numpy.int8)
texture_id = 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 texture_id
if __name__ == '__main__':
run_scene()
这是此代码的结果,简单的绿色球体如下:
This is result of this code, simple green sphere as this:
但这不是我的预期结果.我只想在球体表面上显示此纹理mars.png
:
But this is not my expected result. I want to simply show this texture mars.png
on sphere surface:
帮我解决这个问题,看来我无法靠自己解决.
Help me with this I cannot solve this on my own it seems.
推荐答案
在read_texture()
中,生成纹理名称后,您无需绑定它.因此,后续与纹理相关的调用将转到默认纹理,而不是您新创建的纹理.
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.
texture_id = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, texture_id) # This is what's missing
此外,由于您的图像是PNG图像.然后list(img.getdata())
将是包含(R, G, B, A)
的元组的列表.因此,在调用glTexImage2D
时,您需要告诉您数据是GL_RGBA
而不是GL_RGB
.
Also since your image is a PNG image. Then list(img.getdata())
will be a list of tuples containing (R, G, B, A)
. So when calling glTexImage2D
you need to tell that your data is GL_RGBA
and not GL_RGB
.
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img.size[0], img.size[1], 0,
GL_RGBA, GL_UNSIGNED_BYTE, img_data)
您还可以使其自动化.
format = GL_RGB if img.mode == "RGB" else GL_RGBA
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img.size[0], img.size[1], 0,
format, GL_UNSIGNED_BYTE, img_data)
您也可以将其转换为不具有Alpha通道.
You can also convert it to not have an alpha channel.
img = img.convert("RGB")
当然需要在调用img.getdata()
之前完成.
Which of course needs to be done before calling img.getdata()
.
现在您应该看到以下内容:
Now you should see the following:
也是一个重要的注意事项.您正在draw_sphere()
中呼叫read_texture()
.这意味着每次调用draw_sphere()
时,都会加载图像并创建新的纹理.您真的不想这样做.而是在调用glutMainLoop()
之前调用read_texture()
并将结果存储为全局名称.
Also an important note. You're calling read_texture()
in draw_sphere()
. This means that every time draw_sphere()
is called, the image is loaded and a new texture is created. You really don't want to do that. Instead before calling glutMainLoop()
call read_texture()
and store the result as a global name.
这篇关于为什么我的纹理没有显示PyOpenGL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!