Emetteur de particules : optimisation de code
Re: Emetteur de particules : optimisation de code
j'utilise les deux couches d'uv, la première est utilisée pour l'effet d'éclairage et la seconde pour l'effet de noise en alpha
pour la première couche, c'est calculé par rapport à la position de la particule vis à vis de la camera et de l'orientation la lumière, et le roll du billboard est aussi dépendant de l'orientation de la lumière et de la caméra. (ptain j'vais livrer tous mes secrets de fabrication :p)
Tout ça est normalement calculable dans un shader... le souci c'est qu'une fois dans le shader je n'ai pas trouvé comment faire pour savoir à quel vertex du billboard j'avais affaire, et donc quel calcul effectuer... Mais là c'était dans le cas où on a toujours 4 vertices positionnés au centre du billboard, et ils sont ensuite recalés par le shader en fonction de la taille de la particule.
Si tu me dis que tu peux recréer le billboard simplement à partir de la position d'un seul vertex pour chaque particule, ça m'intéresse énormément de savoir comment tu fais ça
(promis ZJP, je continue sur ma lancée actuelle, et si cette optimisation fonctionne elle sera dans la v2 )
pour la première couche, c'est calculé par rapport à la position de la particule vis à vis de la camera et de l'orientation la lumière, et le roll du billboard est aussi dépendant de l'orientation de la lumière et de la caméra. (ptain j'vais livrer tous mes secrets de fabrication :p)
Tout ça est normalement calculable dans un shader... le souci c'est qu'une fois dans le shader je n'ai pas trouvé comment faire pour savoir à quel vertex du billboard j'avais affaire, et donc quel calcul effectuer... Mais là c'était dans le cas où on a toujours 4 vertices positionnés au centre du billboard, et ils sont ensuite recalés par le shader en fonction de la taille de la particule.
Si tu me dis que tu peux recréer le billboard simplement à partir de la position d'un seul vertex pour chaque particule, ça m'intéresse énormément de savoir comment tu fais ça
(promis ZJP, je continue sur ma lancée actuelle, et si cette optimisation fonctionne elle sera dans la v2 )
Re: Emetteur de particules : optimisation de code
Je t'ai retrouvé un vieux shader de test qui permet de générer un quad billboard en screen space (la taille dépend ne pas de la distance), il est pas fait pour tourner sous unity mais au moins ça te donne une idée de la syntaxe
mainV =>vertex shader
transforme chaque vertex en screen space, définit une couleur
mainG => geometry shader
génére un billboard pour chaque vertex,
ignore la couleur reçu et output 6 vertex (je sais c'est moche mais c'était pour mettre de la couleur) avec à chaque fois la position et la couleur
mainP => fragment shader
affiche la couleur du vertex
Sinon j'ai continué mes test avec les compute shader, ici j'ai 320 000 particules :
http://www.youtube.com/watch?v=k9pOjRSeh00
je calcul et j'affiche tout directement sur le GPU sans jamais retélécharger quoi que ce soit sur le CPU.
edit: V2: http://www.youtube.com/watch?v=K_oJk6yn-Ws
edit: V3: http://www.youtube.com/watch?v=3puot3qlYOg
Code : Tout sélectionner
void mainV(uniform float4x4 worldViewProj,
inout float4 position : POSITION,
inout float2 UV : texcoord0,
inout int vertexID : VERTEXID,
out float4 color : COLOR)
{
color = float4(1,0,0,1);//(vertexID % 2).xxxx;
position = mul(worldViewProj, position);
}
TRIANGLE
void mainG( AttribArray<float4> position : POSITION,
AttribArray<float4> color : COLOR,
AttribArray<int> vertexID : VERTEXID,
uniform float4x4 worldViewProj)
{
for (int i = 0; i < position.length; i++)
{
emitVertex(float4(position[i].x - 1, position[i].y - 1, position[i].z, position[i].w), float4(1, 0, 0, 1) : COLOR);
emitVertex(float4(position[i].x - 1, position[i].y + 1, position[i].z, position[i].w), float4(0, 1, 0, 1) : COLOR);
emitVertex(float4(position[i].x + 1, position[i].y + 1, position[i].z, position[i].w), float4(0, 0, 1, 1) : COLOR);
restartStrip();
emitVertex(float4(position[i].x - 1, position[i].y - 1, position[i].z, position[i].w), float4(1, 0, 0, 1) : COLOR);
emitVertex(float4(position[i].x + 1, position[i].y + 1, position[i].z, position[i].w), float4(0, 1, 0, 1) : COLOR);
emitVertex(float4(position[i].x + 1, position[i].y - 1, position[i].z, position[i].w), float4(0, 0, 1, 1) : COLOR);
restartStrip();
}
}
float4 mainP (float4 color : COLOR) : COLOR
{
return color;
}
transforme chaque vertex en screen space, définit une couleur
mainG => geometry shader
génére un billboard pour chaque vertex,
ignore la couleur reçu et output 6 vertex (je sais c'est moche mais c'était pour mettre de la couleur) avec à chaque fois la position et la couleur
mainP => fragment shader
affiche la couleur du vertex
Sinon j'ai continué mes test avec les compute shader, ici j'ai 320 000 particules :
http://www.youtube.com/watch?v=k9pOjRSeh00
je calcul et j'affiche tout directement sur le GPU sans jamais retélécharger quoi que ce soit sur le CPU.
edit: V2: http://www.youtube.com/watch?v=K_oJk6yn-Ws
edit: V3: http://www.youtube.com/watch?v=3puot3qlYOg
Dernière édition par Titan le 26 Juin 2013 23:51, édité 2 fois.
____________________________________________
Hop Boy
Hop Boy
Re: Emetteur de particules : optimisation de code
Super, merci pour le shader, je vais dépioter ça ^^
Au final, il faudrait que je parvienne à faire un mix de ces deux méthodes
Bien joué !Titan a écrit :Sinon j'ai continué mes test avec les compute shader, ici j'ai 320 000 particules :
http://www.youtube.com/watch?v=k9pOjRSeh00
je calcul et j'affiche tout directement sur le GPU sans jamais retélécharger quoi que ce soit sur le CPU.
Au final, il faudrait que je parvienne à faire un mix de ces deux méthodes
- artemisart
- Messages : 1893
- Inscription : 21 Juin 2011 19:51
- Localisation : Centre
- Contact :
Re: Emetteur de particules : optimisation de code
Ça passe easy avec ParallelAlesk a écrit :Artemisart, actuellement, ma boucle de mise à jour des particules ressemble à ça :Comme la variable liveParticleCount est mise à jour durant la boucle et qu'en plus je procède à des échanges de valeurs dans mon array particlesPointers je doute que ça soit safe d'avoir plusieurs cores qui triturent ce tableau en même temps de cette façon.Code : Tout sélectionner
_deltaTime = Time.deltaTime; int index; int pointer; for(pointer=0; pointer<liveParticleCount; pointer++){ index = particlesPointers[pointer]; particles[index].lifetime += _deltaTime; if(particles[index].lifetime < particles[index].startLifetime){ particles[index].position += particles[index].velocity * _deltaTime; }else{ liveParticleCount--; particleLive = liveParticleCount; particlesPointers[pointer] = particlesPointers[liveParticleCount]; particlesPointers[liveParticleCount] = index; particles[index].startLifetime = 0f; particles[index].lifetime = 0f; pointer--; } }
Par contre, en ajoutant un autre tableau (une List cette fois) où je stockerais les index des particules mortes, je pourrais faire la mise à jour de l'ordre des index dans un second temps.
Penses-tu que ça pourrait passer dans Parallel ?
Nan sérieusement le truc doit pas marcher super vu les échanges, après tu peux toujours lock pour synchroniser le tout mais si ta boucle est rapide je doute que la différence soit visible (et y a surement d'autres trucs à optimiser avant de se faire ch*** à passer ça en parallel, à commencer par particles[index] qui devrait exister une seule fois je pense ).
Re: Emetteur de particules : optimisation de code
nope, si je colle particles[index] dans une variable locale, c'est plus lentartemisart a écrit :Nan sérieusement le truc doit pas marcher super vu les échanges, après tu peux toujours lock pour synchroniser le tout mais si ta boucle est rapide je doute que la différence soit visible (et y a surement d'autres trucs à optimiser avant de se faire ch*** à passer ça en parallel, à commencer par particles[index] qui devrait exister une seule fois je pense ).
Re: Emetteur de particules : optimisation de code
Plop !
Bon, ça avance bien !
J'ai trouvé une petite ruse pour réduire assez drastiquement le temps de tri sur le Z des particules quand il y en a beaucoup, du coup je tombe à environ 1ms pour trier 100 000 particules
(par contre, le rendu avec la fonction GL est totalement à la ramasse, même avec pas trop de particules, d'où le fps moisi)
Du coup maintenant c'est plus long de faire le test de frustum, que je fais avec un dot product entre la position de la particule et la direction de la caméra.
Il ressemble à ça :
Si vous connaissez une méthode encore plus simple je suis intéressé Mais sinon, c'est pas bien grave, ça boost déjà pas mal comme ça (ouiiii ZJP, je ne m'égare pas, promis)
J'ai donc maintenant une classe qui s'occupe de centraliser le test de frustum et le tri de tous mes émetteurs, faut que je rebranche la création du mesh final là dessus.
Bon, ça avance bien !
J'ai trouvé une petite ruse pour réduire assez drastiquement le temps de tri sur le Z des particules quand il y en a beaucoup, du coup je tombe à environ 1ms pour trier 100 000 particules
(par contre, le rendu avec la fonction GL est totalement à la ramasse, même avec pas trop de particules, d'où le fps moisi)
Du coup maintenant c'est plus long de faire le test de frustum, que je fais avec un dot product entre la position de la particule et la direction de la caméra.
Il ressemble à ça :
Code : Tout sélectionner
float angle = Mathf.Cos(_camera.camera.fieldOfView * Mathf.Deg2Rad);
direction = particulePos - camPos;
if( Vector3.Dot(camDir,direction.normalized) > angle ){
// particules visible
}
J'ai donc maintenant une classe qui s'occupe de centraliser le test de frustum et le tri de tous mes émetteurs, faut que je rebranche la création du mesh final là dessus.
- artemisart
- Messages : 1893
- Inscription : 21 Juin 2011 19:51
- Localisation : Centre
- Contact :
Re: Emetteur de particules : optimisation de code
+1, c'est dommage qu'on ai pas accès a plus de fonctions (tu peux montrer comment tu draw les points quand même ?).Alesk a écrit :(par contre, le rendu avec la fonction GL est totalement à la ramasse, même avec pas trop de particules, d'où le fps moisi)
Plus long par rapport à quoi ?Alesk a écrit :Du coup maintenant c'est plus long de faire le test de frustum
Re: Emetteur de particules : optimisation de code
Ah ben comme je veux le vendre sur l'asset store au final, j en vais pas tout publier non plus heinartemisart a écrit :+1, c'est dommage qu'on ai pas accès a plus de fonctions (tu peux montrer comment tu draw les points quand même ?).Alesk a écrit :(par contre, le rendu avec la fonction GL est totalement à la ramasse, même avec pas trop de particules, d'où le fps moisi)
Mais bon, ma fonction pour dessiner les particules ressemble à ça
Code : Tout sélectionner
GL.Begin( GL.QUADS );
for(i = 0; i < visibleParticles ; i++){
groupIndex = -1;
maxValue = -1f;
for(g = 0; g < groupCount; g++){
if(_sortGroups[g].index < _sortGroups[g].count){
if(_sortGroups[g].items[ _sortGroups[g].index ].order >= maxValue){
groupIndex = g;
maxValue = _sortGroups[g].items[ _sortGroups[g].index ].order;
}
}
}
if(groupIndex > -1){
particleIndex = _sortGroups[groupIndex].items[ _sortGroups[groupIndex].index ].particleIndex;
emitterIndex = _sortGroups[groupIndex].items[ _sortGroups[groupIndex].index ].emitterIndex;
_sortGroups[groupIndex].index++;
p = Emitters[emitterIndex].particles[particleIndex];
pos = p.position;
size = p.size;
color = p.color;
color.a = 1f - p.lifetime / p.startLifetime;
GL.Color(color);
GL.Vertex( pos + _billboardShape[0] * size );
GL.Vertex( pos + _billboardShape[1] * size );
GL.Vertex( pos + _billboardShape[2] * size );
GL.Vertex( pos + _billboardShape[3] * size );
}
}
GL.End();
Plus long par rapport à quoi ?[/quote] par rapport au tri, le frustum prend en moyenne deux fois plus de temps.Alesk a écrit :Du coup maintenant c'est plus long de faire le test de frustum
Mais bon, là je me suis réjouis trop vite, j'ai un souci avec le GC je pense, j'ai des pics à 100ms régulièrement sur le test de frustum justement
- artemisart
- Messages : 1893
- Inscription : 21 Juin 2011 19:51
- Localisation : Centre
- Contact :
Re: Emetteur de particules : optimisation de code
Je parlais des fonctions GL (et j'ai pas tout pigé de la fonction de draw ^^ c'est assez chaud quand même).Alesk a écrit :Ah ben comme je veux le vendre sur l'asset store au final, j en vais pas tout publier non plus heinartemisart a écrit :+1, c'est dommage qu'on ai pas accès a plus de fonctions (tu peux montrer comment tu draw les points quand même ?).Alesk a écrit :(par contre, le rendu avec la fonction GL est totalement à la ramasse, même avec pas trop de particules, d'où le fps moisi)
Ça dépend d'où ça vient mais peut-être que tu pourrait regrouper les particules et checker juste les groupes ?Alesk a écrit :Mais bon, là je me suis réjouis trop vite, j'ai un souci avec le GC je pense, j'ai des pics à 100ms régulièrement sur le test de frustum justement
Re: Emetteur de particules : optimisation de code
Ben mes appels à la classe GL se limitent à ce qui est dans le bout de code de mon post précédent...artemisart a écrit :Je parlais des fonctions GL (et j'ai pas tout pigé de la fonction de draw ^^ c'est assez chaud quand même).
En fait je viens de trouver : c'est dû à mon optimisation sur le tri (qui découle de ce qui se passe dans mon test de frustum...) je tente une autre approche ^^artemisart a écrit :Ça dépend d'où ça vient mais peut-être que tu pourrait regrouper les particules et checker juste les groupes ?