2010-12-03 12 views
5

Tengo problemas para representar algo de geometría utilizando un objeto de búfer de vértice. Tengo la intención de dibujar un plano de puntos, por lo que básicamente un vértice en cada posición discreta en mi espacio. Sin embargo, no puedo renderizar ese plano, ya que cada vez que llamo a glDrawElements (...), los bloqueos de la aplicación devuelven una excepción de violación de acceso. Debe haber algún error durante la inicialización, supongo.OpenGL 3.x: infracción de acceso al usar el objeto de búfer de vértice y glDrawElements (...)

Esto es lo que tengo hasta ahora:


#define SPACE_X 512 
#define SPACE_Z 512 

typedef struct{ 
    GLfloat x, y, z; // position 
    GLfloat nx, ny, nz; // normals 
    GLfloat r, g, b, a; // colors 
} Vertex; 

typedef struct{ 
    GLuint i; // index 
} Index; 

// create vertex buffer 
GLuint vertexBufferObject; 
glGenBuffers(1, &vertexBufferObject); 

// create index buffer 
GLuint indexBufferObject; 
glGenBuffers(1, &indexBufferObject); 

// determine number of vertices/primitives 
const int numberOfVertices = SPACE_X * SPACE_Z; 
const int numberOfPrimitives = numberOfVertices; // As I'm going to render GL_POINTS, number of primitives is the same as number of vertices 

// create vertex array 
Vertex* vertexArray = new Vertex[numberOfVertices]; 

// create index array 
Index* indexArray = new Index[numberOfPrimitives]; 

// create planes (vertex array) 
// color of the vertices is red for now 
int index = -1; 
for(GLfloat x = -SPACE_X/2; x < SPACE_X/2; x++) { 
    for(GLfloat z = -SPACE_Z/2; z < SPACE_Z/2; z++) { 
     index++; 
     vertexArray[index].x = x; 
     vertexArray[index].y = 0.0f; 
     vertexArray[index].z = z; 
     vertexArray[index].nx = 0.0f; 
     vertexArray[index].ny = 0.0f; 
     vertexArray[index].nz = 1.0f; 
     vertexArray[index].r = 1.0; 
     vertexArray[index].g = 0.0; 
     vertexArray[index].b = 0.0; 
     vertexArray[index].a = 1.0; 
    } 
} 

// bind vertex buffer 
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject); 

// buffer vertex array 
glBufferData(GL_ARRAY_BUFFER, numberOfVertices * sizeof(Vertex), vertexArray, GL_DTREAM_DRAW); 

// bind vertex buffer again 
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject); 

// enable attrib index 0 (positions) 
glEnableVertexAttribArray(0); 

// pass positions in 
glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), vertexArray); 

// enable attribute index 1 (normals) 
glEnableVertexAttribArray(1); 

// pass normals in 
glVertexAttribPointer((GLuint)1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), &vertexArray[0].nx); 

// enable attribute index 2 (colors) 
glEnableVertexAttribArray(2); 

// pass colors in 
glVertexAttribPointer((GLuint)2, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), &vertexArray[0].r); 

// create index array 
for(GLunit i = 0; i < numberOfPrimitives; i++) { 
    indexArray[i].i = i; 
} 

// bind buffer 
glBindBuffer(GL_ELEMENET_ARRAY_BUFFER, indexBufferObject); 

// buffer indices 
glBufferData(GL_ELEMENET_ARRAY_BUFFER, numberOfPrimitives * sizeof(Index), indexArray, GL_STREAM_DRAW); 

// bind buffer again 
glBindBuffer(GL_ELEMENET_ARRAY_BUFFER, indexBufferObject); 

// AND HERE IT CRASHES! 
// draw plane of GL_POINTS 
glDrawElements(GL_POINTS, numberOfPrimitives, GL_UNSIGNED_INT, indexArray); 

// bind default buffers 
glBindBuffer(GL_ARRAY_BUFFER, 0); 
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 

// delete vertex/index buffers 
glDeleteBuffers(1, &vertexBufferObject); 
glDeleteBuffers(1, &indexBufferObject); 

delete[] vertexArray; 
vertexArray = NULL; 

delete[] indexArray; 
indexArray = NULL; 
+0

Siempre mencione a qué versión de OpenGL se dirige: 3.x es un poco vago. Por cierto, es una buena práctica crear y vincular un objeto de matriz vértice antes de cualquier 'glVertexAttribPointer' o' glEnableVertexAttribArray'. Probablemente esté usando el perfil de compatibilidad OpenGL, por lo que no recibió un error debido a eso. – Kos

+0

Bastante justo. Supongo que 3.x es un poco vago. Pensé que hay grandes diferencias incluso entre las versiones menores de GL. Entonces, actualmente estoy usando OpenGL 3.3. – Walter

Respuesta

0

Mira el segundo ejemplo en esta página y compararlo con lo que hizo: http://www.opengl.org/wiki/VBO_-_just_examples

Y usted tiene una errata: GL_DTREAM_DRAW .

+0

Parece que no vi la madera para los árboles. Conocía esa página, pero por alguna razón había supervisado el hecho de que "glEnableClientState (...)" está en desuso. Eso es un poco embarazoso. Lo siento por molestarte. – Walter

+0

¿Fue ese el único problema? ¿Tu código funciona correctamente ahora? – Bojan

+0

Bueno, funciona de alguna manera. Tengo algunos otros problemas ahora. Después de deshacerme del glEnableClientState (...), pude ejecutar la aplicación por primera vez. Sin embargo, no funciona como se esperaba, ya que se bloquea después de un tiempo. Entonces, intento averiguar qué causa exactamente el bloqueo. Si omito la creación del objeto de búfer de vértice y el dibujo de sus vértices, la aplicación funciona bien a buena velocidad. Pero tan pronto como agregue el código anterior, toma tal vez 15 segundos y la aplicación se bloquea. – Walter

0

El método glEnableClientState (...) está en desuso! Lo siento, por alguna razón, he supervisado ese hecho.

+1

glEnableClientState no solo está en desuso, sino que es incorrecto aquí; recuerde que desea apuntar a vértices en una VBO (por lo tanto, en la memoria de la GPU, no en la memoria del cliente). Eso ya no es estado del cliente si está en una VBO. :) – Kos

6

Cuando está utilizando objetos de búfer, los últimos parámetros en el puntero gl * y el 4 ° parámetro en glDrawElements ya no son direcciones en la memoria principal (¡los suyos todavía lo son!), Sino que se desplazan a los objetos del búfer. ¡Asegúrate de calcular estas compensaciones en bytes! La macro "offsetof" es muy útil allí.

+0

Correcto, si cualquier VBO está obligado a 'GL_ELEMENT_ARRAY_BUFFER', entonces el último argumento usa la posición relativa del búfer como base de direccionamiento. El valor '0' significa" el comienzo de VBO actualmente encuadernado ". El operador 'offsetof' te ayudará. – Kos

+0

Ese es un punto interesante. Entonces, si entiendo bien, para los colores debería verse así: glVertexAttribPoint (1, 4, GL_FLOAT, GL_FALSE, sizeof (Vertex), (GLvoid *) (offsetof (Vertex, r))); ¿Es eso correcto? – Walter

+0

¡Tienes razón! Esa es la solución a mi problema! No fue solo el hecho de que utilicé erróneamente glEnableClientState (...), sino que también malentendí los parámetros que mencionaste. Gracias por esa pista. Mi aplicación funciona bien ahora ... – Walter

Cuestiones relacionadas