WebGL Essentials Partie III

Bienvenue dans ce troisième et dernier volet de notre mini-série WebGL Essentials. Dans cette leçon, nous allons examiner l'éclairage et ajouter des objets 2D à votre scène. Il y a beaucoup de nouvelles informations ici, alors plongons directement dans!


Lumière

L'éclairage peut être l'aspect le plus technique et le plus difficile à comprendre d'une application 3D. Une bonne maîtrise de l'éclairage est absolument essentielle.

Comment fonctionne la lumière?

Avant d'entrer dans les différentes techniques de lumière et de code, il est important de connaître le fonctionnement de la lumière dans le monde réel. Chaque source de lumière (p. Ex. Une ampoule, le soleil, etc.) génère des particules appelées photons. Ces photons rebondissent autour des objets jusqu'à ce qu'ils finissent par entrer dans nos yeux. Nos yeux convertissent les photons pour produire une "image" visuelle. C'est comme ça qu'on voit. La lumière est également additive, ce qui signifie qu'un objet avec plus de couleur est plus lumineux qu'un objet sans couleur (noir). Le noir est l'absence totale de couleur, alors que le blanc contient toutes les couleurs. C'est une distinction importante lorsque vous travaillez avec des lumières très vives ou "saturées".

La luminosité n'est qu'un principe comportant plusieurs états. La réflexion, par exemple, peut avoir différents niveaux. Un objet, comme un miroir, peut être complètement réfléchissant, alors que d'autres objets peuvent avoir une surface mate. La transparence détermine la manière dont les objets courbent la lumière et provoquent une réfraction. un objet peut être complètement transparent alors que d'autres peuvent être opaques (ou n'importe quel stade intermédiaire).

La liste continue, mais je pense que vous pouvez déjà voir que la lumière n'est pas simple.

Si vous vouliez, même une petite scène, simuler une lumière réelle, elle tournait à environ 4 images par heure, sur un ordinateur très puissant. Pour résoudre ce problème, les programmeurs utilisent des astuces et des techniques pour simuler un éclairage semi-réaliste à une cadence raisonnable. Vous devez trouver une forme de compromis entre réalisme et rapidité. Jetons un coup d'oeil à quelques unes de ces techniques.

Avant de commencer à élaborer sur différentes techniques, je voudrais vous donner un petit avertissement. Les noms exacts des différentes techniques d'éclairage font l'objet de nombreuses controverses, et différentes personnes vous donneront des explications différentes sur ce qu'est "Ray Casting" ou "Light Mapping". Donc, avant de commencer à recevoir le courrier haineux, je voudrais dire que je vais utiliser les noms que j'ai appris; Certaines personnes pourraient ne pas être d'accord sur mes titres exacts. Dans tous les cas, l’important est de savoir quelles sont les différentes techniques. Alors sans plus tarder, commençons.

Vous devez trouver une forme de compromis entre réalisme et rapidité.

Tracé laser

Le lancer de rayons est l’une des techniques d’éclairage les plus réalistes, mais aussi l’une des plus coûteuses. Le traçage des rayons émule la lumière réelle; il émet des "photons" ou des "rayons" de la source lumineuse et les fait rebondir. Dans la plupart des implémentations de lancer de rayons, les rayons proviennent de la "caméra" et rebondissent sur la scène dans la direction opposée. Cette technique est généralement utilisée dans les films ou les scènes pouvant être restitués à l'avance. Cela ne veut pas dire que vous ne pouvez pas utiliser le lancer de rayons dans une application en temps réel, mais cela vous oblige à atténuer les autres éléments de la scène. Par exemple, vous devrez peut-être réduire le nombre de "rebonds" que les rayons devraient produire, ou vous pouvez vous assurer qu'aucun objet ne présente de surfaces réfléchissantes ou réfractives. Le lancer de rayons peut également être une option viable si votre application comporte très peu de lumières et d'objets..

Si vous avez une application en temps réel, vous pourrez peut-être précompiler des parties de votre scène..

Si les lumières de votre application ne bougent pas ou ne bougent que dans une petite zone à la fois, vous pouvez précompiler la lumière avec un algorithme de traçage de rayons très avancé et recalculer une petite zone autour de la source de lumière en mouvement. Par exemple, si vous créez un jeu dans lequel les lumières ne bougent pas, vous pouvez précompiler le monde avec toutes les lumières et tous les effets souhaités. Ensuite, vous pouvez simplement ajouter une ombre autour de votre personnage lorsqu'il se déplace. Cela produit un aspect de très haute qualité avec un minimum de traitement.

Ray Casting

La coulée de rayons est très similaire au lancer de rayons, mais les "photons" ne rebondissent pas sur les objets et n'interagissent pas avec différents matériaux. Dans une application typique, vous commencez par une scène sombre, puis vous tracez des lignes à partir de la source de lumière. Tout ce que la lumière frappe est allumé; tout le reste reste sombre. Cette technique est nettement plus rapide que le lancer de rayons tout en vous offrant un effet d’ombre réaliste. Mais le problème avec le lancer de rayon est son caractère restrictif; vous n'avez pas beaucoup de marge de manoeuvre lorsque vous essayez d'ajouter des effets tels que des reflets. Habituellement, vous devez trouver un compromis entre projection de rayon et tracé de rayon, en équilibrant vitesse et effets visuels..

Le problème majeur de ces deux techniques est que WebGL ne vous donne accès à aucun sommet, à l'exception du sommet actuellement actif..

Cela signifie que vous devez tout exécuter sur le processeur (comme dans la carte graphique) ou créer un deuxième shader qui calcule tout l'éclairage et stocke les informations dans une fausse texture. Vous devez ensuite décompresser les données de texture dans les informations d'éclairage et les mapper aux sommets. Donc, fondamentalement, la version actuelle de WebGL n’est pas très bien adaptée à cela. Je ne dis pas que cela ne peut pas être fait, je dis juste que WebGL ne vous aidera pas.

Cartographie des ombres

Le lancer de rayons peut également être une option viable si votre application comporte très peu de lumières et d'objets..

Une meilleure alternative au Ray Ray Cast dans WebGL s'appelle le shadow mapping. Cela donne le même effet que le lancer de rayons, mais il utilise une approche différente. Le mappage des ombres ne résoudra pas tous vos problèmes, mais WebGL est semi-optimisé pour cela. Vous pouvez penser à cela comme une sorte de piratage, mais le mappage des ombres est utilisé dans les applications PC et consoles.

Alors qu'est-ce que vous demandez?

Vous devez comprendre comment WebGL rend ses scènes pour pouvoir répondre à cette question. WebGL pousse tous les sommets dans le vertex shader, qui calcule les coordonnées finales de chaque sommet après l'application des transformations. Ensuite, pour gagner du temps, WebGL élimine les sommets cachés derrière d'autres objets et dessine uniquement les objets essentiels. Si vous vous rappelez comment fonctionne le lancer de rayons, il projette simplement des rayons de lumière sur les objets visibles. Nous avons donc réglé la "caméra" de notre scène sur les coordonnées de la source de lumière et l'avons orientée dans la direction dans laquelle nous voulons que la lumière soit dirigée. Ensuite, WebGL supprime automatiquement tous les sommets qui ne sont pas en vue de la lumière. Nous pouvons ensuite sauvegarder ces données et les utiliser lorsque nous rendons la scène pour savoir quels sont les sommets allumés..

Cette technique sonne bien sur le papier, mais elle présente quelques inconvénients:

  • WebGL ne vous permet pas d'accéder au tampon de profondeur; vous devez faire preuve de créativité dans le fragment shader lorsque vous essayez de sauvegarder ces données.
  • Même si vous enregistrez toutes les données, vous devez toujours les mapper sur les sommets avant qu'ils ne soient intégrés au tableau de sommets lorsque vous rendez le rendu de votre scène. Cela nécessite du temps CPU supplémentaire.

Toutes ces techniques nécessitent une bonne dose de bricolage avec WebGL. Mais je vais vous montrer une technique très basique pour produire une lumière diffuse afin de donner un peu de personnalité à vos objets. Je n'appellerais pas cela une lumière réaliste, mais cela donne une définition à vos objets. Cette technique utilise la matrice des normales de l'objet pour calculer l'angle de la lumière par rapport à la surface de l'objet. Il est rapide, efficace et ne nécessite aucun piratage avec WebGL. Commençons.


Ajout de lumière

Commençons par mettre à jour les shaders pour intégrer l'éclairage. Nous devons ajouter un booléen qui détermine si l'objet doit être éclairé ou non. Ensuite, nous avons besoin du sommet des normales et le transformer pour l'aligner sur le modèle. Enfin, nous devons créer une variable pour transmettre le résultat final au fragment shader. Voici le nouveau vertex shader:

Si nous n'utilisons pas de lumière, nous passons simplement un sommet vide au fragment shader et sa couleur reste la même. Lorsque les lumières sont allumées, nous calculons l'angle entre la direction de la lumière et la surface de l'objet à l'aide de la fonction de point sur la normale, et nous multiplions le résultat par la couleur de la lumière comme une sorte de masque à superposer à l'objet..

Image des normales de surface par Oleg Alexandrov.

Cela fonctionne parce que les normales sont déjà perpendiculaires à la surface de l'objet et que la fonction point nous donne un nombre basé sur l'angle de la lumière par rapport à la normale. Si la normale et la lumière sont presque parallèles, la fonction point renvoie un nombre positif, ce qui signifie que la lumière fait face à la surface. Lorsque la normale et la lumière sont perpendiculaires, la surface est parallèle à la lumière et la fonction renvoie zéro. Toute valeur supérieure à 90 degrés entre la lumière et la normale donne un nombre négatif, mais nous la filtrons avec la fonction "zéro maximal"..

Maintenant, laissez-moi vous montrer le fragment shader:

Ce shader est à peu près le même que dans les parties précédentes de la série. La seule différence est que nous multiplions la couleur de la texture par le niveau de lumière. Cela éclaire ou assombrit différentes parties de l'objet, lui donnant une certaine profondeur.

C'est tout pour les shaders, passons maintenant à la WebGL.js déposer et modifier nos deux classes.

Mise à jour de notre cadre

Commençons par le GLObject classe. Nous devons ajouter une variable pour le tableau de normales. Voici ce que la partie supérieure de votre GLObject devrait maintenant ressembler à:

fonction GLObject (VertexArr, TriangleArr, TextureArr, ImageSrc, NormalsArr) this.Pos = X: 0, Y: 0, Z: 0; this.Scale = X: 1.0, Y: 1.0, Z: 1.0; this.Rotation = X: 0, Y: 0, Z: 0; this.Vertices = VertexArr; // Tableau pour contenir les données de normales this.Normals = NormalsArr; // Le reste de GLObject continue ici

Ce code est assez simple. Revenons maintenant au fichier HTML et ajoutons le tableau de normales à notre objet..

dans le Prêt() fonction où nous chargeons notre modèle 3D, nous devons ajouter le paramètre pour le tableau de normales. Un tableau vide signifie que le modèle ne contient aucune donnée normale, et nous devrons dessiner l'objet sans lumière. Dans le cas où le tableau de normales contient des données, nous allons simplement le transmettre au GLObject objet.

Nous devons également mettre à jour le WebGL classe. Nous devons relier les variables aux shaders juste après avoir chargé les shaders. Ajoutons le sommet des normales; Votre code devrait maintenant ressembler à ceci:

// Lien attribut de position de sommet de shader this.VertexPosition = this.GL.getAttribLocation (this.ShaderProgram, "VertexPosition"); this.GL.enableVertexAttribArray (this.VertexPosition); // Lier l'attribut de coordonnées de texture du shader this.VertexTexture = this.GL.getAttribLocation (this.ShaderProgram, "TextureCoord"); this.GL.enableVertexAttribArray (this.VertexTexture); // Ceci est le nouvel attribut du tableau Normals this.VertexNormal = this.GL.getAttribLocation (this.ShaderProgram, "VertexNormal"); this.GL.enableVertexAttribArray (this.VertexNormal);

Ensuite, mettons à jour le PrepareModel () fonction et ajouter du code pour mettre en mémoire tampon les données de la normale quand elles sont disponibles. Ajoutez le nouveau code juste avant le Modèle.Prêt déclaration en bas:

if (false! == Model.Normals) Buffer = this.GL.createBuffer (); this.GL.bindBuffer (this.GL.ARRAY_BUFFER, Buffer); this.GL.bufferData (this.GL.ARRAY_BUFFER, nouveau Float32Array (Model.Normals), this.GL.STATIC_DRAW); Model.Normals = Buffer;  Model.Ready = true;

Last but not least, mettez à jour le réel Dessiner fonction d'incorporer tous ces changements. Il y a quelques changements ici, alors supportez-moi. Je vais aller morceau par morceau à travers la fonction entière:

this.Draw = fonction (Modèle) if (Model.Image.ReadyState == true && Modèle.Ready == false) this.PrepareModel (Modèle);  if (Model.Ready) this.GL.bindBuffer (this.GL.ARRAY_BUFFER, Model.Vertices); this.GL.vertexAttribPointer (this.VertexPosition, 3, this.GL.FLOAT, false, 0, 0); this.GL.bindBuffer (this.GL.ARRAY_BUFFER, Model.TextureMap); this.GL.vertexAttribPointer (this.VertexTexture, 2, this.GL.FLOAT, false, 0, 0);

Jusqu'ici, c'est comme avant. Vient maintenant la partie normale:

 // Vérifier les normales si (false! == Model.Normals) // Connectez le tampon des normales au shader this.GL.bindBuffer (this.GL.ARRAY_BUFFER, Model.Normals); this.GL.vertexAttribPointer (this.VertexNormal, 3, this.GL.FLOAT, false, 0, 0); // Indiquez au shader d'utiliser la variable d'éclairage UseLights = this.GL.getUniformLocation (this.ShaderProgram, "UseLights"); this.GL.uniform1i (UseLights, true);  else // Même si notre objet n'a pas de données normales, nous devons toujours passer quelque chose // Je passe donc les vertices à la place de ceci.GL.bindBuffer (this.GL.ARRAY_BUFFER, Model.Vertices); this.GL.vertexAttribPointer (this.VertexNormal, 3, this.GL.FLOAT, false, 0, 0); // Indiquez au shader d'utiliser la variable d'éclairage UseLights = this.GL.getUniformLocation (this.ShaderProgram, "UseLights"); this.GL.uniform1i (UseLights, false); 

Nous vérifions si le modèle contient des données normales. Si c'est le cas, il connecte le tampon et définit le booléen. Si ce n'est pas le cas, le shader a encore besoin de données, sinon cela vous donnera une erreur. Donc, au lieu de cela, j'ai passé le tampon des sommets et mis la UseLight booléen à faux. Vous pouvez contourner ce problème en utilisant plusieurs shaders, mais je pensais que ce serait plus simple pour ce que nous essayons de faire..

 this.GL.bindBuffer (this.GL.ELEMENT_ARRAY_BUFFER, Model.Triangles); // Génère la matrice de perspective var PerspectiveMatrix = MakePerspective (45, this.AspectRatio, 1, 1000.0); var TransformMatrix = Model.GetTransforms ();

Encore une fois cette partie de la fonction est toujours la même.

 var NormalsMatrix = MatrixTranspose (InverseMatrix (TransformMatrix));

Ici, nous calculons la matrice de transformation des normales. Je vais discuter de la MatrixTranspose () et InverseMatrix () fonctionne dans une minute. Pour calculer la matrice de transformation du tableau de normales, vous devez transposer la matrice inverse de la matrice de transformation régulière de l'objet. Plus sur cela plus tard.

 // Définit l'emplacement 0 comme texture active this.GL.activeTexture (this.GL.TEXTURE0); // Charge dans la texture à la mémoire this.GL.bindTexture (this.GL.TEXTURE_2D, Model.Image); // Mise à jour du sampler de texture dans le fragment shader pour utiliser l'emplacement 0 this.GL.uniform1i (this.GL.get.UniformLocation (this.ShaderProgram, "uSampler"), 0); // Définition des matrices de perspective et de transformation var pmatrix = this.GL.getUniformLocation (this.ShaderProgram, "PerspectiveMatrix"); this.GL.uniformMatrix4fv (pmatrix, false, new Float32Array (PerspectiveMatrix)); var tmatrix = this.GL.getUniformLocation (this.ShaderProgram, "TransformationMatrix"); this.GL.uniformMatrix4fv (tmatrix, false, new Float32Array (TransformMatrix)); var nmatrix = this.GL.getUniformLocation (this.ShaderProgram, "NormalTransformation"); this.GL.uniformMatrix4fv (nmatrix, false, new Float32Array (NormalsMatrix)); // Dessine les triangles this.GL.drawElements (this.GL.TRIANGLES, Model.TriangleCount, this.GL.UNSIGNED_SHORT, 0); ;

Vous pouvez facilement afficher le source de toute application WebGL pour en savoir plus..

Ceci est le reste de la Dessiner() une fonction. C'est presque la même chose qu'avant, mais il y a le code ajouté qui connecte la matrice des normales aux shaders. Maintenant, revenons à ces deux fonctions que j’avais utilisées pour obtenir la matrice de transformation des normales.

le InverseMatrix () fonction accepte une matrice et retourne sa matrice inverse. Une matrice inverse est une matrice qui, multipliée par la matrice d'origine, renvoie une matrice d'identité. Regardons un exemple d'algèbre de base pour clarifier cela. L'inverse du nombre 4 est 1/4 parce que quand 1/4 x 4 = 1. L'équivalent "un" dans les matrices est une matrice d'identité. Par conséquent, la InverseMatrix () fonction renvoie la matrice d'identité pour l'argument. Voici cette fonction:

 fonction InverseMatrix (A) var s0 = A [0] * A [5] - A [4] * A [1]; var s1 = A [0] * A [6] - A [4] * A [2]; var s2 = A [0] * A [7] - A [4] * A [3]; var s3 = A [1] * A [6] - A [5] * A [2]; var s4 = A [1] * A [7] - A [5] * A [3]; var s5 = A [2] * A [7] - A [6] * A [3]; var c5 = A [10] * A [15] - A [14] * A [11]; var c4 = A [9] * A [15] - A [13] * A [11]; var c3 = A [9] * A [14] - A [13] * A [10]; var c2 = A [8] * A [15] - A [12] * A [11]; var c1 = A [8] * A [14] - A [12] * A [10]; var c0 = A [8] * A [13] - A [12] * A [9]; var invdet = 1.0 / (s0 * c5 - s1 * c4 + s2 * c3 + s3 * c2 - s4 * c1 + s5 * c0); var B = []; B [0] = (A [5] * c5 - A [6] * c4 + A [7] * c3) * invdet; B [1] = (-A [1] * c5 + A [2] * c4 - A [3] * c3) * invdet; B [2] = (A [13] * s5 - A [14] * s4 + A [15] * s3) * invdet; B [3] = (-A [9] * s5 + A [10] * s4 - A [11] * s3) * invdet; B [4] = (-A [4] * c5 + A [6] * c2 - A [7] * c1) * invdet; B [5] = (A [0] * c5 - A [2] * c2 + A [3] * c1) * invdet; B [6] = (-A [12] * s5 + A [14] * s2 - A [15] * s1) * invdet; B [7] = (A [8] * s5 - A [10] * s2 + A [11] * s1) * invdet; B [8] = (A [4] * c4 - A [5] * c2 + A [7] * c0) * invdet; B [9] = (-A [0] * c4 + A [1] * c2 - A [3] * c0) * invdet; B [10] = (A [12] * s4 - A [13] * s2 + A [15] * s0) * invdet; B [11] = (-A [8] * s4 + A [9] * s2 - A [11] * s0) * invdet; B [12] = (-A [4] * c3 + A [5] * c1 - A [6] * c0) * invdet; B [13] = (A [0] * c3 - A [1] * c1 + A [2] * c0) * invdet; B [14] = (-A [12] * s3 + A [13] * s1 - A [14] * s0) * invdet; B [15] = (A [8] * s3 - A [9] * s1 + A [10] * s0) * invdet; retourner B; 

Cette fonction est assez compliquée et, à vrai dire, je ne comprends pas très bien pourquoi les calculs fonctionnent. Mais j'ai déjà expliqué l'essentiel ci-dessus. Je ne suis pas venu avec cette fonction; il a été écrit en ActionScript par Robin Hilliard.

La fonction suivante, MatrixTranspose (), est beaucoup plus simple à comprendre. Il retourne la version "transposée" de sa matrice d'entrée. En bref, il ne fait que faire pivoter la matrice de son côté. Voici le code:

fonction MatrixTranspose (A) return [A [0], A [4], A [8], A [12], A [1], A [5], A [9], A [13], A [ 2], A [6], A [10], A [14], A [3], A [7], A [11], A [15]]; 

Au lieu d’être rangées horizontalement (c’est-à-dire A [0], A [1], A [2]…), cette fonction s’abaisse verticalement (A [0], A [4], A [8]…)..

Vous êtes prêt à aller après avoir ajouté ces deux fonctions à votre WebGL.js fichier, et tout modèle contenant les données normales doit être ombré. Vous pouvez jouer avec la direction et la couleur de la lumière dans le vertex shader pour obtenir différents effets.

Je souhaite aborder un dernier sujet, à savoir l’ajout de contenu 2D à notre scène. L'ajout de composants 2D sur une scène 3D peut avoir de nombreux avantages. Par exemple, il peut être utilisé pour afficher des informations de coordonnées, une mini-carte, des instructions pour votre application, et la liste continue. Ce processus n'est pas aussi simple qu'on pourrait le penser, alors vérifions-le.


2D V.S. 2.5D

HTML ne vous laissera pas utiliser l'API WebGL et l'API 2D à partir du même canevas.

Vous pensez peut-être: "Pourquoi ne pas simplement utiliser le canevas construit dans l'API HTML5 HTML5?" Eh bien, le problème est que HTML ne vous laissera pas utiliser les API WebGL et 2D à partir du même canevas. Une fois que vous avez affecté le contexte du canevas à WebGL, vous ne pouvez pas l'utiliser avec l'API 2D. HTML5 revient tout simplement nul lorsque vous essayez d’obtenir le contexte 2D. Alors, comment pouvez-vous contourner cela? Eh bien, je vais vous donner deux options.

2.5D

2.5D, pour ceux qui ne le savent pas, est le fait de placer des objets 2D (objets sans profondeur) dans une scène 3D. L'ajout de texte à une scène est un exemple de 2.5D. Vous pouvez prendre le texte d'une image et l'appliquer en tant que texture à un plan 3D, ou vous pouvez obtenir un modèle 3D pour le texte et le rendre à l'écran..

Les avantages de cette approche sont que vous n'avez pas besoin de deux toiles et qu'il serait plus rapide de dessiner si vous n'utilisiez que des formes simples dans votre application..

Mais pour faire du texte, vous devez soit avoir des photos de tout ce que vous voulez écrire, soit un modèle 3D pour chaque lettre (un peu trop haut, à mon avis)..

2D

L'alternative consiste à créer une seconde toile et à la superposer par-dessus la toile 3D. Je préfère cette approche car elle semble mieux équipée pour dessiner du contenu 2D. Je ne vais pas commencer à créer un nouveau cadre 2D, mais créons simplement un exemple simple dans lequel nous affichons les coordonnées du modèle ainsi que sa rotation actuelle. Ajoutons un deuxième canevas au fichier HTML juste après le canevas WebGL. Voici la nouvelle toile avec l'actuelle:

  Votre navigateur ne prend pas en charge le canevas HTML5.   Votre navigateur ne prend pas en charge le canevas HTML5. 

J'ai également ajouté des CSS en ligne pour superposer le deuxième canevas au-dessus du premier. L'étape suivante consiste à créer une variable pour le canevas 2D et à obtenir son contexte. Je vais le faire dans le Prêt() une fonction. Votre code mis à jour devrait ressembler à ceci:

var GL; bâtiment var; var Canvas2D; function Ready () // Déclaration et chargement du modèle Gl, fonction ici Canvas2D = document.getElementById ("2DCanvas"). getContext ("2d"); Canvas2D.fillStyle = "# 000"; 

En haut, vous pouvez voir que j'ai ajouté une variable globale pour le canevas 2D. Ensuite, j'ai ajouté deux lignes au bas de la Prêt() une fonction. La première nouvelle ligne obtient le contexte 2D et la seconde nouvelle définit la couleur en noir..

La dernière étape consiste à dessiner le texte à l’intérieur du Mettre à jour() une fonction:

function Update () Building.Rotation.Y + = 0.3 // Efface le canevas du dessin précédent Canvas2D.clearRect (0, 0, 600, 400); // Titre du texte Canvas2D.font = "25px sans-serif"; Canvas2D.fillText ("Bâtiment", 20, 30); // Propriétés de l'objet Canvas2D.font = "16px sans-serif"; Canvas2D.fillText ("X:" + Building.Pos.X, 20, 55); Canvas2D.fillText ("Y:" + Building.Pos.Y, 20, 75); Canvas2D.fillText ("Z:" + Building.Pos.Z, 20, 95); Canvas2D.fillText ("Rotation:" + Math.floor (Building.Rotation.Y), 20, 115); GL.GL.clear (16384 | 256); GL.Draw (bâtiment); 

Nous commençons par faire pivoter le modèle sur son axe Y, puis nous effaçons le canevas 2D de tout contenu précédent. Ensuite, nous définissons la taille de la police et dessinons du texte pour chaque axe. le fillText () méthode accepte trois paramètres: le texte à dessiner, la coordonnée x et la coordonnée y.

La simplicité parle d'elle-même. Cela a peut-être été un peu exagéré de dessiner un texte simple; vous auriez pu simplement écrire le texte dans une position

ou

élément. Mais si vous faites quelque chose comme dessiner des formes, des sprites, une barre de santé, etc., alors c'est probablement votre meilleure option..


Dernières pensées

Dans le cadre des trois derniers tutoriels, nous avons créé un joli moteur 3D, bien que de base. Malgré sa nature primitive, cela vous donne une base solide pour travailler. À l'avenir, je suggère de regarder d'autres frameworks comme three.js ou glge pour avoir une idée de ce qui est possible. De plus, WebGL s'exécute dans le navigateur et vous pouvez facilement visualiser la source de toute application WebGL pour en savoir plus..

J'espère que vous avez apprécié cette série de tutoriels et, comme toujours, laissez vos commentaires et questions dans la section commentaires ci-dessous..