テクスチャ処理では OpenGL ES 2.0 と同等の動作を行うことができますが、いくつか 3DS 固有の制約があります。
11.1. テクスチャユニット
3DS は 4 つのテクスチャユニット(TEXTURE0
~ 3
)を搭載していますが、テクスチャユニットによって扱うことのできるテクスチャの種類が異なります。また、ラスタライズを行うラスタライザからテクスチャユニットに、独立して出力されるテクスチャ座標は 3 組までです。4 つのテクスチャユニットすべてにテクスチャ座標を出力する場合、TEXTURE2
または TEXTURE3
がほかのテクスチャユニットと同じテクスチャ座標を共有することになります。
テクスチャ |
2次元 |
キューブマップ |
シャドウ |
プロジェクション |
プロシージャル |
---|---|---|---|---|---|
|
✓ |
✓ |
✓ |
✓ |
|
|
✓ |
|
|
|
|
|
✓ |
|
|
|
|
|
|
|
|
|
✓ |
1 次元、3 次元テクスチャには対応していません。キューブマップ、シャドウ、プロジェクションのように、w 成分が必要となるテクスチャの処理は TEXTURE0
でのみ行うことができます。また、TEXTURE3
はプロシージャルテクスチャ専用のユニットです。搭載されているテクスチャユニットの数を示す GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
は 4 で定義されています。
11.1.1. テクスチャ座標の入力
テクスチャユニット 0 のみ w 成分を入力することができ、そのほかのテクスチャユニットには u と v の 2 成分のみ入力が可能です。プロジェクションテクスチャは、単に 2 次元テクスチャに w 成分を有効にしたものですが、座標(u, v)が w で除算されて生成されるため、頂点シェーダで出力する座標値には注意が必要となります。
頂点シェーダからテクスチャ座標を送るには属性名 texture0
、texture0w
、texture1
、texture2
で出力レジスタをマッピングします。texture0w
は、キューブマップ、シャドウ、プロジェクションテクスチャのように、w 成分を必要とする場合には必ず出力しなければなりません。出力していない場合のテクスチャ座標 0 の出力は不定です。w 成分を必要としないテクスチャに対する texture0w
の出力は無視されます。
属性名 |
頂点シェーダから送られる属性 |
---|---|
|
テクスチャ座標 0 の u, v 成分 |
|
テクスチャ座標 0 の w 成分 |
|
テクスチャ座標 1 の u, v 成分 |
|
テクスチャ座標 2 の u, v 成分 |
11.1.1.1. テクスチャ座標の精度について
テクスチャユニット内では、テクスチャ座標値は整数部と小数部を合わせて 16 ビットの値で表現され、整数部の絶対値が大きくなると小数部のビット数が小さくなります。
テクスチャのサンプリング精度は小数部のビット精度に依存しています。小数部がテクスチャの幅または高さのテクセル数を表現するのに十分なビット数になる場合は、最適なテクスチャのサンプリングを行うことができます。バイリニアフィルタリングを行う場合は、さらに 6 ビットを小数部に確保するようにしてください。
11.1.2. 使用方法
OpenGL ではテクスチャユニットの有効・無効の切り替えを glEnable()
と glDisable()
の引数に TEXTURE_2D
などを指定することで行っていましたが、3DS では予約ユニフォーム dmp_Texture[i].samplerType
(i
はテクスチャユニットの番号)に対する設定によって行います。GL_TEXTURE_2D
を引数に、glEnable()
または glDisable()
を呼び出した場合の動作は不定です。
テクスチャユニットを無効にするには、どのテクスチャユニットでも GL_FALSE
を指定して glUniform1i()
を呼び出し、予約ユニフォームに値を設定することで行われます。有効にする場合は、テクスチャユニットによって予約ユニフォームに設定する値が異なります。
予約ユニフォーム |
設定する値 |
扱うテクスチャ |
---|---|---|
|
|
無効(デフォルト) |
|
2 次元テクスチャ |
|
|
キューブマップテクスチャ |
|
|
シャドウテクスチャ |
|
|
キューブマップシャドウテクスチャ |
|
|
プロジェクションテクスチャ |
|
|
|
無効(デフォルト) |
|
2 次元テクスチャ |
|
|
|
無効(デフォルト) |
|
2 次元テクスチャ |
|
|
|
無効(デフォルト) |
|
プロシージャルテクスチャ |
テクスチャユニットが入力に使用するテクスチャ座標は、テクスチャユニット 0 がテクスチャ座標 0 固定、テクスチャユニット 1 がテクスチャ座標 1 固定、テクスチャユニット 2 と 3 については予約ユニフォーム dmp_Texture[i].texcoord
(i
はテクスチャユニットの番号で 2 または 3 )で指定しなければなりません。テクスチャユニットによって予約ユニフォームに設定することができる値が異なります。4 つのテクスチャユニットすべてを使用する場合、テクスチャユニット 2 またはテクスチャユニット 3 が入力に使用するテクスチャ座標をほかのテクスチャユニットと共有しなければなりません。
テクスチャコンバイナから無効化されているテクスチャユニットを参照した場合、テクスチャコンバイナに入力されるカラー値は不定になります。
予約ユニフォーム |
設定する値 |
入力に使用するテクスチャ座標 |
---|---|---|
|
|
テクスチャ座標 1 |
|
テクスチャ座標 2(デフォルト) |
|
|
|
テクスチャ座標 0(デフォルト) |
|
テクスチャ座標 1 |
|
|
テクスチャ座標 2 |
予約ユニフォームによる設定を除き、テクスチャユニットに対する設定は glActiveTexture()
で指定したテクスチャユニットに対して行われます。
void glActiveTexture(GLenum texture);
texture
には GL_TEXTURE0
、GL_TEXTURE1
、GL_TEXTURE2
を指定することができます。テクスチャユニット 3 を示す GL_TEXTURE3
を指定した場合や上記以外の値を指定した場合は GL_INVALID_ENUM
のエラーが生成されます。
プロシージャルテクスチャの設定はすべて予約ユニフォームで行います。
11.1.3. 使用するテクスチャの指定
テクスチャユニットで使用するテクスチャは glActiveTexture()
でテクスチャユニットを指定した後の、glBindTexture()
によるテクスチャオブジェクトの指定で行われます。
テクスチャユニットごとに異なるテクスチャを使用する場合は、以下のコード例のように glActiveTexture()
と glBindTexture()
を呼び出してください。
// Texture Unit0 glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, imageTexID); // Texture Unit1 glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, bumpTexID);
11.1.4. テクスチャパラメータ
テクスチャのラッピングモードやフィルタなど、テクスチャにパラメータを付加するには glTexParameter*()
を使用します。
void glTexParameterf(GLenum target, GLenum pname, GLfloat param); void glTexParameterfv(GLenum target, GLenum pname, const GLfloat* params); void glTexParameteri(GLenum target, GLenum pname, GLint param); void glTexParameteriv(GLenum target, GLenum pname, const GLint* params);
glTexParameteri()
はパラメータに整数を、glTexParameterf()
はパラメータに浮動小数点数を渡して付加する関数です。関数名の末尾に "v
" の付いたものはベクトル(配列)を渡さなければならないパラメータの付加に使用します。
target
に指定する値は glTexImage2D()
の target
と同じです(表 7-2)。pname
は付加するパラメータの名前、param
はパラメータの値です。3DS で独自に追加されているパラメータが存在します。
3DS では、1 つのフラグメントに対して最大 8 テクセルを取得してフィルタリングを行っています。
pname |
int / float / vector |
付加されるパラメータ |
---|---|---|
|
|
S 方向のラッピングモード(表 11-6) |
|
|
T 方向のラッピングモード(表 11-6) |
|
|
縮小時のフィルタ(表 11-7) |
|
|
拡大時のフィルタ(表 11-8) |
|
|
ラッピングモードで |
|
|
LOD バイアス値(-16.0 ~ 16.0。デフォルト 0.0) |
|
|
LOD の最小レベル(デフォルト -1000) |
|
|
ミップマップテクスチャの自動生成(デフォルト |
S、T 方向のラッピングモードは以下の値で指定します。
param |
説明 |
---|---|
|
繰り返し(デフォルト) |
|
反転して繰り返し |
|
テクスチャ座標 0.0 ~ 1.0 以外はテクスチャイメージの端のカラー |
|
テクスチャ座標 0.0 ~ 1.0 以外はボーダーカラー |
テクスチャイメージが縮小されてレンダリングされる場合のフィルタは以下の値で指定します。
param |
説明 |
---|---|
|
ニアレストに選定されたテクセルのカラーを使用する(デフォルト) |
|
バイリニアサンプリング(4 サンプルの平均)でカラーを決定する |
|
ミップマップテクスチャの選定をニアレストで行い、ニアレストに選定されたテクセルのカラーを使用する |
|
2 つのレベルのミップマップテクスチャを選定し、それぞれのレベルでニアレストに選定されたカラーから補間する |
|
ミップマップテクスチャの選定をニアレストで行い、バイリニアサンプリングでカラーを決定する |
|
2 つのレベルのミップマップテクスチャを選定し、それぞれのレベルでバイリニアサンプリングされたカラーから補間する |
テクスチャイメージが拡大されてレンダリングされる場合のフィルタは以下の値で指定します。
param |
説明 |
---|---|
|
ニアレストに選定されたテクセルのカラーを使用する(デフォルト) |
|
バイリニアサンプリング(4 サンプルの平均)でカラーを決定する |
11.1.4.1. ミップマップテクスチャの自動生成
テクスチャパラメータ GL_GENERATE_MIPMAP
に GL_TRUE
を設定すると、glTexImage2D()
、glCopyTexImage2D()
、glCopyTexSubImage2D()
の呼び出しで level
に -2 以下の値を渡したときに、最も低いレベルのテクスチャ以外のミップマップテクスチャが自動生成されます。ただし、自動生成されるミップマップテクスチャの幅と高さは、テクスチャのフォーマット(format
と type
の組み合わせ)によって、その最小値が以下のように制限されています。
フォーマット |
format |
type |
幅、高さの最小値 |
---|---|---|---|
|
|
|
64 |
|
|
|
64 |
|
|
|
32 |
|
|
|
64 |
|
|
|
32 |
テクスチャのフォーマットによる最小値の違いにより、同じ幅と高さのテクスチャでも level
に指定することのできる値の範囲が異なります。最小値よりも小さなサイズのミップマップテクスチャを自動生成させるような指定をした場合は GL_INVALID_OPERATION
のエラーが生成されます。例えば、128x128 テクセルのテクスチャに対して、フォーマットが RGB8 のときは level
に -2 または -3 を指定することができますが、フォーマットが RGB565 のときは level
に -2 のみ指定することができます。
自動生成を行う設定をしていた場合は、自動生成されたミップマップテクスチャが優先されます。ミップマップテクスチャのデータを含むテクスチャイメージをロードすると、そのミップマップテクスチャのデータは無効となります。
自動生成を行う設定をしていた場合、glCopyTexImage2D()
と glCopyTexSubImage2D()
の level
には、対象のテクスチャをロードしたときの glTexImage2D()
で level
に渡した値と同じ値を渡さなければなりません。異なる場合は GL_INVALID_OPERATION
のエラーが生成されます。ただし、level
に 0 以外を渡したとしても、コピー先は最も低いレベルのテクスチャであり、ミップマップテクスチャを書き換えることにはなりません。
自動生成を行わない設定をしていた場合は、glCopyTexImage2D()
と glCopyTexSubImage2D()
の level
には、対象のテクスチャをロードしたときの glTexImage2D()
で level
に渡した値に関わらず、0 を指定しなければなりません。0 以外を指定した場合は GL_INVALID_OPERATION
のエラーが生成されます。
11.1.4.2. フィルタに GL_NEAREST を指定した場合の注意事項
テクスチャパラメータの GL_TEXTURE_MIN_FILTER
および GL_TEXTURE_MAG_FILTER
に対して GL_NEAREST
を指定した場合、垂直または水平な直線(色の境界が明確な直線を成す場合を含む)のある画像をテクスチャとして使用し、その直線が画面の走査線に垂直または水平になるようにポリゴンを描画すると、本来直線に見えるはずの模様がデコボコな線として描画されることがあります。
この現象は、ポリゴン内のテクスチャ座標を補間する際の計算精度が起因となっています。走査線に垂直または水平な、ある一列に並んだフラグメント列を考えたとき、各フラグメントがテクスチャ画像上の垂直または水平な、ある一列に並んだテクセルをサンプリングすると、テクスチャの画像上の直線はそのままの直線としてポリゴン上に描画されます。しかし、それらの各フラグメントが、ある一列に並んだテクセルと、その隣の列に並んだテクセルの境界付近をサンプリングする場合、テクスチャ座標の誤差によって、どちらの列のテクセルをサンプルするかがフラグメントごとに異なり、テクスチャの画像上の直線がデコボコな線としてポリゴン上に描画されてしまうことがその原因です。そのため、両端のテクスチャ座標が 0 ~ 1 であるような矩形ポリゴンをテクスチャと同じサイズで描画するのと同じように、各フラグメントがテクセルの中央をサンプルするようにテクスチャ座標や描画面積を調整することで回避することができます。
11.1.4.3. 縮小時のフィルタに GL_XXX_MIPMAP_LINEAR を指定した場合の注意事項
テクスチャパラメータの GL_TEXTURE_MIN_FILTER
に対して GL_XXX_MIPMAP_LINEAR
を指定した場合はトライリニアフィルタが有効となり、2 つのレベルのミップマップテクスチャから取得したカラーを用いて補間処理を行ったカラーで描画されます。しかし、この補間処理には計算精度による誤差が発生する可能性があり、たとえ同じ成分値の 2 つのカラーを処理した場合でも、誤差によって異なるカラーが描画される場合があります。
補間処理が行われるのは LOD 計算の結果、2 つのレベルのミップマップテクスチャからカラーを取得しなければならない場合ですので、あるレベルのミップマップテクスチャだけからカラーを取得する場合は補間処理が行われません。そのため、補間処理が行われた部分が、補間処理が行われなかった部分に比べてわずかに暗くなります。その結果、色味の差異がミップマップレベルの境界に沿ってエッジのように描画されてしまいます。
この現象の緩和策として、テクセルカラーの固定値である成分を利用する方法があります。例えば、GL_RGB
フォーマットのテクスチャはアルファ成分が 1.0 の固定値ですが、この固定値の成分もトライリニアフィルタによる補間処理が行われたテクセルではわずかに減少してしまいます。一方、補間処理が行われなかったテクセルでは、そのまま 1.0 で描画されます。カラーの補正は、補間処理によって減少したアルファ成分の差分値をテクスチャカラーと乗算した結果をテクスチャカラーに加算することで行います。
この補正処理はテクスチャコンバイナで行うことができます。以下に設定例を示します。
glUniform1i(glGetUniformLocation(program, "dmp_TexEnv[0].combineRgb"), GL_MULT_ADD_DMP); glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[0].operandRgb"), GL_SRC_COLOR, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_COLOR); glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[0].srcRgb"), GL_TEXTURE0, GL_TEXTURE0, GL_TEXTURE0);
この設定により、補間処理が行われなかった部分は乗算結果が 0.0 で出力されるためテクスチャカラーそのものが出力されることになり、補間処理が行われた部分はアルファ成分の差分値とテクスチャカラーの乗算結果をテクスチャカラーに加算して補正した結果が出力されることになります。この設定では入力ソースのすべてにテクスチャカラーを指定しますので、1 段目のテクスチャコンバイナ(コンバイナ 0)でなければ設定することができません。
GL_RGBA
フォーマットのように、成分中に固定値のものがない場合は、固定値の成分を持つ別のテクスチャを用意し、マルチテクスチャとすることで補正します。補正のために用意するテクスチャは、元のテクスチャと同じサイズ、同じミップマップレベル数にし、同じ uv の値が入力されなければなりません。データサイズやキャッシュ効率を考慮し、ETC1 圧縮テクスチャで用意することを推奨します。
11.1.4.4. テクスチャレベル(ミップマップ)パラメータの取得
以下の関数で、現在アクティブになっているテクスチャユニットにバインドされているテクスチャの、ミップマップのレベルごとのパラメータを取得することができます。ただし、プロシージャルテクスチャ用のテクスチャユニット(GL_TEXTURE3
)は glActiveTexture()
で指定できないため、プロシージャルテクスチャの情報は取得できません。
void glGetTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat *params); void glGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params);
取得した値を格納する変数の型が異なるだけで、それぞれの関数で取得する値に違いはありません。
target
にはテクスチャの種類を指定します。指定可能な値は以下のとおりです。
target に指定する値 |
テクスチャの種類 |
---|---|
|
2 次元テクスチャ(シャドウテクスチャ、ガステクスチャを含む) |
|
キューブマップテクスチャ(+X 方向の面) |
|
キューブマップテクスチャ(-X 方向の面) |
|
キューブマップテクスチャ(+Y 方向の面) |
|
キューブマップテクスチャ(-Y 方向の面) |
|
キューブマップテクスチャ(+Z 方向の面) |
|
キューブマップテクスチャ(-Z 方向の面) |
level
にはパラメータを取得するミップマップのレベルを指定します。0 を指定すると、一番低いレベルの(サイズが一番大きな)テクスチャのパラメータを取得します。その次のレベルは 1 を、さらに次のレベルは 2 を指定することで取得可能です。
pname
には取得するパラメータの種類を指定します。指定可能な値と params
に格納されるパラメータの対応は以下のとおりです。
pname に指定する値 |
パラメータ |
---|---|
|
テクスチャの幅(テクセル数) |
|
テクスチャの高さ(テクセル数) |
|
未対応のため 0 固定 |
|
テクスチャの内部フォーマット |
|
未対応のため 0 固定 |
|
赤成分のビット数(テクセル単位) |
|
緑成分のビット数(テクセル単位) |
|
青成分のビット数(テクセル単位) |
|
アルファ成分のビット数(テクセル単位) |
|
輝度成分のビット数(テクセル単位) |
|
強度成分のビット数(テクセル単位。シャドウテクスチャのみ) |
|
深度成分のビット数(テクセル単位。シャドウテクスチャのみ) |
|
交差が考慮されない密度情報(密度情報 1)のビット数(テクセル単位。ガステクスチャのみ) |
|
交差が考慮される密度情報(密度情報 2)のビット数(テクセル単位。ガステクスチャのみ) |
|
圧縮テクスチャかどうか
|
|
|
pname
に GL_TEXTURE_INTERNAL_FORMAT
を指定したときに取得するテクスチャの内部フォーマットと、テクセルを構成する各成分のビット数の対応を以下に示します。
内部フォーマット |
赤 |
緑 |
青 |
アルファ |
輝度 |
強度 |
深度 |
密度 1 |
密度 2 |
---|---|---|---|---|---|---|---|---|---|
|
4 |
4 |
4 |
4 |
|
|
|
|
|
|
5 |
5 |
5 |
1 |
|
|
|
|
|
|
8 |
8 |
8 |
8 |
|
|
|
|
|
|
5 |
6 |
5 |
|
|
|
|
|
|
|
8 |
8 |
8 |
|
|
|
|
|
|
|
|
|
|
8 |
|
|
|
|
|
|
|
|
|
4 |
|
|
|
|
|
|
|
|
|
|
8 |
|
|
|
|
|
|
|
|
|
4 |
|
|
|
|
|
|
|
|
8 |
8 |
|
|
|
|
|
|
|
|
4 |
4 |
|
|
|
|
|
|
|
|
|
|
8 |
24 |
|
|
|
|
|
|
|
|
|
|
16 |
16 |
|
8 |
8 |
|
|
|
|
|
|
|
|
8 |
8 |
8 |
|
|
|
|
|
|
|
8 |
8 |
8 |
4 |
|
|
|
|
|
target
や pname
に不正な値を指定した場合は GL_INVALID_ENUM
のエラーを、ロードされていないミップマップレベルを level
に指定した場合は GL_INVALID_VALUE
のエラーを生成します。
11.1.5. テクスチャの設定によるパフォーマンスへの影響
テクスチャのフォーマットやサイズ、各種設定によって、グラフィックス処理のパフォーマンスに影響することがあります。以下にその傾向を列挙します。
- 圧縮テクスチャが最も高速に処理され、以降は 1 テクセルあたりのバイトサイズが小さいフォーマットの方が高速に処理されます。
- サイズが小さいほど高速に処理されます。
- メモリアクセスの競合が起こるため、同時に使用するテクスチャの枚数が多いほど処理が低速になります。
- 縮小時のフィルタ設定では、
GL_NEAREST
とGL_LINEAR
、GL_NEAREST_MIPMAP_NEAREST
とGL_LINEAR_MIPMAP_NEAREST
、GL_NEAREST_MIPMAP_LINEAR
とGL_LINEAR_MIPMAP_LINEAR
のそれぞれが同じ速度で処理されます。ただし、GL_NEAREST(_XXX)
とGL_LINEAR(_XXX)
は 1 ピクセル辺りでフェッチするテクセル数が異なり、GL_NEAREST(_XXX)
が 1 テクセル、GL_LINEAR(_XXX)
が 4 テクセルですので、メモリ負荷はGL_NEAREST(_XXX)
の方が小さくなります。 - テクスチャを縮小して貼る場合は、ミップマップがある方が高速に処理されます。ただし、ミップマップを使用した場合でもフィルタ設定によっては処理負荷が変わり、
GL_*_MIPMAP_LINEAR
はGL_*_MIPMAP_NEAREST
に比べて 2 倍程度の処理負荷がかかる場合があります。 - 拡大時のフィルタ設定では、
GL_NEAREST
とGL_LINEAR
はほぼ同じパフォーマンスですが、GL_NEAREST
がわずかに高速になる場合があります。 - ガステクスチャとシャドウテクスチャはミップマップが使えないため、通常テクスチャより処理が低速になります。
- シャドウテクスチャは、シャドウ専用の特殊なフィルタを使用するため、トライリニアフィルタ(通常テクスチャで縮小フィルタを
GL_*_MIPMAP_LINEAR
に設定したとき)に相当する処理負荷がかかります。つまり、通常テクスチャ(トライリニアフィルタ設定除く)に比べて 2 倍程度の処理負荷がかかります。 - プロシージャルテクスチャには設定条件による差はありません。また、一般的な 2D テクスチャよりも高速に処理されます。
- 複数のテクスチャを使用する場合、すべてのテクスチャが VRAM-A または VRAM-B のどちらか一方にまとめて配置されている方が、分割して配置されているよりも高速に処理されます。
- 描画結果の上方向と一致するように作成されたテクスチャよりも、フレームバッファの上方向と一致するように作成されたテクスチャの方が高速に処理される可能性があります。これはフラグメントを生成する方向とテクスチャを読み込む方向が一致することで、テクスチャキャッシュのヒット率が向上するためです。上下の反転はパフォーマンスに影響しません。なお、フラグメントは 8x8 ピクセル単位で横方向に処理され、テクスチャは 8x4 テクセル単位で読み出されます。また、3DS の LCD は短い長さの辺を上下端としている点に注意してください。
11.1.6. テクスチャキャッシュについて
テクスチャキャッシュのサイズは、1 次キャッシュが 256 Byte、2 次キャッシュが 8 KByte です。キャッシュ内部では、圧縮テクスチャ(ETC フォーマット)だけがそのままのデータフォーマットで扱われ、それ以外のフォーマット(アルファ付き ETC フォーマットを含む)のテクスチャは 32 bit フォーマットに変換されます。
1 次キャッシュはユニットそれぞれに独立していますが、2 次キャッシュは全ユニットで共有しています。
1 次キャッシュにヒットせずに 2 次キャッシュからデータを取得する場合は約 5 サイクル、2 次キャッシュにもヒットせずに VRAM からデータを取得する場合はさらに 30 サイクル程度のペナルティが発生します。ただし、上記のペナルティを隠蔽できるように、テクセルのフェッチを先読みして行うようにハードウェアで実装されています。
テクスチャキャッシュは、4way セットアソシエイティブ方式です。キャッシュラインの数は 16 です。2 次キャッシュのサイズは 8K バイトですので、キャッシュラインは 1 ライン当り 512 バイトとなります。
キャッシュラインは、テクスチャ座標値から計算される、8x4 ブロックアドレス(4x4 テクセル単位のアドレスを 2 で割ったもの)の下位4ビットになります。ETC1 の場合は、4x4 テクセルブロックを 2x2 個並べたブロック単位のアドレスの [5:2] ビットの値になります。同一のキャッシュラインに連続的にアクセスした場合に、キャッシュのスラッシングが発生します。
11.2. コンバイナ
3DS に 6 基搭載されている(テクスチャ)コンバイナは、フラグメントライトのプライマリ、セカンダリのカラー、テクスチャユニットから出力されるテクスチャカラー、頂点カラー、定数カラーなどを合成することができます。ゲームキューブや Wii でのアプリケーション開発経験者でしたら、TEV でのカラー・アルファ合成処理をイメージしていただければ理解しやすいと思います。
OpenGL ES 1.1 ではコンバイナの設定を TexEnv で行っていましたが、3DS では予約ユニフォームへの値の設定で行います。TexEnv のパラメータと予約ユニフォームの対応は以下のようになっています。
TexEnv |
予約ユニフォーム |
設定の内容 |
---|---|---|
|
|
カラーのコンバイナ関数 |
|
|
アルファのコンバイナ関数 |
|
|
カラーのソース |
|
|
アルファのソース |
|
|
カラーのオペランド |
|
|
アルファのオペランド |
|
|
カラーのスケーリング値 |
|
|
アルファのスケーリング値 |
|
|
定数カラー(アルファ成分あり) |
n
はソース(0 ~ 2)、i
はコンバイナの番号(0 ~ 5)
各コンバイナはソースからの入力をオペランドで加工し、3 つのソースからの入力をコンバイナ関数で計算した結果にスケーリング値を乗算したものを 0.0 ~ 1.0 にクランプして出力します。また、コンバイナへの入力は計算前に 0.0 ~ 1.0 にクランプされており、頂点カラー(プライマリカラー)は絶対値でラスタライズした結果がクランプされた値となります。
カラー成分へのオペレーションは共通した設定でそれぞれの成分(赤、緑、青)に対して行われ、アルファ成分へのオペレーションは独立した設定で行われます。なお、無効化されたテクスチャユニットを参照した場合、入力されるカラー値は不定となります。
コンバイナへの 3 つの入力ソースは、それぞれ以下のものから選択(重複可)することができます。
- テクスチャユニットから出力されるテクスチャカラー
- 定数カラー
- プライマリカラー
- フラグメントライトのプライマリカラー
- フラグメントライトのセカンダリカラー
- 前段のコンバイナの出力(コンバイナ 0 以外)
- 前段のコンバイナバッファの出力(コンバイナ 0 以外)
11.2.1. コンバイナ関数の予約ユニフォーム
コンバイナ関数の予約ユニフォームは dmp_TexEnv[i].combineRgb
と dmp_TexEnv[i].combineAlpha
です。glGetUniformLocation()
で取得した予約ユニフォームのロケーションに glUniform1i()
で値を設定します。
コンバイナ関数の予約ユニフォームへの設定値は以下のものから選択します。dmp_TexEnv[i].combineRgb
と dmp_TexEnv[i].combineAlpha
に設定可能な値は同じです。
GL_DOT3_RGBA
を設定する場合は、そのコンバイナのカラー(combineRgb
)とアルファ(combineAlpha
)のコンバイナ関数は同じ(GL_DOT3_RGBA
)でなければなりません。
設定値 |
コンバイナ関数 |
---|---|
|
Src0(デフォルト) |
|
Src0 * Src1 |
|
Src0 + Src1 |
|
Src0 + Src1 - 0.5 |
|
Src0 * Src2 + Src1 * (1 - Src2) |
|
Src0 - Src1 |
|
4 * ((Src0_Red - 0.5) * (Src1_Red - 0.5) + (Src0_Green - 0.5) * (Src1_Green - 0.5) + (Src0_Blue - 0.5) * (Src1_Blue - 0.5)) |
|
4 * ((Src0_Red - 0.5) * (Src1_Red - 0.5) + (Src0_Green - 0.5) * (Src1_Green - 0.5) + (Src0_Blue - 0.5) * (Src1_Blue - 0.5)) |
|
(Src0 + Src1) * Src2 ※加算後にクランプ(0.0 ~ 1.0)されてから乗算されます |
|
(Src0 * Src1) + Src2 |
11.2.2. 入力ソースの予約ユニフォーム
入力ソースの予約ユニフォームは dmp_TexEnv[i].srcRgb
と dmp_TexEnv[i].srcAlpha
です。
glGetUniformLocation()
で取得した予約ユニフォームのロケーションに glUniform3i()
で値を設定します。先頭から、ソース 0、ソース 1、ソース 2 の順です。
入力ソースの予約ユニフォームへの設定値は以下のものから選択します。dmp_TexEnv[0].srcRgb
と dmp_TexEnv[0].srcAlpha
、dmp_TexEnv[i].srcRgb
と dmp_TexEnv[i].srcAlpha
に設定可能な値は同じです。
コンバイナ 0 以外のコンバイナは、3 つの入力ソースのいずれかに GL_CONSTANT
、GL_PREVIOUS
、GL_PREVIOUS_BUFFER_DMP
のうちの 1 つが指定されていなければなりません。
設定値 |
入力ソース |
---|---|
|
テクスチャユニット 0 のテクスチャカラー |
|
テクスチャユニット 1 のテクスチャカラー |
|
テクスチャユニット 2 のテクスチャカラー |
|
テクスチャユニット 3 のテクスチャカラー |
|
定数カラー( |
|
プライマリカラー(頂点カラー) |
|
前段のコンバイナの出力(コンバイナ 0 は設定不可。コンバイナ 0 以外のデフォルト) |
|
前段のコンバイナバッファの出力(コンバイナ 0 は設定不可) |
|
フラグメントライトのプライマリカラー |
|
フラグメントライトのセカンダリカラー |
11.2.3. オペランドの予約ユニフォーム
オペランドの予約ユニフォームは dmp_TexEnv[i].operandRgb
と dmp_TexEnv[i].operandAlpha
です。
glGetUniformLocation()
で取得した予約ユニフォームのロケーションに glUniform3i()
で値を設定します。先頭から、ソース 0、ソース 1、ソース 2 の順です。
オペランドの予約ユニフォームへの設定値は以下のものから選択します。
設定値 |
オペランド |
---|---|
|
Color( |
|
1 - Color( |
|
Alpha( |
|
1 - Alpha |
|
Color_Red |
|
1 - Color_Red |
|
Color_Green |
|
1 - Color_Green |
|
Color_Blue |
|
1 - Color_Blue |
11.2.4. スケーリング値の予約ユニフォーム
スケーリング値の予約ユニフォームは dmp_TexEnv[i].scaleRgb
と dmp_TexEnv[i].scaleAlpha
です。
glGetUniformLocation()
で取得した予約ユニフォームのロケーションに glUniform1f()
で値を設定します。
スケーリング値の予約ユニフォームへの設定値は以下のものから選択します。
設定値 |
スケーリング |
---|---|
1.0 |
コンバイナの出力はそのまま(デフォルト) |
2.0 |
コンバイナの出力を 2 倍にする(0.0 ~ 1.0 にクランプ) |
4.0 |
コンバイナの出力を 4 倍にする(0.0 ~ 1.0 にクランプ) |
11.2.5. 定数カラーの予約ユニフォーム
定数カラーの予約ユニフォームは dmp_TexEnv[i].constRgba
です。glGetUniformLocation()
で取得した予約ユニフォームのロケーションに glUniform4f()
で値を設定します。先頭から R、G、B、A の順です。
定数カラーの予約ユニフォームのデフォルト設定値は (R, G, B, A) = (0.0, 0.0, 0.0, 0.0) です。
11.2.6. コンバイナの設定例
設定例として、プライマリカラーをそのまま描画するために、コンバイナ 2 でプライマリカラーを参照して、そのまま出力する接続の例を以下に示します。
コンバイナ 2 の入力ソース 0 にプライマリカラー(GL_PRIMARY_COLOR
)を、オペランド 0 に入力ソースのカラーそのまま(GL_SRC_COLOR
)を、コンバイナ関数に入力ソース 0 をそのまま出力(GL_REPLACE
)を、スケールに 1.0 を設定すると、コンバイナの出力はプライマリカラーだけになり、それ以外の影響を受けなくなります。この設定では、コンバイナ 0 と 1 は出力結果に影響を与えません。
接続図は以下のようになっています。
実際にプログラムで指定する際のコード例を以下に示します。
glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[2].srcRgb"), GL_PRIMARY_COLOR, GL_PREVIOUS, GL_PREVIOUS); glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[2].srcAlpha"), GL_PRIMARY_COLOR, GL_PREVIOUS, GL_PREVIOUS); glUniform1i(glGetUniformLocation(program, "dmp_TexEnv[2].combineRgb"), GL_REPLACE); glUniform1i(glGetUniformLocation(program, "dmp_TexEnv[2].combineAlpha"), GL_REPLACE); glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[2].operandRgb"), GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR); glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[2].operandAlpha"), GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA); glUniform1f(glGetUniformLocation(program, "dmp_TexEnv[2].scaleRgb"), 1.0); glUniform1f(glGetUniformLocation(program, "dmp_TexEnv[2].scaleAlpha"), 1.0);
より複雑な設定例として、テクスチャ 0 とテクスチャ 1 の出力をコンバイナ 1 で加算し、その結果にコンバイナ 2 でプライマリカラーを乗算するような設定を示します。
glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[1].srcRgb"), GL_TEXTURE0, GL_TEXTURE1, GL_PREVIOUS); glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[1].srcAlpha"), GL_TEXTURE0, GL_TEXTURE1, GL_PREVIOUS); glUniform1i(glGetUniformLocation(program, "dmp_TexEnv[1].combineRgb"), GL_ADD); glUniform1i(glGetUniformLocation(program, "dmp_TexEnv[1].combineAlpha"), GL_ADD); glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[1].operandRgb"), GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR); glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[1].operandAlpha"), GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA); glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[2].srcRgb"), GL_PREVIOUS, GL_PRIMARY_COLOR, GL_PREVIOUS); glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[2].srcAlpha"), GL_PREVIOUS, GL_PRIMARY_COLOR, GL_PREVIOUS); glUniform1i(glGetUniformLocation(program, "dmp_TexEnv[2].combineRgb"), GL_MODULATE); glUniform1i(glGetUniformLocation(program, "dmp_TexEnv[2].combineAlpha"), GL_MODULATE); glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[2].operandRgb"), GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR); glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[2].operandAlpha"), GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA);
11.3. コンバイナバッファ
最終のコンバイナ(コンバイナ 5 )以外にはコンバイナバッファが並列して設置されています。コンバイナバッファは前段のコンバイナまたはコンバイナバッファの出力を入力ソースに選択することができ、前段のコンバイナバッファの出力を受け継いでいけば、後段のコンバイナで直前のコンバイナより前段にあるコンバイナの出力を入力ソースに選択することができます。
11.3.1. コンバイナバッファの予約ユニフォーム
コンバイナバッファ 0 への入力はありませんので、予約ユニフォーム dmp_TexEnv[0].bufferColor
で初期値としての定数カラーを設定します。定数カラーは glGetUniformLocation()
で取得した予約ユニフォームのロケーションに glUniform4f()
で値を設定します。先頭から R、G、B、A の順です。
コンバイナバッファ 0 の定数カラーのデフォルト設定値は (R, G, B, A) = (0.0, 0.0, 0.0, 0.0) です。
コンバイナバッファ 1 ~ 4 への入力ソースは、前段のコンバイナの出力か前段のコンバイナバッファの出力から選択することができます。予約ユニフォームは dmp_TexEnv[i].bufferInput
(i
は 1 ~ 4)で、カラー成分とアルファ成分の入力を個別に選択することができます。glGetUniformLocation()
で取得した予約ユニフォームのロケーションに glUniform2i()
で値を設定します。先頭からカラー成分、アルファ成分の順です。
コンバイナバッファへの入力ソースの予約ユニフォームへの設定値は以下のものから選択します。
設定値 |
入力ソース |
---|---|
|
前段のコンバイナの出力(デフォルト) |
|
前段のコンバイナバッファの出力 |
11.3.2. コンバイナバッファの設定例
コンバイナバッファを使用した設定例として、テクスチャ 0 にフラグメントライティングのプライマリカラーを乗算した結果とテクスチャ 1 にフラグメントライティングのセカンダリカラーを乗算した結果を加算して出力する接続の例を以下に示します。
実際にプログラムで指定する際のコード例を以下に示します。
// Combiner 0 glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[0].srcRgb"), GL_TEXTURE0, GL_FRAGMENT_PRIMARY_COLOR_DMP, GL_PREVIOUS); glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[0].srcAlpha"), GL_TEXTURE0, GL_PREVIOUS, GL_PREVIOUS); glUniform1i(glGetUniformLocation(program, "dmp_TexEnv[0].combineRgb"), GL_MODULATE); glUniform1i(glGetUniformLocation(program, "dmp_TexEnv[0].combineAlpha"), GL_REPLACE); glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[0].operandRgb"), GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR); glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[0].operandAlpha"), GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA); // CombinerBuffer 1 glUniform2i(glGetUniformLocation(program, "dmp_TexEnv[1].bufferInput"), GL_PREVIOUS, GL_PREVIOUS); // Combiner 1 glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[1].srcRgb"), GL_TEXTURE1, GL_FRAGMENT_SECONDARY_COLOR_DMP, GL_PREVIOUS); glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[1].srcAlpha"), GL_TEXTURE1, GL_PREVIOUS, GL_PREVIOUS); glUniform1i(glGetUniformLocation(program, "dmp_TexEnv[1].combineRgb"), GL_MODULATE); glUniform1i(glGetUniformLocation(program, "dmp_TexEnv[1].combineAlpha"), GL_REPLACE); glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[1].operandRgb"), GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR); glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[1].operandAlpha"), GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA); // Combiner 2 glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[2].srcRgb"), GL_PREVIOUS_BUFFER_DMP, GL_PREVIOUS, GL_PREVIOUS); glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[2].srcAlpha"), GL_PREVIOUS_BUFFER_DMP, GL_PREVIOUS, GL_PREVIOUS); glUniform1i(glGetUniformLocation(program, "dmp_TexEnv[2].combineRgb"), GL_ADD); glUniform1i(glGetUniformLocation(program, "dmp_TexEnv[2].combineAlpha"), GL_REPLACE); glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[2].operandRgb"), GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR); glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[2].operandAlpha"), GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA);
11.4. プロシージャルテクスチャ
プロシージャルテクスチャは従来のテクスチャと異なり、画像を参照せず、手続き的計算によりテクセルの色が決定されます。プロシージャルテクスチャは、完全に秩序を持ったパターンや、ややランダムで秩序を伴うパターンで効果を発揮します。テクスチャ画像にアクセスをすることがないため、メモリアクセスの競合を回避したり、コンテンツサイズを抑制したりといった効果があります。
プロシージャルテクスチャを扱うことができるのはテクスチャユニット 3 だけで、テクスチャユニット 3 はプロシージャルテクスチャ専用のテクスチャユニットになっています。計算によりテクセル色を決定しますが、テクスチャ座標 u、v に対応するテクセル色を決定するという意味では通常のテクスチャと同様の働きをしていると考えることもできます。
プロシージャルテクスチャは予約フラグメントシェーダの一部でもありますので、パラメータの設定は予約ユニフォームへの glUniform*()
の呼び出しで行います。
11.4.1. プロシージャルテクスチャユニット
プロシージャルテクスチャユニットは 3 つの計算部で構成されています。入力に近い側から、乱数生成部、クランプ部、マッピング部と呼びます。乱数生成部がテクスチャ座標 u、v に揺らぎを与え、クランプ部がパターンの鏡面対称、繰り返しを決定し、マッピング部が u、v 座標値からテクセル色を計算します。
入力されたテクスチャ座標は上図のように処理されていますが、目的の画像を得るためのパラメータを設定するときには、以下の手順で行った方が直感的で理解しやすいでしょう。
- プロシージャルテクスチャの有効化
- RGBA 共有モードまたはアルファ独立モードの設定
G(u, v) および F(g) の設定に相当します。 - 基本形状の選択
G(u, v) の選択に相当します。 - 基本色の設定
色はカラー参照テーブルとして設定します。Color(f) の設定に相当します。 - 基本形状とカラー参照テーブルの関係の設定
手順 3 の基本形状と手順 4 のカラー参照テーブルがどのように対応するか決定します。F(g) の設定に相当します。 - 乱数パラメータの選択
必要な場合には乱数を有効にして、乱数の影響の大きさを決めます。不要な場合は乱数を無効にします。乱数生成部に相当します。乱数の有効、無効に関わらず、u と v は絶対値化されてクランプ部に出力されます。 - 繰り返しおよび対称性の設定
クランプの設定に相当します。
11.4.2. プロシージャルテクスチャの有効化
プロシージャルテクスチャで使用するテクスチャユニット 3 の有効・無効の設定は、予約ユニフォーム(dmp_Texture[3].samplerType
)への値の設定で行います。glActiveTexture()
によるユニット選択や glEnable()
によるテクスチャ種別の選択はエラーとなりますので注意してください。
有効にする場合は GL_TEXTURE_PROCEDURAL_DMP
を、無効にする場合は GL_FALSE
を glUniform1i()
で設定してください。テクスチャの種別として GL_TEXTURE_PROCEDURAL_DMP
以外には対応していません。
glUniform1i( glGetUniformLocation(s_PgID, "dmp_Texture[3].samplerType"), GL_TEXTURE_PROCEDURAL_DMP);
11.4.3. RGBA 共有モード / アルファ独立モードの設定
アルファ成分のマッピング部での計算に使用する関数を RGB 成分の設定と共有(RGBA 共有モード)するか、独立して設定(アルファ独立モード)するかを選択します。アルファ独立モードを選択した場合、マッピング部の G 関数と F 関数を 2 つずつ設定しなければなりません。とりあえず画像を出力してみたいという場合は、RGBA 共有モードを使用した方が設定は容易です。
予約ユニフォーム(dmp_Texture[3].ptAlphaSeparate
)に glUniform1i()
で GL_FALSE
を設定した場合は RGBA 共有モード、GL_TRUE
を設定した場合はアルファ独立モードが選択されます。デフォルトは RGBA 共有モードです。
11.4.4. 基本形状の選択
プロシージャルテクスチャの基本形状をマッピング部の G 関数によって決定します。
表 11-19 で掲載している基本形状は以下の割り当てで色付けされています。
設定値 |
選択される関数 |
基本形状 |
---|---|---|
|
u |
|
|
v |
|
|
u2 |
|
|
v2 |
|
|
(u + v) / 2 |
|
|
(u2 + v2) / 2 |
|
|
sqrt(u2 + v2) |
|
|
min(u, v) |
|
|
max(u, v) |
|
|
((u + v) / 2 + sqrt(u2 + v2)) / 2 |
|
基本形状はテクスチャ座標に -1.0 ~ 1.0(中心が 0.0)、繰り返しの指定に GL_MIRRORED_REPEAT
を設定して描画されたものです。
G 関数選択のための予約ユニフォームは、RGB 成分が dmp_Texture[3].ptRgbMap
、アルファ成分が dmp_Texture[3].ptAlphaMap
です。それぞれの予約ユニフォームに対して、glUniform1i()
で設定します。
dmp_Texture[3].ptAlphaMap
への設定はアルファ独立モードでのみ有効です。
木目ならば GL_PROCTEX_U_DMP
や GL_PROCTEX_V_DMP
を、年輪ならば GL_PROCTEX_ADDSQRT2_DMP
を選択するなど、目的とするテクスチャ画像に近い形状を選んでください。
11.4.5. カラー参照テーブルの設定
カラー参照テーブルは G 関数と F 関数を経て計算された値を実際のテクセル色へと変換するためのテーブルで、RGBA の各成分で別々に設定することができます。
カラー参照テーブルの内容は LOD を使用するかどうかで異なります。
LOD を使用しない場合、カラー参照テーブルには部分配列として複数のカラーテーブルを格納することができます。オフセットとテーブルの幅を変更することで、同じ計算結果から色合いの異なるテクスチャを描画することもできます。
カラー参照テーブルは最大 512 要素の参照テーブルで、256 要素を境にして前半にはカラーテーブル、後半には前半で格納したカラーテーブルの要素間の差分値を格納します。差分値は必ず 257 要素目から格納しなければならないので、カラー参照テーブルの要素数は "256 +(実際に参照されるカラーテーブルの要素数)+(カラーテーブルの先頭オフセット)" で定義されます。要素数の計算で対象となるのは最後のカラーテーブルです。
実際に参照されるカラーテーブルの幅(dmp_Texture[3].ptTexWidth
)には、128 までの 2 のべき乗を glUniform1i()
で設定します。カラーテーブルの先頭オフセット(dmp_Texture[3].ptTexOffset
)には、0 ~ 128 の整数を glUniform1i()
で設定します。
LOD を使用する場合、カラーテーブルの幅とオフセットは、それぞれ 128 と 0 でなければなりません。LOD のレベルに対応して、実際に参照されるカラーテーブルが決定されます。カラー参照テーブルの要素数は最大の 512 固定です。
LOD のレベル |
開始位置 |
幅 |
---|---|---|
0 |
0 |
128 |
1 |
128 |
64 |
2 |
192 |
32 |
3 |
224 |
16 |
4 |
240 |
8 |
5 |
248 |
4 |
6 |
252 |
2 |
「7.7. 参照テーブルのロード」で説明したとおり、参照テーブルは glTexImage1D()
を呼び出して配列からロードします。カラー参照テーブルの要素数の大きさの浮動小数点配列を用意して、前半部分にカラーテーブルの要素(0.0 ~ 1.0)を格納し、配列の後半(ΔT)には前半 256 要素に格納したカラーテーブル(T)の要素間の差分値を格納していきます。カラーテーブルの要素数を size、先頭オフセットを offset 要素を Ci 、変換関数を func() とすれば、要素と差分値の計算式は以下の式で表されます。
差分値の最後はカラーテーブルの収束値と最終要素との差分を計算して格納するか、単に 0.0 を格納してください。
glTexImage1D()
の呼び出しはカラー参照テーブルの要素数を最大の 512、カラー参照テーブルを格納した配列を data
、設定する参照テーブル番号を 0 とすれば以下のコードで行うことができます。
glTexImage1D(GL_LUT_TEXTURE0_DMP, 0, GL_LUMINANCEF_DMP, 512, 0, GL_LUMINANCEF_DMP, GL_FLOAT, data);
RGBA の各成分で使用するカラー参照テーブルは、glUniform1i()
で参照テーブル番号を以下の予約ユニフォームに指定します。ここで指定する参照テーブル番号は GL_LUT_TEXTUREi_DMP
の i
(0 ~ 31) が表す数値で、テクスチャの名前(ID)や GL_LUT_TEXTUREi_DMP
を直接指定するわけではないことに注意してください。
予約ユニフォーム |
設定する値 |
---|---|
|
赤成分のカラー参照テーブルとする参照テーブル番号を指定する。 |
|
緑成分のカラー参照テーブルとする参照テーブル番号を指定する。 |
|
青成分のカラー参照テーブルとする参照テーブル番号を指定する。 |
|
アルファ成分のカラー参照テーブルとする参照テーブル番号を指定する。 |
どの予約ユニフォームも 0 ~ 31 の値を指定します。
アルファ独立モード時は dmp_Texture[3].ptSamplerA
の設定が無視されます。
プロシージャルテクスチャのカラー参照テーブルにも、縮小時のフィルタには通常のテクスチャと同様のフィルタを適用することができます。予約ユニフォーム(dmp_Texture[3].ptMinFilter
)に glUniform1i()
で設定する値を、以下の表から選択します。
設定する値 |
適用するフィルタ |
---|---|
|
u, v 方向はニアレスト、LOD なし |
|
u, v 方向はリニア、LOD なし(デフォルト) |
|
u, v 方向はニアレスト、LOD はニアレスト |
|
u, v 方向はニアレスト、LOD はリニア |
|
u, v 方向はリニア、LOD はニアレスト |
|
u, v 方向はリニア、LOD はリニア |
カラー参照テーブルの参照時に LOD バイアスをかけることができます。0.0 ~ 6.0 の範囲の値を、予約ユニフォーム(dmp_Texture[3].ptTexBias
)に glUniform1f()
で設定します。0.0 で無効化され、デフォルトは 0.5 に設定されています。
11.4.6. 基本形状とカラー参照テーブルとの対応関係の設定
基本形状を選択した G 関数と基本色を設定したカラー参照テーブルとの対応関係は F 関数で設定されます。F 関数は、G 関数からの出力(0.0 ~ 1.0)をカラー参照テーブルの参照値(0.0 ~ 1.0)へマッピングする参照テーブルとして設定します。参照テーブルは 256 要素の大きさで、128 要素を境にして前半にはマッピングテーブル、後半には前半で格納したマッピングテーブルの要素間の差分値を格納します。形状とカラーの対応関係の設定ですので、同じ形状とカラー参照テーブルを用いていても、マッピングテーブルを変更することで様相の異なるテクスチャとして描画することができます。F 関数に F(x)=x や F(x)=x2 のように単純な計算結果を用いたり、飛び飛びの値でインデックスのように用いたりするだけでも出力結果は大きく異なるものになる可能性があります。
カラー参照テーブルと同様に、F 関数のマッピングテーブルは glTexImage1D()
を呼び出して、配列から参照テーブルとしてロードします。マッピングテーブルの要素数(256)の大きさの浮動小数点配列を用意して、前半部分にマッピングテーブルの要素(0.0 ~ 1.0)を格納し、配列の後半には前半の 128 要素に格納したマッピングテーブルの要素間の差分値を格納していきます。マッピングテーブルの要素を Fi 、変換関数を func() とすれば、要素と差分値の計算式は以下の式で表されます。
glTexImage1D()
の呼び出しはマッピングテーブルの要素数を 256、マッピングテーブルを格納した配列を data
、設定する参照テーブル番号を 0 とすれば以下のコードで行うことができます。
glTexImage1D(GL_LUT_TEXTURE0_DMP, 0, GL_LUMINANCEF_DMP, 256, 0, GL_LUMINANCEF_DMP, GL_FLOAT, data);
F 関数として使用するマッピングテーブルは、glUniform1i()
で参照テーブル番号を以下の予約ユニフォームに指定します。ここで指定する参照テーブル番号は GL_LUT_TEXTUREi_DMP
の i
(0 ~ 31) が表す数値で、テクスチャの名前(ID)や GL_LUT_TEXTUREi_DMP
を直接指定するわけではないことに注意してください。
予約ユニフォーム |
設定する値 |
---|---|
|
RGB の F 関数とする参照テーブル番号を指定する。 |
|
アルファの F 関数とする参照テーブル番号を指定する。 |
どちらの予約ユニフォームも 0 ~ 31 の値を指定します。dmp_Texture[3].ptSamplerAlphaMap
の設定はアルファ独立モード時のみ有効です。
11.4.7. 乱数パラメータの選択
プロシージャルテクスチャのランダム要素として、G 関数に入力されるテクスチャ座標 u と v に揺らぎ(ノイズ)を与えることができます。ノイズは基本形状に影響を与えます。例えば G 関数が GL_PROCTEX_U_DMP
であるとき、テクスチャ座標 u にノイズによる影響を与えれば、直線でしか描画できなかった木目がより自然な歪みを持って描画できるようになります。
ノイズの有効・無効の設定は、予約ユニフォーム(dmp_Texture[3].ptNoiseEnable
)への値の設定で行います。有効にする場合は GL_TRUE
を、無効にする場合は GL_FALSE
を glUniform1i()
で設定してください。
glUniform1i( glGetUniformLocation(s_PgID, "dmp_Texture[3].ptNoiseEnable"), GL_TRUE);
ノイズを与える関数はブラックボックスになっていますが、アプリケーションから波の周波数(F)、位相(P)、振幅(A)の 3 パラメータを与えることで制御することができます。F パラメータは揺らぎの緩急を調整し、大きくすれば険しく、小さくすれば緩やかな波になります。P パラメータは揺らぎの開始位置を変更します。海面のテクスチャなどを描画する際には、P パラメータだけを変更して波の変化を表現することができます。A パラメータを大きくすれば揺らぎの影響が大きくなり、基本形状はより崩れます。
F、P、A の 3 パラメータは u 成分、v 成分で別々のパラメータを設定することができます。
予約ユニフォーム |
設定する値 |
---|---|
|
u 成分の F、P、A パラメータを指定する。A パラメータのみ -8.0 ~ 8.0 の範囲にクランプされます。 (F-parameter, P-parameter, A-parameter) デフォルト (0.0, 0.0, 0.0) |
|
v 成分の F、P、A パラメータを指定する。A パラメータのみ -8.0 ~ 8.0 の範囲にクランプされます。 (F-parameter, P-parameter, A-parameter) デフォルト (0.0, 0.0, 0.0) |
揺らぎのパラメータ以外にも、ノイズを与える関数にノイズ変調と呼ばれる乱数の連続性の変化を制御することができます。ノイズ変調(ノイズ連続性関数)は参照テーブルで指定し、これをノイズ変調テーブルと呼びます。ノイズ関数は与えられたノイズ変調テーブルを使って、計算だけでは離散的な値となってしまう揺らぎを自然な値にしようとします。ノイズ連続性関数には 3x2 - 2x3 のように 0.0 と 1.0 付近で緩やかに変化する関数が適しています。
カラー参照テーブルと同様に、ノイズ変調テーブルは glTexImage1D()
を呼び出して配列からロードします。ノイズ変調テーブルの要素数(256)の大きさの浮動小数点配列を用意して、前半部分にノイズ変調テーブルの要素(0.0 ~ 1.0)を格納し、配列の後半には前半の 128 要素に格納したノイズ変調テーブルの要素間の差分値を格納していきます。ノイズ変調テーブルの要素を Ni 、変換関数を func() とすれば、要素と差分値の計算式は以下の式で表されます。
glTexImage1D()
の呼び出しはノイズ変調テーブルの要素数を 256、ノイズ変調テーブルを格納した配列を data
、設定する参照テーブル番号を 0 とすれば以下のコードで行うことができます。
glTexImage1D(GL_LUT_TEXTURE0_DMP, 0, GL_LUMINANCEF_DMP, 256, 0, GL_LUMINANCEF_DMP, GL_FLOAT, data);
ノイズ連続性関数として使用するノイズ変調テーブルは、参照テーブル番号を以下の予約ユニフォームへ glUniform1i()
によって指定します。ここで指定する参照テーブル番号は GL_LUT_TEXTUREi_DMP
の i
(0 ~ 31) が表す数値で、テクスチャの名前(ID)や GL_LUT_TEXTUREi_DMP
を直接指定するわけではないことに注意してください。
予約ユニフォーム |
設定する値 |
---|---|
|
ノイズ連続性関数とする参照テーブル番号を指定する。 0 ~ 31 |
ノイズの F、P、A の 3 パラメータが出力結果にどのような影響を与えるのかを、ノイズの影響がないときには同心円で描画されるプロシージャルテクスチャに対して、u, v 両方向に関して各パラメータを変化させたときの描画結果で紹介します。これらの描画に際して、ノイズ連続性関数には F(x) = x を使用しています。
図 11-9 は A パラメータのみを変化させたときの描画結果です。そのほかのパラメータについては、F = 0.3、P = 0.0 に設定しています。A が大きいほど大きく波打ちますが、円周上で影響を受ける箇所に変化がほとんどないことに注目してください。
図 11-10 は F パラメータのみを変化させたときの描画結果です。そのほかのパラメータについては、A = 0.3、P = 0.0 に設定しています。F が大きいほど揺らぎの周波数が高くなり、円周上で影響を受ける箇所の間隔が狭くなっていることに注目してください。また、F パラメータはノイズの計算時に絶対値が使用されるため、符号を反転させても結果は変わりません。
図 11-11 は P パラメータのみを変化させたときの描画結果です。そのほかのパラメータについては、A = 0.3、F = 0.3 に設定しています。P が変化すると揺らぎの形状のみが変化していることに注目してください。P パラメータを変化させることで、プロシージャルテクスチャにアニメーションのような変化をもたらすことができます。
P パラメータを変化させてアニメーションさせる場合、P パラメータに大きな値を設定すると、P パラメータの小さな変化が揺らぎの形状に影響を与えなくなります。これはハードウェアの計算精度に起因する現象です。例えば、フレームごとに一定の値を P パラメータに加算してノイズの変化を使ったアニメーションを行う場合は、P パラメータが大きな値になる前に小さな値に戻す必要があります。F パラメータと P パラメータがともに正の数である場合、F パラメータと P パラメータの乗算結果が 16 の倍数となるときと、P パラメータに 0.0 を設定したときは同じ結果を得ることができるという特性があります。つまり、乗算結果が 16 となるときに P パラメータを 0 に戻すことで、アニメーションの連続性を保つことができます。ただし、F パラメータに大きな値が設定されているときは、P パラメータに 0 を指定した場合と、乗算結果が 16 となる場合で同じ形状にならない場合があります。
F パラメータと A パラメータが固定値かつ、(|u| + u の位相)および(|v| + v の位相)の符号が変わらない範囲で P パラメータの値を変化させた場合、F×P が任意の値 X となる場合と、X+16 となる場合とで同じノイズ結果を得ることができます。ただし、ノイズ計算の過程における計算精度により、F パラメータに大きな値を設定すると、上記の場合でも同じ乱数結果を得られない可能性があります。また、P パラメータに大きな値が設定されていると、細かな値の変化がノイズ結果に反映されなくなる場合があります。
11.4.8. 繰り返しおよび対称性の設定
通常のテクスチャで設定したラッピングモードと同様の機能が、プロシージャルテクスチャにもあります。クランプ計算部と呼ばれ、設定可能なモードにはパルスやゼロクランプなどの専用モードがあります。また、繰り返しの途中でテクスチャ座標の整数部分が同じ部分をブロックにしてずらす、シフト計算部もあります。
クランプ計算部ではテクスチャ座標が 0.0 ~ 1.0 の範囲に収まらない部分を、どのように範囲内の値に変換するのかをクランプモードによって決定します。
クランプモード |
座標値のクランプ |
---|---|
|
|
|
|
|
|
|
|
|
|
テクスチャ座標の u 成分と v 成分で別々のクランプモードを設定することができます。設定するには、予約ユニフォーム dmp_Texture[3].ptClampU
または dmp_Texture[3].ptClampV
に対して glUniform1i()
を呼び出します。
GL_SYMMETRICAL_REPEAT_DMP
は、同じ画像が格子状に並びます。GL_MIRRORED_REPEAT
は、偶数番目が鏡のように反転します。GL_PULSE_DMP
は、描画に利用しようとする画素に最も近いテクスチャの端の画素を拾います。GL_CLAMP_TO_EDGE
は、-1.0 ~ 1.0 の範囲内ではテクスチャ内部の画像を参照し、範囲外ではテクスチャの端の画素を参照します。GL_CLAMP_TO_ZERO_DMP
は -1.0 ~ 1.0 の範囲内(-1.0 および 1.0 を含まず)ではテクスチャ画像を参照し、範囲外(-1.0 および 1.0 を含む)では座標 0 の画像を参照します。
シフト計算部では、シフトモードによってどのように座標をシフト操作するのかを決定し、クランプモードによってシフト幅が変化します。この処理はクランプ計算部の前に適用され、同じ画像が連続して描画されるのを防ぐことができます。
シフトモード |
シフト計算 |
シフト幅 |
---|---|---|
|
シフト計算なし |
なし |
|
整数部が奇数から偶数へ変化する座標でシフト |
|
|
整数部が偶数から奇数へ変化する座標でシフト |
|
テクスチャ座標の u 成分と v 成分で別々のシフトモードを設定することができます。設定するには、予約ユニフォーム dmp_Texture[3].ptShiftU
または dmp_Texture[3].ptShiftV
に対して glUniform1i()
を呼び出します。