python - 使用 PyOpenGL 将不同的纹理添加到不同的对象

标签 python opengl pygame textures pyopengl

我觉得问这个问题有点愚蠢,但我已经尝试了几乎每个例子并证明了每个解决方案。

我正在尝试使用 pyOpenGL 和 pygames 创建一个无尽的运行游戏,并面临许多麻烦,其中之一如下:我正在尝试使用 pyOpenGL 为不同对象渲染 2 个纹理 glBindTexture(GL_TEXTURE_2D, id)。我有一个主要对象,即一个立方体,称为 cube 并且我还有一个立方体数组。我想在 cube 中渲染一个纹理,并在数组中的所有立方体中渲染一个不同的纹理,但每次我尝试执行此操作时,最后一个“渲染”的纹理都会与前一个纹理重叠。我能做什么?

这是我的代码:

# Execute with Python 3

import os
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]
]

textureSurface = pygame.image.load('./textures/ursa.png'), pygame.image.load('./textures/caja.png')
textureData = pygame.image.tostring(textureSurface[0], "RGBA"), pygame.image.tostring(textureSurface[1], "RGBA")
width = textureSurface[0].get_width(), textureSurface[1].get_width()
height = textureSurface[0].get_height(), textureSurface[1].get_height()

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, texture=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.vertices_texture = (
            (0.0, 0.0),
            (1.0, 0.0),
            (1.0, 1.0),
            (0.0, 1.0),
        )
        self.texture = texture
        self.center = [0, 0, 0]

    def draw(self):

        if self.texture:
            glEnable(GL_TEXTURE_2D)
            glColor3f(1, 1, 1)

        glBegin(GL_QUADS)

        if self.texture:
            for surface in self.surfaces:
                for x, vertex in enumerate(surface):
                    glTexCoord2fv(self.vertices_texture[x])
                    glVertex3fv(self.vertices[vertex])
        else:
            for surface in self.surfaces:
                for x, vertex in enumerate(surface):
                    glColor3fv(self.colors[x])
                    glVertex3fv(self.vertices[vertex])

        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
        ]
        glEnd()

        if self.texture:
            glDisable(GL_TEXTURE_2D)

    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

    def rotate(self):
        glPushMatrix()
        glRotatef(25, 1, 0, 0)
        glPopMatrix()

    def loadTexture(self, file):

        glEnable(GL_TEXTURE_2D)
        id = [0]*2
        glGenTextures(2, id)

        if file == 0:
            glBindTexture(GL_TEXTURE_2D, id[0])
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width[0], height[0], 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData[0])
        if file == 1:
            glBindTexture(GL_TEXTURE_2D, id[1])
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width[1], height[1], 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData[1])        

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)

        glDisable(GL_TEXTURE_2D)
        #return texid


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)
    glEnable(GL_BLEND)
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
    glTranslatef(0, -10 / 2.4, -50)

    ground = Ground()

    cube = Cube(True)
    cube.loadTexture(0)
    my_cubes = []

    for i in range(20):
        tmp_cube = Cube(True)
        tmp_cube.loadTexture(1)
        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()
            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()

方法loadTexture应该选择要应用的纹理,但事实并非如此,我不知道为什么。我希望有人能帮助我。谢谢!

最佳答案

当每个立方体都有自己的纹理时,添加一个属性 self.id ,它保存立方体的纹理。

创建此纹理对象并在方法loadTexture()中加载纹理:

class Cube:

    # [...]

    def loadTexture(self, file):

        self.id = glGenTextures(1)

        glBindTexture(GL_TEXTURE_2D, self.id)
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width[file], height[file], 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData[file])

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)

在绘制立方体之前绑定(bind)纹理( glBindTexture ):

class Cube:

    # [...]

    def draw(self):

        if self.texture:
            glEnable(GL_TEXTURE_2D)
            glColor3f(1, 1, 1)
            glBindTexture(GL_TEXTURE_2D, self.id) # <-----

        glBegin(GL_QUADS)

        # [...]

关于python - 使用 PyOpenGL 将不同的纹理添加到不同的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58967457/

相关文章:

python - Mac Mojave 上的 Pygame

python - 是否可以在浏览器中运行 pygame 或 pyglet ?

python - repr 足以防止 Python 中的 shell 注入(inject)吗?

python - 在 Python 中查找独眼巨人数字

python - 在 pandas.to_numeric 中向下转换为 float16

ios - 如何以编程方式在 SceneKit 中围绕立方体包装 png 纹理

c++ - 什么 OpenGL 函数在顶点着色器之前修改顶点位置?

python - 使用 Cython 传递 int 和 struct 包装 C 代码的最小示例

opengl - 使用 CMake 将 stb_image 包含到 OpenGL 项目中

python - 我怎样才能得到 Sprite 在pygame中的位置坐标?