gKit2 light
|
le pipeline a besoin d'un vertex shader et d'un fragment shader pour fonctionner, repassez dans introduction api 3d, openGL et pipeline graphique si nécessaire, et dans compiler et linker un shader program pour savoir comment les compiler, et afficher plusieurs triangles, modifier les paramètres uniform d'un shader program pour afficher simplement quelques triangles (un cube, par exemple).
GLSL est le langage permettant d'écrire des shaders, il est très proche du C/C++, avec quelques limitations :
il existe plusieurs versions du langage, il faut préciser laquelle avec la directive #version xxx
. la version classique est la version 330 / openGL 3.3. la plupart des shaders commencent donc par la ligne #version 330
.
les types de base sont classiques : int, uint, bool, float, mais les vecteurs et les matrices sont définies ainsi que leurs opérations :
la librairie standard contient à peu près tout ce qui est nécessaire pour des calculs graphiques, consultez la doc officielle : openGL SDK, par exemple les produits de matrices, les produits matrices / vecteurs...
l'initialisation des vecteurs, matrices et vecteurs n'utilise pas toujours la même syntaxe que le C++, par exemple :
la déclaration des structures est sans surprise :
les opérateurs sur les vecteurs et les matrices fonctionnent, là encore, sans surprises :
l'opérateur de sélection de composantes sur les vecteurs est plutôt pratique :
les constructeurs acceptent aussi d'extraire les premières composantes, pour les vecteurs mais aussi pour les matrices :
et ça fonctionne aussi dans l'autre sens, on peut construire un vecteur à partir d'un autre vecteur plus court, plus d'autres valeurs :
les fonctions (non récursives) s'écrivent comme d'habitude, la seule différence notable est le passage des paramètres qui utilise des mot clés in
, out
, inout
pour indiquer les paramètres d'entrée, de sortie et d'entrée / sortie :
il est également possible d'utiliser const
sur les parametres des fonctions :
un vertex shader est composée d'une fonction principale, void main( void )
, et doit écrire les coordonnées des sommets dans une variable globale vec4 gl_Position
(rappel : coordonnées x, y, z et w dans le repère projectif).
les attributs se déclarent en global avec le mot clé in
, les varyings/sorties avec out
, les constantes initialisées avec const
.
les variables fournies par l'application sont déclarées avec le mot-clé uniform
en plus de leur type et de leur nom.
le vertex shader à également accès à des variables définies par le pipeline, elles sont toutes prefixées par gl_
(cf openGL SDK, section glsl, lettre g), par exemple : gl_VertexID, l'indice du sommet à traiter.
exemple :
le vertex shader déclare, en général, des attributs de sommets initialisés par le pipeline (l'application devra configurer un vertex array et créer des buffers, cf configurer un format de sommet, vertex array object) :
le fragment shader est similaire au vertex shader, mais il ne peut pas utiliser les valeurs des attributs, ils ne sont plus accessibles, uniquement leurs valeurs interpolées, les varyings (repassez dans introduction api 3d, openGL et pipeline graphique et pipeline graphique openGL, si ce n'est pas clair)
la couleur du fragment doit être écrite dans un out vec4 gl_FragColor
ou une variable en sortie déclarée par le shader out vec4 fragment_color;
selon la version d'openGL.
un fragment shader peut déclarer des uniforms et des varyings, et accéder à plusieurs variables définies par le pipeline, par exemple :
vec4 gl_FragCoord
, les coordonnées dans le repère image du fragment,int gl_PrimitiveID
, l'indice de la primitive, du triangle, traité par le shader,bool gl_FrontFacing
, l'orientation de la primitive traitée par le shader, toujours vrai si les faces arrières sont éliminées avant la fragmentation (cf introduction api 3d, openGL et pipeline graphique).exemple:
à quoi servent les différents types de variables ?
uniform
correspondent à des valeurs fournies par l'application, elles ne changent pas de valeur pendant l'exécution des shaders, cf compiler et linker un shader program,in
sont les entrées du shader :out
sont les sorties du shader.exemple : si chaque sommet est décrit par une position et une couleur, les entrées du vertex shader sont 2 attributs, déclarés avec in
et configurés par l'application.
si on veut que le fragment shader utilise la couleur des sommets pour calculer sa couleur, il faut les lui transmettre explicitement, il ne peut pas y accéder tout seul. dans ce cas, la couleur est un varying, déclarée comme sortie optionnelle du vertex shader (avec out
) et comme entrée (avec in
) du fragment shader.