2017-04-11 1 views
0

다수의 정점 (점군과 비슷 함)을 플롯하려고합니다.OpenGL에서 500+ 정점 위치를 업데이트하려고하면 읽기 액세스 위반이 발생합니까?

동시에 VBO를 사용하고 Numpy 배열을 GLSL 프로그램에 전달하고 정점 위치를 애니메이션하는 방법을 배우려고합니다. WindowsError: exception: access violation reading 0x0999B000

때로는 (무작위로) 작동하고 난 그냥 궁금했다 :

나는 내가 일반적으로 오류가 발생 (500)를 통해 나는 array_size 매개 변수 아무것도 설정하는 방법 큰 제한하고 있지만 일부 진전을 생각한다 내가 메모리를 할당하거나 배열을 버퍼링하는 방식에 실수를하고 있습니까?

메모를 추가하기 만하면 앞으로는 2500+ 정점 위치를 한 번에 업데이트하려고합니다. 어떻게하면 가능할 수 있는지 궁금해하고 있었습니까?

array_size = 100

#!/bin/env python 
# coding: utf-8 

import time 
import numpy as np 
from textwrap import dedent 

from OpenGL.GL import * 
from OpenGL.GL.shaders import compileShader, compileProgram 

import pygame 
from pygame.locals import * 

############################################################################## 
# OpenGL funcs 
############################################################################## 
buffers=None 
shader = None 
def init_gl(): 
    glEnable(GL_VERTEX_PROGRAM_POINT_SIZE) #allow the program to specify the point size 

    global shader, buffers 

    vertex_shader = compileShader(dedent(''' 

     uniform mat4 Projection = mat4(1); 
     uniform mat4 ModelView = mat4(1); 

     varying out vec3 _color; 

     void main() { 
      _color = gl_Color; 
      gl_Position = Projection * ModelView * gl_ModelViewProjectionMatrix * gl_Vertex; 

      vec3 ndc = gl_Position.xyz/gl_Position.w ; // perspective divide. 
      float zDist = 1.0-ndc.z ; // 1 is close (right up in your face,) 
      // 0 is far (at the far plane) 
      gl_PointSize = 25*zDist ; // between 0 and 50 now. 

     } 
     '''), GL_VERTEX_SHADER) 
    fragment_shader = compileShader(dedent(''' 

     in vec3 _color; 

     void main() { 
      gl_FragColor = vec4(_color, 1.0); //gl_Color; 
     } 
     '''), GL_FRAGMENT_SHADER) 
    shader = compileProgram(vertex_shader, fragment_shader) 

    buffers=create_vbo() 

yaw=0 
pitch=0 
def draw(): 
    global yaw, pitch 
    glClear(GL_COLOR_BUFFER_BIT)# | GL_DEPTH_BUFFER_BIT) 

    glMatrixMode(GL_MODELVIEW) 
    glLoadIdentity() 

    yaw+=0.39 
    pitch+=0.27 
    glTranslatef(0.0, 0.0, 0.0) 
    glRotatef(yaw, 0, 1, 0) 
    glRotatef(pitch, 1, 0, 0) 

    setPoints() 
    glFlush() 

############################################################################## 
# vertices 
############################################################################## 
array_size = 1000 
scale = 0.15 

#create dataset https://matplotlib.org/mpl_toolkits/mplot3d/tutorial.html 
theta = np.linspace(-4 * np.pi, 4 * np.pi, array_size) 
z = np.linspace(-2, 2, array_size) 
r = z**2 + 1 
x = r * np.sin(theta) 
y = r * np.cos(theta) 

vertices = np.dstack((x,y,z)) * scale 
colors = np.tile(np.array([0.0, 1.0, 0.0]), (array_size,1)) #a bunch of green vertices 
indices=np.arange(array_size) 


def create_vbo(): 
    buffers = glGenBuffers(3) 

    glBindBuffer(GL_ARRAY_BUFFER, buffers[0]) 
    glBufferData(GL_ARRAY_BUFFER, 
      vertices.nbytes, # byte size 
      (ctypes.c_float*len(vertices.flat))(*vertices.flat), 
      GL_STREAM_DRAW) 

    glBindBuffer(GL_ARRAY_BUFFER, buffers[1]) 
    glBufferData(GL_ARRAY_BUFFER, 
      colors.nbytes, # byte size 
      (ctypes.c_float*len(colors.flat))(*colors.flat), 
      GL_STATIC_DRAW) 

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[2]) 
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, 
      indices.nbytes, # byte size 
      (ctypes.c_uint*len(indices.flat))(*indices.flat), 
      GL_STATIC_DRAW) 
    return buffers 

def draw_vbo(): 
    glEnableClientState(GL_VERTEX_ARRAY); 
    glEnableClientState(GL_COLOR_ARRAY); 

    glBindBuffer(GL_ARRAY_BUFFER, buffers[0]); 
    glVertexPointer(3, GL_FLOAT, 0, None); 

    glBindBuffer(GL_ARRAY_BUFFER, buffers[1]); 
    glColorPointer(3, GL_FLOAT, 0, None); 

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[2]); 
    glDrawElements(GL_POINTS, indices.size, GL_UNSIGNED_INT, None); 

    glDisableClientState(GL_COLOR_ARRAY) 
    glDisableClientState(GL_VERTEX_ARRAY); 


def setPoints(): 
    global shader 

    glUseProgram(shader) 
    draw_vbo() 

    projection = np.array([#the matrix generated captured while using HTC Vive 
     [ 0.75752085, 0.  , 0.  , 0.], 
     [ 0.  , 0.68160856, 0.  , 0.], 
     [ 0.05516453, -0.00299519, -1.00040019, -1.], 
     [ 0.  , 0.  , -0.20008004, 0.] 
    ]) 
    modelview = np.array([#the matrix generated captured while using HTC Vive 
     [ 0.99030989, 0.04490654, 0.13141415, 0.], 
     [-0.01430531, 0.9742285 , -0.22510922, 0.], 
     [-0.13813627, 0.22104797, 0.9654305 , 0.], 
     [-0.12975544, -0.9294402 , -1.06236947, 1.] 
    ]) 

    glUniformMatrix4fv(glGetUniformLocation(shader, "Projection"), 1, False, projection) 
    glUniformMatrix4fv(glGetUniformLocation(shader, "ModelView"), 1, False, modelview) 

    glUseProgram(0) 

############################################################################## 
if __name__ == '__main__': 

    pygame.init() 
    pygame.display.set_mode((800, 600), HWSURFACE|OPENGL|DOUBLEBUF) 

    init_gl() 

    start_time = time.time() 
    while time.time() - start_time < 5: #5 second animation 
     draw() 
     pygame.display.flip() 

[업데이트]

나는 내가 제대로 내 NumPy와 배열의 데이터 유형을 캐스팅하지 않은 깨달았을 때 나는 내 자신의 질문에 대답했다 생각합니다. 그래서 내가 그들을 만들 때 내 배열에 .astype()을 추가하여 내가 보여 애니메이션 :

vertices = (np.dstack((x,y,z)) * scale).astype(np.float32) 
colors = (np.tile(np.array([0.0, 1.0, 0.0]), (array_size,1))).astype(np.float32) #a bunch of green vertices 
indices = np.arange(array_size).astype(np.uint32) 

을 위해 2000 + 버텍스를 얻을 수 있었다 그리고 여기에 고정 된 예는있다 :

#!/bin/env python 
# coding: utf-8 

import time 
import numpy as np 
from textwrap import dedent 

from OpenGL.GL import * 
from OpenGL.GL.shaders import compileShader, compileProgram 

import pygame 
from pygame.locals import * 

############################################################################## 
# OpenGL funcs 
############################################################################## 
buffers=None 
shader = None 
def init_gl(): 
    glEnable(GL_VERTEX_PROGRAM_POINT_SIZE) #allow the program to specify the point size 

    global shader, buffers 

    vertex_shader = compileShader(dedent(''' 

     uniform mat4 Projection = mat4(1); 
     uniform mat4 ModelView = mat4(1); 

     varying out vec3 _color; 

     void main() { 
      _color = gl_Color; 
      gl_Position = Projection * ModelView * gl_ModelViewProjectionMatrix * gl_Vertex; 

      vec3 ndc = gl_Position.xyz/gl_Position.w ; // perspective divide. 
      float zDist = 1.0-ndc.z ; // 1 is close (right up in your face,) 
      // 0 is far (at the far plane) 
      gl_PointSize = 25*zDist ; // between 0 and 50 now. 

     } 
     '''), GL_VERTEX_SHADER) 
    fragment_shader = compileShader(dedent(''' 

     in vec3 _color; 

     void main() { 
      gl_FragColor = vec4(_color, 1.0); //gl_Color; 
     } 
     '''), GL_FRAGMENT_SHADER) 
    shader = compileProgram(vertex_shader, fragment_shader) 

    buffers=create_vbo() 

yaw=0 
pitch=0 
def draw(): 
    global yaw, pitch 
    glClear(GL_COLOR_BUFFER_BIT)# | GL_DEPTH_BUFFER_BIT) 

    glMatrixMode(GL_MODELVIEW) 
    glLoadIdentity() 

    yaw+=0.39 
    pitch+=0.27 
    glTranslatef(0.0, 0.0, 0.0) 
    glRotatef(yaw, 0, 1, 0) 
    glRotatef(pitch, 1, 0, 0) 

    setPoints() 
    glFlush() 

############################################################################## 
# vertices 
############################################################################## 
array_size = 2000 
scale = 0.15 

#create dataset https://matplotlib.org/mpl_toolkits/mplot3d/tutorial.html 
theta = np.linspace(-4 * np.pi, 4 * np.pi, array_size) 
z = np.linspace(-2, 2, array_size) 
r = z**2 + 1 
x = r * np.sin(theta) 
y = r * np.cos(theta) 

vertices = (np.dstack((x,y,z)) * scale).astype(np.float32) 
colors = (np.tile(np.array([0.0, 1.0, 0.0]), (array_size,1))).astype(np.float32) #a bunch of green vertices 
indices = np.arange(array_size).astype(np.uint) 


def create_vbo(): 
    buffers = glGenBuffers(3) 

    glBindBuffer(GL_ARRAY_BUFFER, buffers[0]) 
    glBufferData(GL_ARRAY_BUFFER, 
      vertices.nbytes, # byte size 
      (ctypes.c_float*len(vertices.flat))(*vertices.flat), 
      GL_STREAM_DRAW) 

    glBindBuffer(GL_ARRAY_BUFFER, buffers[1]) 
    glBufferData(GL_ARRAY_BUFFER, 
      colors.nbytes, # byte size 
      (ctypes.c_float*len(colors.flat))(*colors.flat), 
      GL_STATIC_DRAW) 

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[2]) 
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, 
      indices.nbytes, # byte size 
      (ctypes.c_uint*len(indices.flat))(*indices.flat), 
      GL_STATIC_DRAW) 
    return buffers 

def draw_vbo(): 
    glEnableClientState(GL_VERTEX_ARRAY); 
    glEnableClientState(GL_COLOR_ARRAY); 

    glBindBuffer(GL_ARRAY_BUFFER, buffers[0]); 
    glVertexPointer(3, GL_FLOAT, 0, None); 

    glBindBuffer(GL_ARRAY_BUFFER, buffers[1]); 
    glColorPointer(3, GL_FLOAT, 0, None); 

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[2]); 
    glDrawElements(GL_POINTS, indices.size, GL_UNSIGNED_INT, None); 

    glDisableClientState(GL_COLOR_ARRAY) 
    glDisableClientState(GL_VERTEX_ARRAY); 


def setPoints(): 
    global shader 

    glUseProgram(shader) 
    draw_vbo() 

    projection = np.array([#the matrix generated captured while using HTC Vive 
     [ 0.75752085, 0.  , 0.  , 0.], 
     [ 0.  , 0.68160856, 0.  , 0.], 
     [ 0.05516453, -0.00299519, -1.00040019, -1.], 
     [ 0.  , 0.  , -0.20008004, 0.] 
    ]) 
    modelview = np.array([#the matrix generated captured while using HTC Vive 
     [ 0.99030989, 0.04490654, 0.13141415, 0.], 
     [-0.01430531, 0.9742285 , -0.22510922, 0.], 
     [-0.13813627, 0.22104797, 0.9654305 , 0.], 
     [-0.12975544, -0.9294402 , -1.06236947, 1.] 
    ]) 

    glUniformMatrix4fv(glGetUniformLocation(shader, "Projection"), 1, False, projection) 
    glUniformMatrix4fv(glGetUniformLocation(shader, "ModelView"), 1, False, modelview) 

    glUseProgram(0) 

############################################################################## 
if __name__ == '__main__': 

    pygame.init() 
    pygame.display.set_mode((800, 600), HWSURFACE|OPENGL|DOUBLEBUF) 

    init_gl() 

    start_time = time.time() 
    while time.time() - start_time < 5: #5 second animation 
     draw() 
     pygame.display.flip() 

답변

2

문제가 있다는 것입니다 전체적으로 dtype을 지정하지 않으므로 float64dtype으로 선택됩니다.

print(vertices.dtype) 
print(colors.dtype) 
print(indices.dtype) 

"float32", "float32", "uint32"를 인쇄해야합니다 그. 그러나 "float64", "float64", "int32"을 인쇄합니다.

이제 문제는 데이터가 두 배 크기라는 것입니다. 따라서 glBufferData()으로 전화하면 datasize에 실제로 실제로 무엇을주고 받는지와 비교하여 크기가 두 배라고 말합니다. 드라이버는 당신이 그것을 준 데이터의 범위를 벗어난 데이터를 읽으려고하기 때문에의 access violation reading 0x0999B000을 트리거 무엇


.

가 정점을 설정 한 후 다음을 수행하는 것입니다 해결하는 가장 쉬운 방법 :

vertices = vertices.astype(np.float32) 
colors = colors.astype(np.float32) 
indices = indices.astype(np.uint32) 

지금 당신은 당신의 RAM과 VRAM이 허용하는만큼의 정점을 추가 할 수 있습니다!


는 마지막으로 vertices으로 glBufferData()를 호출하기 전에 다음을 추가, 미래 두통 자신을 저장 :

assert vertices.dtype == np.float32 

은 마찬가지로 colorsindices (대신 np.uint32를 사용)에 대해 이렇게.

데이터 형식이 원하는 데이터 형식이 아닌 경우 어설 션을 트리거합니다. 2 31보다 작은 인덱스를 들어


-1 당신이 변경되지 않습니다 int32 또는 uint32을 사용하는지 여부. 그러나 예상되는 유형으로가는 것이 현명 할 수 있습니다. 따라서 미래에 실수로 자신을 넘어지는 것을 피할 수 있습니다. 비록 그 문제에 관해서는 아마 그 양의 색인이나 다른 누군가에게 다가 가지 못할 것입니다. 하지만 미안보다 더 안전합니다.

+0

답변 해 주셔서 감사합니다. 나는 또한 이것을 목격했다 (당신이 이것을 타이핑하는 것처럼)! 내 게시물을 개정 된 코드로 업데이트했으며 제안한대로 정확하게 수정했습니다. 나는 이것을 잘 설명하고 원래의 문제를 해결하기 때문에 이것을 답으로 받아 들일 것입니다. – Logic1

+0

여러분을 환영합니다! 또한 자신에게 답을 똑같이 찾는 당신을위한 소품! :) – Vallentin

관련 문제