Itérateur et générateur en JavaScript

Comment créer facilement une liste d’éléments qu’il sera possible de parcourir à l’aide de l’instruction for… of… (à ne pas confondre avec for… in…) ? Cette liste doit pouvoir être totalement spécifique, et non seulement une liste prédéfinie dans JavaScript, comme notamment un tableau. En particulier, ses éléments doivent pouvoir n’être générés qu’au fil de l’itération.

Continuer la lecture de « Itérateur et générateur en JavaScript »

Itérateur et générateur en JavaScript

Clipping de droite par un rectangle

Comment déterminer l’intersection d’une demi-droite avec le périmètre d’un rectangle dans lequel l’origine de la demi-droite est situé, sans nécessairement que ce soit au centre de ce rectangle ?
figure0
Ce problème de découpage (ou « clipping ») est assez classique. Plus généralement, il se rencontre quand il s’agit de découper un polygone dès qu’il sort d’une surface de rendu, parce qu’il faut déterminer précisément les coordonnées des sommets résultant du découpage et/ou plus basiquement parce qu’il faut optimiser le rendu en le limitant à ce qui est visible.

Continuer la lecture de « Clipping de droite par un rectangle »

Clipping de droite par un rectangle

Génération aléatoire d’un labyrinthe de cavernes et de tunnels

Comment générer aléatoirement un labyrinthe à base de tunnels et de cavernes en creusant tant qu’il est possible un surface ? Le résultat doit ressembler à cette sorte de gruyère (la partie praticable est en gris) :
Labyrinthe aléatoire avec murs droits

Continuer la lecture de « Génération aléatoire d’un labyrinthe de cavernes et de tunnels »

Génération aléatoire d’un labyrinthe de cavernes et de tunnels

Shader d’explosion de pixels avec WebGL (2/2)

Cet article est le second (et donc dernier) d’une série portant sur la production d’une animation de « pixels » s’éloignant d’un point d’origine en tournoyant (autour de leurs centres et autour du centre de l’écran), en grossissant et devenant toujours plus transparents jusqu’à disparaître de l’écran.
L'explosion de "pixels"
Dans le premier article, nous avons vu comment créer le vertex shader (VS) et fragment shader (FS) et les alimenter en données pour que tous les « pixels » soient transformés et rendus en appelant une seule fois drawElements () par étape de l’animation.
Reste à voir comment produire l’animation. A étape régulière, il faut :
  • mettre à jour l’angle de rotation β, le facteur de zoom Z et les composantes du vecteur de translation de chaque « pixels » ;
  • alimenter les shaders avec les données des points auxquelles ces données relatives à la transformation sont annexées ;
  • commander la transformation et le rendu des « pixels ».

Continuer la lecture de « Shader d’explosion de pixels avec WebGL (2/2) »

Shader d’explosion de pixels avec WebGL (2/2)

Shader d’explosion de pixels avec WebGL (1/2)

En s’appuyant sur les shaders – le vertex shader (VS) et le fragment shader (FS) – de WebGL, produire une animation de « pixels » s’éloignant d’un point d’origine en tournoyant (autour de leurs centres et autour du centre de l’écran), en grossissant et devenant toujours plus transparents jusqu’à disparaître de l’écran, comme sur la figure suivante qui reprend quatre étapes :
Quatre étapes de l'explosion de "pixels"
WebGL est simple à utiliser. La difficulté réside dans un dilemme auquel le développeur est inévitablement confronté dès qu’il s’attaque à des effets un peu compliqués :
  • déporter la transformation des points dans les shaders si bien qu’il suffit d’appeler une fois drawElements () pour rendre tous les éléments lors d’une étape de l’animation, mais c’est au prix d’une inflation du buffer des points et d’une mise à jour fréquente de ce dernier ;
  • déporter la transformation des points dans le programme principal (ie : le programme JavaScript) si bien qu’il est possible de créer une fois pour toutes le buffer des points, mais c’est au prix d’autant d’appels à drawElements () qu’il y a d’éléments à rendre lors d’une étape de l’animation.
Pour être complet, il faut évoquer une troisième solution qui consiste à déporter la transformation des points dans le programme principal, lequel met à jour le buffer des points avec les résultats de cette transformation avant d’appeler une seule fois drawElements (), et ce à chaque étape de l’animation. Toutefois, cette solution doit être écartée, car elle revient à réduire le VS au rang de passe-plat entre le programme principal et le FS puisque le VS est alimenté avec des points déjà transformés. Or si le GPU peut assurer la transformation des points, autant l’utiliser, car cela libère le CPU pour d’autres tâches.
Cet article est le premier d’une série de deux. Il est consacré à la logique générale du programme et à l’initialisation de WebGL incluant l’écriture du code des shaders. Le second article sera consacré à la boucle d’animation. Les deux articles ne rentreront pas dans le détail d’un commentaire ligne par ligne du code de l’exemple mis à disposition, mais rien de ce qui concerne WebGL ne sera ignoré.

Continuer la lecture de « Shader d’explosion de pixels avec WebGL (1/2) »

Shader d’explosion de pixels avec WebGL (1/2)

Enveloppe régulière d’un polygone quelconque

Comment calculer les coordonnées des points formant une enveloppe régulière d’un polygone quelconque, c’est-à-dire une version plus grande ou plus petite du polygone qui semble parfaitement s’emboîter avec ce dernier (enveloppe homothétique) ? :
Enveloppe homothétique d'un polygone
Le parfait emboîtage de l’enveloppe et du polygone tient au fait que la distance entre un sommet du polygone et le sommet correspondant de l’enveloppe est constante.
Calculer les coordonnées des sommets de l’enveloppe par simple application d’un facteur d’agrandissement aux coordonnées des sommest du polygone ne permet pas de parvenir au résultat souhaité. En effet, un tel facteur ne pourrait s’appliquer qu’autour d’un centre, c’est-à-dire un point qui devrait se trouver à égale distance de tous les sommets du polygone pour entraîner un éloignement ou un rapprochement de la distance attendue des sommets correspondants de l’enveloppe.
Or l’existence d’un ensemble de cercles de même rayon, centrés sur chacun des sommets du polygone, qui se recoupent en un unique point constituant ce centre, n’a rien de systématique. En fait, ce n’est le cas que pour des polygones très particuliers :
Possibilité d'enveloppe homothétique par agrandissement
Dans les autres cas, on constate en pratique qu’il est impossible de trouver ce jeu de cercles qui se recoupent en un même point. Ainsi, sur cet exemple, il serait impossible de positionner l’enveloppe résultant de la simple application d’un facteur d’agrandissement de sorte que les sommets de l’enveloppe se trouvent même à une distance constante des sommets du polygone auxquels ils correspondent :
Impossibilité d'enveloppe homothétique d'un polygone par agrandissement

Continuer la lecture de « Enveloppe régulière d’un polygone quelconque »

Enveloppe régulière d’un polygone quelconque

Tracer un arc avec le canvas 2D et SVG

Comment tracer un arc d’un angle donné, centré sur un point O donné et à partir d’un point A donné, avec le contexte 2d du canvas et avec SVG ? En plus d’être des technologies différentes, le canvas et SVG ne se fondent pas sur la même technique pour décrire un arc…
Tracé d'un arc
La tâche n’a rien d’évident, comme il est possible d’en juger d’après le code permettant de la remplir dans l’un et l’autre cas :
  • Avec le contexte 2d du canvas, il faut demander le tracé d’un chemin en utilisant les fonctions moveTo (x0, y0) et arcTo (x1, y1, x2, y2, r), l’arc étant défini comme la plus petite partie du cercle de rayon r tangent aux droites joignant les points de tangence de ce cercle avec la droite de (x1, y1) à (x0, y0), d’une part, et avec la droite de (x1, y1) à (x2, y2), d’autre part.
  • En SVG, il faut demander le tracé d’un chemain en utilisant un objet path dont l’attribut p prend la valeur M x0 y0 A r r 0 largeArc sweep x1 y1, où (x0, y0) est le point de départ de l’arc et (x1, y1) son point d’arrivée, le cercle dont l’arc est une partie étant de rayon r et de centre déterminé par une combinaison de largeArc et sweep.

Continuer la lecture de « Tracer un arc avec le canvas 2D et SVG »

Tracer un arc avec le canvas 2D et SVG

Closures pour gérer les événements en JavaScript

La fonction addEventListener () permet d’associer une fonction (le gestionnaire d’événement) à un événement. Lorsque l’événement survient, le navigateur appelle le gestionnaire d’événement en lui transmettant un unique argument sous la forme d’un objet décrivant l’événement.
Comment transmettre autre chose à ce gestionnaire, comme par exemple une référence sur un objet spécifique ?

Continuer la lecture de « Closures pour gérer les événements en JavaScript »

Closures pour gérer les événements en JavaScript

Désactivation de l’anti-aliasing du canvas 2D

Comment désactiver l’antialiasing par défaut dans le canvas ? L’anti-aliasing est le traitement qui permet de limiter la perception de l’effet d’escalier que la juxtaposition de pixels aux couleurs contrastées peut générer du fait de leur forme rectangulaire.
Ce traitement peut se révéler gênant dans certains cas (dessin au pixel, jeu old school, etc.), car il n’y a plus de certitude sur les pixels qu’une opération graphique vient modifier.
Par exemple, sur un canvas où on aura d’abord dessiné un rectangle jaune :
context2d.strokeStyle = "rgb (255, 255, 0)";
context2d.fillStyle = "rgb (0,255, 0)";
context2d.fillRect (2, 2, 1, 1);
context2d.strokeRect (1, 1, 2, 2);
Anti-aliasing avec fillRect () et strokeRect ()

Continuer la lecture de « Désactivation de l’anti-aliasing du canvas 2D »

Désactivation de l’anti-aliasing du canvas 2D