Der Inhalt dieses Artikels dient der Veranschaulichung der Arbeitsprinzipien und Prozesse von WebGL und Three.js. Er hat einen gewissen Referenzwert.
Lassen Sie uns über zwei Dinge sprechen:
1. Was ist das Funktionsprinzip hinter WebGL?
2. Welche Rolle spielt das Framework hinter den Kulissen?
Wir gehen davon aus, dass Sie bereits über ein gewisses Verständnis von WebGL verfügen oder etwas mit Three.js gemacht haben. Zu diesem Zeitpunkt können folgende Probleme auftreten:
1. Ich habe nicht einmal irgendwelche Ideen;
2. Ich kann keine Fehler beheben und habe auch keine Anleitung.
3.
Zu diesem Zeitpunkt müssen wir mehr wissen.
1. Was ist eine Matrix?
Um es einfach auszudrücken: Die Matrix wird für die Koordinatentransformation verwendet, wie unten gezeigt:
2. Wie wird sie konkret transformiert, wie unten gezeigt:
3. Übersetzen Sie die Koordinaten beispielsweise um 2, wie unten gezeigt:
Wenn hier Zeit, Sie verstehen es immer noch nicht, es spielt keine Rolle, Sie müssen nur wissen, dass die Matrix für die Koordinatentransformation verwendet wird.
Bevor wir eine neue Technologie verstehen, werfen wir zunächst einen Blick auf ihre Entwicklungsdokumentation bzw API.
Wenn wir uns die Canvas-Zeichen-API ansehen, werden wir feststellen, dass sie gerade Linien, Rechtecke, Kreise, Bögen und Bezier-Kurven zeichnen kann.
Also haben wir uns die WebGL-Zeichen-API angesehen und Folgendes gefunden:
Es kann nur Punkte, Linien und Dreiecke kennen? Ich muss es falsch gelesen haben.
Nein, das hast du richtig gelesen.
Selbst ein so komplexes Modell wird einzeln in Dreiecken gezeichnet.
Einfach ausgedrückt umfasst der WebGL-Zeichnungsprozess die folgenden drei Schritte:
1. Ermitteln der Scheitelpunktkoordinaten
2 Elemente Zusammenbau (d. h. Dreiecke einzeln zeichnen)
3. Rasterisierung (Fragmente, d. h. Pixel einzeln erzeugen)
Als nächstes erklären wir jeden Schritt Schritt für Schritt.
Woher kommen die Scheitelpunktkoordinaten? Ein Würfel ist in Ordnung, aber was ist, wenn es ein Roboter ist?
Richtig, wir werden diese Koordinaten nicht einzeln aufschreiben.
Häufig kommt es vom 3D-Softwareexport oder der Frame-Generierung, wie unten gezeigt:
Was ist der Schreibpufferbereich?
Ja, um den Prozess zu vereinfachen, habe ich ihn vorher nicht eingeführt.
Da es oft Tausende von Scheitelpunktdaten gibt, speichern wir diese nach Erhalt der Scheitelpunktkoordinaten normalerweise im Videospeicher, also im Cache-Bereich, damit die GPU sie schneller lesen kann.
Wir wissen bereits, dass der Zusammenbau von Graphenelementen Graphelemente (d. h. Dreiecke) aus Eckpunkten generiert. Wird dieser Vorgang automatisch abgeschlossen? Die Antwort ist nicht ganz.
Um uns eine höhere Steuerbarkeit zu geben, dh die Scheitelpunktposition frei zu steuern, gibt uns WebGL diese Möglichkeit. Dies ist die programmierbare Rendering-Pipeline (keine Notwendigkeit, sie zu verstehen).
WebGL erfordert, dass wir zuerst die Scheitelpunkte verarbeiten. Wie gehen wir also damit um? Schauen wir uns das Bild unten an:
Wir haben einen neuen Begriff namens „Vertex-Shader“ eingeführt, der von Opengles geschrieben und von Javascript in Form einer Zeichenfolge definiert wird an die GPU-Generierung übergeben.
Das Folgende ist beispielsweise ein Vertex-Shader-Code:
1 2 3 4 |
attribute vec4 position; void main() { gl_Position = position; } Nach dem Login kopieren |
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; } Nach dem Login kopieren |
这就是应用了矩阵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); } Nach dem Login kopieren |
gl_FragColor ist der Ausgabefarbwert.
Wie steuert der Fragment-Shader konkret die Farberzeugung?
Wie im Bild oben gezeigt, gibt der Vertex-Shader an, wie viele Vertices er hat und wie oft er ausgeführt wird, während der Fragment-Shader angibt, wie viele Fragmente (Pixel) er generiert und wie oft es wird ausgeführt.
Bisher hat WebGL im Wesentlichen den folgenden Verarbeitungsablauf durchlaufen:
1 Stufe
In dieser Phase müssen wir Scheitelpunktkoordinaten, Index (Dreieckszeichnungsreihenfolge), UV (Texturkoordinaten bestimmen), Normal (Lichteffekt bestimmen) und verschiedene Matrizen (z. B. Projektionsmatrix) angeben.
Die Vertexdaten werden im Pufferbereich gespeichert (da die Menge riesig ist) und mit dem Modifikatorattribut an den Vertex-Shader übergeben.
Die Matrix wird mit dem Modifikatoruniform an den Vertex-Shader übergeben.
2. Generieren Sie einen Vertex-Shader
Definieren Sie entsprechend unseren Anforderungen eine Zeichenfolge eines Vertex-Shader-Programms (Opengles), generieren Sie es, kompilieren Sie es in ein Shader-Programm und übergeben Sie es an das GPU.
3. Zusammenbau der Diagrammelemente
Die GPU führt das Vertex-Shader-Programm nacheinander entsprechend der Anzahl der Scheitelpunkte aus, generiert die endgültigen Koordinaten der Scheitelpunkte und schließt die Koordinatenkonvertierung ab.
4. Fragment-Shader generieren
Welche Farbe hat das Modell, welche Textur sieht es aus, Lichteffekte und Schatten (der Vorgang ist komplizierter und muss zuerst in die Textur gerendert werden). , Sie müssen also noch nicht darauf achten) werden zu diesem Zeitpunkt alle verarbeitet.
5. Rasterisierung
Wir haben die Farbe jedes Fragments anhand des Tiefenpuffers bestimmt und schließlich gespeichert die Fragmentinformationen im Farbpufferbereich und schließen Sie schließlich das gesamte Rendering ab.
Wir wissen, dass three.js uns dabei geholfen hat, viele Dinge zu erreichen, aber was genau macht es und welche Rolle spielt es im gesamten Prozess?
Lassen Sie uns einen kurzen Blick auf den Prozess der Teilnahme von three.js werfen:
Die gelben und grünen Teile sind die Teile, in denen three.js partizipiert, wobei Gelb der Javascript-Teil und Grün der OpenGL-Teil ist.
Wir haben festgestellt, dass three.js im Grunde alles für uns tun kann.
辅助我们导出了模型数据;
自动生成了各种矩阵;
生成了顶点着色器;
辅助我们生成材质,配置灯光;
根据我们设置的材质生成了片元着色器。
而且将webGL基于光栅化的2D API,封装成了我们人类能看懂的 3D API。
从WebGL工作原理的章节中,我们已经知道了顶点着色器会将三维世界坐标转换成屏幕坐标,但实际上,坐标转换不限于投影矩阵。
如下图:
之前WebGL在图元装配之后的结果,由于我们认为模型是固定在坐标原点,并且相机在x轴和y轴坐标都是0,其实正常的结果是这样的:
5.1.1、模型矩阵
现在,我们将模型顺时针旋转Math.PI/6,所有顶点位置肯定都变化了。
1 | box.rotation.y = Math.PI/6; Nach dem Login kopieren |
但是,如果我们直接将顶点位置用javascript计算出来,那性能会很低(顶点通常成千上万),而且,这些数据也非常不利于维护。
所以,我们用矩阵modelMatrix将这个旋转信息记录下来。
5.1.2、视图矩阵
然后,我们将相机往上偏移30。
1 | camera.position.y = 30; Nach dem Login kopieren |
同理,我们用矩阵viewMatrix将移动信息记录下来。
5.1.3、投影矩阵
这是我们之前介绍过的了,我们用projectMatrix记录。
5.1.4、应用矩阵
然后,我们编写顶点着色器:
1 | gl_Position = position * modelMatrix * viewMatrix * projectionMatrix; Nach dem Login kopieren |
Auf diese Weise berechnen wir die endgültige Scheitelpunktposition in der GPU.
Tatsächlich hat three.js alle oben genannten Schritte für uns erledigt.
Wir wissen bereits, dass der Fragment-Shader für die Verarbeitung von Materialien, Beleuchtung und anderen Informationen verantwortlich ist, aber speziell Wie damit umgehen?
Wie unten gezeigt:
Wenn wir ein Material auswählen, wählt three.js den entsprechenden Vertex-Shader und Fragment-Shader basierend auf dem von uns ausgewählten Material aus.
Unsere häufig verwendeten Shader wurden in three.js integriert.
Volltext ist vorbei.
Das obige ist der detaillierte Inhalt vonVeranschaulichung der Arbeitsprinzipien und Prozesse von WebGL und Three.js. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!