Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





error vertex array en opengl

Iniciado por killgates, 17 de Noviembre de 2015, 06:49:16 PM

« anterior - próximo »

killgates

Hola,

Soy nuevo en el foro. Encantado!

Estoy haciendo un programa con opengl que lee un fichero obj, y guarda los vértices e índices de polígono en arreglos. Para luego visualizarlos en pantalla con la función glDrawElements();

El problema que tengo es que si hago un render con el modo inmediato y dibujo un triangulo se ve en pantalla bien..
Pero si cargo los arreglos de vértices y los dibujo aparecen manchurrones en vez del objeto.
Estoy 100% seguro de que los vértices e índices están bien leidos del fichero. Y hago el procedimiento correcto para mostrarlos con glVertexPointer() y glDrawElements();

Llevo semanas releyendo y no encuentro el error
Gracias por vuestras respuestas



Gallo

#1
Pon el código entero de la parte de render si puedes por favor. Si estas utilizando glDrawElements necesitas bindear un GL_ELEMENT_ARRAY_BUFFER con el orden en el que se pintan esos vertices. Si el Array de vértices ya está en orden entonces deberías utilizar glDrawArrays. Por supuesto ha de haber un shader program activo valido y toda la pesca.

De todas formas yo nunca he utilizado glVertexPointer, de hecho ni conocía la función pero podria ser interesante cuando la memoria de la GPU y la CPU son la misma y no hay que copiar, me la miraré. Yo habitualmente creo un buffer con glGenBuffers lo bindeo con glBindBuffer como GL_ARRAY_BUFFER y copio los datos del array de vertices con glBufferData, luego uso glVertexAttribPointer para especificar donde empiezan los datos de cada atributo. Para que sea mas cómodo  de utilizar lo bindeo todo a un un Vertex Array Object así solo tengo que bindear ese objeto.  Te pongo un ejemplo con un GL_ARRAY_BUFFER que se pintaria con glDrawArrays, para hacerlo con glDrawElements seria parecido pero ademas del GL_ARRAY_BUFFER se deberia crear y subir un GL_ELEMENT_ARRAY_BUFFER




struct VertexStruct
{
    float x, y, z; //posicion
    float tx, ty; //coordenadas de textura
}

VertexStruct* vertexList; //array de vértices
int vertexCount; //número de vértices
GLuint vao, vbo;

//Genero y bindeo un vertex array object
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);

//Genero y bindeo un vertex buffer object
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);

//Copio los datos a ese buffer
glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(VertexStruct), vertexList, GL_STATIC_DRAW);

//Hago el setup de los atributos
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexStruct), (void*)offsetof(VertexStruct, x));
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(VertexStruct), (void*)offsetof(VertexStruct, tx));
glEnableVertexAttribArray(1);
   
glBindVertexArray(0);


Para pintarlo solo hay que hacer:

glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, vertexCount);


También se pueden crear dos arrays separados para cada atributo pero no soy muy fan de ese método. glBufferData lo que hace es copiar los datos del puntero que especificas a la memoria gráfica para utilizarlo mas tarde (permanentemente hasta que se elimine el contexto o los borres manualmente con glDeleteBuffers y glDeleteVertexArrays), y de hecho podrías borrar ese array de la memoria ram ya que sus datos se quedan guardados en los buffers generados en la memoria gráfica, esta manera de hacerlo ya sea con o sin un array de indices es la habitual a partir de OpenGL 3 incluso antes con extensiones.

killgates

#2
Hola,

Estoy comenzando a programar con opengl aunque ya llevo tiempo estudiando en mis ratos libres.
El método que tu utilizas es el buffer object "creo que se llama así ahora no recuerdo" que utiliza la memoria de la tarjeta de video.
El modo que estoy intentando utilizar es el de los "vertex array" utilizando la memoria del sistema.
El render que hago es el siguiente:    "esto está en main"

        glLoadIdentity();
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glEnableClientState(GL_VERTEX_ARRAY);
        glVertexPointer(3, GL_FLOAT, 0, objeto3d1.submodelo[0].vertice);
        glColor4f(1.0f, 2.0f, 0.0f, 5.0f);  //Al azar ahora no importa.. no hay texturas
        glTranslatef(0,0, -10);
        glDrawElements(GL_TRIANGLES, objeto3d1.submodelo[0].NumeroIndices, GL_UNSIGNED_INT, objeto3d1.submodelo
[0].IndicesVertice);
      VentanaOpenGL.ActualizarBuffer();          //Esto actualiza el buffer en la clase que controla la ventana de opengl en windows


Y lo que hago es crear una clase que contenga todo lo concerniente a un objeto3d: vértices, texturas y normales, índices etc... extraido de un fichero obj.  los arreglos que contienen toda la información son punteros, así que se pueden eliminar o poner a NULL en cualquier momento, liberando así la memora del sistema.

Mi intención es hacer que salga bien el render para luego continuar con donde estás tú y practicar con shaders

Pero estoy atascadísimo, no se lo que estoy haciendo mal


Nota que al utilizar gldrawelements() estoy dibujando el objeto utilizando un índice de vértices con lo que me ahorro llamadas que haría con gldraw();

Gracias


killgates

UUUUUUUUUUUUUUUUUUUUUUUUUhoooooooooooooooooooooooo que pasa amiiiiiigoooooooooooooo !!!!
Solucionado!!!

Resulta que los índices de vértices "en el fichero obj" comienzan por 1 y en el arreglo el primer vértice está en la posición "vértice[0]" 0.
Con lo que al leer los índices en el fichero, al guardarlos en el arreglo, le debemos restar  1.
Queda de esta forma: (Es última parte del código que guarda los índices)

            if (registra == 1){
                        switch (y) {
                        case 0: submodelo[IndiceModelo].IndicesVertice[x]= numero-1; break;    //Nótese aquí que resto 1
                        case 1: submodelo[IndiceModelo].IndicesTextura[x]= numero; break;
                        case 2: submodelo[IndiceModelo].IndicesNormal[x]= numero; break;
                        }
                        y++;
                        if (y>2) y=0;
            }


Gracias,  >.< >.<






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.