この記事の内容は、WebGL と Three.js の動作原理とプロセスを説明するものであり、必要な友人は参考にしてください。
次の 2 つのことについて話しましょう:
2. なぜ原理を理解する必要があるのですか?
あなたはすでに WebGL についてある程度の理解を持っているか、Three.js を使って何かを行ったことがあると想定しています。この時点では、次の問題が発生する可能性があります。
1. まだ多くのことができない、または何もできない。アイデア;現時点では、もっと知る必要があります。
3. まずは基本的な概念を理解する
1.
簡単に言えば、以下に示すように、行列は座標変換に使用されます。
2. 以下に示すように、具体的にはどのように変換されますか:
3. たとえば、座標を 2 だけ変換します。 、以下に示すように、画像:
この時点でまだ理解できなくても問題ありません。行列が座標変換に使用されることを知っていれば十分です。
4. WebGL の仕組み
4.1、WebGL API
点、線、三角形しか理解できないのですか?きっと読み間違えたのでしょう。
いいえ、そのとおりです。
こんな複雑なモデルでも、一つ一つ三角形で描かれています。
簡単に言えば、WebGL 描画プロセスには次の 3 つのステップが含まれます:
1. 頂点座標の取得
2. グラフ要素のアセンブリ (つまり、三角形を 1 つずつ描画)
3.フラグメント、つまり各ピクセル)
次に、各ステップを順を追って説明します。
頂点座標はどこから来るのでしょうか?立方体なら大丈夫ですが、ロボットだったらどうでしょうか?
そうです、これらの座標を 1 つずつ書きません。
多くの場合、以下に示すように、3D ソフトウェアのエクスポートまたはフレーム生成から発生します:
書き込みバッファ領域とは何ですか?
そうです、プロセスを簡略化するために、以前は導入していませんでした。
多くの場合、頂点データは数千個あるため、頂点座標を取得した後、GPU がより速く読み取れるように、通常はそれをビデオ メモリ、つまりキャッシュ領域に保存します。
グラフ要素のアセンブリが頂点からグラフ要素 (つまり、三角形) を生成することはすでにわかっています。このプロセスは自動的に完了しますか?答えは完全ではありません。
より高い制御性、つまり頂点位置を自由に制御できるようにするために、WebGL はこの機能を提供します (理解する必要はありません)。
WebGL では最初に頂点を処理する必要がありますが、どうすればよいでしょうか?下の写真を見てみましょう:
「頂点シェーダー」と呼ばれる新しい用語を導入しました。これは OpenGL ES によって記述され、JavaScript によって文字列形式で定義され、生成のために GPU に渡されます。
たとえば、次は頂点シェーダーのコードです:
1 2 3 4 |
りー |
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 は出力カラー値です。
フラグメントシェーダーは具体的にどのように色の生成を制御するのでしょうか?
上の図に示すように、頂点シェーダーは頂点の数と実行回数を表し、フラグメント シェーダーは生成するフラグメント (ピクセル) の数と実行回数を表します。
これまで、WebGL は本質的に次の処理フローを経てきました:
1. データの準備段階
この段階では、頂点座標とインデックスを提供する必要があります。三角形の描画順序)、uv (テクスチャ座標を決定)、法線 (照明効果を決定)、およびさまざまな行列 (投影行列など)。
頂点データはバッファ領域に保存され(数が膨大なため)、モディファイア属性で頂点シェーダーに渡されます。
マトリックスはモディファイアユニフォームで頂点シェーダーに渡されます。
2. 頂点シェーダーを生成します
必要に応じて、Javascript で頂点シェーダー (opengl es) プログラムの文字列を定義し、それを生成してシェーダー プログラムにコンパイルし、GPU に渡します。
3. グラフ要素の組み立て
GPU は頂点の数に応じて頂点シェーダー プログラムを 1 つずつ実行し、頂点の最終座標を生成し、座標変換を完了します。
4. フラグメント シェーダーを生成します
モデルの色、テクスチャの外観、照明効果、影 (プロセスはより複雑で、最初にテクスチャにレンダリングする必要があるため、これを行う必要はありません)まだ注意してください)、すべてがこの段階で処理されます。
5. ラスター化
は、各フラグメントの色を決定し、どのフラグメントがブロックされるかを決定しました。最終的に、フラグメント情報はカラー バッファー領域に保存されます。最後にレンダリング全体が完了します。
three.js が多くのことを達成するのに役立っていることはわかっていますが、それは正確には何をするのでしょうか?また、プロセス全体でどのような役割を果たしているのでしょうか?
three.js の参加プロセスを簡単に見てみましょう:
黄色と緑色の部分は、three.js が参加する部分です。黄色の部分は JavaScript 部分、緑色の部分はopenGL の部分。
three.js が基本的にすべてを実行できることがわかりました。
辅助我们导出了模型数据;
自动生成了各种矩阵;
生成了顶点着色器;
辅助我们生成材质,配置灯光;
根据我们设置的材质生成了片元着色器。
而且将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; ログイン後にコピー |
このようにして、GPU で最終的な頂点位置を計算します。
実際、three.js は上記の手順をすべて完了しました。
フラグメント シェーダーがマテリアル、ライト、その他の情報を処理することはすでにわかっていますが、具体的にはどのように処理するのでしょうか?
以下に示すように:
マテリアルを選択すると、three.js は選択したマテリアルに基づいて対応する頂点シェーダーを選択します。そしてフラグメントシェーダー。
Three.js には、よく使用されるシェーダーが組み込まれています。
全文完成しました。
以上がWebGL と Three.js の動作原理とプロセスの図解の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。