パーフラグメントオペレーションでは、ライティング結果などの関連データをもとに、フラグメントのウィンドウ座標系での位置にあたるフレームバッファ上のピクセルデータを更新します。
フラグメントすべてが考慮されるわけではなく、アルファテストなどのテストで不要なフラグメントを棄却したあと、ブレンディングや論理演算で既存のピクセルデータとのカラー合成が行われます。
フラグメントオペレーションモード(mp_FragOperation.mode
)が標準モード(GL_FRAGOP_MODE_GL_DMP
)のときは、パーフラグメントオペレーションは図 13-1 の処理の流れとなります。
3DS の仕様と OpenGL ES 2.0 の仕様には、パーフラグメントオペレーションで行われる処理に以下のような相違点があります。
- シザーテストがラスタライズで行われます。
- マルチサンプリングには対応していないため、
glSampleCoverage()
は実装されていません。 - アルファテストは OpenGL ES 1.1 相当の機能を提供していますが、その制御は予約ユニフォームで行います。
- ステンシルテストはポリゴンの表裏を区別しないため、
glStencil*Separate()
は実装されていません。 - ブレンディングでは論理演算の演算子(
GL_LOGIC_OP
)を選択することができません。 - ブレンディングの
glBlendFunc*()
で、OpenGL ES の仕様ではディスティネーションに選択することのできなかったGL_SRC_ALPHA_SATURATE
を選択することができます。 - ディザリングは適用されません。
- 論理演算は OpenGL ES 1.1 相当の仕様で実装されています。
13.1. アルファテスト
アルファテストはフラグメントのアルファ値と参照値とを比較し、フラグメントを次のプロセスに通過させるのか棄却するのかを決定する機能です。
3DS のアルファテストは OpenGL ES 1.1 のアルファテスト相当の機能を持っていますが、その制御はすべて予約ユニフォームで行われます。
13.1.1. 予約ユニフォーム
アルファテストの予約ユニフォームには、以下のものが存在します。
アルファテストの有効・無効
アルファテスト機能を有効にするには、予約ユニフォーム(dmp_FragOperation.enableAlphaTest
)に glUniform1i()
で GL_TRUE
を設定してください。デフォルトでは無効(GL_FALSE
)に設定されています。
比較方法
比較方法は予約ユニフォーム(dmp_FragOperation.alphaTestFunc
)に glUniform1i()
で設定します。設定することのできる値には、以下の 8 種類があります。
設定値 |
比較内容 |
---|---|
|
すべて棄却(すべて通過しない) |
|
すべて通過 |
|
参照値より小さければ通過 (alpha < reference) |
|
参照値以下ならば通過 (alpha <= reference) |
|
参照値と等しければ通過 (alpha == reference) |
|
参照値以上ならば通過 (alpha >= reference) |
|
参照値より大きければ通過 (alpha > reference) |
|
参照値と等しくなければ通過 (alpha != reference) |
参照値
アルファテストの参照値は予約ユニフォーム(dmp_FragOperation.alphaRefValue
)に glUniform1f()
で設定します。参照値は比較時に 0.0 ~ 1.0 の範囲にクランプされて使用されます。
以下の表は、アルファテストで使用する予約ユニフォームの一覧です。
予約ユニフォーム |
種別 |
設定値 |
---|---|---|
|
|
アルファテストの有効/無効を指定する。
|
|
|
アルファテストで使用する参照値を指定する。 0.0 ~ 1.0 (デフォルト)0.0 |
|
|
アルファテストの比較方法を指定する。
|
13.2. ステンシルテスト
ステンシルテストは、フラグメントのウィンドウ座標系での座標にあるステンシルバッファの内容と参照値とを比較し、フラグメントを次のプロセスに通過させるのか棄却するのかを決定する機能です。
3DS では、ポリゴンの表裏を区別しないため、glStencilFuncSeparate()
と glStencilOpSeparate()
は実装されていません。
13.2.1. 使用方法
ステンシルテストの使用方法は OpenGL と同じです。
ステンシルテストの有効・無効
ステンシルテストの有効・無効の制御は、cap
に GL_STENCIL_TEST
を渡して glEnable()
または glDisable()
を呼び出すことで行います。現在の設定を取得するには、cap
に GL_STENCIL_TEST
を渡して glIsEnabled()
を呼び出してください。デフォルトではステンシルテストは無効になっています。無効に設定されている場合、ステンシルバッファの変更やフラグメントの棄却は行われません。フレームバッファにステンシルバッファが関連付けられていない場合、ステンシルテストは無効に設定されているものとして処理されます。ステンシルテストとデプステストは、どちらも有効・どちらか一方が有効のいずれの場合でも、性能の差はありません。
比較方法、参照値、マスク
ステンシルテストは glStencilFunc()
で指定された比較方法、参照値、マスクの 3 要素をもとに行われます。
void glStencilFunc(GLenum func, GLint ref, GLuint mask);
ref
には比較で使用する参照値を整数で指定します。参照値は、ステンシルテストの比較時に符号なしの数値として扱われ、0 ~ 255(3DS のステンシルバッファが 8 bit 固定であるため)の範囲にクランプされます。デフォルトでは 0 が使用されます。
mask
にはマスキング値を指定します。比較時の参照値とステンシルバッファの内容には、マスキング値とビット単位での論理積を適用した値が使用されます。デフォルトでは 0xFFFFFFFF(全ビットが 1)が使用されます。
func
には比較方法を設定します。設定することのできる値には、以下の 8 種類があります。
設定値 |
比較内容 |
---|---|
|
すべて棄却(すべて通過しない) |
|
すべて通過 |
|
参照値がバッファの内容より小さければ通過 (reference < stencil buffer) |
|
参照値がバッファの内容以下ならば通過 (reference <= stencil buffer) |
|
参照値がバッファの内容と等しければ通過 (reference == stencil buffer) |
|
参照値がバッファの内容以上ならば通過 (reference >= stencil buffer) |
|
参照値がバッファの内容より大きければ通過 (reference > stencil buffer) |
|
参照値がバッファの内容と等しくなければ通過 (reference != stencil buffer) |
テスト結果への対処
ステンシルテストでは、参照値とステンシルバッファの比較結果だけでなく、後述するデプステストの結果によってもステンシルバッファに対して値をどのように変化させるのかを glStencilOp()
で設定することができます。
void glStencilOp(GLenum fail, GLenum zfail, GLenum zpass);
fail
は、ステンシルテストの結果がフラグメントの棄却であった場合に、ステンシルバッファの内容をどのように変化させるのかを設定します。設定することのできる値には、以下の 8 種類があります。
設定値 |
ステンシルバッファの内容 |
---|---|
|
そのままの値で変化しません。 |
|
0 に設定します。 |
|
参照値に置き換えます。 |
|
1 増加させます。255 を超えることはありません。 |
|
1 減少させます。0 未満になることはありません。 |
|
ビット反転させます。 |
|
1 増加させます。255 の次は 0 になります。 |
|
1 減少させます。0 の次は 255 になります。 |
zfail
はデプステストでフラグメントが棄却されたとき、zpass
はデプステストでフラグメントが通過したときにステンシルバッファの内容がどのように変化するのかを設定します。設定することのできる値は fail
と同じです。
13.3. デプステスト
デプステストは、フラグメントのデプス値とフラグメントのウィンドウ座標系での座標にあるデプスバッファの内容とを比較し、フラグメントを次のプロセスに通過させるのか棄却するのかを決定する機能です。ステンシルバッファでも述べたように、デプステストの結果でステンシルバッファの内容を変化させることもできます。
13.3.1. 使用方法
デプステストの使用方法は OpenGL と同じです。
デプステストの有効・無効
デプステストの有効・無効の制御は、cap
に GL_DEPTH_TEST
を渡して glEnable()
または glDisable()
を呼び出すことで行います。現在の設定を取得するには、cap
に GL_DEPTH_TEST
を渡して glIsEnabled()
を呼び出してください。デフォルトではデプステストは無効になっています。無効に設定されている場合、デプスバッファの変更やフラグメントの棄却は行われません。フレームバッファにデプスバッファが関連付けられていない場合、デプステストは無効に設定されているものとして処理されます。デプステストとステンシルテストは、どちらも有効・どちらか一方が有効のいずれの場合でも、性能の差はありません。
比較方法
比較方法は glDepthFunc()
で設定します。
void glDepthFunc(GLenum func);
func
に設定することのできる値には、以下の 8 種類があります。
設定値 |
比較内容 |
---|---|
|
すべて棄却(すべて通過しない) |
|
すべて通過 |
|
デプス値がバッファの内容より小さければ通過 (fragment depth < depth buffer) |
|
デプス値がバッファの内容以下ならば通過 (fragment depth <= depth buffer) |
|
デプス値がバッファの内容と等しければ通過 (fragment depth == depth buffer) |
|
デプス値がバッファの内容以上ならば通過 (fragment depth >= depth buffer) |
|
デプス値がバッファの内容より大きければ通過 (fragment depth > depth buffer) |
|
デプス値がバッファの内容と等しくなければ通過 (fragment depth != depth buffer) |
比較の結果、フラグメントが棄却されるときはデプスバッファに変化はありません。フラグメントが通過するときはデプスバッファの内容がフラグメントのデプス値で上書きされます。
13.4. ブレンディング
ブレンディングは、フラグメントの持つカラー(ソースカラー)とフラグメントのウィンドウ座標系での座標にあるフレームバッファのカラー(ディスティネイションカラー)を合成する機能です。ブレンディングの結果は、フラグメントの持つカラーとして次のプロセスに渡されます。
13.4.1. 使用方法
ブレンディングの使用方法は OpenGL と同じです。
ブレンディングの有効・無効
ブレンディングの有効・無効の制御は、cap
に GL_BLEND
を渡して glEnable()
または glDisable()
を呼び出すことで行います。現在の設定を取得するには、cap
に GL_BLEND
を渡して glIsEnabled()
を呼び出してください。デフォルトではブレンディングは無効になっています。無効に設定されている場合、ブレンディングは行われません。
フレームバッファにカラーバッファが関連付けられていない場合、または後述する論理演算が有効になっている場合、ブレンディングは無効に設定されているものとして処理されます。
ブレンディングの計算式(合成方法)
フラグメントの持つカラー(ソースカラー)とフレームバッファのカラー(ディスティネーションカラー)をどのように合成するかは、glBlendEquation()
または glBlendEquationSeparate()
で設定することができます。
void glBlendEquation(GLenum mode); void glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha);
glBlendEquation()
は、mode
で RGB 成分とアルファ成分の計算式をまとめて設定することができます。
glBlendEquationSeparate()
は、modeRGB
で RGB 成分の、modeAlpha
でアルファ成分の計算式を個別に設定することができます。それぞれに設定する値は共通で、以下の 5 種類があります。
設定値 |
RGB 成分 |
アルファ成分 |
---|---|---|
|
R = Rs * Sr + Rd * Dr |
A = As * Sa + Ad * Da |
|
R = Rs * Sr - Rd * Dr |
A = As * Sa - Ad * Da |
|
R = Rd * Sr - Rs * Dr |
A = Ad * Sa - As * Da |
|
R = min( Rs, Rd ) |
A = min( As, Ad ) |
|
R = max( Rs, Rd ) |
A = max( As, Ad ) |
Rs, Gs, Bs, As :ソースカラーの各成分
Rd, Gd, Bd, Ad :ディスティネーションカラーの各成分
Sr, Sg, Sb, Sa :ソースの重み係数
Dr, Dg, Db, Da :ディスティネーションの重み係数
OpenGL ES 2.0 では指定可能となっている GL_LOGIC_OP
には対応していません。
ソースとディスティネーションの重み係数
ソースとディスティネーションに適用される重み係数は glBlendFunc()
または glBlendFuncSeparate()
で設定することができます。
void glBlendFunc(GLenum sfactor, GLenum dfactor); void glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
glBlendFunc()
は、sfactor
と dfactor
でソースとディスティネーションの重み係数をまとめて設定することができます。glBlendFuncSeparate()
は、srcRGB
と srcAlpha
でソースの RGB 成分とアルファ成分の重み係数を、dstRGB
と dstAlpha
でディスティネーションの RGB 成分とアルファ成分の重み係数を個別に設定することができます。それぞれに設定する値は共通で、以下の 15 種類があります。
設定値 |
カラーの重み係数 |
アルファの重み係数 |
---|---|---|
|
(0, 0, 0) |
0 |
|
(1, 1, 1) |
1 |
|
(Rs, Gs, Bs) |
As |
|
(1, 1, 1) - (Rs, Gs, Bs) |
1 - As |
|
(Rd, Gd, Bd) |
Ad |
|
(1, 1, 1) - (Rd, Gd, Bd) |
1 - Ad |
|
(As, As, As) |
As |
|
(1, 1, 1) - (As, As, As) |
1 - As |
|
(Ad, Ad, Ad) |
Ad |
|
(1, 1, 1) - (Ad, Ad, Ad) |
1 - Ad |
|
(Rc, Gc, Bc) |
Ac |
|
(1, 1, 1) - (Rc, Gc, Bc) |
1 - Ac |
|
(Ac, Ac, Ac) |
Ac |
|
(1, 1, 1) - (Ac, Ac, Ac) |
1 - Ac |
|
(f, f, f) |
1 |
Rs, Gs, Bs, As :ソースカラー
Rd, Gd, Bd, Ad :ディスティネーションカラー
Rc, Gc, Bc, Ac :定数カラー
f = min(As, 1 - Ad)
3DS では、ディスティネーションにも GL_SRC_ALPHA_SATURATE
を設定することができます。
定数カラー
定数カラーは glBlendColor()
で設定することができます。
void glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
red
、green
、blue
、alpha
で RGB とアルファの各成分を指定します。各成分値は 0.0 ~ 1.0 の浮動小数点数で指定します。デフォルトでは、すべて 0.0(0.0, 0.0, 0.0, 0.0)に設定されています。
13.5. 論理演算
論理演算は、フラグメントのカラーとフレームバッファのカラーに対して、パーフラグメントオペレーションの最後に適用される、画像の論理演算を行う機能です。論理演算の結果は、ウィンドウ座標系でのフラグメントの座標に対応するフレームバッファに書き込まれます。
13.5.1. 使用方法
論理演算の使用方法は OpenGL ES 1.1 と同じです。
論理演算の有効・無効
論理演算の有効・無効の制御は、cap
に GL_COLOR_LOGIC_OP
を渡して glEnable()
または glDisable()
を呼び出すことで行います。現在の設定を取得するには、cap
に GL_COLOR_LOGIC_OP
を渡して glIsEnabled()
を呼び出してください。デフォルトでは論理演算は無効になっています。無効に設定されている場合、論理演算は行われませんが、フレームバッファにはフラグメントのカラーが書き込まれます。論理演算を有効に設定すると、ブレンディングは無効となります。
演算方法
フラグメントのカラー(ソース)とフレームバッファのカラー(ディスティネーション)をどのように論理演算するのかは、glLogicOp()
で設定します。現在の設定を取得するには、pname
に GL_LOGIC_OP_MODE
を渡して glGetIntegerv()
を呼び出してください。デフォルトでは GL_COPY
が設定されています。
void glLogicOp(GLenum opcode);
opcode
には、RGB とアルファの各成分に対する演算方法をまとめて指定します。
設定値 |
演算方法 |
C スタイルでの表記 |
---|---|---|
|
0 |
0 |
|
s ∧ d |
|
|
s ∧ ¬ d |
|
|
s |
|
|
¬ s ∧ d |
|
|
d |
|
|
s xor d |
|
|
s ∨ d |
|
|
¬ (s ∨ d) |
|
|
¬ (s xor d) |
|
|
¬ d |
|
|
s ∨ ¬ d |
|
|
¬ s |
|
|
¬ s ∨ d |
|
|
¬ (s ∧ d) |
|
|
all 1 |
|
n
は各成分でのビット数
13.6. フレームバッファのマスク
パーフラグメントオペレーションで行われる、フレームバッファへのカラー(RGBA)、ステンシル、デプスの書き込みに対してマスキングを行うことができます。それぞれ、glColorMask()
、glStencilMask()
、glDepthMask()
で設定することができます。
void glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); void glStencilMask(GLuint mask); void glDepthMask(GLboolean flag);
カラーの RGBA 成分ごととデプス値に対しては、書き込みを許可する(GL_TRUE
)か、許可しない(GL_FALSE
)かを指定することができます。デフォルトでは、どちらも GL_TRUE
が設定されています。
ステンシルに対しては、ステンシルのマスキング値を変更することができます。このマスキング値は、ステンシルテストのマスキング値とは独立した設定です。デフォルトでは 0xFFFFFFFF(全ビットが 1)が設定されています。