スムーズシェーディング

Smooth Shading別名:スムースシェーディング

概要

ポリゴンの面を一色で塗らず、頂点ごとの法線を面の内側で補間して、曲面のようになめらかな陰影を付ける描き方。対になるフラットシェーディングは、面ごとに一つの法線で塗る。

デモ

デモを読み込んでいます
白い線を左右にドラッグすると、同じポリゴンをフラットとスムーズで見比べられます。オレンジの線は面の法線、水色の線は頂点の法線です。「円柱(角あり)」では、角まで法線を平均したときの陰影の崩れ方を確認できます。

使われる場面

  • 曲面のモデル全般

    キャラクター、車体、食器のような丸みのある物体。少ないポリゴンでも曲面に見せられるので、ほとんどのモデルはスムーズシェーディングで描く。

  • 角のあるモデル

    機械や建物では、曲面はなめらかにし、角では頂点を分けて法線を別々に持たせる(ハードエッジ)。隣り合う面の角度が一定以上の箇所だけを自動で分ける設定もある。

  • ローポリ調の表現

    面の形をあえて見せるローポリ調のイラストやゲームでは、フラットシェーディングを使う。

  • 陰影の不具合の確認

    陰影に筋やにじみが出たときは、法線を線で表示して、向きと平均のされ方を確かめる。

判断基準

こういうときこうする
曲面を少ないポリゴンで表したいスムーズシェーディングにする。輪郭の角ばりは残るので、シルエットが目立つ場合は分割数を増やす。
角があるはずの箇所に、ぼんやりした陰影のにじみが出る角で頂点を分ける(ハードエッジ)。または、面同士の角度が一定以上の箇所だけ法線を分ける設定を使う。
面の形を見せたい(ローポリ調、結晶、切り出した岩)フラットシェーディングにする。
角を立てつつ、角のハイライトはわずかに丸く光らせたい角に細い面取り(ベベル)を入れ、その部分をなめらかにする。
分割を増やしても陰影に筋や黒い斑点が出る法線が壊れている可能性がある。法線を表示し、裏返った面や、同じ位置に重なった頂点がないか確認する。

こう見えたら

  • 丸いはずの物体に、面の継ぎ目が見える形と陰影
  • 角のあるはずの物体が、ぼんやり丸く見える形と陰影
  • 陰影はなめらかなのに、輪郭がカクカクしている形と陰影

指示の例

  • 丸いはずの物体に面の継ぎ目が見えて、カクカクしている。スムーズシェーディングにして

  • 角のある部品まで、ぼんやり丸くにじんで見える。角の部分だけ頂点を分けてハードエッジにして。面どうしの角度が 30° 以上の箇所だけ分ける設定でもよい

  • スムーズにしても輪郭がカクカクしている。分割数を増やして

  • ローポリ調にしたいので、フラットシェーディングにして

詳細

面の法線と頂点の法線

面の明るさは、面の向きを表す法線と光の方向で決まる(計算は「ノーマルマップ」の項を参照)。ポリゴンは平らなので、三角形の向きから法線を一つ決められる。三角形の中をすべてこの面法線で塗ると、三角形ごとに一様な明るさになり、面の継ぎ目が見える。これがフラットシェーディングである。

スムーズシェーディングでは、頂点ごとに法線(頂点法線)を持たせる。頂点法線は、その頂点を共有する面の法線を平均したもので、元の曲面の向きに近い。

nv=normalize⁡(∑f∋vnf)\mathbf{n}_v = \operatorname{normalize}\Big( \sum_{f \ni v} \mathbf{n}_f \Big)

三角形の内側では、三つの頂点の法線を位置に応じた重み(重心座標 w0+w1+w2=1w_0 + w_1 + w_2 = 1)で混ぜ、ピクセルごとに向きを決める1。

n=normalize⁡(w0n0+w1n1+w2n2)\mathbf{n} = \operatorname{normalize}(w_0 \mathbf{n}_0 + w_1 \mathbf{n}_1 + w_2 \mathbf{n}_2)

法線が面の内側で連続的に変わるので、隣の面との境目で明るさが途切れず、曲面のように見える。

// スムーズ: 頂点シェーダーから渡した法線は、面の内側で自動的に補間される
vec3 n = normalize(vNormal);
// フラット: 画面上の位置の変化から、その三角形の向きを求める
vec3 nf = normalize(cross(dFdx(vViewPos), dFdy(vViewPos)));

頂点を共有するかどうか

平均は、隣り合う面が同じ頂点を共有している場合にだけ行われる。角を立てたい箇所では、同じ位置に頂点を二つ置き、それぞれに別の法線を持たせる。デモの「円柱(角あり)」は、側面と上下の面の境目で頂点を共有させた例である。角の法線が斜め 45° 付近に平均されるため、スムーズにすると上の面の陰影が縁に向かって傾き、平らなはずの面が丸く膨らんだように見える。側面の上端にも、上の面の明るさがにじむ。

スムーズシェーディングが変えるのは陰影だけで、形は変わらない。分割数を下げると、陰影はなめらかなまま輪郭だけが角ばる。デモで分割数を 6 前後にして、球の輪郭を見ると分かる。

脚注

  1. 頂点で計算した明るさを面の内側で補間する方法をグーローシェーディング、法線を補間してピクセルごとに明るさを計算する方法をフォンシェーディングと呼び分けることがある。現在のスムーズシェーディングは、ほとんどが後者である。 ↩

関連