Introduction à GLSL

Objectif : Remplir le Frame Buffer

  • Rapidement
  • De manière pertinente
  • En utilisant la programmation parallèle
  • Utilisation de shaders simples
  • Ici, ShaderToy

Un shader, qu'est ce que c'est ?

  • Un algorithme (ici en GLSL)
  • S'exécute sur la carte graphique
  • S'applique à tous les éléments
  • Le même code pour chaque élément

Les contraintes

  • La programmation est parallèle
  • Le code est invoqué pour chaque élément
  • Chaque invocation est aveugle (ne connaît pas les autres)
  • Chaque invocation est sans mémoire (pas de sauvegarde d'une fois sur l'autre)
  • Impossible d'accéder directement à la mémoire centrale

GLSL : OpenGL Shading Langage

  • Programmation du pipeline graphique
  • Langage de haut niveau basé sur du C
  • Des évolutions conjointes à OpenGL
  • En WebGL, shaders limmités à openGL ES 2.0 (env. OpengL 3.2)

GLSL : OpenGL Shading Langage

  • float : variable réelle
  • vec* avec * dans {2,3,4} : vecteur de 2,3 ou 4 éléments réels
  • mat*x* avec * dans {2,3,4} : matrice de 2,3 ou 4 lignes (ou colonnes) (abrv : mat* )
  • opérateur swizzle (mélange des tableaux) : var.xyzw, var.yzx, var.yyy
    • Soit vec4 var = vec4(1.0,-3.0,0.1,0.5);
    • var.y est un réel (la deuxieme valeur de var, ici -3.0)
    • var.zzx est un vec3 de valeur (0.1,0.1,1.0)

GLSL : OpenGL Shading Langage

  • Des boucles : while,for...
  • Des branchements : if... then... else
  • Définition de fonctions ou procédures
  • Opérations vectorielles : dot, cross, length, normalize
  • Trigonométrie : cos, sin, tan

Plus d'information sur la carte de réference rapide WebGL

Un exemple 2D (ShaderToy)

Invocation du code pour chaque pixel

Objectif : Définir la couleur

La variable gl_FragColor (sortie par défaut)

Se nomme fragColor en ShaderToy


            void main() 
      {
          // définir la couleur sous la forme RGBA (0.0 - 1.0)
          fragColor = vec4(0.0,0.5,0.5,1.0);
       }
      

De quels informations dispose-t-on ?

Informations venant du CPU (identiques pour tous)

ShaderToy contient des variables uniform


uniform vec3 iResolution;   // viewport resolution (in pixels)
uniform vec4 iMouse;        // mouse pixel coords. xy: current, zw: click
uniform float iTime;        // shader playback time (in seconds)
      

Comment différencier les pixels ?

Une entrée par défaut


          vec2 fragCoord; // les coordonnées en nb de pixels depuis l'origine (special ShaderToy)
vec4 gl_FragCoord; // les coordonnées en nb de pixels depuis l'origine (en GLSL classique)
        

Un nouvel exemple 2D

Définir la couleur de chaque pixel en fonction de sa position


              void main() 
        {
            // Normalized pixel coordinates (from 0 to 1)
            vec2 uv = fragCoord/iResolution.xy;
            fragColor = vec4(uv,0.0,1.0);
         }
        

Un nouvel exemple 2D

Définir la couleur de chaque pixel en fonction de sa position

Rajouter le temps


              void main() 
        {
            // Normalized pixel coordinates (from 0 to 1)
            vec2 uv = fragCoord/iResolution.xy;
            vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4));

    // Output to screen
    fragColor = vec4(col,1.0);
         }
        

Beaucoup d'autres effets à réaliser

  • Des fonctions d'interpolation : step, smoothstep
  • Des fonctions trigonométriques sine, cosine
  • Différents espace de couleurs (RGB, HSV...)
  • Il nous faut de l'imagination

Des formes géometriques

Avec des opérateurs simples

Afficher des lignes horizontales


          void main() 
        {
            // Normalized pixel coordinates (from 0 to 1)
            vec2 uv = fragCoord/iResolution.xy;

            vec3 col = vec3(sign(cos(uv.y*80.0)));

            // Output to screen
            fragColor = vec4(col,1.0);
         }
        

Des interpolations

Avec des opérateurs simples

La fonction step : Noir ou blanc


          void main() 
        {
            // Normalized pixel coordinates (from 0 to 1)
            vec2 uv = fragCoord/iResolution.xy;

            vec3 col = vec3(step(0.2,uv.x));

            // Output to screen
            fragColor = vec4(col,1.0);
         }
        

Des interpolations

Avec des opérateurs simples

La fonction step


          void main() 
        {
            // Normalized pixel coordinates (from 0 to 1)
            vec2 uv = fragCoord/iResolution.xy;

            vec3 col = vec3(step(0.7,uv.x));

            // Output to screen
            fragColor = vec4(col,1.0);
         }
        

Des interpolations

Avec des opérateurs simples

La fonction smoothstep


          void main() 
        {
            // Normalized pixel coordinates (from 0 to 1)
            vec2 uv = fragCoord/iResolution.xy;

            vec3 col = vec3(smoothstep(0.2,0.6,uv.x));

            // Output to screen
            fragColor = vec4(col,1.0);
         }
        

Des fonctions a construire

Un rectangle en une position donnée


          void main() 
        

            // Normalized pixel coordinates (from 0 to 1)
            vec2 uv = fragCoord/iResolution.xy;

            vec2 size = vec2(0.4,0.15);
            vec2 center = vec2(0.4,0.6);

            uv = uv -center;
            vec2 box = step(-size*0.5,uv);
            box *= step(-size*0.5,-uv);

            vec3 col = vec3(0.4,0.4,box.x*box.y*0.8);

            // Output to screen
            fragColor = vec4(col,1.0);
         }
        

Des fonctions a construire

Pour mieux visualiser


          void main() 
        

            // Normalized pixel coordinates (from 0 to 1)
            vec2 uv = fragCoord/iResolution.xy;

            vec2 size = vec2(0.4,0.15);
            vec2 center = vec2(0.4,0.6);

            uv = uv -center;
            vec2 box = step(-size*0.5,uv);
            box *= step(-size*0.5,-uv);

            vec3 col = vec3(box.x,box.y,0.0);

            // Output to screen
            fragColor = vec4(col,1.0);
         }