numpy 数组的 glDrawPixels 没有显示
glDrawPixels of numpy array not showing up
我正在尝试用opengl画康威的人生游戏。它在常规 pygame 中工作正常,但我读到 glTexImage2D 是快速绘制数组中已有内容的方法。我检查了 the examples and docs provided 但不仅有相当数量的示例链接已失效,而且它们是为 python 2 编写的,所以我什至无法 运行 很多不翻译它。我注意到,与大多数现代 GUI 包不同,opengl 并没有真正 return 任何东西,所以我认为我只是没有正确应用纹理。 (例如,在 pygame 中,您将生成曲面,然后应用 returned 曲面)。 conways 代码的工作原理是接收 alive 和 dead 值以及 dtype,然后仅根据构造函数参数进行所有必要的检查,这意味着我可以在眨眼间将它从 ubyte 更改为 float,所以如果那是很棒的问题。
目前只是黑屏。当 pygame.display.flip() 被移除时,它只是保持白色,所以理论上在某处绘制了一些东西以将其更改为黑色。我感觉问题出在 glbindtexture 方法上,但老实说我不知道解决方案是什么。
我会把 conways 代码放在一起,以防万一有人想要 运行。在 pygame 模式下,我通过 scale 变量缩放图像,但对于 opengl 我只想先 运行ning 所以 conways 数组的大小现在将是 window 大小,因此是 400。这意味着它需要一点时间,但是一旦 window 标题更新,这表明更新已经完成。
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()
康威:
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;
由于数组值在[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
and 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 固定功能管道的客户端功能已被弃用。
阅读 Fixed Function Pipeline and see Vertex Specification and Shader 了解最先进的渲染方式。
我正在尝试用opengl画康威的人生游戏。它在常规 pygame 中工作正常,但我读到 glTexImage2D 是快速绘制数组中已有内容的方法。我检查了 the examples and docs provided 但不仅有相当数量的示例链接已失效,而且它们是为 python 2 编写的,所以我什至无法 运行 很多不翻译它。我注意到,与大多数现代 GUI 包不同,opengl 并没有真正 return 任何东西,所以我认为我只是没有正确应用纹理。 (例如,在 pygame 中,您将生成曲面,然后应用 returned 曲面)。 conways 代码的工作原理是接收 alive 和 dead 值以及 dtype,然后仅根据构造函数参数进行所有必要的检查,这意味着我可以在眨眼间将它从 ubyte 更改为 float,所以如果那是很棒的问题。
目前只是黑屏。当 pygame.display.flip() 被移除时,它只是保持白色,所以理论上在某处绘制了一些东西以将其更改为黑色。我感觉问题出在 glbindtexture 方法上,但老实说我不知道解决方案是什么。
我会把 conways 代码放在一起,以防万一有人想要 运行。在 pygame 模式下,我通过 scale 变量缩放图像,但对于 opengl 我只想先 运行ning 所以 conways 数组的大小现在将是 window 大小,因此是 400。这意味着它需要一点时间,但是一旦 window 标题更新,这表明更新已经完成。
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()
康威:
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;
由于数组值在[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
and 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 固定功能管道的客户端功能已被弃用。
阅读 Fixed Function Pipeline and see Vertex Specification and Shader 了解最先进的渲染方式。