同じOpenGLで利用できるのシェーダーでも、Nvidia のCgシェーダー用の関数と、GLSL用の関数では、関数名が違いだけではなく、いろいろ使い方が異なる場合がある。
Cgシェーダー用語と glsl用語ではいろいろ違うが、varying の意味が違っているのは大きな違いのひとつである。これは、cgのシェーダーソースでは、c言語の main関数のように、引数と戻り値で指定した構造体や引数が、シェーダーへの入出力変数になることも影響していると思われる。 (glsl では グローバル変数のように定義される)
GLSLでは、gLinkProgramの後にプログラムオブジェクト内に、各シェーダーで利用される attribute や uniform 変数のID(Location)が確定されるために、変数のID(Location)の取得はこのタイミングで行われる必要がある。しかし cgシェーダーの場合は、シェーダーが割り振られた時点でID(Location)が確定するため、早めの取得ができてしまう。
cgでは、profile というシェーダーのバージョンや機能を管理するためのものが存在するが、glsl では、version によって管理されているため、glsl では profile という概念を意識する必要はない。
cgにも programという単語は出てくるが、cg ではシェーダー1つ1つをプログラムと読んでいるだけであり、glslでの、vertexシェーダー、fragmentシェーダー(バージョンによっては、geometoryシェーダー)の組み合わせたものを program と呼んで纏めて管理することができるものとは違う。
cgにおけるcontextは、概念的には OpenGLの context と同じ概念ではあるが、実質1つしか作る必要性が無い(将来的機能だったが結局実装されていない)ため、glsl ではよのような概念は採用されずに認識せずに利用できる。
※但し、glslにとっての program と、cgにおける contextは非常に近い関係にあるので、コードによっては置き換えで対応することが可能
cg関数名 | glsl関数 | 注意点 |
cgCreateProgram | glCreateShader + glShaderSource + glCompileShader | glslでは、上記の通り programという概念があるため、厳密に一致しないが。この3つのglsl関数でほぼ合致 |
cgDestroyProgram | glDeleteShader | ほぼ合致すると考えて問題ない |
cgCreateContext | 無し | |
cgDestroyContext | 無し | |
cgGLEnableProfile | 無し | |
cgGLDisableProfile | 無し | |
cgGLGetLatestProfile | 無し | |
cgGLEnableClientState | 無し | glsl では常に varying変数は有効だが、ES3.0 から varying変数は仕様から無くなった。 |
cgGLLoadProgram | glAttachShader | ただし、glslの場合は program に bind される。 |
cgGLBindProgram | glLinkProgram + glUseProgram | glslの場合は、LinkProgramまでは初期処理で、UseProgramは毎フレームのレンダリングで利用される |
これらの関数は、すでにシェーダー時代において古い設計になっている。
cg関数名 | glsl関数 | 注意点 |
cgGLEnableTextureParameter | 無し | |
cgGLDisableTextureParameter | 無し |
cgでは特殊なパラメータ取得方法がある。cgGetFirstParameterと、cgGetNextParameterである。これらは引き渡すパラメータをシェーダーの定義の中から順に取得するものであり、glslには存在しない。また変数の型以外にもセマンティックという変数の役割というものが設定されており glsl の変数のように役割無いものとは大きく違う。(逆に glslには、ビルトイン変数という形で特殊は変数には専用変数名が割り振られる)
cgパラメータ情報取得関数 | glsl関数 | 注意点 |
cgGetFirstParameter | 無し | |
cgGetNextParameter | 無し |
cgGetNamedParameterを利用して取得する。戻り値に CGParameterという構造体らしきポインタを返し、それを使って下記のパラメータ設定方法で設定する。引数はシェーダーを作った時のプログラムID(cgにとってのprogram)と、変数名だけ。
下記の関数はCGParameterの具体的な情報を取得する関数になる。glslでは変数の型については、プログラマーが認識するべきもののため、このような関数は存在しない。逆にglslでは、CPU側で glVertexAttribPointerなどの関数使って、変数の定義情報を設定しシェーダーへのデータを送るが、cgではこれらのようにシェーダーから情報を取得して、それに合わせてデータを送る形になる。
cgパラメータ情報判定関数 | glsl関数 | 注意点 |
cgGetParameterDirection | 無し | 対象のパラメーターが in、out、inout 属性のいずれかであるかを調べる |
cgGetParameterName | 無し | 対象のパラメーターのパラメーター名を獲得する |
cgGetParameterSemantic | 無し | 対象のパラメーターのセマンティック名を獲得する |
cgGetParameterType | 無し | 対象のパラメーターの型を獲得する 戻り値はCG_FLOAT、CG_FLOAT4x4 など |
cgGetParameterVariability | 無し | 対象のパラメーターが varying、uniform か、あるいは定数かを調べる |
下記関数は実際にcgシェーダーにデータを設定する関数となる。基本的にこれらのパラメーター定義関数は、型などによって末尾に付く文字が違う。
cg関数 | glsl関数 | 注意点 |
cgGLSetMatrixParameter | glUniformMatrix | 行列を渡す関数 |
cgGLSetParameterPointer | 配列で行列を渡す関数。cgでの配列は専用関数だが、glslの場合はただの配列渡しのため関数は同じ | |
cgGLSetParameter | glUniform | uniform変数に値を渡す関数 |
cgGLSetTextureParameter | glslではtextureも一緒。テクスチャーIDを渡すだけ。cgの場合は専用関数 |
cgにおける引数は、シェーダーID+値だが、gl系では、UseProgramの後に設定されるので、programIDはステート情報として前提されるため、シェーダーIDは無く値だけとなる。
また、cgの行列指定関数には行優先、列優先の指定ができるが、glslでは、ES3.0から、uniform 指定時に layout 指定を行うことで行と列の優先を指定できる。
layout(row_major) uniform mat4 mtxProjection;
row_majorが行優先、column_majorが列優先。