渋谷ほととぎす通信

完全趣味でやってるUnityメモ。説明できないところを説明できるようにするための個人ブログ。昨日の自分より少しでも大きくなれるように。。。 ※所属団体とは一切関係がありません

「シェーダとは何なのか」を自分の言葉でまとめてみる


f:id:esakun:20150730215258g:plain

今回ふわっとしているシェーダを分からないなりに調べて自分の言葉でまとめてみます。

  1. 一言で「シェーダとは何なのか」
  2. Unityにおけるシェーダの処理

これらを順番にまとめていきます。調べていく中で発生した副産物は別途記事にしていく予定です。
※間違っていたら出来ればコメントくださいorz

1.一言で「シェーダとは何なのか」

仕事をしていて、非プログラマからはシェーダってエフェクトでしょ?みたいな感じで思われている印象があります。
とりあえずググってみてみると、

シェーダ(英: shader)とは、3次元コンピュータグラフィックスにおいて、シェーディング(陰影処理)を行うコンピュータプログラムのこと。

Wikipedia:シェーダ

シェーダとは、物体そのものが元々持つ設定

教えてgoo:シェーダとは

レンダリングパイプラインにおいて、頂点単位の処理、ピクセル単位の処理 をカスタマイズするためのプログラムのこと

Slide Share:OpenGL ES2.0 一問一答

などなど。

などなどと書きつつ、あまりシェーダを一言で表現したページは見つかりませんでした。
僕なりに出した答え。

シェーダとは一言で表すと

「3Dオブジェクトをディスプレイに映し出すためのプログラム」

です。

シェーダでエフェクトを表現することもできますが、シェーダがエフェクトなのではなく、シェーダとは3Dオブジェクトをディスプレイに表示させるためのプログラムのことです。

なぜシェーダは「3Dオブジェクトをディスプレイに映し出すためのプログラム」なのか

まずは3Dオブジェクトがディスプレイに映し出されるまでの流れを説明します。

f:id:bao_bao:20160508210300p:plain

  1. 表示したい3Dオブジェクトデータをとある筒に渡す
  2. とある筒からディスプレイに表示される

非常に簡略化するとこのような工程を踏みます。

このとある筒とは何かというと、これがレンダリングパイプラインと呼ばれる、ディスプレイに映し出すまでの流れ作業のような過程のことです。(グラフィックスパイプラインとも言う)

レンダリングパイプラインの中には非常に沢山の処理が含まれており、3Dオブジェクトデータをレンダリングパイプラインに渡すことで、様々な変換作業を経て3D上から2Dのディスプレイに表示されます。

下図のように、シェーダはレンダリングパイプラインの一部に含まれます。

f:id:bao_bao:20160508212120p:plain

また、2種類のシェーダユニットが存在します。
本記事はシェーダの概念的な話なので話の単純化ということでSM2.0をターゲットとし、頂点シェーダ、フラグメントシェーダ以外のユニットについては割愛します。

f:id:bao_bao:20160508212530p:plain

  • 頂点シェーダ (バーテックスシェーダとも言われる)
  • フラグメントシェーダ (ピクセルシェーダとも言われる)

頂点シェーダはその名も通り、3Dオブジェクトの頂点に関わる処理を行います。 フラグメントシェーダは、ディスプレイの1ピクセル毎に処理するシェーダです。

概念的には受け取った3Dオブジェクトの頂点データを頂点シェーダで座標変換などを行い、その結果をフラグメントシェーダに渡し、各ピクセルの色を決め、ディスプレイに映し出されます。

一昔前まではシェーダを使うことはできませんでした。
※ここで言うシェーダはプログラマブルシェーダの事

固定機能パイプラインと呼ばれるハードウェア側に定義された固定機能を使って描画するという方法がとられていました。

f:id:bao_bao:20160508214206p:plain

現在はというと。

f:id:bao_bao:20160508214746p:plain

図のように頂点シェーダフラグメントシェーダの2箇所をプログラムをすることによりでカスタマイズでき、様々な表現が可能になっています。

よって、シェーダとは一言で表すと

「3Dオブジェクトをディスプレイに映し出すためのプログラム」

です。

逆にシェーダが存在しなければ、ディスプレイは真っ暗のままになってしまいます。何かが表示しているということは、プログラマが何かしらのシェーダを書いているということになります。


2.Unityにおけるシェーダの処理

UnityのシェーダはShaderLabと呼ばれるUnity独自の記法で書かれています。
参考 : Unity - マニュアル: ShaderLab シンタックス

Unityのシェーダは全てShaderLabで書かなければなりません。

GLSL、Cg、HLSLはどこにいったのか?

ShaderLabの言語仕様は、Cg、HLSLを組み合わせたようなものになっています。

Cg、HLSLで書いたシェーダ(ShaderLab)は、OpenGL向けに書きだされる端末の場合、HLSL2GLSLで変換され、GLSLに書き出される仕組みになっています。
※Metal環境向けならMetalのシェーダ言語(MSL)に書きだされます

確認方法

変換されたファイルを見ることで確認できます。

おそらくShaderLab界では最小コードだと思われるのシェーダを書いてみます。

このコードをOpenGLES2.0の環境に変換してみます。
Shaderファイルを選択しInspecterで変換後のシェーダを確認できます。

f:id:bao_bao:20160508234656p:plain

するとこうなります。
※見やすくするために整形しています

複数環境選択して、変換後のシェーダを確認すると各環境でどのようなシェーダが使われているか分かります。先のソースコードのように、見慣れたGLSLが記述されているため、OpenGLES2.0環境ではGLSLが使われているということを確認できます。

余談ですが、ShaderファイルのインスペクタにはCompiled Codeとコンパイル済みコードとあります。 ここで言うコンパイルとはShaderLabから各環境への言語の変換処理のことです。バイナリデータになるわけではありません。
変換されたものは、ただのテキストなので最終的なシェーダソースコードを確認できます。

各環境のコードは1ファイル内に#ifdefで切り分けられており、OpenGLES2、Metalなど環境毎で実行時にコンパイル(ここではバイナリへのコンパイル)されて処理されます。

まとめ

前半シェーダとは何か?ということについて、後半Unity内でのシェーダについて割りとゆるめな内容でまとめてみました。

  • UnityのシェーダはShaderLabという独自言語を使って書く
  • ShaderLabはCg、HLSLを使うことが出来る*1
  • 最終的には各環境に向けたシェーダ言語に変換される
  • 実行時にシェーダはコンパイルされる(実行前ではただの文字列でしか無い)

まだまだShaderを人に説明できるところまではいけていません。
引き続き本ブログではどんな細かいところでも僕が理解できていなかったら調べてそれを調査した記事を書いていこうと思っています。

ゲーム制作者になるための3Dグラフィックス技術 増補改訂版

ゲーム制作者になるための3Dグラフィックス技術 増補改訂版

コチラの西川善司さんの本がとてもオススメです。
前提知識が多少必要ですが、3DゲームにおけるGPUのの歴史・変遷、また描画テクニックが分かりやすく図解ありで紹介されています。ネットにも同じような情報が散乱していますが、じっくり読みたい人には良いかもしれません。

GPU Gems 2 日本語版 ?ハイパフォーマンス グラフィックスとGPGPUのためのプログラミング テクニック?

GPU Gems 2 日本語版 ?ハイパフォーマンス グラフィックスとGPGPUのためのプログラミング テクニック?

分厚いし内容は難しいのですが Shaderを書く上では読んでおきたい1冊。


環境

  • MacOS 10.10.5
  • Unity5.3.4f1

あわせてどうぞ

www.shibuya24.info

www.shibuya24.info

www.shibuya24.info

www.shibuya24.info

*1:厳密にはGLSLを直接書くことも出来る