コンテンツにスキップ

第 19 章 コンピュータグラフィックス

まえがき — 数学で「絵」を描く

3D ゲームのキャラがリアルに動く、Pixar の映画が美しく動く、Stable Diffusion で 1 枚の画像が生まれる――これらすべてを 数学 で実現しているのが、コンピュータグラフィックス (CG) です。

CG は「線形代数と微積分の最も派手な応用」とも言えます。学んだ数式が「絵」になる即時フィードバックは、学習を最高速で加速します。

🎯 章の目標

  • 2D / 3D グラフィックスの数学的基盤(座標変換、行列)と幾何処理を理解する
  • ラスタライズとレイトレーシングという 2 大レンダリングパラダイムを把握する
  • シェーダ・ライティング・テクスチャ・アニメーションを学ぶ
  • GPU プログラミングと AI との関係を語れる

19.1 なぜ CG を学ぶか

場面 CG の使い道
ゲーム リアルタイム 3D
映画 オフラインレンダリング
AR/VR 没入感のある体験
データ可視化 グラフ・地図
医療画像 CT / MRI のボリューム
機械学習 入力データ生成、NeRF
シミュレーション 物理、流体、粒子

絵で確認しながら学べる」のが CG の最大の魅力。


19.2 画像の基礎

19.2.1 ピクセルと解像度

画像 = 2 次元のピクセルグリッド。

[ R G B ] [ R G B ] [ R G B ] ...
[ R G B ] [ R G B ] [ R G B ] ...
[ R G B ] [ R G B ] [ R G B ] ...

各ピクセルは色を表す数値の組。

19.2.2 色空間

空間 用途
RGB ディスプレイ
HSV カラーピッカー、画像処理
CMYK 印刷
sRGB Web の標準
Linear RGB 計算用
P3, Rec.2020 広色域

19.2.3 ガンマ補正

人間の目は 明るさを対数的に感じる。ディスプレイは線形に光るので、ガンマ (\(\approx 2.2\)) で補正:

\[\text{display} = \text{value}^{1/\gamma}\]

ガンマを忘れると画像が 暗く・濁って 見える。

19.2.4 アルファチャンネル

透明度を表す追加成分。Porter-Duff 合成: $\(\text{out} = \text{src} \cdot \alpha_{src} + \text{dst} \cdot \alpha_{dst} (1 - \alpha_{src})\)$

19.2.5 ファイル形式

形式 特徴
PNG 可逆、透明度可、Web
JPEG 非可逆、写真向き
WebP 高効率、Google
AVIF 最新、高効率
SVG ベクター
HDR (EXR) 高ダイナミックレンジ

19.3 2D グラフィックス

19.3.1 ラスター描画

Bresenham の直線描画

整数演算だけで線を引く古典アルゴリズム。

( 0,0 ) → (10, 4) を結ぶ:

* * * * *
        * * * *
                * *

各ピクセルで「右に進むか、斜めに進むか」を判定。1965 年の発明、今も基礎。

円・楕円

Bresenham の 8 対称性を活用。

多角形フィル

スキャンライン法、エッジテーブル。

アンチエイリアス

ジャギー (ギザギザ) を抑える。サブピクセルの重みで色を混ぜる。MSAA, FXAA, TAA など。

19.3.2 ベクター

ベジエ曲線

2 次:  P(t) = (1-t)² P₀ + 2t(1-t) P₁ + t² P₂
3 次:  3 次の項
P₀ ●         ● P₃
       \  /
        \/
   ●─────●
   P₁    P₂

フォント、Illustrator、SVG、CSS の cubic-bezier() で使われます。

B スプライン、NURBS

CAD で使う、より自由度の高い曲線。

19.3.3 2D 変換 — 同次座標

平行移動を行列で表すために、同次座標を導入: $\((x, y) → (x, y, 1)\)$

平行移動:
[ 1 0 tx ] [ x ]   [ x + tx ]
[ 0 1 ty ] [ y ] = [ y + ty ]
[ 0 0  1 ] [ 1 ]   [    1   ]

回転:
[ cosθ  -sinθ  0 ] [ x ]   [ ... ]
[ sinθ   cosθ  0 ] [ y ] = [ ... ]
[  0      0    1 ] [ 1 ]   [  1  ]

スケール、剪断も 3×3 で表現

合成も行列の積。変換 = 行列の積 という統一的な扱いが線形代数の威力。


19.4 3D の基礎

19.4.1 座標系

       y
       |
       +────→ x
      /
    z

右手系と左手系がある。OpenGL は右手、DirectX は左手 (慣習)。

19.4.2 同次座標と 4×4 行列

3D 変換は 4×4 行列で統一表現。

gl_Position = Projection × View × Model × vec4(pos, 1.0)

これがシェーダの定石。

19.4.3 投影

平行投影 (Orthographic)

距離に関係なく同じサイズ」。CAD・工学図面。

透視投影 (Perspective)

遠いほど小さい」。リアル感。

透視投影行列 (簡略):
[ 1/aspect    0       0      0   ]
[    0        1       0      0   ]
[    0        0      ...    ...  ]
[    0        0      -1      0   ]

z で割る (perspective divide) ことで遠近感が出る。


19.5 ジオメトリ

19.5.1 メッシュ

3D オブジェクトを 三角形の集まり で表現。

頂点リスト:    [v0, v1, v2, v3, ...]
インデックス: [(0,1,2), (1,2,3), ...]

各頂点に: - 位置 (x, y, z) - 法線 - UV (テクスチャ座標) - 色

19.5.2 暗黙曲面 (SDF)

点 P が物体の内/外/表面のどこか」を関数で表す。レイマーチングで描画。

球: \(f(x, y, z) = \sqrt{x^2 + y^2 + z^2} - r\)

19.5.3 ボリューム

3D ピクセル (ボクセル) の集まり。医療画像 (CT, MRI)。

19.5.4 ポイントクラウド

点の集合。LiDAR、3D スキャン。


19.6 レンダリングパイプライン (ラスタライズ)

GPU は 固定 + プログラマブル な段階で動きます:

graph TD
    VB[頂点バッファ<br/>三角形メッシュ]
    VS[Vertex Shader<br/>プログラマブル<br/>頂点座標変換]
    TS[Tessellation / Geometry<br/>オプション]
    RS[ラスタライズ<br/>三角形 → ピクセル]
    FS[Fragment Shader<br/>プログラマブル<br/>ピクセル色決定]
    OM[出力結合<br/>Blend / Z-test]
    FB[フレームバッファ<br/>画面に表示]

    VB --> VS
    VS --> TS
    TS --> RS
    RS --> FS
    FS --> OM
    OM --> FB

    style VS fill:#c5e1a5
    style FS fill:#c5e1a5
    style FB fill:#ffe0b2

緑のステージが プログラマブル(シェーダで書ける)。固定ステージは GPU が自動で実行。

19.6.1 頂点シェーダ

各頂点を変換:

void main() {
    gl_Position = uMVP * vec4(aPosition, 1.0);
}

19.6.2 ラスタライズ

三角形をピクセルに変換。「三角形内のピクセル」を判定し、頂点属性を補間。

19.6.3 フラグメントシェーダ

各ピクセルの色を計算:

void main() {
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);  // 赤
}

19.6.4 隠面消去

Z バッファ

各ピクセルに「最前面の深度」を記録。後ろの絵は捨てる。

カリング

  • 背面カリング: 裏向きの面を描かない
  • 視錐台カリング: 視野外を描かない
  • 遮蔽カリング: 隠れているものを描かない

19.6.5 シェーダ言語

言語 プラットフォーム
GLSL OpenGL, WebGL
HLSL DirectX
MSL Metal (Apple)
WGSL WebGPU

GPU は SIMT (Single Instruction Multiple Threads) で実行。数千ピクセルが同じシェーダを並列に走る。


19.7 ライティング

19.7.1 Phong モデル

光の反射を 3 成分に分解:

\[I = k_a I_a + k_d (\mathbf{l} \cdot \mathbf{n}) I_d + k_s (\mathbf{r} \cdot \mathbf{v})^\alpha I_s\]
  • 環境光 (ambient)
  • 拡散反射 (diffuse): 表面の方向性
  • 鏡面反射 (specular): 光沢

19.7.2 物理ベースレンダリング (PBR)

物理法則に基づいた材質モデル:

  • アルベド: 基本色
  • ラフネス: 表面の粗さ
  • メタリック: 金属度
  • 法線マップ: 凹凸の方向
  • AO: 環境遮蔽
PBR の支配方程式 (BRDF):
f_r(ω_i, ω_o) = ...

GGX / Cook-Torrance モデルが現代の標準。

19.7.3 グローバルイルミネーション (GI)

間接光まで考慮」する高度なレンダリング:

  • レイトレーシング
  • パストレーシング (モンテカルロで積分)
  • 放射輝度伝達 (Radiosity)
  • スクリーンスペース近似 (SSAO, SSR)

19.7.4 リアルタイム GI

  • ボクセルコーン
  • RTX (NVIDIA のハードウェアレイトレ)
  • Lumen (Unreal Engine 5)

19.8 テクスチャ

19.8.1 UV マッピング

3D メッシュに 2D 画像を貼る:

メッシュ頂点    UV 座標
   ●(x,y,z)    (0.5, 0.3)

19.8.2 フィルタリング

方式 内容
最近傍 速い、ジャギー
双線形 4 ピクセル補間
三線形 ミップマップ間も補間
異方性 角度をなめらかに

19.8.3 ミップマップ

異なる解像度の画像を事前計算。距離に応じて選択。

原画像 1024x1024
半分    512x512
       256x256
       ...
       2x2
       1x1

19.8.4 法線マップ・ディスプレースメント

低ポリゴンモデルに 凹凸感 を与える。


19.9 レイトレーシング

各ピクセルから光線を投げ、物体との交差を計算し、反射・屈折・散乱を再帰的に追う。

カメラ → 光線 → 物体 → 影レイ → 光源
                反射レイ → ...

19.9.1 加速構造

「全物体と交差判定」は遅い。空間分割で高速化:

  • BVH (Bounding Volume Hierarchy)
  • kd 木
  • グリッド

\(O(\log n)\) で交差判定可能。

19.9.2 パストレーシング

確率的に光線を分岐させ、モンテカルロで積分。物理的に正確。

ノイズが出るので デノイズ (AI ベースが主流)。

19.9.3 リアルタイムへ

  • NVIDIA RTX, AMD RDNA2
  • 専用のレイトレーシングコア
  • ゲームでもリアルタイムに使える時代

19.10 アニメーション

19.10.1 キーフレーム + 補間

主要な瞬間 (キーフレーム) だけ指定し、間を補間: - 線形補間 - 球面線形補間 (slerp): クォータニオンで回転 - ベジエ補間

19.10.2 スケルトンアニメーション

ボーン階層 + スキニング:

├ 胸
│ ├ 左肩 → 左肘 → 左手
│ └ 右肩 → 右肘 → 右手
└ ...

各頂点が複数のボーンに重みづけられる 線形ブレンドスキニング (LBS) が標準。

19.10.3 物理ベース

  • リジッドボディ: 衝突判定 (GJK, EPA)、拘束ソルバ
  • : マス・スプリングモデル
  • 流体: SPH, FLIP
  • パーティクル: 雲、煙、火花

積分: Verlet, RK4。

19.10.4 逆運動学 (IK)

手先をここに」と指定すると、各関節の角度を計算。CCD, FABRIK, ヤコビアン法。


19.11 GPU プログラミング

19.11.1 CUDA / Compute Shader

汎用的な並列計算を GPU で:

__global__ void add(int *a, int *b, int *c) {
    int i = blockIdx.x * blockDim.x + threadIdx.x;
    c[i] = a[i] + b[i];
}
  • スレッドブロック・グリッド: 階層的並列
  • 共有メモリ: ブロック内で共有
  • アトミック演算

19.11.2 メモリ階層

グローバルメモリ (遅い、大容量)
共有メモリ (速い、ブロック内共有)
レジスタ (各スレッド)

共有メモリを活用」が GPU 高速化の定石。

19.11.3 機械学習との接続

  • テンソルコア: 行列積を高速化
  • FlashAttention: GPU メモリ階層を意識した高速 Attention

CUDA のスキルは現代の AI エンジニアに必須。


19.12 計算機幾何

トピック アルゴリズム
凸包 Graham scan, QuickHull
ボロノイ図 / ドロネー Fortune's algorithm
衝突判定 GJK
多角形クリッピング Sutherland-Hodgman
直線・線分交差 スイープライン

19.13 リアルタイム vs オフライン

リアルタイム オフライン
FPS 30 / 60 / 120 1 フレーム数時間も可
用途 ゲーム、AR/VR 映画
技法 近似多用 物理的に正確
エンジン Unity, Unreal RenderMan, Arnold

リアルタイムは妥協の芸術」と言われます。


19.14 GPGPU と AI との関係

GPU の SIMT は密行列演算に最適。CUDA → cuDNN → PyTorch のスタックが現在の主流。

CG と AI の境界は曖昧化: - NeRF: 写真から 3D 再構成 (微分可能レンダリング) - Gaussian Splatting: 高速な 3D 表現 - 拡散モデル: 画像生成


19.15 演習問題

  1. 2D で点を原点周りに 45° 回転 + (3, 0) 移動する 3×3 同次行列を書け。
  2. 透視投影行列の各成分が表す意味を述べよ。
  3. Phong モデルで拡散反射が「光と法線の内積」に比例する理由を説明せよ。
  4. BVH を用いるとレイトレーシングの計算量が \(O(\log n)\) になる理由を述べよ。
  5. ガンマ補正なしで合成すると暗い色が濃く見える理由を、線形と非線形空間の混同で説明せよ。
  6. シャドーマップ法でジャギーが出る原因と緩和策(PCF, Cascaded SM)を挙げよ。
  7. リジッドボディ衝突解決で「貫通」を防ぐ Position-Based Dynamics の発想を説明せよ。
  8. WebGL で三角形を 1 つ描画する最小限のコードを書け。
  9. CUDA で 2 つのベクトルの内積を計算するカーネルを書け。
  10. 物理ベースレンダリングのアルベド、ラフネス、メタリックがそれぞれ何を表現するか説明せよ。

19.16 この章のまとめ

概念 役割
2D / 3D 変換 行列の積で統一
ラスタライズ リアルタイム描画
レイトレーシング 物理的に正確
シェーダ GPU プログラム
PBR 物理ベース材質
アニメーション キーフレーム、IK
GPU 並列計算の主役

CG は数学・並列計算・AI が交差する領域。「絵が出る」即時フィードバック は学習を加速します。

19.17 次に読むもの

  • Shirley & Marschner, Fundamentals of Computer Graphics
  • Akenine-Möller et al., Real-Time Rendering
  • Pharr, Jakob, Humphreys, Physically Based Rendering無料公開、定番
  • LearnOpenGL.com、WebGPU Fundamentals
  • Gregory, Game Engine Architecture
  • 『ゲームプログラミングパターン』

🌟 メッセージ CG は「手を動かして絵が出る」最高の学習環境。1 つ三角形を描いた瞬間から、3D の世界が広がります。