glDrawPixels массива numpy не отображается - PullRequest
0 голосов
/ 30 ноября 2018

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

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

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

ящик opengl:

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;

1 Ответ

0 голосов
/ 30 ноября 2018

Поскольку значения массива находятся в диапазоне [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 для рисования в области просмотра:

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 устарели с десятилетий.Прочитайте о конвейере с фиксированными функциями и посмотрите Спецификация вершин и Шейдер для современного способа рендеринга.

...