Once vertex and fragment shaders became available, all this changed. You can
now program whatever functions you wanted. When you select a material and
lighting, what the 3JS library does under the hood is create efficient vertex
and fragment shader programs for you. However, you can create and modify your
own materials by using 3JS's shading material. Vertex and fragment shaders have
similar structures. You first define the inputs to the shader. There are 2
kinds of declaration in 3JS, uniform and varying. In web GL itself, there are
also attributes to a vertex shader, which are the values such as the vertex
position normal and UV coordiinate data. These attributes are built in 3JS, so
do not have to be declared. In fact, they have those exact names, position,
normal, UV. Uniform data is whatever is constant for the triangle being shaded.
For example, values such as the position of the light sources and the color and
shininess of the material are uniforms. A value is labeled as varying if it is
computed or set by the vertex shader as an output, and passed to the fragment
shader as an input. The vertex shader outputs these values and then the
rasterizer interpolates these across the triangle's surface. In other words,
these values can and will vary per fragment. You're in total control of what
gets interpolated. The more data per vertex that you want interpolated, the
more time and resources it takes. Nothing comes for free. The fragment shader
also takes uniform data as inputs. The fragment shader then, as a minimum,
outputs a fragment color with the name GL frag color. I say as a minimum,
because in fact, in many graphics APIs, the fragment shader can output to a
number of images at one time. This is called MRT, for multiple render targets.
Targets is another name for output images. Unfortunately, WebGL does not
support this, yet. To summarize, here's 3JS's view of the world. A vertex
shader has inputs that are uniforms and attributes. And always outputs a GL
position, and can output varying values. The fragment shader takes these
varying values along with whatever uniforms it wants, and outputs a GL.Frag
Color.
両方のシェーダがプログラマブルなら状況は変わり
どんな機能も思いのままに作れます
マテリアルとライトを決めればthree.jsのライブラリが
最適なプログラムを作成してくれます
またShader Materialを使えば
好きなマテリアルも作れます
2つのシェーダは構造が似ています
まず入力値を決めます
three.jsの変数はuniformとvaryingがありますが
WebGLには
頂点の位置や法線、UV座標を示す
attribute変数があります
three.jsでは これらの変数は組み込まれており
位置やUV座標、法線と名付けられています
uniform変数はあまり変化のないデータ
例えばライトの位置、色、マテリアルの輝きを表します
頂点シェーダが算出した値は
varying変数と呼ばれ
フラグメントシェーダへと送られます
順番は まず頂点シェーダが値を計算し
その後ラスタライザが
三角形の面全体の値を補間します つまり
これらの値はフラグメントごとに変わるわけです
補間したい頂点のデータが多ければ多いほど
時間とリソースが必要となってしまいます
フラグメントシェーダに送られたuniformデータは
最小単位のgl_FragColorとして出力されます
グラフィックAPIでは
大抵フラグメントシェーダが一度に
多数の出力を行います これをMRT
マルチプルレンダーターゲットと呼びます
ただしWebGLではまだサポートされていません
ではここでthree.jsのシェーダの仕組みを
まとめてみましょう
頂点シェーダでuniformとattributeを入力し
gl_Positionと
varying値を出力
フラグメントシェーダにこのvarying値と
uniform値が取り込まれ gl_FragColorが出力されます