Cg(C for Graphics) レビュー

[Cgとは何か?]

Cg(C for Graphics)とは2002年6月にNVIDIAが発表した、C言語ベースのリアルタイムグラフィックス用のプログラミング言語の事である。また最近のグラフィックカードに搭載されている, GPU(Graphics Processing Unit)という専用のチップに対してプログラミングを行うものである。

従来GPUのプログラミングにはマシン言語や下にあるようなアセンブリ言語で複雑で生産効率の悪いプログラミングをせざるを得なった。そこで、Cgの登場によって、現在一般的に使われているC言語のプログラムできるようになり、以前に比べると手軽にGPUを制御できるようになってきた。

アセンブリ言語の記述例

...................

DEFINE LUMINACE = {0.299, 0.587, 0.144, 0.0}

TEX H0, f[TEX0], TEX4, 2D;

TEX H1, f[TEX2], TEX5, CUBE;

DP3X H1.xyz, H1, LLUMINACE;

MULX H0.w, H0.w LUMINACE.w;

MULX H1.w, H1.x, H1,x;

MOVh H2, f[TEX3]wxyz;

MULX H0.xyz, H0, H3;

MADX H1.w, H1.w, 0.5, 0.5;

MULX H1.xyz, H1, {0.15, 0.15, 1.0, 0.0}

MOVX H0.w, H1.w, {0.15, 0.15, 1.0, 0.0}

MOVX HO.w, H1.w;

TEX H1, H1, TEX7, CUBE;

TEX H3, f[TEX3], TEX2, 1D;

MULX H2.w, H0.w, H2.w;

MULX H3.xyz, H3, H3.w;

...................

詳しい情報はNVIDIAのCgのページに載っているので参考にしてください。

Cg のGPU 用プログラミングモデル

CPUには、通常1つのプログラマブルプロセッサしかありませんが、 GPUには、少なくとも頂点プロセッサとフラグメントプロセッサの2つのプログラマブルプロセッサがあり、加えてその他の非プログラマブルなハードウェアユニットがあります。プロセッサ、非プログラマブルなユニットおよびアプリケーションは、すべてデータフローによってリンクされます。下の図が、CgによるGPUのモデルを示します。

Cg 言語では、頂点プロセッサとフラグメントプロセッサの両方のプログラムを作成する事ができます。Cg コードは、実行時に、または事前に、GPU アセンブリコードにコンパイルできます。

はじめに行う事は頂点の変換です。それぞれの頂点でスクリーンの位置に置き換える(下図左)。 その頂点から三角形、線、点に変換する(下図左→中)。 その結果からラスタライズを行う(下図中→右)。 あとは、ピクセルごとに色やテクスチャを補間することによってスクリーンの描画を行う。

Cgの動作

Cgによるプログラムは基本的に頂点やピクセルのシェーディングを行うためのものであり、そのほかのレンダリングプロセスを扱うためのプログラムを必要とする。CgはOpenGLDirectXAPIを通して使用することができます(下図)

Cgのシェーダのソースコードは、最終的にはGPUが解読可能なバイナリコードに変換されます。そして、DirectXまたはOpenGLの環境で3D画像に描画されます。

Cgを利用できる環境

ソフトウェアの環境

Cgは、Windows, Linux, Mac OS Xで利用できる。環境として一番いいのはWindowsであるようだ、後ほど述べるCg Browserなどの開発補助ツールなども整っている。Cg Complier (Cg をGPU用にコンパイルするもの)がWindowsとLunux用に公開されているようで、どちらもオープンソースプログラムでソースコードが公開されており、使用する事が可能である。Cgの動作やサンプルを確認するぐらいなら、特別な開発環境は必要としないが、本格的にプログラムを作成する場合はVisual C++などの開発環境がないと難しいだろう。プログラムの作成に興味がある人はhttp://if.dynsite.net/t-pot/program/40_cg/index.htmlにインクルードやライブラリの追加の仕方が簡単に説明されているので参考にしてみるといいだろう。

ハードウェアの環境

最低でもGeForce3以降の環境が必須である。推奨の環境としては、GeForce Fx 以降の環境がほしいところである。

[ToolKit]

手っ取りばやくCgで確認するために、CgToolKitというものを使ってみる。

http://developer.nvidia.com/object/cg_toolkit_1_1.html のリンク先の下の画像の赤い枠の部分からCgToolKitをダウンロードできます。

インストールが終了したら下ようなCg Browserを起動してみましょう。

起動したら下のようなブラウザが立ち上がってきます。

左側はCgのサンプルの一覧、真ん中はCgのソースコード、右側はCgを実行されたものです。

下の画像みたいにバンプマップやトゥーンをリアルタイムに表現できます。3つ目の画像はキャラクタがアニメーションをしているのですが、影の描画もリアルタイムにできています。静止画ではよくわからないという人は是非自分でインストールして確かめてみる事をお勧めします。

[Cgの基本ルール]

ここでは、Cgの型や文法を少し紹介します。

基本データ型

Cg では、6 つの基本データ型がサポートされます。

  • float
    32ビットのIEEE浮動小数点数
  • half
    16ビットのIEEEに似た浮動小数点数
  • int
    32ビットの整数。各プロファイルでは、このデータ型のサポートを省略している場合や、intをfloatとして扱うオプションがある場合があります。
  • fixed
    12ビットの固定小数点数(s1.10)。
  • bool
    ブールデータ(true/flase)。比較によって生成され、if および条件演算子で使用されます。
  • sampler*
    テクスチャオブジェクトへのポインタ。

構造体

Cgでは、Cと同じ方法で構造体がサポートしされています。Cgは、structが宣言されるときにタグ名に基づいてtypedefを暗黙的に実行するC++方式が採用されています。

struct mystruct {

/* ... */ };

mystruct s;

制御フロー

Cg では、次のCのような制御を行うことができます。

  • 関数呼出しとreturn
  • if/else
  • while
  • for

これらの制御では、条件式の型がbool である必要があります。i <= 3 などのCg式の型はboolであるため、Cからのこの変更は通常は明らかではありません。

forおよびwhileループが完全にサポートされます。forおよびwhileループは、 コンパイラコンパイル時に反復回数を決定できる場合にのみ使用できます。

Cg では、関数の再帰(および副再帰)は禁止されています。

switch、caseおよびdefaultのキーワードは予約語ですが、現在のリリース のCg コンパイラでは、GPUの構造上サポートされていないようです。将来対応していくことを期待したいです。

Cの算術演算子

Cgでは、Cのすべての標準算術演算子+、-、*、/)が含まれていて、これらの演算子ベクトルスカラの両方で使用できます。ベクトル演算は、常に要素ごとに実行されます。次に例を示します。

float3(a, b, c) * float3(A, B, C) = float3(a*A, b*B, c*C)

これらの演算子は、スカラとベクトルが混在したフォームでも使用できます。

スカラは、要素ごとの演算の実行に必要なサイズのベクトルを作成するために展開されます。次のようになります。

a * float3(A, B, C) = float3(a*A, a*B, a*C)

ブール演算子と比較演算子

Cg には、C の標準ブール演算子のうち3つが含まれています。

  • && 論理AND
  • || 論理OR
  • ! 論理否定

Cでは、これらの演算子にはint型の値を使用し、生成される値もint型ですが、Cgでは、使用する値も生成される値もbool型です。

Cgは、bool型の値を生成するCの比較演算子もサポートしています。

  • < より小さい
  • <= 以下
  • != 等しくない
  • == 等しい
  • >= 以上
  • > より大きい

スウィズル演算子

Cgには、スウィズル演算子(.)というものがあります。この演算子では、ベクトルの成分を再配置して新しいベクトルを作成できます。新しいベクトルを元のベクトルと同じサイズにする必要はなく、要素は反復または省略できます。文字x、y、zおよびwは、それぞれ元のベクトルの1番目、2番目、3番目および4番目の成分を表しています。文字r、g、bおよびaも同じ目的に使用できます。

次に、スウィズルの例を示します。スウィズル演算子を使用して、スカラからベクトルを作成することもできます。

  • float3(a, b, c).zyx → float3(c, b, a)
  • float4(a, b, c, d).xxyy → float4(a, a, b, b)
  • float2(a, b).yyxx → float4(b, b, a, a)
  • float4(a, b, c, d).w → d
  • a.xxxx → float4(a, a, a, a)

書込みマスク演算子

書込みマスク演算子(.)は、代入ステートメントの左側に配置されて、書込みマスクを使用すると、ベクトルのコンポーネントを選択的に上書きできます。 次に、書込みマスクの例を示します。書込みマスク演算子の優先順位は、スウィズル演算子の優先順位と同じです。

float4 color = float4(1.0, 1.0, 0.0, 0.0);

color.a = 1.0; // RGBの値は変化させずに、アルファ値だけ上書き

Cg標準ライブラリ関数

これらの関数は、C の標準ライブラリと性質が類似しており、よく使用する関数の便利なセットを提供しています。パフォーマンスまたは精度上の理由から、特定の関数をカスタマイズして記述することもできるようですが、一般には、可能なかぎり標準ライブラリ関数を使用する方が賢明のようです。

では、数学関数幾何学関数を少しみてみましょう。

数学関数

Cg 標準ライブラリに用意されている数学関数をいくつか紹介します。数学関数は、特に三角関数、指数関数、丸め、ベクトルおよび行列演算に役立つ関数が含まれています。関数は、ほとんどのサイズのスカラとベクトルに対して使えるようです。

abs(x) xの絶対値。
cos(x) xのコサイン。
sin(x) xのサイン。
dot(a, b) ベクトルaとbの内積
exp(x) 指数関数ex。

などの関数があります。ほかにもたくさんあるので詳しく知りたい方は、CgのUser"e;s Manualを参照してください。

幾何学関数

normalize(v) ベクトルv と同じ方向を指す長さ1のベクトルを返します。

reflect(i, n) 入射方向i と表面法線n から反射ベクトルを計算します。

その他の関数としてテクスチャマッピング関数導関数もあります。

[Cg Tutorial]

実際にプログラムをみてみよう。Cgを作成するチュートリアルツールがあるので、

まずhttp://developer.nvidia.com/object/cg_tutorial_software.htmlからCg Tutorial Examples Installerをダウンロードしてきてインストールしよう。

インストールしたら、デフォルトでは、\Program Files\NVIDIA Corporation\Cg Tutorial Examples\Binの中に下のようなアイコンがあるので起動してみよう(ショートカットでも作っておきましょう)。

起動するとこのようなウィンドウが開きます。

Cgのファイル単体を開くときはOpenで開き、今回使用するチュートリアルでは、Open Setupの方を使用します。

Open Setupを開くと下のようなチュートリアル一覧のウィンドウが開きます。Cg Tutorialにはカラーの設定から、反射、バンプマッピング、トゥーンシェーディングなど色々用意されています。今回は一番簡単なカラーの設定を使ってみます。

C2_green.iniを開くと下のようになります。

左上の部分がCgのプログラムで右上の部分がそのプログラムを実行したものになります。

下の下線部で色を指定しています。コメントのどおり、左から赤、緑、青、アルファ値となります。今は緑色です。

その色を青に変えてみましょう。

変更が終了したらコンパイルしてみましょう。

コンパイルツールバーのCompileから選択する事で行えます。

実行結果はコンパイルを実行した時点で自動的に反映されます。実行結果は下のようになります。

Cg Tutorialでは、このように簡単に設定を変える事ができます。、他には反射、バンプマッピング、トゥーンシェーディングなどもあるので、自分でプログラムを変更してみて、実行結果を確かめるのもいいかもしれません。

まとめ

本格的にプログラミングする場合はVisual C++などの環境とDirectXまたは、OpenGLの知識が必要ですが、Cgの動作を試すまたは、デモを動かす程度であれば、今回紹介したようなツールを使えば十分できるのではないでしょうか?GPUのプログラミングからみると、Cg自体のプログラミングはアセンブリ言語の時代と比べるとかなり使いやすくなってきていると思います。

また、先月(2004年9月)にNVIDIAがGoForce 3D 4500というモバイルようのチップを開発したようなので(詳しくはここ)、近い将来Cgなどを使用したリアルタイムの3Dを携帯で見る事ができるようになるかも知れません。