Avec l’arrivé proche de la version 1.2 de Studio, il était temps qu’on lève le rideau sur le fonctionnement des Shaders, ce qu’on peut faire avec, et la manière dont on va les utiliser dans Studio. Cependant, étant vu qu’il s’agit d’un sujet vaste, Je ferai en sorte de le décortiquer en plusieurs articles, dont le premier étant simplement un aperçu pour vous donner une idée de la manière dont vous allez les utiliser.
Il faut noter que, du fait que Studio est conçu pour le développement sur plusieurs plateformes, nous avons choisi un langage de shaders qui sera indépendant de celles-ci :
GLSL ES, ce qui signifie que vous allez écrire le shader qu’une seul fois, et ça va fonctionner dans n’importe quelle plateforme tant qu’il y a un support des shaders dans celle-ci.
Cependant il faut noter que GLSL ES a ses limitations, mais nous allons s’y pencher plus tard. Alors pour commencer on va parler brièvement de ce que c’est que les shaders, et de leurs fonctionnements.
Partie 1 - Vue d’ensemble des shaders.Alors premièrement, qu’est-ce que c’est qu’exactement un shader ? Eh bien, quand on parle de shaders, on parle de deux différents types de programmes qui s’exécutent directement dans le processeur graphique, un vertex shader, et un fragment (ou pixel) shader. Ces deux microprogrammes fonctionnent ensembles afin de manipuler ce que la carte graphique affiche dans l’écran, vous permettant alors de changer, en temps réel, la position et la couleur (en valeurs RGBA) qui sont actuellement rendues dans le tampon d’affichage (display buffer).
Alors quel sorte d’effet pourrions nous produire avec les shaders ? Eh ben, en bref, presque tout :
Saturation de couleur, disons par exemple qu’un joueur tire une balle sur le méchant, on veut que celui "clignote" pour montrer que la cible a bien été touchée, pour l’instant tout ce qu’on peut faire c’est assombrir le sprite, et non l’éclairer.
C'est-à-dire c’est que si on règle la couleur de dessin à
c_black, le sprite deviendra entièrement noir (comme un ombre), mais on peut pas le faire dans l’autre sens, au moins, pas très facilement. Certains développeurs ont trouvés des techniques en utilisant la fonction de brouillard (
d3d_set_fog), mais ce n’est pas une solution pratique. Cependant, avec les shaders, cela devient beaucoup plus simple, étant vu que l’information de couleur est en cours d’écriture, vous pouvez simplement changer les valeurs à
c_white ou n’importe qu’elle couleur tout en gardant la même valeur alpha (de transparence) afin de garder la forme du sprite intacte. Cela produit l’effet de flash voulu, et c’est le shader qui a permis de le faire.
Vous pouvez bien évidemment faire beaucoup plus, comme par exemple réaliser un effet de profondeur de champ, effet de "verre" ou réfraction d’eau, déplacement des coordonnées de couleurs HSV, ou même l’utilisation de plusieurs texture pour créer des effets telle que le normal mapping et ainsi de suite. Si vous pouvez l’imaginer, alors vous pouvez probablement le faire.
Dans le passé j’avais l’habitude de les utiliser pour faire des choses qui n’ont réellement pas grand-chose à voir avec les rendus. J’ai par exemple assigné à chaque objet une valeur et je les ai créé, un fois que tout l’affichage a été rendu, J’étais alors capable de « prendre » une couleur de l’écran, et de le passer de nouveau sur l’objet que j’ai cliqué dessus, pour les dizaines de milliers d’objet que j’ai choisi, c’était très pratique – et simple.
Tout cela est évidemment incroyablement puissant. Alors, qu’est-ce que Studio fait pendant le rendu ? Eh ben quand on affiche un QUAD (quadrilatère), c’est en réalité 2 triangles, chacun avec ses propres coordonnées de vertex, un vertex étant un point avec des valeurs de position, couleurs et coordonnées de texture que la carte graphique utilise pour le rendu.
Alors à quoi ressemble ces données ? Chaque point contient des coordonnées X, Y, Z (Z n’étant pas nécessaire pour la 2D), couleur et 0.0 à 1.0 pour les coordonnées de textures U et V, cela fait en sorte que chaque point ou vertex ressemble à ça :
- Code:
-
X=10
Y=10
Z=1
Colour=$FFFFFFFF
U=0.0
V=1.0
Avant de commencer dans l’écriture des shaders, regardons comment nous allons créer et utiliser un shader dans Studio.
Les shaders ont été ajouté en tant que ressource standard, vous pouvez les éditer dans l’éditeur de scripts, avec un support total de syntaxe colorés, on a cependant modifié un peu l’éditeur pour permettre une création encore plus facile.
Comme vous voyez, il y a maintenant deux onglets dans l’éditeur de scripts, nommés Vertex et Fragment, vous écrivez à l’intérieur de chaque onglet le script approprié. Chaque ressource de shader est utilisé de la même manière qu’un script, c'est à dire que vous pouvez les utiliser avec les noms que vous leur avez assigné, Cela rend le processus d’écriture et d’intégration de shaders une partie naturelle de votre flux de travail.
Comme vous pouvez le voir dans l’image ci-dessus, Studio vous passera certaines choses, comme les matrices, les éclairages, et autres paramètres. Vous libérant ainsi de la nécessité de les mettre en place.
Alors, maintenant qu’on peut créer un shader, comment allions-nous l’utiliser dans Studio ? Il y deux aspects pour utiliser un shader, le premier étant le shader lui-même, et le deuxième est les deux constantes du shader (vertex et fragment).
Premièrement, mettre en place un shader est la simplicité même :
- Code:
-
shader_set( MaskShader );
et ensuite pour arrêter de l’utiliser, tout simplement :
- Code:
-
shader_reset();
Maintenant, alors que vous pouvez déjà faire des trucs géniaux juste avec ça, ce qui fait la puissance des shader, est le fait qu’on peut créer des constants dans le shader lui-même, pour obtenir une constante qui est à la fois visible dans le shader, GML et dans
GLSL ES, vous devez utiliser le mot-clé
UNIFORM. Vous pouvez alors passer certains éléments spécifique aux instances comme par exemple, une teinte de couleur, un index de réfraction, une valeur de fluorescence.
La première chose à faire cependant c’est de retourner le
handle de chaque constante. Il y a 2 types de constantes ;
Uniforms et
Samplers.
Uniforms sont les constantes standards ;
ints, bools, floats, vectors, matrices et ainsi de suite, alors que les
Samplers sont des textures. Contrairement à l’usage normal dans le GML, vous pouvez utiliser à un maximum de 8 textures simultanément, ou autant que la carte graphique est capable de supporter- Il peut être moins.
Dans l’exemple de masque ci-dessous nous avons besoin d’accéder à l’uniforme
u_vMaskCol. Il s’agit d’un vecteur à 4 dimensions (ou
vec4) que nous utilisons dans le fragment shader pour définir la couleur du masque utilisé quand le sprite est touché, ce qui nous permettra d’utiliser le clignotement (ou saturation) du sprite comme effet.
- Code:
-
global.maskshader_col = shader_get_uniform( MaskShader, “u_MaskCol” );
Celle-ci va chercher la variable, et si il a trouve, il va assigner son
handle à la variable globale
maskshader_col. Vous pouvez alors utiliser cette variable à chaque fois que vous réglez la constante, ce qui ressemblera à ça…
- Code:
-
shader_set( MaskShader );
shader_set_uniform_f( global.maskshader_col, Red, Green, Blue, AlphaMask );
Définissez d’abord le shader, qui prend alors le processus du rendu de studio et indique au système quel constantes de shader sont sur le point d’être réglés. Ces valeurs qui sont transmise sont en simples variables à virgules flottantes, leurs nature sont, bien sur, spécifiques à vos shaders.
Et c’est tout ! Studio va remplir toute la view/matrice de projections, définir la texture de base (nommée
gm_BaseTexture) et ensuite appeler votre shader quand il affiche les sprites/tiles/arrière-plans et ainsi de suite.
Tout ce dont un fragment shader nécessite de votre part c’est de régler le
gl_FragColor à la sortie, il va en suite retourner le vec4 à l’écran.
Pour l’utilisation normale, vous pouvez toujours utiliser des commandes comme
draw_self(),
draw_sprite_ext() et ainsi de suite, et Studio va créer les primitives, paramétrer les matrices et textures, vous laissant alors la simple tâche du dessin des pixels.
Et c’est tout pour la première partie. La deuxième partie concernera le fonctionnement technique de la création des shaders, et comment vous allez les utiliser.
Pour plus d'information, voici un peu de *ahem* lecture légère (en anglais) :
http://www.khronos.org/registry/gles/specs/2.0/GLSL_ES_Specification_1.0.17.pdf