Vertex Shaderはグラフィックスパイプラインのプログラマブルステージであり、3Dモデルの各頂点を個別に処理します。Khronos Group、2025年によると、バーテックスシェーダーは頂点属性(座標、法線、色、テクスチャ座標)を入力として受け取り、定義されたロジックに従って変換します。Vertex Shaderは各頂点に対して独立して実行され、GPUの数千ものコアで計算を効率的に並列化できます。
重要なポイント
Vertex Shaderはグラフィックスパイプラインのプログラマブルステージであり、3Dモデルの各頂点を個別に処理します。頂点(vertex)とは、xyz座標、法線、色、UVテクスチャ座標などの属性を含む3次元空間内の点です。
固定機能パイプライン(fixed-function pipeline)では変換が固定アルゴリズムに従って実行されていたのに対し、Vertex Shaderは開発者に頂点変換の完全な制御を提供します。これにより、プロシージャルアニメーション、モデル変形、スケルタルスキニング、GPU側でのあらゆる数学的変換を実装できます。
OpenGL ESのグラフィックスパイプラインは、入力データから最終画像までの一連のステージで構成されています。Vertex Shaderは頂点アセンブリステージの後、ラスタライゼーションステージの前に位置します。CPUから頂点バッファを介して送信された各頂点は、Vertex Shaderを正確に1回通過し、結果はプリミティブアセンブリのために次のステージに転送されます。
| パイプラインステージ | 目的 |
|---|---|
| Vertex Specification | VBOからの頂点データと属性の転送 |
| Vertex Shader | 各頂点の処理、座標変換 |
| Tessellation | ジオメトリのサブプリミティブへのオプション分割 |
| Geometry Shader | プリミティブのオプション生成または削除 |
| Rasterization | 塗りつぶしのためのプリミティブからフラグメントへの変換 |
Vertex Shaderは、CPUコードで設定された頂点属性ポインタを介して頂点バッファ(VBO)から頂点属性を受け取ります。開発者はGLSL(OpenGL Shading Language)または同等の言語でシェーダーコードを記述し、GPUドライバーが特定のチップ用のマシン命令にコンパイルします。
各頂点に対して、Vertex Shaderは順次3つの操作を実行します:入力属性の読み取り→開発者が定義した変換の適用→出力変数への結果の書き込み。最小限必要な出力はクリップ空間での頂点位置(gl_Position)です。その他すべての出力データ(色、法線、テクスチャ座標)は補間され、次のステージ(Fragment Shader)に渡されます。
#version 300 es
in vec3 aPosition;
in vec2 aTexCoord;
uniform mat4 uMVP;
out vec2 vTexCoord;
void main() {
gl_Position = uMVP * vec4(aPosition, 1.0);
vTexCoord = aTexCoord;
}
Vertex Shaderは、ジオメトリ変換に関連するグラフィックスパイプラインタスクの幅広い範囲を解決します。各タスクはベクトルと行列に対する数学的操作を通じて実装され、数千の頂点に対して並列に実行されます。
基本的かつ最も一般的なタスクは、頂点座標をmodel、view、projection(MVP)行列で乗算することです。MVP行列は頂点をローカルモデル空間からクリップ空間に変換し、その後パイプラインの自動ステージで正規化されてスクリーン座標に変換されます。
アニメーション化されたキャラクターの場合、Vertex Shaderはスケルタルアニメーション(スキニング)を実装します。各頂点は特定の重みで複数のボーンにバインドされています。Vertex blending(バインドされたボーンからの変換の加重和)により、スケルトンが動くときにキャラクターのスキンをスムーズに変形できます。
Vertex Shaderは、CPUの関与なしに時間やその他のuniformパラメータに基づいてジオメトリを変更できます。ウェーブ変形、パーリンノイズ変位、水面の波紋効果など、これらすべての効果はRAMからジオメトリを再読み込みすることなくバーテックスシェーダーで実装されます。
両方のタイプのシェーダーがグラフィックスパイプラインのプログラマブルステージですが、Vertex ShaderとFragment Shaderは根本的に異なるタスクを解決し、画像処理の異なるステージで動作します。
| 特性 | Vertex Shader | Fragment Shader |
|---|---|---|
| 入力データ | VBOからの頂点属性 | VSからの補間データ |
| 呼び出し回数 | 頂点数 | フラグメント数 |
| 主要タスク | ジオメトリ変換 | ピクセル色計算 |
| 計算負荷 | ジオメトリの複雑さ | 画面解像度 |
| テクスチャアクセス | 制限あり(texture lookup経由) | フルアクセス |
主な違いは呼び出し頻度です。Vertex Shaderは頂点ごとに1回呼び出されるのに対し、Fragment Shaderはフラグメント(ピクセル)ごとに呼び出されます。高解像度シーンでは、Fragment Shaderの呼び出し回数はVertex Shaderの呼び出し回数を数千倍上回り、ピクセルシェーダーの最適化がさらに重要になります。
Vertex Shaderのパフォーマンスはリアルタイムアプリケーションにとって極めて重要であり、特に電力消費が制限されるモバイル開発では重要です。主なパフォーマンス要因は、頂点数、シェーダーコードの複雑さ、GPUメモリ帯域幅です。
Vertex Shaderの負荷を軽減するために、以下のアプローチが使用されます。Level of Detail(LOD) — カメラがオブジェクトから遠ざかる際にモデルの簡略化バージョンに切り替えます。Instancing — 1つのドローコールで異なる変換行列を使用して同じジオメトリを複数回描画します。
// インスタンシング対応のVertex Shader
in vec3 aPosition;
in mat4 aInstanceMatrix;
uniform mat4 uViewProjection;
void main() {
vec4 worldPos = aInstanceMatrix * vec4(aPosition, 1.0);
gl_Position = uViewProjection * worldPos;
}
Vertex Shaderは異なるグラフィックスAPI間で同様のロジックを持ちますが、構文と命名規則が異なります。OpenGL ES 3.0用のGLSLと、iOS/macOS用のMetal Shading Languageでの基本的なバーテックスシェーダーの実装を見てみましょう。
#version 300 es
in vec4 position;
in vec3 normal;
in vec2 texcoord;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform mat3 normalMatrix;
out vec3 vNormal;
out vec2 vTexCoord;
out vec3 vPosition;
void main() {
vec4 mvPosition = modelViewMatrix * position;
vPosition = mvPosition.xyz;
vNormal = normalMatrix * normal;
vTexCoord = texcoord;
gl_Position = projectionMatrix * mvPosition;
}
#include <metal_stdlib>
using namespace metal;
struct VertexIn {
float3 position [[attribute(0)]];
float3 normal [[attribute(1)]];
};
struct VertexOut {
float4 position [[position]];
float3 worldNormal;
};
vertex VertexOut
vertexMain(VertexIn in [[stage_in]],
constant float4x4& mvp [[buffer(1)]]) {
VertexOut out;
out.position = mvp * float4(in.position, 1.0);
out.worldNormal = in.normal;
return out;
}
よくある質問
Vertex ShaderはGPU上のプログラムで、3Dモデルの各頂点を処理し、その座標をスクリーン座標に変換します。モデルを点のメッシュとして想像してください。バーテックスシェーダーは定義された数学的ルールに従ってこれらの点を移動します。
Vertex Shaderは頂点を処理してジオメトリを担当し、Fragment Shaderは各ピクセルの色を決定します。前者は頂点ごと(数千回)、後者はピクセルごと(数百万回)呼び出されます。
Vertex ShaderはグラフィックスAPIに対応する言語で書かれます:OpenGL ES用のGLSL、iOS/macOS用のMetal Shading Language、Direct3D用のHLSL。概念的には、すべて頂点に対して同じ操作を実行します。
バーテックスシェーダーの複雑さはFPSに直接影響します:頂点あたりの命令が多いほど処理時間が長くなります。最適化には、LODによる頂点数の削減、インスタンシングの使用、シェーダーコード内の条件分岐の最小化が含まれます。
主なゲームタスク:MVP行列による座標変換、アニメーションキャラクターのスキニング、衣装や髪のプロシージャル変形、表情のモーフィング、GPUアニメーションを用いたパーティクルエフェクト。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。