Обработка текстур и изображений с помощью (py) OpenGL - PullRequest
0 голосов
/ 17 января 2019

Я совсем недавно начал проникать в pygame и в конечном итоге в pyOpenGL (используя только два измерения), поскольку рисование изображений на экране происходило из-за заикания в pygame. Тем не менее, я столкнулся с двумя проблемами, которые я, по жизни, не могу понять, как исправить. А именно, обработка двух текстур и обход координатной несовместимости pygame и OpenGL при загрузке изображений.

Я создал простой класс под названием Thingie1:

class Thingie1:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.width = 0
        self.height = 0
        self.sprite = "imageOne.png"
        self.lastsprite = ""
        self.img_data = 0
        self.load()

    def load(self):
        if self.sprite != self.lastsprite:
            im = open(self.sprite)
            self.width, self.height, self.img_data = im.size[0], im.size[1], im.tobytes("raw", "RGB", 0, -1)
            self.lastsprite = self.sprite

            self.Texture = glGenTextures(1)
            glBindTexture(GL_TEXTURE_2D, self.Texture)
            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_MIN_FILTER, GL_LINEAR)
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, self.width, self.height, 0, GL_RGB, GL_UNSIGNED_BYTE, self.img_data)
            glEnable(GL_TEXTURE_2D)
        else:
            return

    def draw(self):
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()
        glTranslate(self.x, self.y, 0)
        glBegin(GL_QUADS)
        glVertex(0, 0, 0)
        glTexCoord2f(0, 0)
        glVertex(self.width, 0, 0)
        glTexCoord2f(0, 1)
        glVertex(self.width, self.height, 0)
        glTexCoord2f(1, 1)
        glVertex(0, self.height, 0)
        glTexCoord2f(1, 0)
        glEnd()
        glFlush()

и точная копия (на данный момент) упомянутого класса, называемая Thingie2. (Функция open() взята из пакета изображений PILLOW (from PIL.Image import open).)

Я тогда позвоню

pygame.init()
pygame.display.set_mode((1024,768), pygame.DOUBLEBUF | pygame.OPENGL)

if True:
    glClearColor(*(0,0,0,255))
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluOrtho2D(0, 1024, 768, 0)
    Thing1 = Thingie1(200,200)
    Thing2 = Thingie2(0,0)

    while True:
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

        Thing2.load()
        Thing1.load()

        Thing2.draw()
        Thing1.draw()
        pygame.display.flip()

нарисовать Thing1 поверх Thing2, что работает частично; раньше, когда функции load() и draw() были объединены в одну, это корректно текстурировало объекты, но не совсем подходило для моего компьютера. Теперь он текстурирует оба экземпляра класса с помощью текстуры Thing2, которая является первой проблемой.

Вторая проблема заключается в том, что нарисованное изображение поворачивается на 180 °. Я пытался использовать matplotlib, cv2 и другие пакеты для загрузки изображения, но ближе всего я подошел к тому, чтобы исправить это, когда я изменил строку glTexImage2D с помощью glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, self.width, self.height, 0, GL_RGB, GL_UNSIGNED_BYTE, self.img_data[::-1]) (используя PIL.Image's open()), но это рисует изображение в оттенках серого + синего (?).

Итак, во-первых , как pyOpenGL вообще обрабатывает текстуры? Я ожидаю, что обе текстуры будут храниться в своих соответствующих self.Texture с. Проблема в том, что они оба связаны с GL_TEXTURE_2D? Как мне отличить две текстуры друг от друга?

Во-вторых , есть ли лучший способ загрузить изображение или есть способ отформатировать байтовый массив изображения таким образом, чтобы его можно было легко перевернуть (это будет работать для изображений RGBA как хорошо)?

1 Ответ

0 голосов
/ 17 января 2019

Обратите внимание, что рисование с помощью glBegin / glEnd последовательностей и набора матриц фиксированных функций устарело с десятилетий. См. конвейер с фиксированными функциями и Legacy OpenGL . Прочитайте о Vertex Specification и Shader , чтобы узнать о современном способе рендеринга.


Теперь он текстурирует оба экземпляра класса с помощью текстуры Thing2, которая является первой проблемой.

Двумерное текстурирование включается glEnable(GL_TEXTURE_2D) и может быть отключено glDisable(GL_TEXTURE_2D).
Если текстурирование включено, то текстура, которая в настоящее время привязана, когда геометрия рисуется с помощью последовательности glBegin / glEnd.

Вы должны связать правильную текстуру, прежде чем рисовать геометрию:

def draw(self):

    # [...]

    glEnable(GL_TEXTURE_2D)
    glBindTexture(GL_TEXTURE_2D, self.Texture)
    glBegin()

    # [...]     

    glEnd()
    glDisable(GL_TEXTURE_2D)

Вторая проблема заключается в том, что нарисованное изображение поворачивается на 180 °

.

Когда вызывается glVertex, текущие координаты текстуры связываются с координатой вершины. Координата текстуры задается как glTexCoord2f.

Это означает, что glTexCoord2f должно быть сделано до glVertex.

glBegin(GL_QUADS)

glTexCoord2f(0, 0)
glVertex(0, 0, 0)

glTexCoord2f(0, 1)
glVertex(self.width, 0, 0)

glTexCoord2f(1, 1)
glVertex(self.width, self.height, 0)

glTexCoord2f(1, 0)
glVertex(0, self.height, 0)

glEnd()
...