Shaderとは - シェーダーの種類と仕組み

著者: IT Sectr 公開日: 2026-06-11 読了時間: 8 分

Shader(シェーダー)とは、GPU上で実行され、頂点、フラグメント、または計算タスクなどのグラフィックデータを処理するプログラムです。CPU上の通常のコードとは異なり、シェーダーは数百ものコアで並列に動作し、各要素を独立して処理します。Khronos Group(2025年)によると、シェーダーはモバイルゲームからシステムアプリケーションのUIエフェクトまで、最新の3Dアプリケーションの100%で使用されています。開発者はGLSL、HLSL、Metal Shading Language、SPIR-Vなどの専門言語でシェーダーを記述します。

重要ポイント

  • ShaderはGPU用のプログラムであり、シーンの各要素に対して数百ものコアで並列に実行されます。
  • シェーダーの種類:頂点シェーダー、フラグメントシェーダー、Compute、Geometry、Tessellation、Meshシェーダー。
  • 言語:GLSL(OpenGL)、HLSL(DirectX)、MSL(Metal)、SPIR-V(Vulkan)—すべてGPUのマシンコードにコンパイルされます。
  • モバイル開発におけるシェーダーは、エフェクト、ポストプロセッシング、ライティング、計算に使用されます。
  • シェーダーの最適化:mediump精度、分岐の最小化、モバイルGPU向けATF(Adaptive Texture Fetch)。

Shaderとは?

Shader(シェーダー)は、専門言語で記述されGPU上で実行される小さなプログラムです。各シェーダーは、頂点、フラグメント(ピクセル)、またはワークアイテムという1つのデータ要素を他の要素から独立して処理します。GPUの並列処理により、何千ものシェーダーインスタンスを同時に実行できます。

この用語は1980年代にPixarがRenderManでサーフェスの外観を制御するプログラムを説明するために導入しました。リアルタイムのシェーダーは、プログラマブルパイプラインを備えた最初のグラフィックカードであるNVIDIA GeForce 3(2001年)とともに登場しました。シェーダー以前は、グラフィックスは色、テクスチャ、ブレンドモードといった固定パラメータで設定されていました。

Unity Technologies(2025年)によると、平均的なモバイルゲームは50~200のシェーダーを使用しています。各シェーダーには、異なるプラットフォーム、品質レベル、ライティング設定に対応するバリアントがあります。バリアント数はプロジェクトあたり10,000に達することもあります。

シェーダーのアーキテクチャは、入力データ(属性、uniform変数、テクスチャ)、プログラムコード出力データ(色、位置)に分けられます。Uniform変数はシェーダー実行前にCPUから設定され、フレームのすべての要素で不変です。属性は要素ごとのデータ(頂点座標、法線、UV座標)です。

SIMT実行モデル

SIMT(Single Instruction, Multiple Threads)は、GPU上でのシェーダー実行モデルです。1つの命令が1回ロードされ、異なるデータに対して数百のスレッドで実行されます。例えば、1000ピクセルに対するFragment Shaderは、同じコードを持つ1000のスレッドを実行しますが、各スレッドは独自のUV座標と補間された属性を受け取ります。

SIMTの重要な結果として、シェーダー内の分岐はコストが高くなります。ifブロック内で半分のスレッドが一方の分岐に、残り半分が他方の分岐に進む場合、GPUは両方の分岐をすべてのスレッドに対して順次実行します。パフォーマンスは50%に低下します。シェーダー内の動的分岐を避けるか、CPUでの事前計算によって最小化してください。

シェーダーの種類

最新のGPUは、グラフィックパイプラインまたは計算パイプラインの各ステージに対応する複数のタイプのシェーダーをサポートしています。主要な種類である頂点シェーダー、フラグメントシェーダー、Compute、そして最新のMeshシェーダーを見ていきましょう。

シェーダーの種類パイプラインステージ処理内容言語
Vertex Shader頂点各頂点GLSL, HLSL
Fragment Shaderフラグメント各ピクセルGLSL, HLSL
Compute Shader計算任意のデータGLSL, HLSL
Geometry ShaderジオメトリプリミティブGLSL, HLSL
Tessellation ShaderテッセレーションパッチGLSL, HLSL
Mesh ShaderMeshパイプラインTask + MeshHLSL, MSL

Vertex Shader

Vertex Shaderはジオメトリの各頂点を処理します:座標変換、ライティング計算、フラグメントシェーダーへのデータ受け渡し。これはグラフィックパイプラインの必須ステージであり、これなしでは頂点は画面に表示されません。Vertex Shaderは各フレームの各頂点に対して呼び出されます。

Fragment Shader

Fragment Shader(またはPixel Shader)は最もリソースを消費するステージです。テクスチャ、ライティング、マテリアルを使用して各フラグメントの最終的な色を計算します。Fragment Shaderは、ジオメトリで覆われた各ピクセルに対して、適用されたすべてのテクスチャとエフェクトを考慮して実行されます。このシェーダーの最適化が最大のパフォーマンス向上をもたらします。

Compute Shader

Compute Shaderは、GPU上での任意の計算のための汎用シェーダーです。グラフィックシェーダーとは異なり、ジオメトリやピクセルに結びつきません。Compute Shaderは、ワークグループを介して任意のデータバッファを操作します。物理演算、パーティクルシミュレーション、ポストエフェクト、ニューラルネットワーク推論に使用されます。

Mesh Shader

Mesh Shaderは、NVIDIA Turing(2018年)とMetal 3で登場した最新のシェーダータイプです。Mesh Shaderは、頂点シェーダー、ジオメトリシェーダー、テッセレーションシェーダーを単一のメッシュパイプラインに置き換えます。Task Shaderと連携して動作します:Task Shaderがレンダリングするメッシュグループを決定し、Mesh Shaderがその場でジオメトリを生成します。

シェーダー記述言語

シェーダーは、GPUのマシンコードにコンパイルされる専門言語で記述されます。言語の選択はプラットフォームとAPIに依存します。主要な言語であるGLSL、HLSL、Metal Shading Language、および中間形式のSPIR-Vを見ていきましょう。

GLSL(OpenGL Shading Language)

GLSLは、OpenGL、OpenGL ES、WebGL向けのシェーダー言語です。構文はCをベースに、ベクター型(vec2、vec4、mat4)と組み込み関数(texture、normalize、reflect)が追加されています。GLSL ESは、モバイルデバイス向けに精度が制限されたバージョンです(lowp、mediump、highp)。Khronos(2025年)によると、GLSLはクロスプラットフォーム対応により、最も広く普及しているシェーダー言語であり続けています。

glsl
#version 300 es
precision mediump float;
in vec2 v_texCoord;
uniform sampler2D u_texture;
out vec4 fragColor;

void main() {
    fragColor = texture(u_texture, v_texCoord);
}

シンプルなフラグメントシェーダーは、UV座標からテクスチャの色を読み取ります。precision mediumpは、GPUにfloatの半精度を使用するよう指示し、モバイルデバイスでの実行を25~40%高速化します。

HLSL(High-Level Shader Language)

HLSLは、MicrosoftのDirectX向けシェーダー言語です。構文はC++に近く、クラス、構造体、テンプレートをサポートしています。HLSLはWindowsアプリケーションで使用され、Shader Model 6.7+以降はRay Tracing、Mesh Shaders、Sampler Feedbackをサポートしています。モバイル開発ではHLSLは直接使用されませんが、Vulkan向けにSPIR-Vにコンパイルされます。

Metal Shading Language

MSL(Metal Shading Language)は、Appleのシェーダー言語であり、C++14をベースとしています。GLSLやHLSLとは異なり、MSLはアプリケーションと一緒にコンパイルされるため、デバイス上でのJITコンパイルが不要です。MSLはポインタ、テンプレート、C++標準ライブラリをサポートしています。iPhone、iPad、Mac、Apple TVなど、すべてのAppleデバイスで使用されています。

cpp
#include <metal_stdlib>
using namespace metal;
struct VertexOut {
    float4 position [[position]];
    float2 texCoord;
};

fragment float4
myFragment(VertexOut in [[stage_in]],
            texture2d<float> tex [[texture(0)]]) {
    constexpr sampler s = sampler(filter::linear);
    return tex.sample(s, in.texCoord);
}

MSLは[[position]]、[[stage_in]]、[[texture(N)]]属性を使用してリソースをバインドします。Appleのコンパイラは、レジスタ数とキャッシュを考慮して、現在のGPUに最適化されたコードを生成します。

SPIR-V

SPIR-Vは、Vulkan向けの標準的な中間バイナリシェーダーフォーマットです。シェーダーはGLSLまたはHLSLで記述され、SPIR-VにコンパイルされてVulkanアプリケーションに読み込まれます。SPIR-Vは特定の言語に結びついておらず、Rust、Python、OpenCL CからSPIR-Vへのコンパイラも存在します。

モバイル開発におけるシェーダー

モバイルプラットフォームでのシェーダーは、デスクトップと比較して制限があります:レジスタ数が少なく、精度が制限され、一部の命令がサポートされていません。Android(Vulkan/OpenGL ES)とiOS(Metal)でのシェーダーの特性を見ていきましょう。

Androidのシェーダー

Androidは、OpenGLにGLSL ESを、VulkanにSPIR-Vを使用します。OpenGL ES 3.2はデフォルトでmediumpのシェーダーをサポートしています。Vulkanでは、glslangValidatorを介してGLSLからSPIR-Vへの明示的なコンパイルが必要です。Androidでは、シェーダーは文字列リソースまたはコンパイル済みのSPIR-Vファイルから読み込まれます。

Qualcomm Adreno GPUはドライバーレベルでシェーダーを最適化します。推奨事項:色とUVにはmediumpを、位置にのみhighpを使用し、頂点シェーダーでのテクスチャサンプリングを避け、計算をベクターにグループ化します(4x floatの代わりにvec4)。Qualcomm(2025年)によると、これらの最適化により30~50%の向上が得られます。

iOSのシェーダー

iOSは専らMetal Shading Languageを使用します。シェーダーはXcodeを介してアプリケーションと一緒にマシンコードにコンパイルされます。MetalはシェーダーのプロファイリングのためのShader DebuggerGPU Captureを提供します。Apple GPU(TBDR)には、early fragment test、memoryless render targets、programmable blendingといった固有の最適化があります。

Apple WWDC 2024によると、iOSシェーダーではfloatの代わりにhalfを使用し、レジスタプレッシャーを制限し(最大64レジスタ)、依存テクスチャサンプリングを避けることが重要です。iOSシェーダーはコンパクトである必要があり、理想的なサイズは50~100のALU命令です。

UnityとUnreal Engineのシェーダー

ゲームエンジンのUnityとUnreal Engineは、ビジュアルシェーダーエディタ(Shader Graph、Material Editor)と抽象言語(ShaderLab、USF)を提供しています。開発者は高レベル言語でシェーダーを記述し、エンジンがターゲットプラットフォーム用にコンパイルします。Unityは中間言語としてHLSLを、UnrealはUSF(Unreal Shader Format)を使用します。

シェーダーの最適化

シェーダーの最適化は、モバイルデバイス向けグラフィック開発の重要なステップです。適切に記述されていないシェーダーはFPSを60から20に低下させる可能性があります。主要な最適化ルールとテクニックを見ていきましょう。

計算精度

必要最小限の精度を使用します:色とUVにはlowp、法線とライティングにはmediump、位置と行列にのみhighpを使用します。ARM(2025年)によると、Mali GPUではmediump演算はhighpの2倍高速です。GLSL ESでは、これは精度修飾子を介して設定されます。

テクスチャサンプリングの最小化

テクスチャサンプリングはシェーダー内で最もコストの高い操作です(ALU命令の1~2サイクルに対して10~30サイクル)。サンプリング数を減らすには、テクスチャをアトラスに結合し、テクスチャの代わりにuniform配列にデータを格納し、微分命令を使用して隣接ピクセルの結果をキャッシュします。

分岐を避ける

動的分岐(uniform変数を使用したif文)はSIMTパイプラインのパフォーマンスを低下させます。分岐を数学関数に置き換えます:mix()step()smoothstep()clamp()。これらの関数は1~2命令で実行されるのに対し、分岐はスレッドの発散により8~16命令かかる可能性があります。

glsl
// シェーダー内の動的分岐: 悪い例
if (u_enableLight) {
    color *= computeLighting(normal);
}

// 数学的な分岐置き換え: 良い例
color *= mix(1.0, computeLighting(normal),
              float(u_enableLight));

mix()は2つの値の間で線形補間を実行します。u_enableLight=0の場合、1.0を返します—色は変わりません。u_enableLight=1の場合、ライティングの結果を返します。分岐なし—すべてのスレッドが同じコードを実行します。

シェーダーの例

モバイル開発向けの実践的なシェーダー例を見ていきましょう—シンプルなシェーディングからプロシージャルテクスチャ生成まで。各例は特定のテクニックを示しています。

フォンシェーディング(頂点シェーダー)

フォンモデルは、拡散反射と鏡面反射の成分を持つ古典的なライティングモデルです。Vertex Shaderが各頂点のライティングを計算し、Fragment Shaderは結果を補間するだけです(Gouraudシェーディング)。コストが低いためモバイルデバイスに適しています。

glsl
#version 300 es
layout(location = 0) in vec4 a_position;
layout(location = 1) in vec3 a_normal;
uniform mat4 u_mvp;
uniform mat4 u_modelView;
out vec3 v_color;

void main() {
    vec3 normal = normalize(mat3(u_modelView) * a_normal);
    vec3 lightDir = normalize(vec3(0.0, 1.0, 1.0));
    float diff = max(dot(normal, lightDir), 0.0);
    v_color = vec3(0.8, 0.2, 0.2) * (0.3 + diff * 0.7);
    gl_Position = u_mvp * a_position;
}

シェーダーは拡散ライティングを計算します:法線と光の方向のドット積。結果は環境光(0.3)と拡散光(0.7)の成分と混合されます。頂点あたり10~15のALU命令—モバイルGPUで60 FPSでの100,000ポリゴンに十分対応できます。

プロシージャルテクスチャ(フラグメントシェーダー)

プロシージャルテクスチャは、ファイルから読み込まずにFragment Shaderで生成されます。ビデオメモリを節約し、アニメーションを簡素化します。例—セルサイズを変更可能なチェッカーボード。わずか数個のALU命令—GPUへの負荷は最小限です。

glsl
#version 300 es
precision mediump float;
in vec2 v_uv;
uniform float u_cells;
out vec4 fragColor;

void main() {
    vec2 cell = floor(v_uv * u_cells);
    float isWhite = mod(cell.x + cell.y, 2.0);
    fragColor = mix(vec4(0.1, 0.1, 0.1, 1.0),
                     vec4(0.9, 0.9, 0.9, 1.0),
                     isWhite);
}

8つのALU命令—モバイルデバイスに理想的なシェーダーです。u_cellsは軸あたりのセル数を指定します。floormodは安価な演算で、すべてのモバイルGPUで1サイクルで実行されます。

よくある質問

C++の通常のプログラムとシェーダーの違いは何ですか?

シェーダーはSIMTモードでGPU上で実行されます—1つの命令が数百のスレッドで実行されます。C++の通常のプログラムはMIMDモードでCPU上で実行されます。シェーダーはファイルシステム、入出力、動的メモリにアクセスできません。バッファとテクスチャを介してデータを受け取り、位置または色を返します。

モバイル開発にはどのシェーダー言語を学ぶべきですか?

GLSL—OpenGL ESとWebGL向け、クロスプラットフォーム。Metal Shading Language—iOS向け。HLSL—UnityとUnreal Engineの基礎。GLSLから始めてください—基礎の理解はどのシェーダー言語にも応用できます。

モバイルデバイスでシェーダーが遅いのはなぜですか?

主な原因:高精度(mediumpの代わりにhighp)、過剰なテクスチャサンプリング、動的分岐、レジスタ制限の超過。シェーダー分析にはRenderDocまたはXcode GPU Frame Debuggerを使用してください。

Compute Shaderとは何で、なぜ必要ですか?

Compute Shaderは、GPU上での任意の計算のためのシェーダーです:パーティクル物理、画像処理、布地シミュレーション。Fragment Shaderとは異なり、ピクセルに結びつかず、任意のバッファに書き込むことができます。

プログラミング言語を知らなくてもシェーダーを書けますか?

はい、ビジュアルエディタを介して可能です:UnityのShader Graph、Unreal EngineのMaterial Editor、またはMetal Shader Converter。これらはノードベースのスキーマからシェーダーコードを生成します。高度な最適化にはシェーダー言語の理解が必要です。

まとめ

  • Shaderは、頂点、フラグメント、または任意のデータを大量に処理するGPU用の並列プログラムです。
  • シェーダーの種類:Vertex、Fragment、Compute、Geometry、Tessellation、Mesh—各々がパイプラインの特定のステージを担当します。
  • 言語:GLSL(OpenGL)、HLSL(DirectX)、MSL(Metal)、SPIR-V(Vulkan)—GPUのマシンコードにコンパイルされます。
  • モバイルの特性:mediump精度、最小限のテクスチャサンプリング、動的分岐の排除。
  • 最適化:ifの代わりにmix()、half精度、ATF、テクスチャのアトラス結合、CPUでの事前計算。
  • 用途:フォンライティング、プロシージャルテクスチャ、ポストエフェクト、パーティクル物理、UIエフェクト。
  • ツール:RenderDoc、Xcode GPU Debugger、Qualcomm Adreno Profiler、Mali Offline Compiler。

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください