Maison > Article > interface Web > Illustration des principes de fonctionnement et des processus de WebGL et Three.js
Le contenu de cet article est d'illustrer les principes de fonctionnement et les processus de WebGL et Three.js. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer
1. Quel est le principe de fonctionnement derrière WebGL ?
2. En prenant Three.js comme exemple, quel rôle le framework joue-t-il en coulisses ?
Beaucoup de choses ne peuvent toujours pas être faites. Je n'ai même pas d'idées ;
2. Je n'arrive pas à résoudre les bugs et je n'ai même aucune direction
3 Il y a des problèmes de performances et je ne sais pas du tout comment les optimiser ;
En ce moment, nous avons besoin d’en savoir plus.
En termes simples, la matrice est utilisée pour la transformation des coordonnées, comme indiqué ci-dessous :
2. Comment est-elle transformée, comme indiqué ci-dessous :
3. Par exemple, traduisez les coordonnées par 2, comme indiqué ci-dessous :
En regardant l'API de dessin de Canvas, nous constaterons qu'elle peut dessiner des lignes droites, des rectangles, des cercles, des arcs et des courbes de Bézier.
Nous avons donc examiné l'API de dessin WebGL et trouvé :
Il ne peut connaître que des points, des lignes et des triangles ? J'ai dû mal lire.
Non, vous avez bien lu.
Même un modèle aussi complexe est dessiné un par un.
En termes simples, le processus de dessin WebGL comprend les trois étapes suivantes :
Obtention des coordonnées des sommets
2. Assemblage des éléments (c'est-à-dire dessiner des triangles un par un)
3. Rastérisation (générer des fragments, c'est-à-dire des pixels un par un)
Ensuite, nous expliquerons chaque étape par étape.
D'où viennent les coordonnées des sommets ? Un cube, c’est bien, mais et si c’était un robot ?
C’est vrai, nous n’écrirons pas ces coordonnées une par une.
Souvent, cela provient d'un export logiciel 3D, ou d'une génération de cadres, comme indiqué ci-dessous :
Quelle est la zone tampon d'écriture ?
Oui, afin de simplifier le processus, je ne l'ai pas présenté auparavant.
Comme il y a souvent des milliers de données de sommet, après avoir obtenu les coordonnées du sommet, nous les stockons généralement dans la mémoire vidéo, c'est-à-dire la zone de cache, afin que le GPU puisse les lire plus rapidement.
Nous savons déjà que l'assemblage d'éléments graphiques génère des éléments graphiques (c'est-à-dire des triangles) à partir de sommets. Ce processus est-il terminé automatiquement ? La réponse n’est pas entièrement.
Afin de nous offrir une plus grande contrôlabilité, c'est-à-dire un contrôle libre des positions des sommets, WebGL nous donne ce pouvoir. Il s'agit du pipeline de rendu programmable (pas besoin de comprendre).
WebGL nous oblige à traiter les sommets en premier, alors comment faire ? Regardons d'abord l'image ci-dessous :
Nous avons introduit un nouveau terme appelé "vertex shader", qui est écrit par opengl es et défini par javascript sous la forme d'une chaîne et passé à la génération GPU.
Par exemple, ce qui suit est un code de vertex shader :
1 2 3 4 |
attribute vec4 position; void main() { gl_Position = position; } |
attribute修饰符用于声明由浏览器(javascript)传输给顶点着色器的变量值;
position即我们定义的顶点坐标;
gl_Position是一个内建的传出变量。
这段代码什么也没做,如果是绘制2d图形,没问题,但如果是绘制3d图形,即传入的顶点坐标是一个三维坐标,我们则需要转换成屏幕坐标。
比如:v(-0.5, 0.0, 1.0)转换为p(0.2, -0.4),这个过程类似我们用相机拍照。
回到刚才的话题,顶点着色器是如何处理顶点坐标的呢?
如上图,顶点着色器会先将坐标转换完毕,然后由GPU进行图元装配,有多少顶点,这段顶点着色器程序就运行了多少次。
你可能留意到,这时候顶点着色器变为:
1 2 3 4 5 |
attribute vec4 position; uniform mat4 matrix; void main() { gl_Position = position * matrix; } |
这就是应用了矩阵matrix,将三维世界坐标转换成屏幕坐标,这个矩阵叫投影矩阵,由javascript传入,至于这个matrix怎么生成,我们暂且不讨论。
和图元装配类似,光栅化也是可控的。
在图元生成完毕之后,我们需要给模型“上色”,而完成这部分工作的,则是运行在GPU的“片元着色器”来完成。
它同样是一段opengl es程序,模型看起来是什么质地(颜色、漫反射贴图等)、灯光等由片元着色器来计算。
如下是一段简单的片元着色器代码:
1 2 3 4 |
precision mediump float; void main(void) { gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); } |
gl_FragColor est la valeur de couleur de sortie.
Comment le fragment shader contrôle-t-il spécifiquement la génération de couleurs ?
Comme le montre l'image ci-dessus, le vertex shader indique le nombre de sommets qu'il possède et le nombre de fois qu'il est exécuté, tandis que le fragment shader indique le nombre de fragments (pixels) qu'il génère et le nombre de fois. c'est couru.
Jusqu'à présent, WebGL est passé par le flux de traitement suivant :
1. étape
À ce stade, nous devons fournir les coordonnées du sommet, l'index (ordre de dessin du triangle), uv (déterminer les coordonnées de la texture), normal (déterminer l'effet d'éclairage) et diverses matrices (telles que la matrice de projection).
Les données du sommet sont stockées dans la zone tampon (car la quantité est énorme) et sont transmises au vertex shader avec l'attribut modificateur
La matrice est transmise au vertex shader avec le modificateur uniform ;
2. Générer un vertex shader
Selon nos besoins, définir une chaîne de programme vertex shader (opengl es) en Javascript, la générer et la compiler dans un programme de shader et la transmettre au GPU.
3. Assemblage d'éléments graphiques
Le GPU exécute le programme de vertex shader un par un en fonction du nombre de sommets, génère les coordonnées finales des sommets et termine la conversion des coordonnées.
4. Générer un shader de fragment
De quelle couleur est le modèle, à quelle texture ressemble-t-il, les effets d'éclairage et les ombres (le processus est plus compliqué et doit d'abord être rendu à la texture , vous n'avez donc pas besoin d'y prêter attention pour l'instant) , sont tous traités à ce stade.
5. La rastérisation
peut transmettre le shader de fragment. Nous avons déterminé la couleur de chaque fragment et déterminé quels fragments sont bloqués en fonction du tampon de profondeur, et finalement stocké. les informations de fragment dans la zone tampon de couleur, et enfin terminer le rendu complet.
Nous savons que three.js nous a aidé à accomplir beaucoup de choses, mais que fait-il exactement et quel rôle joue-t-il dans l'ensemble du processus ?
Jetons un bref aperçu du processus de participation de three.js :
Les parties jaune et verte sont les parties où three.js participe , où le jaune est la partie javascript et le vert la partie opengl es.
Nous avons découvert que three.js pouvait pratiquement tout faire pour nous.
辅助我们导出了模型数据;
自动生成了各种矩阵;
生成了顶点着色器;
辅助我们生成材质,配置灯光;
根据我们设置的材质生成了片元着色器。
而且将webGL基于光栅化的2D API,封装成了我们人类能看懂的 3D API。
从WebGL工作原理的章节中,我们已经知道了顶点着色器会将三维世界坐标转换成屏幕坐标,但实际上,坐标转换不限于投影矩阵。
如下图:
之前WebGL在图元装配之后的结果,由于我们认为模型是固定在坐标原点,并且相机在x轴和y轴坐标都是0,其实正常的结果是这样的:
5.1.1、模型矩阵
现在,我们将模型顺时针旋转Math.PI/6,所有顶点位置肯定都变化了。
1 |
box.rotation.y = Math.PI/6; |
但是,如果我们直接将顶点位置用javascript计算出来,那性能会很低(顶点通常成千上万),而且,这些数据也非常不利于维护。
所以,我们用矩阵modelMatrix将这个旋转信息记录下来。
5.1.2、视图矩阵
然后,我们将相机往上偏移30。
1 |
camera.position.y = 30; |
同理,我们用矩阵viewMatrix将移动信息记录下来。
5.1.3、投影矩阵
这是我们之前介绍过的了,我们用projectMatrix记录。
5.1.4、应用矩阵
然后,我们编写顶点着色器:
1 |
gl_Position = position * modelMatrix * viewMatrix * projectionMatrix; |
De cette façon, nous calculons la position finale du sommet dans le GPU.
En fait, three.js a effectué toutes les étapes ci-dessus pour nous.
Nous savons déjà que le fragment shader est responsable du traitement des matériaux, de l'éclairage et d'autres informations, mais spécifiquement. Comment y faire face ?
Comme indiqué ci-dessous :
Lorsque nous sélectionnons un matériau, three.js sélectionnera le vertex shader et le fragment shader correspondants en fonction du matériau que nous avons sélectionné.
Nos shaders couramment utilisés ont été intégrés dans three.js.
Texte intégral terminé.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!