Appliquer des découpes simples

Dans cet article, on illustre comment dessiner des rectangles et des carrés grâce à des opérations de découpe simple (scissoring).

Appliquer les changements sur le buffer lors de la découpe

Voici une démonstration simple des opérations appliquées sur le contexte de rendu avec la méthode scissor (en-US).

La commande clear() permet de dessiner la couleur d'applique (définie à l'aide de clearColor() (en-US)) sur tous les pixels du tampon (buffer) de dessin. La commande scissor() (en-US) permet quant à elle de définir un masque qui permet de ne modifier que les pixels contenus dans un rectangle donné.

Cet article représente une excellente occasion pour distinguer les pixels des fragments. Un pixel est un élément d'une image (en pratique c'est un point) sur l'écran ou un élément unique du tampon de dessin (l'espace mémoire qui contient les données relatives aux pixels comme les différentes composantes couleur). Un fragment fait référence au pixel manipulé par les processus WebGL.

Cette distinction existe car la couleur d'un fragment (et ses autres caractéristiques comme la profondeur) peut être manipulée et modifiée à plusieurs reprises avant d'être écrite à l'écran. On a déjà vu comment la couleur d'un fragment pouvait être modifiée au cours des opérations graphiques en appliquant un masque de couleur (en-US). Il existe d'autres cas où les fragments sont ignorés (le pixel n'est pass mis à jour) ou d'autres où ils interagissent avec la valeur du pixel existant (afin de fusionner les couleurs pour les éléments transparents qui composent une scène).

Ici, on voit une autre distinction entre les fragments et les pixels. La découpe est une étape distincte du processus graphique de WebGL/OpenGL (elle est traitée après l'applique de couleur et avant le masque de couleur). Avant que les pixels réels soient mis à jour, les fragments doivent passer le test de la découpe. S'ils réussissent ce test, ils continuent dans le processus de traitement et les pixels correspondants sont mis à jours. S'ils échouent, le processus rejette les fragments et ils ne sont plus gérés pour les traitements ultérieurs, les pixels correspondants ne seront pas mis à jour. Seuls les fragments appartenant à la zone rectangulaire donnée réussissent le test et seuls les pixels correspondants sont mis à jour. Au final, on obtient un rectangle qui est dessiné à l'écran.

Par défaut, l'étape de découpe est désactivée dans le processus. Ici, on l'active avec la méthode enable() (enable() sera utilisée pour activer de nombreuses autres fonctionnalités liées à WebGL) avec la constante SCISSOR_TEST. Là aussi, on voit l'ordre généralement utilisé pour les commandes WebGL. Tout d'abord, on modifie l'état de WebGL (ici on active le test de découpe et on crée un masque rectangulaire). Une fois que l'état a bien été modifié, on exécute les commandes de dessin (ici clear()) pour commencer le processus de traitement des fragments.

html
<p>Le résultat de la découpe.</p>
<canvas
  >Il semblerait que votre navigateur ne supporte pas l'élément canvas.</canvas
>
css
body {
  text-align: center;
}
canvas {
  display: block;
  width: 280px;
  height: 210px;
  margin: auto;
  padding: 0;
  border: none;
  background-color: black;
}
js
window.addEventListener(
  "load",
  function setupWebGL(evt) {
    "use strict";
    window.removeEventListener(evt.type, setupWebGL, false);
    var paragraph = document.querySelector("p");
    var canvas = document.querySelector("canvas");

    // Les deux lignes suivantes définissent la taille,
    // en pixels CSS, du buffer de dessin qui est la même
    // que celle du canevas (définie avec CSS).
    canvas.width = canvas.clientWidth;
    canvas.height = canvas.clientHeight;

    var gl =
      canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
    if (!gl) {
      paragraph.innerHTML =
        "Échec de la récupération du " +
        "contexte WebGL. Votre navigateur pourrait ne pas " +
        "supporter WebGL.";
      return;
    }
    gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);

    // On applique une découpe et on définit la taille de
    // la zone de découpe.
    gl.enable(gl.SCISSOR_TEST);
    gl.scissor(40, 20, 60, 170);

    // On applique un jaune uni dans le contexte de rendu.
    gl.clearColor(1.0, 1.0, 0.0, 1.0);
    gl.clear(gl.COLOR_BUFFER_BIT);
  },
  false,
);

Le code source de cet exemple est également disponible sur GitHub.