2009-07-01 6 views
1

J'ai un grand atlas de texture et je dessine beaucoup de textures sur l'écran. En ce moment, chaque texture de l'atlas est établi séparément avec le code comme ceci:Combinez beaucoup d'atlas de texture dessinez des appels avec OpenGL ES

 
GLfloat coordinates[] = { 
     bla, bla, 
     bla, bla, 
     bla, bla, 
     bla, bla 
}; 

GLfloat vertices[] = { 
     bla, bla, bla, 
     bla, bla, bla 
     bla, bla, bla 
     bla, bla bla 
}; 


glEnable(GL_TEXTURE_2D); 
glBindTexture(GL_TEXTURE_2D, name); 
glVertexPointer(3, GL_FLOAT, 0, vertices); 
glTexCoordPointer(2, GL_FLOAT, 0, coordinates); 
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 

Nous faisons cela avec une bande de triangle.

Maintenant, je viens d'essayer de mettre en cache ce genre d'appels en sauvegardant les coordonnées/sommets, et en les dessinant tous en un seul appel. Mais OpenGL ES n'a pas de quads, donc essayer d'utiliser des bandes triangulaires signifie que l'opération les fusionnera toutes et que vous obtiendrez des textures qui se déforment sur l'écran à partir du point précédent.

J'ai essayé à la fois avec glDrawArrays et glDrawElements mais je n'ai pas eu de succès. Est-ce seulement possible?

Répondre

2

Pouvez-vous dessiner chaque quadrilatère comme deux triangles (GL_TRIANGLES)? Bien sûr, vous aurez dupliqué des sommets et des coordonnées dans vos tableaux.

+0

Oui, c'est ce que j'ai fini par faire. Au lieu de définir une bande de triangle avec 4 points dans mes tableaux, j'ai défini deux triangles (6 points) et utilisé glDrawArrays (GL_TRIANGLES, 0, totalSize * 6). Donc, cela empêche tout être déformé en une bande de triangle géante. –

+0

La création de la version GL_TRIANGLE_STRIP présente des avantages en termes de performances. –

0

changement

glVertexPointer(3, GL_FLOAT, 0, vertices); 

à

glVertexPointer(2, GL_FLOAT, 0, vertices); 

et il devrait fonctionner, en supposant que la bande triangle coords vous élidée sont corrects.

+0

Cela ne devrait pas faire de différence. C'est 3 maintenant juste parce que j'avais des valeurs z là-dedans mais elles sont toutes 0.0. –

0

Vous pourriez être intéressé par la classe TextureAtlas du moteur Cocos 2D pour iPhone.

+0

Merci, ils semblent faire exactement ce que je tentais. Peut-être que j'ai juste fait une erreur stupide quelque part. –

0

Utilisez glDrawElements avec GL_TRIANGLES avec 4 verts et 6 index. Le matériel moderne mettra en cache les récupérations de mémoire pour les verts répétés, ainsi les performances seront presque égales à GL_TRIANGLE_STRIP, et le fait que vous puissiez traiter GL_TRIANGLES beaucoup plus efficacement que des bandes pour des choses comme des quads individuels est une énorme victoire. Assurez-vous que l'enroulement du triangle est correct ou désactivez l'élimination de la face arrière.

// triangle vertex order 
// 1--2 
// | /| 
// |/ | 
// 0--3 

vertex foo[4] = { 
    {<vtx0>}, 
    {<vtx1>}, 
    {<vtx2>}, 
    {<vtx3>} 
}; 

// same clockwise winding for both triangles 
GLushort idx[2][3] = { 
    { 0, 1, 2 }, 
    { 0, 2, 3 } 
}; 

<setup vertex array> 
// use a VBO for both the vertex and index array if possible... 

glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, idx); 
1

Vous pouvez utiliser une bande dégénérée.

Dans ce cas, cela n'a pas de sens, puisque vous ne sauvegardez que deux sommets par bande, mais si vous obtenez des bandes plus longues et moins d'arrêts, il est bon d'avoir cette arme dans votre arsenal.

La bande dégénérée est basée sur le fait que le matériel saute des triangles avec une zone nulle, ce qui est vrai pour les triangles avec deux sommets identiques.

(codeur Horrible art ascii à la délivrance.)

A--D 
| /| 
|/ | 
B--C 

    E--H 
    | /| 
    |/ | 
    F--G 

Triangles

ABD DBC EFH HFG -> 12 

Va = f (Q) = 6XQ

Trianglestrips

ABD  C  C  E  E  F  H  G -> 10 
ABD (BD)C (DC)C (CC)E (CE)E (EE)F (EF)H (FH)G 
CCW CW CCW CW CCW CW CCW CW 
NOR NOR DEG DEG DEG DEG NOR NOR 

Vb = f (Q) = 4+ (4 + 2) (Q-1)

Q | Va | Vb 
1 | 6 | 4 
2 | 12 | 10 
3 | 18 | 16 
10 | 60 | 58 

D'après OpenGL 3.1 vous pouvez simplement utiliser "Primitive Restart" qui rendrait votre vie beaucoup plus facile.

Questions connexes