Cylindrical Billboard

Questions à propos du scripting Shader.
Le_duke
Messages : 28
Inscription : 18 Juin 2010 10:55

Cylindrical Billboard

Message par Le_duke » 06 Avr 2016 00:52

Salut !

Je suis actuellement en train de travailler sur un système de forêt billboard inspiré de TurboForest (http://forum.unity3d.com/threads/turbof ... ng.224165/)

Mais le shader utilisé par le système d'origine ne me convient pas.
Pour résumer c'est du billboard classique mais en fonction de la position de la caméra on a une vue différente de l'arbre (vue de dessus, de 3/4 ect)

L'idée est bonne mais il faudrait bien améliorer le shader pour avoir un bon résultat.
D'ailleurs on peux obtenir des résultat assez fou avec ce genre de technique :

https://www.youtube.com/watch?v=4Ghulpp6CPw

Enfin Bref c'est pas la question, pour l'instant je voudrais me contenter d'un billboarding classique mais qui permet la rotation du billboard uniquement sur l'axe Y.
Ce qui évite les rotation des arbres lorsque la caméra fait une rotation sur Z par exemple.

D'après ce que j'ai pu lire sur le net ce type de billboarding est appelé Cylindrical Billboarding.

J'ai trouvé et adapté une bonne solution qui utilise un geometry shader mais j'aimerais utiliser un shader compatible avec du matériel plus ancien et aussi compatible mac.

Donc je cherche une méthode alternative et comme je ne connais pas encore très bien le dev de shader j'ai besoin de votre aide :-D .

J'ai donc trouvé un shader de billboarding tout simple que je vais utiliser comme point de départ :

Code : Tout sélectionner

Shader "Cg  shader for billboards" {
   Properties {
      _MainTex ("Texture Image", 2D) = "white" {}
   }
   SubShader {
      Pass {   
         CGPROGRAM
 
         #pragma vertex vert  
         #pragma fragment frag 

         // User-specified uniforms            
         uniform sampler2D _MainTex;        
 
         struct vertexInput {
            float4 vertex : POSITION;
            float4 tex : TEXCOORD0;
         };
         struct vertexOutput {
            float4 pos : SV_POSITION;
            float4 tex : TEXCOORD0;
         };
 
         vertexOutput vert(vertexInput input) 
         {
            vertexOutput output;

            output.pos = mul(UNITY_MATRIX_P, 
              mul(UNITY_MATRIX_MV, float4(0.0, 0.0, 0.0, 1.0))
              - float4(input.vertex.x, input.vertex.y, 0.0, 0.0));
 
            output.tex = input.tex;

            return output;
         }
 
         float4 frag(vertexOutput input) : COLOR
         {
            return tex2D(_MainTex, float2(input.tex.xy));   
         }
 
         ENDCG
      }
   }
}
Le problème étant de limiter la rotation du billboard à l'axe Y.

De ce que je comprend du shader et de l'explication donnée avec, voir source: https://en.wikibooks.org/wiki/Cg_Progra ... Billboards

On transforme l'origine de l'object dans les coordonnées de l'espace relatif à la caméra et on y soustrait la position des vertex sur l'axe x et y ce qui fait que l'objet est toujours face à la caméra. :super:

donc si on applique une rotation sur :
output.pos = mul(UNITY_MATRIX_P,
mul(UNITY_MATRIX_MV, float4(0.0, 0.0, 0.0, 1.0))
- float4(input.vertex.x, input.vertex.y, 0.0, 0.0));

Il y est possible de bloquer le billboard sur l'axe Y uniquement.
Le problème c'est que je comprend bien qu'il faut calculer une matrice de rotation pour ça, mais je ne sais pas comment m'y prendre.

Help :] ?


Merci pour votre aide !
Dernière édition par Le_duke le 09 Avr 2016 00:49, édité 1 fois.

Avatar de l’utilisateur
Alesk
Messages : 2302
Inscription : 13 Mars 2012 09:09
Localisation : Bordeaux - France
Contact :

Re: Cylindrical Billboard

Message par Alesk » 06 Avr 2016 12:15

Yo !

Une piste ici : http://answers.unity3d.com/questions/97 ... grass.html
Qui mène à ce shader : http://answers.unity3d.com/storage/atta ... lboard.txt

Où tu trouves ceci :

Code : Tout sélectionner

// billboard's normal is a projection plane's normal
					float3 viewDirection = UNITY_MATRIX_IT_MV[2].xyz;
					viewDirection.y = 0;
					viewDirection = normalize(viewDirection);
					
					float3 up = float3(0, 1, 0);
					float3 right = normalize(cross(up, viewDirection));
Donc tu te retrouves avec les vecteurs directeurs, et non pas une matrice, à voir si ça peut quand même t'être utile.

Par contre, si tu comptes avoir un gameobject par billboard, ça risque de consommer pas mal si tu colles bcp d'arbres dans ta forêt.

Le_duke
Messages : 28
Inscription : 18 Juin 2010 10:55

Re: Cylindrical Billboard

Message par Le_duke » 06 Avr 2016 23:32

Hey,

Merci pour ton aide je vais regarder de ce coté j'aurais un peu de temps pour tester demain.
J'ai aussi remarqué que le shader billboard speedtree à le fonctionnement que je veux, mais j'y comprend pas grand chose pour l'instant, ça reste une autre piste.
Par contre, si tu comptes avoir un gameobject par billboard, ça risque de consommer pas mal si tu colles bcp d'arbres dans ta forêt.
Non t’inquiète pas j'ai plusieurs milliers d'arbre par gameobject :-D du coup les perfs sont plutôt bonnes.
D'ailleurs il y a moyen d'avoir une foret avec une bonne densité !

Je posterais des screenshots dès que ça marche.

Avatar de l’utilisateur
Alesk
Messages : 2302
Inscription : 13 Mars 2012 09:09
Localisation : Bordeaux - France
Contact :

Re: Cylindrical Billboard

Message par Alesk » 07 Avr 2016 10:20

Ok bon courage ! J'attends de voir la suite ;)

Avatar de l’utilisateur
boubouk50
ModoGenereux
ModoGenereux
Messages : 5402
Inscription : 28 Avr 2014 11:57
Localisation : Toulouse

Re: Cylindrical Billboard

Message par boubouk50 » 07 Avr 2016 10:36

+1. Très intéressant.
"Ce n'est pas en améliorant la bougie, que l'on a inventé l'ampoule, c'est en marchant longtemps."
Nétiquette du forum
Savoir faire une recherche
Apprendre la programmation

Avatar de l’utilisateur
@RLG
Messages : 367
Inscription : 17 Jan 2015 00:13
Localisation : Rennes

Re: Cylindrical Billboard

Message par @RLG » 07 Avr 2016 10:37

+2 ::d
Everything happens for a reason. Sometimes the reason is that you're stupid and make bad decisions.

Le_duke
Messages : 28
Inscription : 18 Juin 2010 10:55

Re: Cylindrical Billboard

Message par Le_duke » 09 Avr 2016 01:16

Je suis bien content j'y suis arrivé :-D

Voici à quoi ressemble le vertex shader au final.

Code : Tout sélectionner


struct vertexInput {
		float3 vertex : POSITION;		 //vertex pos
		float4 texcoord : TEXCOORD0;	 //uvs
		float2 texcoord1 : TEXCOORD1; //permet de switcher entre plusieurs type d'arbres
		float4 pos : NORMAL;			 //Lorsque je genere le mesh pour une chunk de forêt tous les quad sont sur 0,0,0 , je passe ensuite la position de l'arbre dans la normal (qui est inutile pour un billboard) pour le placer directement dans le shader.
	};

	struct vertexOutput {
		float4 pos : SV_POSITION;
		float2 tex : TEXCOORD0;
	};

	vertexOutput vert(vertexInput input)
	{
		vertexOutput output;

		//position de l'arbre en coord world
		float3 worldPos = mul(_Object2World, input.pos).xyz;

		// vecteur de direction object -> camera
		float3 look = _WorldSpaceCameraPos - worldPos;
		look.y = 0;
		look = normalize(look);

		float3 up = fixed3(0, 1, 0);
		//vecteur tangent à look
		float3 right = normalize(cross(up, look));
		//vecteur de référence pour le calcul de la rotation sur Y
		float3 xVector = float3(-1, 0, 0);

		//calcul de l'angle de rotation de l'abre nécessaire
		float angle = atan2(right.z, right.x) - atan2(xVector.z, xVector.x)+ 3.1415;

		//calcul de la matrice de rotation
		float3x3  rotMatrix;
		float cosinus =  cos(angle);
		float sinus =   sin(angle);
		rotMatrix[0].xyz = float3(cosinus, 0 , sinus);
		rotMatrix[1].xyz = float3(0, 1, 0);
		rotMatrix[2].xyz = float3(sinus, 0, cosinus);

		//rotation du vertex
		float4 newPos = float4(mul(rotMatrix, input.vertex), 1);
		//positionement de l'arbre
		newPos.xyz += input.pos.xyz;
		output.pos = mul(UNITY_MATRIX_MVP, newPos);


		/************Textures************/
		float2 treeShift= input.texcoord2;
		output.tex = input.texcoord + treeShift;

		return output;
	}
Au départ j'avais prévu de faire un shader où tous les billboards seraient orientés face au plan de la caméra mais en faite vue du dessus c’était pas optimal.

Donc au final, je me suis surtout inspiré de ce que j'ai trouvé dans le shader speedtree, voir (SpeedTreeBillboardCommon.cginc dans les built-in shaders Unity).

Le principe c'est de calculer l'orientation de l'arbre en fonction de ça position par rapport à la caméra.
Ensuite, on tourne chaque quad pour que ça normale pointe vers la camera.
Et le résultat est meilleur du coup je trouve.

Voici quelques screenshots du résultat.

Image

Image

En vue du dessus :
Image

Je vais utiliser ce système de forêt dans un projet de simulateur de parapente sur lequel je travaille depuis déjà pas mal de temps.

Pour l'instant j'utilise du billboard uniquement parce que ça permet d'afficher beaucoup d'arbres, de les afficher sur une bonne distance, mais surtout je peux les générer au fur et à mesure que le joueur avance et c'est plutôt pratique sur une map de 10K km² ::d

Il y a encore du travail pour avoir quelque chose de vraiment bien, notamment la gestion des ombres ect. mais pour ça je verrais plus tard.

Et Merci Alesk pour le lien ça ma mis sur la bonne piste !

Avatar de l’utilisateur
Alesk
Messages : 2302
Inscription : 13 Mars 2012 09:09
Localisation : Bordeaux - France
Contact :

Re: Cylindrical Billboard

Message par Alesk » 09 Avr 2016 09:42

Super !

Il ne te reste plus qu'à réussir à leur donner du volume ... bon courage ! :-D

Pour les ombres, j'ai un truc similaire ici : viewtopic.php?f=8&t=12097
Dans mon cas j'utilise un geometry shader, mais tu devrais pouvoir t'en sortir de la même façon que ce que tu as fait ici.

Avatar de l’utilisateur
F@B
Messages : 1843
Inscription : 01 Août 2013 10:41
Contact :

Re: Cylindrical Billboard

Message par F@B » 09 Avr 2016 10:38

Alesk a écrit :Super !

Il ne te reste plus qu'à réussir à leur donner du volume ... bon courage ! :-D

Pour les ombres, j'ai un truc similaire ici : viewtopic.php?f=8&t=12097
Dans mon cas j'utilise un geometry shader, mais tu devrais pouvoir t'en sortir de la même façon que ce que tu as fait ici.
Sympa ton shader :)

Pour les ombres Tout est présent sur l'exemple qu'a donné Alesk :
http://answers.unity3d.com/questions/97 ... grass.html
ʕ·͡ᴥ·ʔ ==> Mon Portfolio <== ʕ·͡ᴥ·ʔ

Merci de lire et de prendre en considération la Nétiquette des Forums avant de poster un sujet !

Le_duke
Messages : 28
Inscription : 18 Juin 2010 10:55

Re: Cylindrical Billboard

Message par Le_duke » 09 Avr 2016 23:10

Il ne te reste plus qu'à réussir à leur donner du volume ... bon courage ! :-D

Pour les ombres, j'ai un truc similaire ici : viewtopic.php?f=8&t=12097
Dans mon cas j'utilise un geometry shader, mais tu devrais pouvoir t'en sortir de la même façon que ce que tu as fait ici.
0 x
Pour ce shader je voulais justement une version plus simple sans la partie 'texture 3D' pour donner du volume.
Mais je pense que de toute façon ça ne serait pas trop compliqué à implémenter étant donnée que l'on pourrait facilement calculer l'angle par rapport à la caméra qui correspond le mieux à une des vue et ensuite décaler les uvs pour l'afficher.

Merci pour le lien je le met de coté pour étudier ça en détail dès que j'aurais la motiv et le temps de gérer les ombres :cote: .
Sympa ton shader :)
Merci ! J’espère que ça pourra servir à d'autres en tout cas ça m'a permis de comprendre un peu mieux comment les shaders fonctionnent donc c'est cool =)

Répondre

Revenir vers « les Shaders »