Mon 1er Shader... need help

Questions à propos du scripting Shader.
etxtra
Messages : 7
Inscription : 29 Mars 2016 14:17

Mon 1er Shader... need help

Message par etxtra » 26 Avr 2016 20:38

Salut! :-D
j'ai récemment écrit mon 1er shader, pour remplir les besoins spécifique d'un projet avec unity3d
j'ai lu la documentation de mon mieux, souvent en anglais, sur unity3d.com et d'autres blogs, et appris uniquement sur le tas.

je poste ici, pour avoir vos retours, et peut être comprendre des trucs que je pige pas à 100%,
le voici, avec donc mes commentaires, qui sont ce que je pense avoir compris avec la marge d'erreur probables et des questions non élucidés:

Code : Tout sélectionner

/*
=== AlphaUniform_VertNFragShader ===== by SLH24; 2016; credits & thanks to : https://mispy.me/unity-alpha-blending-overlap/ (to the author)
(ce shader se base sur cet excellent article... avec un apport de modifications)
description:
Simple Shader qui gère la transparence, en évitant l'effet additif
lorsque les surfaces transparentes se chevauchent. le niveau de transparence est ajustable via _Transp entre 0 et 1 ... ou: (l'alpha value de la coleur _Tint)
note: _Tint n'influe que sur l'opacité, pas sur les couleurs finales!
*/
Shader "StickMan_Shaders/AlphaUniform_VertNFragShader"//je déclare le nom du shader, et le chemin d'accès....
{
	Properties
	{
		_Transp("Transparency Value", Range(0,1)) = 1// déclare une propriété publique: pour définir l'opacité;
		//_Tint("Transparency Color", Color) = (1,1,1,1)// déclare une propriété publique: Couleur, pour définir l'opacité principalement;
		_MainTex("Color (RGB) Alpha (A)", 2D) = "white"// déclare une propriété publique: La Texture Principale
	}

	SubShader
	{

		Tags{ "Queue" = "Transparent" "RenderType" = "Transparent" }// le shader opère dans l'étape de Rendu des shader Transparents, "L'Alpha Test"... (3000)

		Pass// la pass principale
		{
			Cull Off

			Stencil// On a recours au Stencil Buffer, afin de savoir si on travail sur pixel déjà transparent ou non
			{
				Ref 250// la valeur de référence est 250
				Comp NotEqual// si la valeur d'origine du stencil buffer est différente de la ref (250), alors le test "passe", or la ligne suivante fait en sorte que si
				// ça passe, car different, ça ne passera plus ensuite car stencil buffer égalera la ref;
				Pass Replace// quelque soit la valeur du stencil buffer à l'origine, je la remplace par 250; ainsi elle ne peut plus "passer" le test par la suite,
				// donc a droit à un seul rendu de ce shader pour un pixel donné;
			}
			
			Blend SrcAlpha OneMinusSrcAlpha // Transparence Traditionelle
			CGPROGRAM // mot-clé pour débuter le (vertex/fragment) program

				#pragma vertex vert// je dit que la fonction nommée vert contient un vertex program
				#pragma fragment frag// je dit que la fonction nommée frag contient un fragment program
				#include "UnityCG.cginc"// j'inclue le fichier UnityCG pour bénéficer de fonctions courantes...
				uniform sampler2D _MainTex;// je link (je lie) une variable "dans" le shader avec une variable property du début shader: de type sampler2D
				// le lien doit porter le même nom, les deux variables à lier, propriété et variable ont la même orthographe-syntaxe
				//float4 _Tint;
				float _Transp;// idem avec un float et la propriété _Transp


				// je déclare une structure, faite de 3 variables de type différents, et ces variables sont définies comme des Input Parameters (paramètres d'entrées)
				// ses paramètres d'entrées reçoivent en fait des données déjà établies et prêtes à l'emploi, telles que les couleur & position de texture ainsi que de vertex etc...
				// pour recevoir ces données là en entrée, il faut se conformer à une notion: la Cg/HLSL Semantic; je met donc la donnée Input en relation avec ma variable séparé par
				// deux points (:) il faut respecter l'orthographe de l'input désiré, par ex: COLOR pour la couleur des vertex, NORMAL pour la normal d'une vertice (vertex)
				struct v2f
				{
					half4 pos : POSITION;// the vertex position, typically a float3 or float4.
					half2 uv : TEXCOORD0;// the first UV coordinate, typically a float2..float4.
					float4 _Tint2 : COLOR0;// the per-vertex color, typically a float4.
					half2 ColorIN : TEXCOORD1;
					/*
					half2 TexCoordIN; //= uv;
					half2 ColorOUT; //= _Tint2;
					half2 TexCoordOUT; //= uv;
					*/
				};

				// questions: comment est appellé exécuté cette fonction? que recoit elle comme argument? quand? ce qu'elle renvoie c'est pour qui et quoi ?
				// ma fonction vert, comme dit explicitement dans #pragma, contient un vertex program
				// elle renvoie une structure de type v2f, structure que j'ai déjà déclaré
				v2f vert(appdata_img v)// cette fonction a pour paramètre une vertex structure de type appdata_img, que j'emploie avec la var v, cette structure me vient de l'include  UnityCG, incluse plus haut; appdata_img: vertex shader input with position and one texture coordinate.
				{
					v2f o;
					o.pos = mul(UNITY_MATRIX_MVP, v.vertex);//mul() Returns the vector result of multiplying a matrix M by a column vector v; a row vector v by a matrix M; or a matrix A by a second matrix B.
					// UNITY_MATRIX_MVP	(type: float4x4)	Current model * view * projection matrix.
					half2 uv = MultiplyUV(UNITY_MATRIX_TEXTURE0, v.texcoord);//The UV matrix (MultiplyUV() ) works the same as the regular model-view matrix It scales, translates and rotates (well, it never does rotates, but it can) the UV coords. It's a built-in part of the graphics card, but since most wrapped models never want to change UVs, it's often unused.
					// I suspect that Unity uses it to apply the offset and scale set in the Material.You might think, "why not just multiply by scale and add offset?" But the matrix is already there, and might run faster.
					// * UNITY_MATRIX_TEXTURE0 float4x4	Texture transformation matrices.
					o.uv = uv;
					// +++++++++++++++++++++
					//o.ColorOUT = o.ColorIN;
					//o.TexCoordOUT = o.TexCoordIN;
					// +++++++++++++++++++++++++
					return o;// renvoie la structure calculée; question ou on envoie cela ? réponse plausible:
					// le shader execute d'abord le vertex program/function. le paramètre est structure toute prête aves des données fixes, qui utilisent donc la semantics: appdata_img
					// puis le vertex program renvoie alors une variable du type de ma structure (v2f), bien traitée comme voulu à coups de mul(UNITY_MATRIX_MVP, v.vertex) par ex
					// ensuite le shader va executer le fragment program/function, et si ce dernier prends pour argument ma structure (v2f)
					// alors, l'argument reçu ,c'est bien la variable du type de ma structure v2f qui fut renvoyé précédement par vertex program....(?)
				}




				// ma fonction frag, comme dit explicitement dans #pragma, contient un fragment program
				// comme elle a pour vocation de traiter et renvoyer une couleur Color, elle se conforme à la semantic :COLOR
				// Elle prend pour argument la structure v2f (i)
				half4 frag(v2f i) : COLOR0// l'argument reçu v2f i , c'est bien la variable du type de ma structure v2f qui fut renvoyé précédement par vertex program....?
				{
					bool AlfaIgnore = true;// determinera s'il faut ou non ignorer un pixel en fonction de sa transparence
					half4 pixel1 = tex2D(_MainTex, i.uv.xy);
					half4 color = tex2D(_MainTex, i.uv);// recupère la couleur de la texture principale
					if (color.a > 0.9)// si la texture est bien opaque alors on calcule un nouveau pixel, sinon on annule
						AlfaIgnore = false;

					if(_Transp <0.95)//if(_Tint.a <1)
						color.a = _Transp;//_Tint.a ou i._Tint2.a
					else
						color.a = pixel1.a;// j'opte pour un alpha provenant de la propriété _Transp, si possible (si inférieur à 1), sinon je prends la vertex color

					if (AlfaIgnore)
						discard;

					return color;
				}

			ENDCG
		}
	}
	Fallback off// Explicitly state that there is no fallback and no warning should be printed, even if no subshaders can run on this hardware.
}
les questions que je pose: comment & quand est exécuté la fonction définie comme vertex program grace à #pragma vertex?
Que reçoit-elle comme argument? quand? ce qu'elle renvoie c'est pour qui et quoi ?
idem pour fragment program, j'ai pas saisi comment ça marche, et vous ???
dans ordre quel il execute tout ça? vert en 1er puis frag ensuite ?
ah ben j'aimerais mieux piger.

également, si ce qui est commenté dans le code est inexact, merci aussi de m'envoyer vos retours....

donc il y a vraisemblablement des choses poussées que l'on peut faire avec un shader, mais pour piger le truc sans aide..... pas fastoche.

sinon pour finir: ce shader est fonctionnel, il gère la transparence classique de alpha 0 à 100%
mais sa particularité est que lorsque les polygones utilisant ce shader se superposent, alors
il n'ya pas de mélange additif ni soustractif car seul les 1ers pixels transparents (ceux du fond) sont calculés. ceux, transparent, qui devaient se superposer sont ignorés. cela donne une transparence, de valeurs uniformes....

peut être servira t'il à quelqu'un d'autre! :-D

si vous connaissez déjà des shaders de ce type merci, ou si vous avez une meilleure méthode, je suis curieux.
illustration:
opaque standard:
Image

transparence ordinaire donc avec addition des valeurs d'opacité:
Image

ma version, semi transparente mais reste uniforme:
Image

un possible inconvénient: les polygones semi-transparents du dessous sont donc dessinés au dessus de ceux du 1er plan lors des superpositions, car ceux du dessus sont effacés (au niveau des recouvrements).
-or :
peut être que l'on voudrait l'inverse, c-à-d donner la priorité aux polygones en premier plan. l'astuce que j'emploie: je m'arrange donc pour mettre le 1er plan derrière l'arrière plan devant (pour les objets transparents uniquement)..

Avatar de l’utilisateur
Titan
Messages : 582
Inscription : 12 Sep 2011 13:54
Contact :

Re: Mon 1er Shader... need help

Message par Titan » 27 Avr 2016 12:08

Pour un premier shader tu t'attaque tout de suite a un sujet complexe (stencyl buffer)

A lire tes commentaires le plus flou pour toi semble être l'usage qui est fait de tes fonctions, c'est logique puisque tu ne les appellera jamais toi même; même dans du développement bas niveau (direct3d/opengl) on ne va pas maîtriser le pipeline graphique. Prendre le temps de te renseigner sur le fonctionnement des cartes graphiques et de leurs pipeline devrait t'aider à y voir plus clair. Se sera l'occasion de découvrir les autres fonctions que tu peut créer: geometry, hull et domain. Il faut aussi comprendre les étapes effectuer sans ton intervention, comme le rasterizer qui passe entre ton vertex et ton frag.
https://www.opengl.org/wiki/Rendering_Pipeline_Overview

Ton fragment shader ne retourne pas nécessairement uniquement une couleur, selon la plateforme de destination, tu peut également modifier le depth buffer en déclarant une structure de retour avec les semantique DEPTH et COLOR. Changer la depth peut servir par exemple pour que le modèle 3d du fusil d'un perso ne passe pas à travers la géométrie de la scène ou encore pour faire de la réalité augmenté en utilisant les valeurs de la depth map d'une camera de profondeur (ex: kinect) quand tu applique la color map sur un plan, etc
____________________________________________
Hop Boy

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

Re: Mon 1er Shader... need help

Message par F@B » 27 Avr 2016 12:09

C'est un bon début,
EDIT : en complément de Titan qui répond déja ;)

je te recommande ce wikibook sur le sujet si tu prends bien depuis le début tu vas piger beaucoup de choses.
https://en.wikibooks.org/wiki/Cg_Programming/Unity

Code : Tout sélectionner

les questions que je pose: comment & quand est exécuté la fonction définie comme vertex program grace à #pragma vertex?
le vertexShader est executé pour chaque vertex d'un modèle rendu par la carte vidéo, t'as pas la main sur quand c'est appellé c'est ta carte vidéo et le moteur qui s'occupe de ça. le Fragment c'est pour chaque pixel d'un triangle.

Code : Tout sélectionner

Que reçoit-elle comme argument? quand? ce qu'elle renvoie c'est pour qui et quoi ?
C'est quoi qui définir la struct de sortie et d'entrée du vertex et du fragment, ce que renvoie le vertext est passé au fragment.

Code : Tout sélectionner

idem pour fragment program, j'ai pas saisi comment ça marche, et vous ???
dans ordre quel il execute tout ça? vert en 1er puis frag ensuite ?
ah ben j'aimerais mieux piger.
je crois avoir répondu plus haut.
ʕ·͡ᴥ·ʔ ==> Mon Portfolio <== ʕ·͡ᴥ·ʔ

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

Répondre

Revenir vers « les Shaders »