オブジェクトの頂点変換やピクセルを色付けするシェーダー言語「WGSL」の文法を学ぼう

2025年9月17日(水)
大西 武 (オオニシ タケシ)
第8回の今回は、WebGPUで使うシェーダー言語「WGSL」の頂点シェーダーとフラグメントシェーダーの文法を解説します。

フラグメントシェーダー

頂点シェーダーは頂点の位置だけでしたが、フラグメントシェーダーでは実際にそこに塗る色を決めます。例えば、図2のように黒い頂点で囲まれた三角形の中に塗る青白いピクセルを決めます。

図2:シェーダーのピクセル

フラグメントシェーダーの文法

フラグメントシェーダーは次の書式のように記述します。戻り値の型は「@location(0) vec4f」という32ビットずつのRGBA色になることが多いです。

・フラグメントシェーダーの書式
@fragment fn main(引数) -> 戻り値の型 {
  頂点の色を計算
  return 戻り値;
}

プログラムは通常上から順に下へ流れて実行されて行きますが、制御構文はその流れを変える働きをします。制御構文の中では「{ }(波括弧)」は必須です。

・条件構文「if文」
var i = 1;
if (i < 3) {
  ステートメント
} else if (i > 6) {
  ステートメント
} else {
  ステートメント
}
・繰り返し構文「for文」
for (var i = 0; i < 8; i++) {
  ステートメント
}
・繰り返し構文「while文」
var i = 1;
while (i < 5) {
  i++;
}
・繰り返し構文「loop文」
var i = 1;
loop {
  i++;
  if ( i < 10 ) { continue; }
  if (i >= 15) { break; }
}
・分岐構文「switch文」
var i = 1;
var j: i32;
switch i {
  case 0: {
    j = 1;
  }
  default {
    j = 2;
  }
}

フラグメントシェーダーのサンプル

フラグメントシェーダーは色を決定しますが、次のサンプルコードではテクスチャ画像を使って色を決定します。法線で各ピクセルの向きに合わせて明るさを決め、反射強度で光る強さを決め、UV座標でテクスチャ画像のどの部分の色を使うかを決めて、それらを計算して1ピクセルずつの色を決めます。

・サンプルコード「lib」→「WGSL.js」
@group(0) @binding(1) var mySampler : sampler;
@group(0) @binding(2) var myTexture : texture_2d<f32>;

struct VertexOutput {
  @builtin(position) position : vec4f,
  @location(0) normal : vec3f,
  @location(1) color : vec4f,
  @location(2) specular : f32,
  @location(3) uv : vec2f
}
@fragment
fn main(fragData: VertexOutput) -> @location(0) vec4f {
  var lightDirection = normalize(vec3f(-1.0,-2.0,-4.0));
  var normal = normalize(fragData.normal);
  var diffuseLightWeighting = (1+dot(normal,lightDirection))/2;
  var texColor = textureSample(myTexture, mySampler, fragData.uv);
  var emi = fragData.color.r;
  var reflect = normalize(2.0*diffuseLightWeighting*normal-lightDirection);
  var spc = pow(clamp(dot(reflect,lightDirection),0.0,1.0),5.0);
  var specular = vec4(fragData.specular,fragData.specular,fragData.specular,1);
  var color = texColor*clamp(emi+diffuseLightWeighting,0.0,1.0)+spc*specular;
  return vec4f(color.rgb,1.0);
}

【サンプルコードの解説】
「sampler(サンプラー)」はテクスチャからサンプリング(色などのデータを取得)する際に使われるオブジェクトです。テクスチャのフィルタリングやアドレッシング(境界の処理)方法を指定します。
「texture_2d<f32>」は1ピクセルが32ビットのテクスチャ画像データです。@groupはデバイスの「createBindGroup」メソッドから送られたバインディングです。
「VertexOutput」構造体は前出の頂点シェーダーの戻り値と全く同じ型でなければなりません。
「lightDirection」変数は正規化した光の向きです。
「normal」変数は引数のnormalプロパティを正規化した法線ベクトルです。
「diffuseLightWeighting」変数は法線ベクトルとライトの向きからピクセルの拡散光(明るさ)を取得します。
「texColor」変数はmyTextureをサンプリングしてUV座標の色を取得します。
「emi」変数は発光色です。
「reflect」変数は反射を取得します。
「spc」は反射から反射強度を取得します。
「specular」変数は引数のspecularプロパティから反射の色を取得します。
「color」変数はテクスチャの色と発光色と拡散光と反射強度から最終的な色を取得します。
「return」で戻り値vec4f(color.rgb,1.0)を返します。見ての通り不透明です。

【コラム】「何でそんなことしてるの?」

以前、高校・大学と同期だった知人が筆者のWebサイトを見て「驚いた」とメールしてきました。そのことをメル友に話すと「何で大学まで行ってそんな畑違いのことをしてると思われたの?」と言うので「いや、そんなすごいことはできない、と驚いたらしい」と答えました。ビジネスでクリエイティブなことをやっているのはおかしくなくて、半分趣味でクリエイティブなことをやっているのはおかしなことなのでしょうか?

おわりに

今回は「シェーダー(頂点シェーダーとフラグメントシェーダー)」の基本的な文法解説しました。次回は、Uniformバッファを使った三角形の描画について解説します。

著者
大西 武 (オオニシ タケシ)
1975年香川県生まれ。大阪大学経済学部経営学科中退。プログラミング入門書など30冊以上を商業出版する作家。Microsoftで大賞やNTTドコモでグランプリなど20回以上全国区のコンテストに入賞するアーティスト。オリジナルの間違い探し「3Dクイズ」が全国放送のTVで約10回出題。
https://profile.vixar.jp

連載バックナンバー

開発言語技術解説
第8回

オブジェクトの頂点変換やピクセルを色付けするシェーダー言語「WGSL」の文法を学ぼう

2025/9/17
第8回の今回は、WebGPUで使うシェーダー言語「WGSL」の頂点シェーダーとフラグメントシェーダーの文法を解説します。
開発言語技術解説
第7回

3Dの移動や回転、拡大・縮小する「行列」について学ぼう

2025/8/27
第7回の今回は、ベクトル座標を移動したり、カメラの視線に合わせて変形したり、遠近法で変形したりする「行列」について解説します。
開発言語技術解説
第6回

2D〜4Dで向きや大きさを持つ数字の集まり「ベクトル」について学ぼう

2025/8/8
第6回の今回は、向きや大きさを持つ数字の集まりである「ベクトル」について解説します。

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています