Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Duda Opengl

Iniciado por misscelan, 18 de Enero de 2006, 09:37:59 AM

« anterior - próximo »

misscelan

 Buenas.

Tengo un array con los vertices de un modelo "md_vertices[num_vert]" y otro array ordenado con los indices a los vértices "md_vertices_index[num_vert]". Debe ser renderizado formando triángulos.

Mi pregunta es como podría pasar todo esto directamente a renderizar (sin usar glBegin-glEnd).

Se me ocurre crear una copia de "md_vertices" y reorganizarla según "md_vertices_index"y luego mandarlo con glDrawArrays(GL_TRIANGLES, 0 , num_vert). Pero trendría que reorganizar ese array en tiempo de renderizado y no creo que sea la opción más elegante.

¿Existe algún comando parecido a glDrawArrays al que le pueda pasar el array de vertices y el de los indices y el se encargue de mandarlo todo de golpe?

Si se os ocurren más cosas son bienvenidas.

Muchas gracias.

Un saludo.


Ray

 
Citar¿Existe algún comando parecido a glDrawArrays al que le pueda pasar el array de vertices y el de los indices y el se encargue de mandarlo todo de golpe?

si, glDrawElements

Marci

 Supongo que con glDrawElements se podrá utilizar bastante menos memoria. Ray sabes si en rapidez se puede equiparar a glDrawArrays?

Ray

 Puede ser mucha velocidad, sobre todo si hay vertices compartidos.

Por ejemplo un cubo sin indexar formado por 6 caras, o sea.. 12 triangulos, la tarjeta calcularía 4x12 = 48 vértices o en el mejor de los casos 24 si son rectangulos.

Indexado solo calcularía los 8 vertices de cada esquina, por lo que en teoría debería ser mucho más rapido, al menos en lo que a la transformación de cada vértice se refiere.

Pero a veces puede ser mejor no usarlos, por ejemplo para hacer tiras de triángulos con GL_TRIANGLE_STRIP o GL_TRIANGLE_FAN, ya que así ni se duplican los vértices, ni se tienen que leer los índices, se va leyendo secuencialmente cada vértice y es lo más rápido.

Marci

 
CitarIndexado solo calcularía los 8 vertices de cada esquina

No entiendo porque solo 8 :huh:  

misscelan

 De primeras muchas gracias.

De segundas...tengo dudas.

Si el método que tenía para imprimirmos era GL_TRIANGLES supongo que dentro de esos índices habra vértices repetidos.

Primera pregunta. Si mando la malla entera a un glDrawArrays o glDrawElements y los saco con GL_TRIANGLE_STRIP esos mismos procedimientos se encargarían de crear los triángulos uniendo los vértices más cercanos o va creando las líneas según le llegan los vértices y me dejará un pupurrí de triángulos.

En el caso de mandarlos con GL_TRIANGLE_STRIP el proc mismo se encargaría de no usar los vértices duplicados?.

En el caso de no poder usar GL_TRIANGLE_STRIP desde el punto de vista de la rapidez cual creeis que sería más rápido.
El método de reorganizar los vértices que os dije al principio del post o dejar que lo organice él y pasárselos con glDrawElements.

Muchas gracias de nuevo.

Un saludo.

Ray

 
Cita de: "Marci"
CitarIndexado solo calcularía los 8 vertices de cada esquina

No entiendo porque solo 8 :huh:
porque son 8 los vértices que tiene el cubo.

a la tarjeta le llegan los 8 vértices, y un índice por cada vértice que hay que apuntar para dibujar todos los triángulos, el caso del cubo 48.

Esos 8 vértices son transformados para que queden proyectados en la pantalla.

Durante la rasterización se dibujan los triángulos mediante los índices que apuntan a cada vértice, si son 8, del 0 al 7.

0,1,2....0,3,4.....4,6,5....,1,6,7... (por ejemplo)

si tu le pasas esos 48 vértices duplicados en cada triángulo, la tarjeta transforma los 48 vértices.  Como están dibujados mediante GL_TRIANGLES dibujaría cada triángulo usando la serie de vértices 0,1,2....3,4,5....6,7,8....9,10,11, etc.  Esto si ha de hacerse con cientos de miles, la ganancia puede ser enorme indexandolos.

Hay que tener en cuenta que aunque tengan la misma posición no tienen porque estar duplicados ya que cada uno puede tener sus propias normales, o coordenadas de textura, por lo que muchas veces no quedará más remedio que mandar los 48, a no ser que hayan inventado algo ya para solucionar esto.

Entonces, por lo general y si yo no estoy errado, si los vértices comparten el mismo vértice incluido la normal y la coordenada de textura mejor indexarlo, si no, mejor no hacerlo.

Edit: me he hecho la picha un lío ahora y antes con los vértices del cubo, no son 48 si no 36 , 6 caras x 2 triángulos x 3 vértices.

Ray

 
Cita de: "misscelan"Primera pregunta. Si mando la malla entera a un glDrawArrays o glDrawElements y los saco con GL_TRIANGLE_STRIP esos mismos procedimientos se encargarían de crear los triángulos uniendo los vértices más cercanos o va creando las líneas según le llegan los vértices y me dejará un pupurrí de triángulos.

Se van creando los triángulos de una manerá lógica según están en la lista o le llegan.

aquí se ven las 3 formas de dibujar, strip, fan y normal.

http://bhbn.free.fr/etudes/rsc/OpenGL.doc....c.html-wv-2.png

Citar
En el caso de mandarlos con GL_TRIANGLE_STRIP el proc mismo se encargaría de no usar los vértices duplicados?.

El procedimiento hará lo que tu le digas de acuerdo a las normas que tiene cada forma de dibujar, lo normal es que salga un churro si no sabes exactamente lo que estás haciendo.

Citar
En el caso de no poder usar GL_TRIANGLE_STRIP desde el punto de vista de la rapidez cual creeis que sería más rápido.
El método de reorganizar los vértices que os dije al principio del post o dejar que lo organice él y pasárselos con glDrawElements.

según cada caso es mejor una forma u otra, pero la tarjeta no te va a organizar nada, que yo sepa.

Por ejemplo un cubo con caras con su propia textura y normales, dibujar triangulos sin indexar.

Para una esfera donde todos comparten textura y normales mejor indexado.

Para un cono o una sombrilla, o un círculo plano, con FAN

Para un terreno que comparte normales, textura y posición, lo más rápido sería indexado y con STRIP, dibujando en tiras cada fila o columna.

Pero siempre tienes que tener en cuenta que la posición de cada vertice en la lista es lo que la tarjeta gráfica tiene en cuenta a la hora de dibujar los triángulos. Quitar o añadir uno sería un desastre al menos para los que le preceden.


Marci

 misscelan
Lo que yo hago es crear un solo array ordenado con textura, normales y vertices. Este array contiene toda la geometria del objeto y solo se crea una vez. Despues en la funcion de render hay que preparar el array con glInterLeavedArrays y con glDrawArrays dibujo todos los vertices, texturas y normales con una sola llamada. Lo malo del metodo es que le paso un monton de datos repetidos.

Ray

glDrawArrays(GL_TRIANGLES, 0, 36);

glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, index);


A mi me parece que le estamos enviando a la GPU la misma información con las dos funciones. Solo varía el origen de los datos, no?

misscelan

 Buenas.

La geometría de mi objeto es variable. No puedo hacer exactamente lo mismo pero hago algo parecido.

Cuando dices que pintas todo en una llamada, te refieres a una sola llamada por material o que pasas el modelo entero? ¿Es posible que alguna función te haga el bindig de las texturas preparando un array o algo así? :blink:

No sé si estoy soltando una gilipollez si es así no contestéis y reiros un rato.

Un saludo


Marci

 Para trabajar con materiales lo que hago es dividir el objeto en grupos segun su material.


// Funcion que dibuja un objeto
for(int i = 0; i < numeroGrupos; ++i)
{
    Grupo[i].UsaMaterial();
    glInterLeavedArray(Grupo[i].Vertices)
    glDrawArrays();
}


Funciona bastante bien pero hago justo lo que tu querias evitar, mando vertices, normales y coordenadas de textura repetidas.

P.D. Todavia no le he añadido multitextura a los materiales :(

Ray

Cita de: "Marci"Ray

glDrawArrays(GL_TRIANGLES, 0, 36);

glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, index);


A mi me parece que le estamos enviando a la GPU la misma información con las dos funciones. Solo varía el origen de los datos, no?
Se supone que la información de los vértices la envías en glInterLeavedArrays y en glDrawElements envías además los índices.

Si los vértices no están indexados no tiene sentido dibujar con glDrawElements.

En el caso del cubo de ejemplo anterior si se dibuja indexado se han de mandar 8 vertices pero si no lo está hay que enviarlos todos con los que haya que formar todos los triángulos, aunque estén repetidos.

DraKKaR

 Además siempre es preferible utilizar primitivas indexadas para renderizar. Ya que de esa forma entra en juego la caché de vértices y eso repercute en mayor velocidad al no tener que transformar cada vértice que llega al procesador de vértices.

zupervaca

 Agregando a lo que ha dicho DraKKaR es que cuando nos metemos en vertex shaders es cuando mas se nota la velocidad de utilizar indices en el renderizado, sobre todo si el vertex shader es una funcion muy tocha.

Marci

 
Citar
Se supone que la información de los vértices la envías en glInterLeavedArrays

Ya cai joer (rules)
Es que me estaba liando con que los datos se le enviaban a la tarjeta en glDrawArrays o con glDrawElements y no con glVertexPointer (o glInterLeavedArrays).

Acabo de hacer la prueba y sin indexar le envio a la tarjeta 12 triangulos x 3 vertices x 3 float = 108 float mientras que indexado le mando 8 vertices x 3 float = 24 float






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.