Deux normales différentes sur un même vertex

Questions à propos du scripting Shader.
Avatar de l’utilisateur
Alesk
Messages : 2303
Inscription : 13 Mars 2012 09:09
Localisation : Bordeaux - France
Contact :

Deux normales différentes sur un même vertex

Message par Alesk » 17 Nov 2015 19:54

Bonjour tout le monde !

Je débarque avec un souci bien velu :)

J'ai besoin d'avoir deux normales différentes pour chaque vertex de mon mesh, une incluant le smoothing avec les voisins, et une autre pouvant être arbitraire.
Et j'ai besoin que ces deux normales réagissent aux déformations du mesh lorsqu'il est déformé avec des bones.

J'avais tenté de stocker ma seconde normale dans la couleur des vertices, mais malheureusement ça ne tient pas compte des déformations induites par les bones.

Pour être plus précis sur ce que je cherche à faire, je travaille actuellement à faire quelque chose qui ressemble au shader utilisé sur les robots dans le jeu Transformers Devastation.
La normale smoothée me sert à générer l'outline du mesh (avec faisant une dilatation du mesh le long de la normale)
Et la normale arbitraire me sert à définir des zones en flat shading.

Le souci est donc que seule la normale qui est stockée dans l'attribut prévu à cet effet est bien affectée par les déformation du skinning, ce qui fait que je ne peux pas avoir à la fois l'outline et le shading, puisque seulement l'un des deux dispose au final des normales transformées correctement.

Au pire il me reste l'option d'intégrer aussi l'outline dans le mesh, mais je préfèrerais éviter d'en arriver là.

Si vous avez des pistes...

Avatar de l’utilisateur
boubouk50
ModoGenereux
ModoGenereux
Messages : 6186
Inscription : 28 Avr 2014 11:57
Localisation : Saint-Didier-en-Bresse (71)

Re: Deux normales différentes sur un même vertex

Message par boubouk50 » 18 Nov 2015 10:23

La normale du mesh sera celle du smoothing group, ça parait normal. Donc il te faut trouver comment récupérer cette deuxième normale arbitraire.
Une normalMap n'est pas possible? Elle serait dépendante de la normale du mesh, donc dépendante de la déformation du mesh par le skin.
Ensuite pour la créer, il te faut dupliquer le mesh, lui mettre tes normales arbitraires, faire une projection sur ton mesh smoothé, et générer la normalMap (Enfin, je me doute bien que tu sais faire cela).
Sinon, tu pourrais avoir les normales arbitraires dans le mesh, et générer au runtime les normales smoothées dans Unity. C'est possible puisque Unity peut le faire à l'import, après niveau ressources et complexité et accès au mesh, je ne sais pas du tout si c'est viable, mais c'est une piste quand même. La recréer par rapport aux tangentes?
"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
Alesk
Messages : 2303
Inscription : 13 Mars 2012 09:09
Localisation : Bordeaux - France
Contact :

Re: Deux normales différentes sur un même vertex

Message par Alesk » 18 Nov 2015 12:35

boubouk50 a écrit :Sinon, tu pourrais avoir les normales arbitraires dans le mesh, et générer au runtime les normales smoothées dans Unity.
C'est actuellement ce que j'ai tenté :
1) import du mesh avec les normales en flat par endroit et smooth ailleurs.
2) analyse du mesh pour faire une version smoothée des normales.

C'est de toute manière obligatoire de faire le smoothing dans unity, car un rendu flat implique d'avoir des normales différentes pour un vertex partagé par deux triangles, et donc avoir en fait deux vertices. Ce qui est géré automatiquement à l'import.

J'ai pensé à la normal map, mais j'aurais préféré éviter... il faut que je teste.
Actuellement j'ai déjà besoin d'utiliser deux jeux de coordonnées UV : 1 pour les textures de reflets, et l'autre pour les contours.
Utiliser une normal map impliquerait d'avoir une couche d'UV supplémentaire, il faut que je vérifie qu'Unity le supporte (je crois que oui, dans les dernières mises à jour)

Merci pour les idées ;)

Et pour info, ça donne ça actuellement : http://www.alesk.fr/demo/wakame/
(et l'objectif c'est ça : http://wccftech.com/transformers-devast ... y-trailer/)

Je précise que c'est un test à l'arrache et qu'il faut revoir l'intégralité du dépliage UV pour obtenir un truc correct.
Le mesh de droite affiche une version correcte du shader (mais qui déconne encore trop vis à vis de ce que je veux obtenir)
Celui de gauche est skinné, et le shader réagit mal, justement à cause des normales que j'avais stocké dans la couleur... et qui ne sont donc pas mises à jour par le skinning.

Avatar de l’utilisateur
boubouk50
ModoGenereux
ModoGenereux
Messages : 6186
Inscription : 28 Avr 2014 11:57
Localisation : Saint-Didier-en-Bresse (71)

Re: Deux normales différentes sur un même vertex

Message par boubouk50 » 18 Nov 2015 13:10

Humm, ce n'est qu'une idée, et je ne sais absolument pas si cela est possible ou accessible. Mais t'est-il possible de savoir quels sommets sont dupliqués?
L'idée: tu exportes ton mesh en flat. Donc tes sommets sont dupliqués pour avoir chacun une normale différente. Si tu peux savoir quels sommets sont les mêmes, tu peux calculer la normale moyenne de ces sommets qui devient alors ta normale unique lissée.
"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
Alesk
Messages : 2303
Inscription : 13 Mars 2012 09:09
Localisation : Bordeaux - France
Contact :

Re: Deux normales différentes sur un même vertex

Message par Alesk » 18 Nov 2015 13:26

Oui c'est ce que je fais déjà d'ailleurs.
Le souci c'est que je me retrouve alors avec deux listes de normales, mais un seul canal pour les stocker !

Seules les valeurs stockées dans mesh.normals seront traitées par les déformations liées au skinning. (Sur un mesh non déformé, je n'ai aucun problème de ce point de vue.)

Bref, à part la normal map... je crois que je n'ai pas tellement d'autres options.

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

Re: Deux normales différentes sur un même vertex

Message par F@B » 19 Nov 2015 01:16

Salut Alesk,

une idée comme ça, dans un geometry shader t'as les trois vertices d'un triangle et donc tu peux recalculer la normale flat?

je le fait dans un shader avec un truc du genre :

Code : Tout sélectionner

					
	float3 norm = normalize(cross((input[1].pos-input[0].pos), (input[2].pos-input[0].pos)));
et d’ailleurs ça m’ennuie car je voudrais le smooth en utilisant le TriangleAdj mais pas moyen dans unity.... ça fait n’importe quoi. :(
ʕ·͡ᴥ·ʔ ==> Mon Portfolio <== ʕ·͡ᴥ·ʔ

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

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

Re: Deux normales différentes sur un même vertex

Message par Alesk » 16 Fév 2016 13:01

Ok merci pour l'info :)
(et désolé pour le retour tardif...)

Mais là, si je pouvais éviter de passer par du DX11, ça m'arrangerait ;)

Sinon, c'est quoi ton souci de smoothing exactement ?

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

Re: Deux normales différentes sur un même vertex

Message par F@B » 16 Fév 2016 16:27

oula c'est vieux je sais plus! :D

mais unity ne gère pas le triangleAdj et le lineAdj.

et toi, t'as trouvé une réponse a ton problème?
ʕ·͡ᴥ·ʔ ==> Mon Portfolio <== ʕ·͡ᴥ·ʔ

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

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

Re: Deux normales différentes sur un même vertex

Message par Alesk » 16 Fév 2016 16:47

Toujours pas... (mais j'y ai pas trop touché non plus)

Là il faut que je génère une normalmap qui corresponde à mon mesh avec ses zones non lissées (avec du flat par endroits donc) et que je l'applique au mesh où toutes les normales sont lissées (donc du smooth partout)

J'avais commencé à chercher comment faire ça, mais ça me faisait n'importe quoi... Donc n'importe quel lien vers un tuto clair expliquant comment faire pour intégrer une normalmap dans un shader, sera le bienvenu :)

C'est vraiment la plaie ce manque de doc sur les shaders >_<

Avatar de l’utilisateur
boubouk50
ModoGenereux
ModoGenereux
Messages : 6186
Inscription : 28 Avr 2014 11:57
Localisation : Saint-Didier-en-Bresse (71)

Re: Deux normales différentes sur un même vertex

Message par boubouk50 » 16 Fév 2016 17:02

Pour intégrer les normalMaps, j'ai du chercher un bon moment, qui plus est, c'était pour Android, et la fonction de base est fausse, mais par magie ça marche dans presque tous les cas.
Je te file un de mes shaders avec une normalMap qui est utilisée 2 fois pour créer un effet de vague:

Code : Tout sélectionner

Shader "Custom/Normal" {
	Properties {
		_DiffuseColor ("Diffuse Color", Color) = (0, 0, 0, 0.5)
		_BumpMap ("Normal Map", 2D) = "bump" {}
		_Cube ("Reflection Cubemap", Cube) = "" {}
		_Fresnel ("Fresnel Intensity", Float) = 1.0
	}
	SubShader {
		Pass {
			Tags {"Queue" = "Opaque"}
			
			CGPROGRAM
			// Physically based Standard lighting model, and enable shadows on all light types
			#pragma vertex vert
			#pragma fragment frag
			#include "UnityCG.cginc"

			uniform sampler2D _BumpMap;
			uniform float4 _BumpMap_ST;
			uniform samplerCUBE _Cube;
			uniform fixed4 _DiffuseColor;
			uniform half _Fresnel;

			struct vertexInput {
				float4 vertex : POSITION;
				float4 texcoord : TEXCOORD0;
				float3 normal : NORMAL;
				float4 tangent : TANGENT;
			};
			
			struct vertexOutput {
	            float4 pos : SV_POSITION;
	            float4 posWorld : TEXCOORD0;
	            float4 tex : TEXCOORD1;
	            float3 tangentWorld : TEXCOORD2;  
	            float3 normalWorld : TEXCOORD3;
	            float3 binormalWorld : TEXCOORD4;
	         };
	         
	        vertexOutput vert(vertexInput input) 
			{
				vertexOutput output;

				float4x4 modelMatrix = _Object2World;
				float4x4 modelMatrixInverse = _World2Object;

				output.tangentWorld = normalize (mul (modelMatrix, float4 (input.tangent.xyz, 0.0)).xyz);
				output.normalWorld = normalize (mul (float4(input.normal, 0.0), modelMatrixInverse).xyz);
				output.binormalWorld = normalize (cross (output.normalWorld, output.tangentWorld) * input.tangent.w); // tangent.w is specific to Unity

				output.posWorld = mul (modelMatrix, input.vertex);
				output.tex = input.texcoord;
				output.pos = mul (UNITY_MATRIX_MVP, input.vertex);
				return output;
			}

			float4 frag(vertexOutput input) : COLOR
			{
				float4 encodedNormal1 = tex2D (_BumpMap, _BumpMap_ST.xy * input.tex.xy + float2 (_BumpMap_ST.z, 0.0));
				float3 localCoords1 = float3 (2.0 * encodedNormal1.a - 1.0, 2.0 * encodedNormal1.g - 1.0, 0.0);
				localCoords1.z = sqrt (1.0 - dot (localCoords1, localCoords1));
				float4 encodedNormal2 = tex2D (_BumpMap, _BumpMap_ST.xy * float2 (input.tex.x, -input.tex.y) + float2 (0.0, _BumpMap_ST.w));
				float3 localCoords2 = float3 (2.0 * encodedNormal2.a - 1.0, 2.0 * encodedNormal2.g - 1.0, 0.0);
				localCoords2.z = sqrt (1.0 - dot (localCoords2, localCoords2));

				float3x3 local2WorldTranspose = float3x3 (input.tangentWorld, input.binormalWorld, input.normalWorld);
				
				float3 normalDirection = normalize (normalize (mul (localCoords1, local2WorldTranspose)) + normalize (mul (localCoords2, local2WorldTranspose)));
				return fixed4 (abs (normalDirection), 1.0);
			}
			ENDCG
	    }
	}
	Fallback "Transparent/Diffuse"
}
Il y a une fonction normalement UnPackNormal () qui s'occupe de sortir les NormalMaps, mais elle était fausse pour certains cas (par magie la composante alpha était utilisée au lieu de rouge, et ça passait...)
Teste avec quand même, moi c'était pour de l'Android en OpenGL2.0.
"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

Répondre

Revenir vers « les Shaders »