2009-11-02 7 views
26

Estoy tratando de renderizar un cubo utilizando una matriz de 8 vértices y una matriz de índices de 24 (4 * 6) índices en la matriz de vértices. Pero, ¿cómo puedo especificar variables cara por cara, como colores y normales sin usar funciones obsoletas? Para esto necesito un conjunto separado de índices, pero cuando especifico dos matrices índice (GL_ELEMENT_ARRAY_BUFFERs) y las apunto a diferentes variables shader (con dos llamadas a glVertexAttribPointer) algo sale mal, y no representa nada (pero doesn) no denuncie ningún error, se lo verifica con glGetError). ¿Tengo que usar diferentes llamadas a glDrawElements para cada cara, con color y normal cargado en variables uniformes?¿Cómo puedo especificar los colores por cara cuando uso matrices de vértices indexados en OpenGL 3.x?

Para aclarar, el problema surge cuando cada uno de los 8 vértices son parte de caras diferentes y necesitan diferentes valores de color y normal.

Respuesta

30

La respuesta real primero:
Ver la respuesta de Goz. Mantenga 24 vértices separados.

Alguna nomenclatura segunda:
A Vertex es un conjunto de atributos de vértice. Tenga en cuenta esta distinción al leer lo siguiente:

Tiene la idea errónea de que el uso de API obsoletas lo ayudará a resolver el problema. Este no es el caso. OpenGL maneja (y siempre manejó) cada vértice como un conjunto único de atributos. Si usted lee la especificación original con cuidado, se dará cuenta de que cuando se hace:

glNormal() 
glVertex() 
glVertex() 
glVertex() 

La especificación establece claramente que glNormal establece el current normal state, y que provoca glVertex un nuevo vértice, copia de paso toda la current state, incluyendo el current normal state. Es decir, aunque haya pasado solo una Normal, el GL todavía ve 3.

El GL, por lo tanto, no tiene atributos "por cara".

Además, se están mezclando las matrices de índice GL_ELEMENT_ARRAY_BUFFER, que se utilizan de glDrawElements(..., pointer), donde pointer es un desplazamiento dentro de la matriz de índice, y el vértice atribuyen matrices GL_ARRAY_BUFFER, que se utilizan de glVertexAttribPointer (y todo el DEPRECATED glVertexPointer/glNormalPointer ...

Cada índice que está en el búfer de índice se usará como índice en cada uno de los atributos, pero solo puede especificar un único índice para cada vértice. Por lo tanto, establecer GL_ELEMENT_ARRAY_BUFFER y llamar al glVertexAttribPointer, no funciona en absoluto lo que piensas que hace. Utiliza la última matriz configurada en GL_ARRAY_BUFFER para definir los atributos de los vértices, o si no mantienes una ligada, está entre Preting su desplazamiento como puntero (y es probable que se bloquee).

Lo que intentaba hacer, establecer una matriz de índice para cada atributo de vértice, no es compatible con GL. Permítanme repetir esto: solo tiene 1 matriz de índice por sorteo.

Algunos detalles adicionales para la historia enclined:

glVertex es un nombre poco apropiado. Especifica solo el Vertex posición. Pero, y de esto recibe su nombre, también provoca que un vértice pase al GL. Para la API de estar completamente limpio, que podría haber imaginado tener que hacer 2 llamadas:

// not valid code 
glPosition(1,2,3); // specifies the current vertex position 
glProvoke(); // pass the current vertex to GL 

Sin embargo, cuando GL se especifica en primer lugar, siempre se requiere de posición, por lo que la fusión de los 2 a provocar un vértice tenía sentido (si solo para reducir el conteo de llamadas API).

Avance rápido hasta vertex_program_arb: el intento de alejarse del modelo de función fija sin dejar de ser compatible significaba que la naturaleza especial de glVertex tenía que llevarse adelante. Esto se logró haciendo que el vertex attribute 0 provocara, y un sinónimo de glVertex.

avance rápido hasta GL3.2: Begin/End modelo se ha ido, y todo esto especificación de lo que provoca un vértice puede finalmente desaparecerá, junto con la gestión de la current state. También lo pueden hacer todas las API semánticas (glVertex *, glNormal * ...), ya que todas las entradas son solo atributos de vértices ahora.

+0

Gracias de nuevo, Bahbar, por una respuesta muy completa :) Pero ahora tengo problemas para ver el punto de los búferes de índice en absoluto ...El "libro rojo" (7ma edición) me llevó a creer que estaba destinado a acomodar las posiciones de los vértices de reutilización que aparecen más de una vez en un modelo. incluso utiliza el cubo como ejemplo, indicando que "cada vértice se usa exactamente con tres caras". Por supuesto, no mencionan las normales/colores en el ejemplo ... – Wonko

+0

¿Hay alguna manera de obtener este comportamiento en OpenGL? Para almacenar la posición, el color normal y el color por separado (y únicamente) y conectarlos a los vértices "sobre la marcha" ? Sería muy conveniente cuando se trabaja con archivos .obj, que hacen exactamente esto, y algoritmos que procesan cada posición de vértice una vez. – Wonko

+1

Normalmente, una sola posición de vértice con diferentes normales es un signo de una costura. En cuanto a la mayoría de las mallas, estos vértices son la excepción, no la norma. La mayoría de las aplicaciones se benefician enormemente del uso de índices, ya que todos los atributos en superficies lisas son compartidos. En cuanto a los archivos .obj ... bueno, se crearon para 3ds max, no para renderizado en tiempo de ejecución. Tienes que hacer algún procesamiento para usarlos con cualquier API de gráficos. No hay forma de obtener este comportamiento en GL, porque no es así como lo hace el __hardware__. – Bahbar

6

Necesita más de 8 vértices. Verts puede compartir posiciones, pero a menos que todo lo demás en el vértice sea único, no es un vértice único. Normals es otra razón clásica para necesitar más de 8 verts en una definición de cubo.

36

Las personas interesadas en utilizar o no los índices de matriz pueden encontrar alguna utilidad en un diagrama que he creado para resumir gráficamente el comportamiento de las diferentes llamadas OpenGL, para que pueda ver, por ejemplo, cuáles dibujan bloques contiguos de vértice datos, frente a los que 'omiten' usar índices.

OpenGL draw calls http://tartley.com/wp-content/uploads/2010/03/opengl-draw-calls.png.

publiqué esta imagen bajo Creative Commons BY-SA, como se ha señalado en this source.

+0

Esa es una buena foto. ¿Cuidar para especificar una licencia? – Bahbar

+0

seguro. ¿Hay una buena manera de declararlo formalmente, o simplemente lo agrego aquí en un comentario? No estoy familiarizado con la elección de licencias para las imágenes, pero me complace hacerlo lo más abierto posible. ¿Hay una licencia de CC liberal que sea apropiada? (otras sugerencias bienvenidas) –

+0

Si desea CC, tiene una buena herramienta para elegir una licencia aquí: http://creativecommons.org/choose/. La imagen es uno de los formatos seleccionables. De lo contrario, puede decir que es de dominio público si no le importa guardar los derechos de autor. En todos los casos, debe especificarlo directamente en su sitio web. (No hace falta decir, IANAL, pero bueno, intento cuidar) – Bahbar

6

explicaciones interesantes, pero parece que oscurecer el hecho de que la pregunta original contiene su propia respuesta: "¿Tengo que utilizar diferentes llamadas para glDrawElements para cada cara, con color y normal cargado en variables uniformes? " - Si tener que alimentar los mismos datos de posición de vértice al procesador de gráficos tres veces cuando una vez debería ser suficiente ofende el sentido estético de uno (y debería), entonces sí es así.

El interlocutor original no quiere saber que OpenGL no puede hacer lo que está tratando de hacer, y que necesita mantener veinticuatro vértices para un cubo que tanto las matemáticas estándar como el sentido común nos dicen que solo debería necesitar ocho. Él ya sabe que PUEDE hacer lo que quiere, e incluso sabe cómo hacerlo. Solo quiere confirmación de que su enfoque propuesto tiene sentido, y que no hay una mejor manera de hacerlo que él haya pasado por alto.

Realizar llamadas para cada cara sí agrega una sobrecarga, pero eso no es importante cuando se dibuja un solo cubo. Al dibujar muchas, todas las caras de atributos iguales se pueden agrupar juntas, p. todo orientado hacia el sur, luego todo el oeste, o todo el rojo, luego todo verde, o lo que sea.

1

En OpenGL 3.x tiene acceso al tipo interpolation qualifiers. Con el calificador flat, forzaría el uso de la variable aprobada por provoking vertex solamente. En algunos casos, esto debería ser suficiente para hacer lo que quiera, pero tiene la desventaja de que debe prestar mucha atención al orden en que dibuja los vértices.

Cuestiones relacionadas