简体   繁体   English

在 Python 中使用 OpenGL 渲染纹理不是

[英]Rendering a texture with OpenGL in Python is not

I want to render a texture (using a.png) using the next code:我想使用下面的代码渲染纹理(使用 a.png):

Everything goes well until I uncomment object_cube.loadTextures()一切顺利,直到我取消注释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()

The main problem I got is that I get a little cube with the rendered image, but the rest is black.我遇到的主要问题是我得到了一个带有渲染图像的小立方体,但 rest 是黑色的。 I don't know what happens with the rest of the elements it should draw.我不知道它应该绘制的元素的 rest 会发生什么。

If texturing is enabled, then by default the color of the texel is multiplied by the current color, because by default the texture environment mode ( GL_TEXTURE_ENV_MODE ) is GL_MODULATE .如果启用了纹理,则默认情况下纹理元素的颜色乘以当前颜色,因为默认情况下纹理环境模式( GL_TEXTURE_ENV_MODE )是GL_MODULATE See glTexEnv .请参阅glTexEnv
This causes that the color of the texels of the texture is "mixed" by the last color which you have set by glColor3fv .这会导致纹理纹素的颜色与您设置的最后一种颜色“混合” glColor3fv

Set a "white" color before you render the textured objects:在渲染纹理对象之前设置“白色”颜色:

glColor3f(1, 1, 1)

Two-dimensional texturing is enabled by glEnable(GL_TEXTURE_2D) and can be disabled by glDisable(GL_TEXTURE_2D) .二维纹理由glEnable(GL_TEXTURE_2D)启用,可以由glDisable(GL_TEXTURE_2D)禁用。
If texturing is enables then the texture wich is currently bound when the geometry is drawn by the glBegin / glEnd sequence is applied.如果启用了纹理,则应用glBegin / glEnd序列绘制几何图形时当前绑定的纹理。

If you've want to draw objects which are textured, and other objects which are not, then you've to enable texturing before the object is drawn and to disable it after:如果您想绘制带纹理的对象和其他没有纹理的对象,那么您必须在绘制 object 之前启用纹理并在之后禁用它:

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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM