THREE.JS入門チュートリアル(3)シェーダー編その2_基礎知識

WBOY
リリース: 2016-05-16 17:43:01
オリジナル
1204 人が閲覧しました
翻訳
Three.js は、優れたオープンソース WebGL ライブラリです。WebGL を使用すると、JavaScript が GPU を操作してブラウザ側で真の 3D を実現できます。ただし、このテクノロジーはまだ開発段階にあり、情報が非常に少ないため、愛好家は基本的にデモのソース コードや Three.js 自体のソース コードを通じて学ぶ必要があります。

. はじめに
これは WebGL シェーダー チュートリアルの後半です。前のチュートリアルを読んでいない場合は、このチュートリアルを読むことをお勧めします。前回のチュートリアル。

前回の記事の最後で、画面の中央に美しいピンク色の球体を描きました。これからはもっと面白いものを作り始めます。

このチュートリアルでは、アニメーション ループを追加し、次に頂点属性変数とユニフォーム変数を追加します。また、頂点シェーダーがフラグメント シェーダーに情報を渡せるように、いくつかのさまざまな変数を追加する必要があります。最終結果は、上から側面に向かって「点火」し、規則的なパターンで動くピンクの球体です。これは少しサイケデリックですが、シェーダー内の 3 つの変数をより深く理解するのに役立ちます。これらは相互に関連しており、アセンブリ全体を実装します。もちろん、これは Three.js フレームワークで行います。
1. 照明をシミュレートします
球体が平らな暗い円のように見えないように色を更新しましょう。 Three.js がライティングをどのように処理するかを確認したい場合は、必要以上に複雑であることがわかると思います。そのため、最初にライティングをシミュレートしてみましょう。 Three.js の素晴らしいシェーダーや、Chris Milk と Google (ローマ) による最近の WebGL プロジェクトのいくつかをご覧ください。
シェーダーに戻ります。頂点法線ベクトルをフラグメント シェーダーに渡すために、頂点シェーダーを更新する必要があります。可変変数を使用します:
コードをコピー コードは次のとおりです:

// を作成します。可変変数 vNormal 。頂点シェーダーとフラグメント シェーダーの両方にこの変数が含まれます。
variing vec3 vNormal;
void main() {
// vNormal を Normal に設定します。これは Three.js によって作成され、 に渡されます。シェーダの属性変数
vNormal =normal;
gl_Position = projectMatrix *
modelViewMatrix *
vec4(position, 1.0)

;シェーダ内で同じ名前の変数を作成し、法線ベクトルと右上からの光線を表す別のベクトルをドット乗算し、その結果を色に適用します。最終結果は指向性ライトのように見えます。

コードをコピー コードは次のとおりです。
// 変数 vNormal は、頂点シェーダ
variing vec3 vNormal;
void main() {
// ライト ベクトルを定義します
vec3 light = vec3(0.5,0.2,1.0); Normalized
light = Normalize(light);
// ライト ベクトルと法線ベクトルの内積を計算します。内積が 0 未満の場合 (つまり、光が到達できない場合)、それを設定します。 to 0
float dProd = max(0.0, dot(vNormal, light));
// 塗りつぶしフラグメントの色
gl_FragColor = vec4(dProd, // R
dProd, // G
dProd, // B
1.0) ; // A
}


ドット積を使用する理由は、2 つのベクトルのドット積は、それらがどの程度「似ているか」を示すためです。両方のベクトルが正規化されており、方向がまったく同じである場合、内積の値は 1 になります。2 つのベクトルの方向がたまたま逆である場合、内積の値は -1 になります。ここで行うのは、内積値をファイバーに適用することです。したがって、この点が球の右上にある場合、内積値は 1 になります。これは、完全に照明されていることを意味し、反対側の点については、次のようになります。内積値が 0 または -1 に近い値を取得します。取得した負の値はすべて 0 に設定されます。データを渡すと、最も基本的な照明効果が表示されます。

以下は何ですか?頂点の座標を組み込みます。

2. 属性変数
次に、属性変数を介して各頂点に乱数を渡す必要があります。この乱数は、頂点を法線ベクトルに沿って一定の距離に移動するために使用されます。新しい結果は、ページが更新されるたびにランダムに変化する奇妙な不規則なオブジェクトに似ています。今のところ、彼は動きません (後で動かします) が、数回更新すると、彼の形状がランダムであることがよくわかります。 頂点シェーダーに属性変数を追加してみましょう:


コードをコピーします コードは次のとおりです:

attribute float offset;
variing vec3 vNormal;
void main() {
vNormal = Normal;
// 乱数を 3 次元ベクトルに変換します。法線は乗算されます。
vec3 newPosition = Position
normal * vec3(displacement);
gl_Position = projectMatrix *
modelViewMatrix *
vec4(newPosition, 1.0); 🎜>}

アトリビュート変数ディスプレイスメントがまだ設定されていないため、シェーダーはデフォルト値として 0 を使用するため、何も変わっていないことがわかります。現時点ではディスプレイスメントはまだ有効になっていませんが、すぐにシェーダー マテリアルに属性変数を追加し、Three.js がそれらを自動的に結び付けて実行する予定です。

また、更新された位置を新しい 3 次元ベクトル変数に割り当てたことにも注意してください。これは、元の位置変数は、すべての属性変数と同様に読み取り専用であるためです。

3. シェーダー マテリアルを更新します 次に、シェーダー マテリアルを更新し、属性オブジェクトのディスプレイスメントに何かを渡します。属性オブジェクトは頂点に 1 対 1 で対応するため、次のように球の各頂点に値があります:

コードをコピー コードは次のとおりです:
varattributs = {
displacement: {
type: 'f', // 浮動小数点数
value: [] // 空の配列
}
};
var vShader = $('#vertexshader');
var fShader = $('#fragmentshader');シェーダー マテリアル
var shadermaterial =
new THREE.MeshShadermaterial({
attributes: 属性,
vertexShader: vShader.text(),
fragmentShader: fShader.text()
} ) ;
// 変位を乱数で埋めます
var verts = sphere.geometry.vertices;
var 値
for(var v = 0; v < verts.length; v ) {
values.push(Math.random() * 30);
}


このようにして、変形した球を見ることができます。最も素晴らしい点は、これらの変換はすべて GPU で行われることです。

4. 動かします
これを動かすにはどうすればよいですか?そうですね、この2つをやるべきです。 均一な可変振幅は、各フレームでの変位によって引き起こされる実際の変位を制御します。これら 2 つの関数は -1 から 1 までの値を取るため、サイン関数またはコサイン関数を使用して各フレームで生成できます。
フレームループ。

このユニフォーム変数をシェーダ マテリアルに追加する必要があり、また頂点シェーダにも追加する必要があります。まず頂点シェーダーを見てみましょう:


コードをコピーします コードは次のとおりです:
均一な浮動小数点振幅;
属性浮動小数点変位;
可変 vec3 vNormal;
void main() {
vNormal = 通常
// 各フレームで振幅を滑らかに変更します。 、画面は移動します
vec3 newPosition =
position
normal *
vec3(displacement *
amplitude); , 1.0);
}


次に、シェーダー マテリアルを更新します:



コードをコピーします
コードは次のとおりです: var uniques = { amplitude: { type: 'f', // float
value: 0
}
} ;
var vShader = $('#vertexshader');
var fShader = $('#fragmentshader');
// 最終的なシェーダ マテリアルを作成します
var shadermaterial =
new THREE.MeshShaderMaterial({
ユニフォーム: ユニフォーム,
属性: 属性,
頂点シェーダー: vShader.text(),
フラグメントシェーダー: fShader.text()
}); 🎜>
シェーダーも準備が整いました。しかし、私たちはまた一歩後退したようで、画面には滑らかなボールだけが残っています。心配しないでください。これは振幅値が 0 に設定されており、振幅に変位を乗算したため、変化は見られません。まだループを設定していないため、振幅は 0 のみにすることができます。

JavaScript では、レンダリング プロセスを関数にパッケージ化し、requestAnimationFrame を使用して関数を呼び出す必要があります。この関数では、uniform (訳者注: 振幅) の値を更新します。



コードをコピー


コードは次のとおりです:

var Frame = 0;
function update() {
// 振幅はフレームの正弦値から取得されます
uniforms.amplitude.value =
Math.sin(frame) ;
// グローバル変数を更新します
frame = 0.1;
renderer.render(scene, Camera)
// 次回画面を更新するときに update
を呼び出すことを指定しますrequestAnimFrame(update);
}
requestAnimFrame(update);

以上です。球体が奇妙に脈動しているのがわかります。シェーダーについてはまだ説明していないことがたくさんありますが、このチュートリアルがお役に立てば幸いです。他のシェーダーをいくつか見て、それらを理解していただければ幸いです。自信を持って独自のシェーダーを作成できるはずです。
いつものように、このレッスンの
ソース コード
をパッケージ化しました
関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!