在 Python 中使用 OpenGL 渲染纹理不是
Posted
技术标签:
【中文标题】在 Python 中使用 OpenGL 渲染纹理不是【英文标题】:Rendering a texture with OpenGL in Python is not 【发布时间】:2019-11-19 23:29:41 【问题描述】:我想使用下面的代码渲染纹理(使用 .png):
一切顺利,直到我取消注释 object_cube.loadTextures()
# Execute with Python 3
import pygame
import random
import math
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
camera_x = 0
camera_z = 0
camera_y = 0
x = 0
Vertices = [
[1, -1, 1],
[-1, -1, 1],
[-1, -1, -1],
[1, -1, -1],
[1, 1, -1],
[-1, 1, -1],
[-1, 1, 1],
[1, 1, 1]
]
class Ground:
global camera_z
def __init__(self):
self.ground_vertices = (
(-11, -2.01, 20),
(11, -2.01, 20),
(11, -2.01, -300),
(-11, -2.01, -300)
)
def draw(self):
glPushMatrix()
glTranslatef(0, 0, camera_z)
glBegin(GL_QUADS)
for vertex in self.ground_vertices:
glColor3fv((0, 0.5, 0.5))
glVertex3fv(vertex)
glEnd()
glPopMatrix()
class Cube:
def __init__(self, v=False):
self.vertices = [
[1, -1, 1],
[-1, -1, 1],
[-1, -1, -1],
[1, -1, -1],
[1, 1, -1],
[-1, 1, -1],
[-1, 1, 1],
[1, 1, 1]
]
self.surfaces = (
(0, 1, 6, 7),
(0, 1, 2, 3),
(0, 3, 4, 7),
(1, 2, 6, 5),
(2, 3, 4, 5),
(4, 5, 6, 7)
)
self.colors = (
(105 / 255, 210 / 255, 231 / 255),
(167 / 255, 219 / 255, 216 / 255),
(224 / 255, 228 / 255, 204 / 255),
(243 / 255, 134 / 255, 48 / 255)
)
self.colors2 = (
(0.91, 0.31, 0.47),
(0.84, 0.51, 0.54),
(0.78, 0.64, 0.6),
(0.78, 0.9, 0.85)
)
self.vertices_texture = (
(0.0, 0.0),
(1.0, 0.0),
(1.0, 1.0),
(0.0, 1.0),
)
self.v = v
self.center = [0, 0, 0]
def draw(self):
glBegin(GL_QUADS)
if not self.v:
for surface in self.surfaces:
x = 0
for vertex in surface:
glColor3fv(self.colors2[x])
# glTexCoord2f(self.vertices_texture[x])
glVertex3fv(self.vertices[vertex])
x += 1
else:
for surface in self.surfaces:
x = 0
for vertex in surface:
glColor3fv(self.colors[x])
glTexCoord2fv(self.vertices_texture[x])
glVertex3fv(self.vertices[vertex])
x += 1
glEnd()
def set_vertices(self, max_distance, min_distance=-40):
x_value_change = random.randrange(-10, 10)
y_value_change = -1
z_value_change = random.randrange(-1 * max_distance, min_distance)
new_vertices = []
for vertex in Vertices:
new_vertex = []
new_x = vertex[0] + x_value_change
new_y = vertex[1] + y_value_change
new_z = vertex[2] + z_value_change
new_vertex.append(new_x)
new_vertex.append(new_y)
new_vertex.append(new_z)
new_vertices.append(new_vertex)
self.vertices = new_vertices
self.center = [
(self.vertices[2][0]+self.vertices[7][0])/2,
(self.vertices[2][1]+self.vertices[7][1])/2,
(self.vertices[2][2]+self.vertices[7][2])/2
]
def rotate(self):
glPushMatrix()
glRotatef(25, 1, 0, 0)
glPopMatrix()
def loadTexture(self):
textureSurface = pygame.image.load('./textures/ursa.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)
# return texid
def movInverse(event):
global x
y = 0
if event.type == pygame.KEYDOWN:
if(math.fabs(x) < 11):
if event.key == pygame.K_LEFT:
x -= 1
if event.key == pygame.K_RIGHT:
x += 1
else:
if(x < 0):
if event.key == pygame.K_RIGHT:
x += 1
else:
if event.key == pygame.K_LEFT:
x -= 1
if event.key == pygame.K_UP:
y += 1
if event.key == pygame.K_DOWN:
y -= 1
glTranslatef(0, y, 0)
def leave(event):
if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key == K_ESCAPE):
pygame.quit()
quit()
def main():
global camera_x, camera_y, camera_z, x
pygame.init()
display = (800, 600)
pygame.display.set_mode(display, DOUBLEBUF | OPENGL | OPENGLBLIT)
max_distance = 300
gluPerspective(45, (display[0] / display[1]), 0.1, max_distance)
glEnable(GL_DEPTH_TEST)
glTranslatef(0, -10 / 2.4, -50)
ground = Ground()
cube = Cube(True)
# cube.loadTexture()
# I want to render the texture here, but when I do it, everything get screwed.
my_cubes = []
for i in range(50):
tmp_cube = Cube()
# tmp_cube.loadTexture()
# I also tried to render it here, but I got the same result
tmp_cube.set_vertices(max_distance)
my_cubes.append(tmp_cube)
while True:
for event in pygame.event.get():
leave(event)
movInverse(event)
M = glGetDoublev(GL_MODELVIEW_MATRIX)
# print(M)
camera_x = M[3][0]
camera_y = M[3][1]
camera_z = M[3][2]
glTranslatef(0, 0, 1.5)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
ground.draw()
glPushMatrix()
if(math.fabs(x) < 11):
glTranslatef(x, -1.5, camera_z-20)
glScalef(1 / 2, 1 / 2, 0)
cube.draw()
glPopMatrix()
for tmp_cube in my_cubes:
tmp_cube.draw()
tmp_cube.center[2] += camera_z
print(tmp_cube.center)
for tmp_cube in my_cubes:
if camera_z <= tmp_cube.vertices[0][2]:
new_max = int(-1 * (camera_z - max_distance * 2))
tmp_cube.set_vertices(new_max, int(camera_z - max_distance))
pygame.display.flip()
if __name__ == '__main__':
main()
我遇到的主要问题是渲染图像有一个小立方体,但其余部分是黑色的。我不知道它应该绘制的其余元素会发生什么。
【问题讨论】:
【参考方案1】:如果启用纹理,则默认情况下纹理元素的颜色乘以当前颜色,因为默认情况下纹理环境模式 (GL_TEXTURE_ENV_MODE
) 为GL_MODULATE
。见glTexEnv
。
这会导致纹理纹理像素的颜色与您设置的最后一个颜色“混合”glColor3fv
。
在渲染纹理对象之前设置“白色”颜色:
glColor3f(1, 1, 1)
二维纹理由glEnable(GL_TEXTURE_2D)
启用,可以由glDisable(GL_TEXTURE_2D)
禁用。
如果启用了纹理,则应用glBegin
/glEnd
序列绘制几何时当前绑定的纹理。
如果你想绘制有纹理的对象,而其他没有纹理的对象,那么你必须在绘制对象之前启用纹理并在之后禁用它:
class Cube:
# [...]
def draw(self):
if self.v:
glEnable(GL_TEXTURE_2D)
glColor3f(1, 1, 1)
glBegin(GL_QUADS)
if not self.v:
for surface in self.surfaces:
for x, vertex in enumerate(surface):
glColor3fv(self.colors2[x])
glVertex3fv(self.vertices[vertex])
else:
for surface in self.surfaces:
for x, vertex in enumerate(surface):
glTexCoord2fv(self.vertices_texture[x])
glVertex3fv(self.vertices[vertex])
glEnd()
if self.v:
glDisable(GL_TEXTURE_2D)
【讨论】:
嗨。您提出的解决方案有效,我对此表示感谢,但我还有另一个问题,我如何渲染多个纹理?也就是说,一旦最后一个纹理被加载,它就会与上面的另一个“加载”重叠。我在不同的对象中加载了一个新的“纹理”,但它不起作用。 @AnthonyLuzquiños 您所要做的就是在绘制四边形之前绑定正确的纹理对象 (glBindTexture(GL_TEXTURE_2D, texid)
)。如果您有超过 1 个纹理,那么您必须为每个纹理创建 1 个纹理对象(例如 texid1
、texid2
、...)以上是关于在 Python 中使用 OpenGL 渲染纹理不是的主要内容,如果未能解决你的问题,请参考以下文章