2010-08-02 3 views
2

J'ai récemment travaillé sur un lecteur de nuage de points qui devrait être idéalement capable de visualiser des points de données de terrain à partir d'une capture lidar et de les afficher séquentiellement à environ 30 images par seconde. Cependant, je semble être arrivé à un mur résultant de PCI-e IO. Ce que je dois faire pour chaque image est de charger un gros nuage de points stocké en mémoire, puis calculer une carte de couleurs en fonction de la hauteur (j'utilise quelque chose comme la carte de jet de matlab), puis transférer les données au GPU . Cela fonctionne très bien sur les captures de nuages ​​avec des points < un million. Cependant, à environ 2 millions de points, cela commence à ralentir en dessous de 30 images par seconde. Je sais que cela est beaucoup de données (2 millions d'images par points * [3 flotteurs par point + 3 flotteurs par point de couleur] * 4 octets par flotteur * 30 images par seconde = autour de 1,34 giga-octets par seconde)Accélération d'une application OpenGL liée à IO

mon code de rendu ressemble à ce moment:

glPointSize(ptSize); 
glEnableClientState(GL_VERTEX_ARRAY); 
if(colorflag) { 
    glEnableClientState(GL_COLOR_ARRAY); 
} else { 
    glDisableClientState(GL_COLOR_ARRAY); 
    glColor3f(1,1,1); 
} 
glBindBuffer(GL_ARRAY_BUFFER, vbobj[VERT_OBJ]); 
glBufferData(GL_ARRAY_BUFFER, cloudSize, vertData, GL_STREAM_DRAW); 
glVertexPointer(3, GL_FLOAT, 0, 0); 
glBindBuffer(GL_ARRAY_BUFFER, vbobj[COLOR_OBJ]); 
glBufferData(GL_ARRAY_BUFFER, cloudSize, colorData, GL_STREAM_DRAW); 
glColorPointer(3, GL_FLOAT, 0, 0); 
glDrawArrays(GL_POINTS, 0, numPoints); 
glDisableClientState(GL_VERTEX_ARRAY); 
glEnableClientState(GL_COLOR_ARRAY); 
glBindBuffer(GL_ARRAY_BUFFER, 0); 

Le pointeur pour vertData et ColorData sont changés chaque image. Ce que je voudrais être capable de faire est de pouvoir jouer à un minimum de 30 images par seconde, même si plus tard, j'utilise de gros nuages ​​de points pouvant atteindre jusqu'à 7 millions de points par image. Est-ce seulement possible? Ou peut-être serait-il plus facile de les mettre en grille et de construire une carte de hauteur et de l'afficher en quelque sorte? Je suis encore assez novice en programmation 3D, donc tout conseil serait apprécié.

+0

avez-vous vraiment besoin d'envoyer toutes les données de chaque trame? Ne pouvez-vous pas simplement mettre à jour la hauteur en cas de besoin, n'envoyez que ceci sur le GPU, et calculer la couleur dans un shader? Qu'est-ce que vous avez à mettre à jour sur le processeur qui ne peut pas être fait sur le GPU? – Calvin1602

+0

Le problème que j'ai est que les nuages ​​de points sont tous pré-enregistrés, donc je dois juste les afficher. Je ne fais pas vraiment de calculs, donc je ne peux pas simplement mettre à jour les choses: \ – Xzhsh

+0

J'ai la même idée que @ Calvin1602. Je ne sais pas si cela pourrait aider: http://stackoverflow.com/questions/371898/how-does-differential-execution-work mais ce qu'il fait est de comparer les choses nouvelles vs anciennes, obtenir des différences, et d'utiliser les mettre à jour une structure de données "distante", si la bande passante est un problème. –

Répondre

7

Si vous le pouvez, implémentez la carte de couleurs en utilisant la texture 1D. Vous n'aurez besoin que d'une seule coordonnée de texture au lieu de trois couleurs et les sommets seront également alignés sur 128 bits. EDIT: Il vous suffit de créer une texture à partir de votre palette de couleurs et d'utiliser glTexCoordPointer au lieu de glColorPointer (et de modifier les valeurs de vertex color pour les coordonnées de texture dans la plage [0, 1] bien sûr). Ici s'interpolées linéairement 6 texel colormap:

// Create texture 
GLuint texture; 
glGenTextures(1, &texture); 
glBindTexture(GL_TEXTURE_1D, texture); 
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 

// Load textureData 
GLubyte colorData[] = { 
    0xff, 0x00, 0x00, 
    0xff, 0xff, 0x00, 
    0x00, 0xff, 0x00, 
    0x00, 0xff, 0xff, 
    0x00, 0x00, 0xff, 
    0xff, 0x00, 0xff 
}; 
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 6, 0, GL_RGB, GL_UNSIGNED_BYTE, colorData); 
glEnable(GL_TEXTURE_1D); 
+0

Merci pour la réponse. Je ne suis pas vraiment sûr de savoir comment utiliser les textures 1D comme une palette de couleurs, y at-il quelque chose que je peux lire pour apprendre? Merci d'avance (désolé, je suis un peu d'un opengl noob: D) – Xzhsh

+0

Merci encore pour l'aide – Xzhsh

4

Je ne connais rien à opengl, mais la compression de données ne sera-t-elle pas une solution de contournement naturelle ici? La prise en charge des types entiers ou des flottants 16 bits n'est-elle pas prise en charge? D'autres représentations de couleurs que 3 flottants par point?

+0

La compression des données semble bonne, mais je ne sais pas si je peux décompresser sur le côté GPU avec opengl. Je vais essayer d'indexer les couleurs, merci – Xzhsh

+0

Eh bien, même une vraie compression pourrait être possible avec GPGPU, mais je voulais simplement dire que glVertexPointer supporte apparemment GL_SHORT et glColorPointer - GL_BYTE. Avez-vous vraiment besoin d'une précision flottante là-bas? Bien sûr, l'indexation des couleurs est encore meilleure. – Shelwien

3

Si vous êtes prêt à faire face à la latence, vous pouvez double (ou plus!) Tamponner votre VBOs, le transfert de la géométrie dans un tampon tout en rendant d'un autre:

while(true) 
{ 
    draw_vbo(cur_vbo_id); 
    generate_new_geometry(); 
    load_vbo(nxt_vbo_id); 
    swap(cur_vbo_id, nxt_vbo_id); 
} 

EDIT: Vous pouvez également essayer interleaving vos vertex au lieu d'utiliser un VBO par composant.

+0

La latence n'est pas un problème, mais je ne suis pas sûr que je vois comment double VBOs buffering aidera à accélérer les temps de transfert . Y a-t-il des frais généraux par VBO? Et merci, je vais essayer d'entrelacer demain – Xzhsh

1

Vous dites que c'est lié aux E/S. Cela implique que vous l'avez profilé et que vous l'avez vu passer 50% ou plus de son temps à attendre des E/S.

Si oui, c'est ce sur quoi vous devez vous concentrer, pas les graphiques.

Sinon, alors certaines des autres réponses me semblent bonnes. Peu importe, le profil, ne devinez pas.This is the method I use.

+0

Par I/O lié il veut dire E/S sur le bus PCI-express du GPU, pas de disque dur ou de réseau. Mais tu as quand même raison. – Calvin1602

+0

Je suis à peu près sûr que c'est lié à l'IO parce que j'utilise juste le même cadre joué encore et encore pour les tests. Il accélère jusqu'à 60fps si je commente juste le memcpy: \. – Xzhsh

+0

@ Calvin1602: Merci pour la correction, ainsi édité. –

0

Quelques pointeurs:

  • stocker autant de données que possible sur la carte graphique et la charge que ce qui est vraiment nécessaire (assez évident)
  • utiliser les niveaux de LOD dans les arbres (kd- ou octtrees) et calculer autant que possible en vue de surmonter avant
  • compression sur le disque est trop utile goulots d'étranglement io
Questions connexes