glDrawPixels массива numpy не отображается

1

Я пытаюсь нарисовать игру жизни с opengl. Он отлично работает в обычном pygame, но я читал, что glTexImage2D - это способ быстро нарисовать материал уже в массиве. Я ознакомился с примерами и документами, но не только изрядным количеством ссылок на ссылки, но они были написаны для python 2, поэтому я не могу даже запустить их много, не переведя его. Я заметил, что в отличие от большинства современных графических пакетов, opengl на самом деле ничего не возвращает, поэтому я думаю, что просто не применяю текстуру правильно. (например, в pygame вы создадите поверхность, затем примените возвращаемую поверхность). Код conways работает, принимая живые и мертвые значения и dtype, а затем выполняет всю необходимую проверку, основанную исключительно на аргументах конструктора, что означает, что я могу изменить его с ubyte, чтобы плавать в мгновение ока, поэтому, если это это замечательно.

На данный момент это просто черный экран. Когда pygame.display.flip() удаляется, он просто остается белым, поэтому теоретически что-то рисуется где-то, чтобы изменить его на черный. У меня такое чувство, что проблема кроется в методе glbindtexture, но, честно говоря, я не знаю, что это за решение.

Я положу код conways на всякий случай, если кто-то захочет его запустить. В режиме pygame я масштабирую изображение по переменной масштаба, но для opengl я просто хочу, чтобы он запускался первым, поэтому размер массива контуров теперь будет размером окна, следовательно, 400. Это означает, что это займет немного, но как только заголовок окна будет обновлен, появится индикатор того, что обновление завершено.

выдвижной ящик:

import pygame
from pygame.locals import *

from OpenGL.GL import *
from OpenGL.GLU import *
from random import random,seed
import numpy as np
from conways3 import Conways
from time import time

size = 400;
scale = 1;

conways = Conways(size,dead=0.0,alive=1.0,dtype=np.ubyte)

pygame.init()
flags = OPENGL|HWSURFACE|DOUBLEBUF
display = pygame.display.set_mode((size*scale, size*scale),flags)
########OPTIMIZATIONS##########
pygame.event.set_allowed([pygame.QUIT]);
###############################

running = True

clock = pygame.time.Clock()
t1 = t2 = t3 = 0
glEnable(GL_TEXTURE_2D)
try:
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
        clock.tick()
        t1 = time()
        Z = conways.update()
        t2 = time()
        tid = glGenTextures(1)
        glBindTexture(GL_TEXTURE_2D, tid)
        glPixelStorei(GL_UNPACK_ALIGNMENT,1)
        glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE, size,size,0,GL_LUMINANCE, GL_UNSIGNED_BYTE, Z)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) 

    ##    surf = pygame.surfarray.make_surface(Z)
    ##    display.blit(pygame.transform.scale(surf,(size*scale, size*scale)), (0, 0))
    ##    pygame.display.update()
        pygame.display.flip()
        t3 = time()
        pygame.time.wait(10)
        pygame.display.set_caption("fps: {:.4f} calc: {:.4f} draw: {:.4f} tot: {:.4f}".format(clock.get_fps(), t2-t1, t3-t2,t3-t1))
##        print(t2-t1)
except Exception as e:
    print('-'*20)
    print(e)

pygame.quit()

Conways:

from random import random, seed
import numpy as np
from time import time

class Conways:
    def __init__(self,size,dead=False,alive=True,dtype = np.bool8):
        seed(1)

        self.using1 = True;

        self.size = size;
        self.dead = dead;
        self.alive = alive;
        self.dtype = dtype;

        self.arr1 = np.zeros((self.size,self.size),dtype=self.dtype);
        self.arr2 = np.zeros((self.size,self.size),dtype=self.dtype);

        for i in range(self.size):
                for j in range(self.size):
                        self.arr1[i][j] = self.alive*(random() < 0.5);
    def calcNeighbors(self,arr, i, j):
            count = -1*arr[i][j];    
            for x in range(-1, 2):
                    for y in range(-1, 2):
                            count += (arr[(x+i)%self.size][(y+j)%self.size] == self.alive);
            return count;
    def calcEffi(self,arr, i, j):
            count = 0
            maxi = self.size - 1
            if i > 0:
                    count     += arr[i - 1][j] == self.alive
            if i < maxi:
                    count     += arr[i + 1][j] == self.alive
            if j > 0:
                    count     += arr[i][j - 1] == self.alive
                    if i > 0:
                            count += arr[i - 1][j - 1] == self.alive
                    if i < maxi:
                            count += arr[i + 1][j - 1] == self.alive
            if j < maxi:
                    count     += arr[i][j + 1] == self.alive
                    if i > 0:
                            count += arr[i - 1][j + 1] == self.alive
                    if i < maxi:
                            count += arr[i + 1][j + 1] == self.alive
            return count;

    def calc(self,arr1, arr2):
            for i in range(self.size):
                    for j in range(self.size):
                            neighbors = self.calcEffi(arr1, i, j);
                            if neighbors < 2 or neighbors > 3:
                                    arr2[i][j] = self.dead;
                            elif neighbors == 3:
                                    arr2[i][j] = self.alive;
                            else:
                                    arr2[i][j] = arr1[i][j];
    def update(self):
            if self.using1:
                    self.calc(self.arr1,self.arr2);
            else:
                    self.calc(self.arr2,self.arr1);
            self.using1 = not self.using1;
            return self.arr2 if self.using1 else self.arr1;
Теги:
opengl
pygame
pyopengl

1 ответ

1
Лучший ответ

Поскольку значения массива находятся в диапазоне [0, 1], вы должны использовать float32 соответственно GL_FLOAT:

conways = Conways(size,dead=0.0,alive=1.0,dtype=np.float32)
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, size, size, 0, GL_LUMINANCE, GL_FLOAT, Z)

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

glBindTexture(GL_TEXTURE_2D, tid)
glPixelStorei(GL_UNPACK_ALIGNMENT,1)
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, size,size, 0, GL_LUMINANCE, GL_FLOAT, Z)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) 

glBegin(GL_TRIANGLE_FAN)
glTexCoord2f(0, 1)
glVertex2f(-1, -1) 
glTexCoord2f(1, 1)
glVertex2f(1, -1) 
glTexCoord2f(1, 0)
glVertex2f(1, 1) 
glTexCoord2f(0, 0)
glVertex2f(-1, 1) 
glEnd()

Или используйте glEnableClientState, glVertexPointer, glTexCoordPointer и glDrawArrays для рисования на видовом glDrawArrays:

vertices   = np.array([-1, -1, 1, -1, 1, 1, -1, 1], dtype=np.float32)
tex_coords = np.array([0, 1, 1, 1, 1, 0, 0, 0], dtype=np.float32)

glEnableClientState(GL_VERTEX_ARRAY)
glVertexPointer(2, GL_FLOAT, 0, vertices)
glEnableClientState(GL_TEXTURE_COORD_ARRAY)
glTexCoordPointer(2, GL_FLOAT, 0, tex_coords)

glDrawArrays(GL_TRIANGLE_FAN, 0, 4)

glDisableClientState(GL_VERTEX_ARRAY)
glDisableClientState(GL_TEXTURE_COORD_ARRAY)

Но обратите внимание, что рисование с помощью glBegin/glEnd последовательностей, а также клиентская способность конвейера фиксированной функции OpenGL устарела с десятилетий. Читайте о трубопроводе с фиксированной функциональностью и см. Спецификация вершин и шейдер для современного способа рендеринга.

  • 0
    Большое спасибо, что касается вопроса, который у меня возникло, спасибо, что показали мне, как это делается.
  • 0
    @Neywiny Не за что

Ещё вопросы

Сообщество Overcoder
Наверх
Меню