2013-02-24 22 views
9

Tôi đang bắt đầu sử dụng OpenGL 4 bằng Python (thông qua Pyglet và một số mã khung tôi đã thoát khỏi mạng/viết bản thân để tải Shaders/Programs), nhưng tôi nghĩ rằng tôi hiểu những điều khá tốt, vì vậy tôi không nghĩ rằng có một vấn đề ở đâu đó trong mã của tôi.Các vấn đề với OpenGL 4 VBO và mảng Numpy, Pyglet/Python

Vì vậy, vấn đề của tôi là gì? Dường như khi một trong hai mảng numpy hoặc bộ đệm đạt đến một kích thước nhất định, những điều kỳ lạ xảy ra khi tôi đang vẽ. Hãy nhìn vào hình ảnh liên kết để xem những gì tôi có ý nghĩa. http://i.imgur.com/8Oym6VA.png?1

Trên ảnh, bạn có thể thấy rằng tôi đang vẽ một số "Robot", mỗi ô được tạo thành từ 8 hộp. Dữ liệu cho rô bốt được tính một lần, sử dụng dữ liệu chỉ số đỉnh/màu/chỉ số Cube cơ bản và sau đó được dịch/thu nhỏ/xoay một cách thích hợp và nối vào một mảng lớn hơn. Trong hình bên trái tôi vẽ 172 của những robot đó trong một VAO, hình ảnh bên phải có 173 rô bốt. Như bạn có thể thấy, những thứ kỳ lạ xảy ra khi tôi đi qua con số "huyền diệu" đó. Có vẻ như tất cả các đỉnh được kết nối bằng cách nào đó với điểm đầu tiên được vẽ trên màn hình (phần trên bên phải của phần đầu tiên của rô bốt được vẽ "cơ thể"). Nếu tôi di chuyển con robot đầu tiên ở một nơi khác, tất cả các điểm vẫn được kết nối với điểm đó - để minh họa rằng tôi đã đảm bảo rằng điểm trong hình không được căn giữa đến (0,0,0) hoặc một cái gì đó tương tự. Ảnh bên trái có dữ liệu đỉnh và màu với nổi 131328, dữ liệu chỉ mục dài 49248. Hình ảnh bên phải có dữ liệu đỉnh và màu với 132096 nổi trong khi dữ liệu chỉ mục là 49536 phao dài. Nếu tôi chia dữ liệu thành nhiều hơn thì một VAO, sau đó tôi có thể dễ dàng rút 100 lần giá trị của robot (với 100 VAO tất nhiên) mà không gặp bất kỳ vấn đề gì (thậm chí 1000 lần giá trị của robot với 1000 VAO nhiều bộ nhớ và làm việc với khoảng 0,2 FPS).

Để kiểm tra xem có điều gì sai với các lớp Pyglets (hay của riêng tôi), tôi cũng viết lại toàn bộ nội dung với các cuộc gọi OpenGL và tôi gặp phải vấn đề tương tự. Vì vậy, các VBO chỉ đơn giản là không có nghĩa là lớn (tôi bằng cách nào đó nghi ngờ rằng VBOs chỉ có thể có khoảng 17k hình tam giác mỗi)? Hay nó có liên quan đến Numpy (Tôi đã từng làm việc với các mảng lớn hơn ở Numpy trước đây và tôi không nhớ có vấn đề gì)? Oh btw, kích thước của phao không có vẻ quan trọng (cùng một điều sẽ xảy ra nếu tất cả các đỉnh nằm trong thang [-1,1] nếu đi lên [-35000, 35000].

I ' Tôi đã tìm kiếm chủ đề khá rộng rãi nhưng tôi đã không tìm thấy bất cứ thứ gì tương tự trong tìm kiếm của tôi - nếu có, tôi xin lỗi.Tất cả những gì tôi có thể tìm thấy là MemoryError khi sử dụng các mảng rất lớn, nhưng mảng của tôi không ở gần kích thước cần thiết . sản xuất mà

hệ thống thông số kỹ thuật của tôi là:

  • Intel Core i7
  • Nvidia GeForce GTX 465
  • Windows 8 64-bit
  • Python 3.3 (64-bit)
  • Pyglet 1.2alpha1
  • NumPy gói nhị phân cho Python 3.3 64-bit từ here

Và trong khi tôi gần như chắc chắn không có gì sai với mã của tôi, tôi vẫn popping các đoạn có liên quan đến bản vẽ ở đây (một lần nữa, tôi đã thử nó với các cuộc gọi cơ bản OpenGL quá và nó đã không làm việc tốt hơn).

Trước hết, tôi có một lớp "Trình xử lý", có nghĩa là lưu trữ nhiều dữ liệu tĩnh để tôi có thể vẽ nó bằng một cuộc gọi glDraw * (ví dụ cấp độ của trò chơi hoặc thứ gì đó tương tự).Nó tạo ra có các phương thức để thêm vào dữ liệu của nó, một phương thức để khởi tạo các VBO và VAO của nó và một hàm vẽ, mà lấy một chồng và vẽ lên nó. Nó cũng nhận được chương trình (vertex/color shader) mà nó vẽ.

class Handler: 
def __init__(self, program): 
    self.vertexData = numpy.array((), dtype=GLfloat) 
    self.colorData = numpy.array((), dtype=GLfloat) 
    self.indexData = numpy.array((), dtype=GLshort) 

    self.program = program 

def initBuffers(self): 
    self.vao = GLuint() 
    glGenVertexArrays(1, self.vao) 
    glBindVertexArray(self.vao) 

    #======================================================================= 
    # Vertices 
    #======================================================================= 
    self.vertexBufferObject = pyglet.graphics.vertexbuffer.create_buffer(self.vertexData.nbytes, GL_ARRAY_BUFFER, GL_STATIC_DRAW) 
    self.vertexBufferObject.bind() 
    self.vertexBufferObject.set_data(self.vertexData.ctypes.data) 
    glEnableVertexAttribArray(0) 
    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0) 

    #======================================================================= 
    # Color 
    #======================================================================= 
    self.colorBufferObject = pyglet.graphics.vertexbuffer.create_buffer(self.colorData.nbytes, GL_ARRAY_BUFFER, GL_STATIC_DRAW) 
    self.colorBufferObject.bind() 
    self.colorBufferObject.set_data(self.colorData.ctypes.data) 
    glEnableVertexAttribArray(1) 
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0) 

    #======================================================================= 
    # Index 
    #======================================================================= 
    self.indexBufferObject = pyglet.graphics.vertexbuffer.create_buffer(self.indexData.nbytes, GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW) 
    self.indexBufferObject.bind() 
    self.indexBufferObject.set_data(self.indexData.ctypes.data) 

    glBindBuffer(GL_ARRAY_BUFFER, 0) 
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) 
    glBindVertexArray(0) 

    self.len = len(self.indexData) 

def addTo(self, vertices, color = None, index = None): 
    if(color != None): 
     self.colorData = numpy.append(self.colorData, color) 
    if(index != None): 
     self.indexData = numpy.append(self.indexData, index + len(self.vertexData)//4) 
    self.vertexData = numpy.append(self.vertexData, vertices) 

def draw(self, stack): 
    glBindVertexArray(self.vao) 
    self.indexBufferObject.bind() 
    self.program.install() 

    stack.push() 
    self.program.usetM4F("modelToWorldMatrix", stack.ready(), row = GL_FALSE) 
    glDrawElements(GL_TRIANGLES, self.len, GL_UNSIGNED_SHORT, 0) 
    stack.pop() 
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) 
    glBindVertexArray(0) 
    self.program.uninstall() 

Và tôi khởi xử lý với một số mã rất đơn giản, nơi translateMatrix (x, y, z) trả về một dịch ma trận và applyTrans (cơ sở, trans) áp dụng xuyên để mỗi vertice (x, y, z, w) trong cơ sở.

self.handler = Handler(self.ObjectColor) 
    for i in range(1,n): 
     self.handler.addTo(applyTrans(self.robots.vertexData, translateMatrix(2*i*(-1)**(i//2), 1.5*i*(-1)**i, 0.5*i*(-1)**i)), self.robots.colorData, self.robots.indexData) 
self.handler.initBuffers() 

Và gọi nó là ở phần on_draw của Pyglet Window với

self.handler.draw() 

UPDATE:

Tôi đã phát hiện ra vấn đề là gì và tôi cảm thấy hoàn toàn và hoàn toàn ngu ngốc nay : P. Dường như tôi đã quên chỉ định kiểu dtype của một trong các mảng cứng nhắc, và nó được mặc định là 'int32'. Vì tôi đã vẽ với cờ GL_UNSIGNED_SHORT (aka 'uint16'), nó đã trở thành một vấn đề. Bây giờ tôi đã đảm bảo rằng nó vẫn 'uint16' càng lâu càng tốt (cho đến khi tối đa dữ liệu chỉ mục được cao hơn sau đó 2^16) và thêm một kiểm tra để xem indexData là 'uint16' hoặc 'uint32' và thêm cờ thích hợp trên lệnh glDraw.

Điều này dường như đã sửa nó, vì bây giờ tôi có thể dễ dàng thêm một vài nghìn (cố gắng với 5.000 max) robot vào một VBO và nó vẫn hoạt động.

Điều tôi vẫn chưa hiểu, là lý do tại sao nó trông giống như nó (tất cả các đỉnh được kết nối với điểm đầu tiên) và tại sao nó lại bắt đầu khi nó thực hiện. Giá trị tối đa của indexData khi nó vẫn OK là 32831, giá trị tối đa khi nó bắt đầu hoạt động là 33023. Vì vậy, cả hai giá trị rõ ràng là thấp hơn sau đó 2^16, vậy tại sao GL_UNSIGNED_SHORT vẫn hoạt động? Tôi sẽ để câu hỏi mở thêm một chút trong trường hợp ai đó có thể trả lời câu hỏi này và sẽ đóng sau vài ngày/khi tôi nhận được câu trả lời. Cảm ơn!

+0

_Màu đen của người đàn ông trong bóng tối: Có vẻ như sau: Nếu tam giác vượt qua 'z = 0' trước khi chiếu, các điểm có' z <0' được ánh xạ tới '-inf' và những người có 'z> 0' hướng tới' + inf'. Vâng, những hình tam giác này rõ ràng sẽ bị cắt bớt ... –

+0

Cảm ơn ý tưởng này, mặc dù nó đã sai. Các giá trị đỉnh không đóng vai trò gì trong vấn đề này (tất cả chúng có thể là < or > rồi 0 và nó vẫn xuất hiện) và các điểm không được ánh xạ tới + -inf, tất cả chúng đều chỉ đến điểm bắt đầu (nếu bạn xoay bạn có thể thấy nó dừng lại ở điểm đó). Tôi đã tìm ra vấn đề và cập nhật câu hỏi. Nếu bạn có bất kỳ ý tưởng nào về câu hỏi được cập nhật, tôi rất muốn nghe chúng! :) – NightmareBadger

+0

Tôi muốn có robut cho avatar skype của tôi ... :) – mlvljr

Trả lời

1

Bạn có thể sử dụng mảng nổi Numpy trực tiếp với đối tượng bộ đệm đỉnh. Tôi đã không sử dụng chúng trong bối cảnh của Pyglet mặc dù. Một cái gì đó như:

from OpenGL.arrays import vbo 

# setup 
vertices_gl = vbo.VBO(vertPoints) 
colours_gl = vbo.VBO(vertPoints) 

# in drawing code 
vertices.bind() 
colours.bind() 
glVertexPointer(2, gl.GL_FLOAT, 0, vertices_gl) 
glColorPointer(2, gl.GL_FLOAT, 0, vertices_gl) 
Các vấn đề liên quan