13. パーフラグメントオペレーション

パーフラグメントオペレーションでは、ライティング結果などの関連データをもとに、フラグメントのウィンドウ座標系での位置にあたるフレームバッファ上のピクセルデータを更新します。

フラグメントすべてが考慮されるわけではなく、アルファテストなどのテストで不要なフラグメントを棄却したあと、ブレンディングや論理演算で既存のピクセルデータとのカラー合成が行われます。

フラグメントオペレーションモード(mp_FragOperation.mode)が標準モード(GL_FRAGOP_MODE_GL_DMP)のときは、パーフラグメントオペレーションは図 13-1 の処理の流れとなります。

図 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 種類があります。

表 13-1. アルファテストの比較方法

設定値

比較内容

GL_NEVER

すべて棄却(すべて通過しない)

GL_ALWAYS(デフォルト)

すべて通過

GL_LESS

参照値より小さければ通過 (alpha < reference)

GL_LEQUAL

参照値以下ならば通過 (alpha <= reference)

GL_EQUAL

参照値と等しければ通過 (alpha == reference)

GL_GEQUAL

参照値以上ならば通過 (alpha >= reference)

GL_GREATER

参照値より大きければ通過 (alpha > reference)

GL_NOTEQUAL

参照値と等しくなければ通過 (alpha != reference)

参照値

アルファテストの参照値は予約ユニフォーム(dmp_FragOperation.alphaRefValue)に glUniform1f() で設定します。参照値は比較時に 0.0 ~ 1.0 の範囲にクランプされて使用されます。

以下の表は、アルファテストで使用する予約ユニフォームの一覧です。

表 13-2. アルファテストで使用する予約ユニフォーム

予約ユニフォーム

種別

設定値

dmp_FragOperation.enableAlphaTest

bool

アルファテストの有効/無効を指定する。

GL_TRUE
GL_FALSE(デフォルト)

dmp_FragOperation.alphaRefValue

float

アルファテストで使用する参照値を指定する。

0.0 ~ 1.0

(デフォルト)0.0

dmp_FragOperation.alphaTestFunc

int

アルファテストの比較方法を指定する。

GL_NEVER
GL_ALWAYS(デフォルト)
GL_LESS
GL_LEQUAL
GL_EQUAL
GL_GEQUAL
GL_GREATER
GL_NOTEQUAL

13.2. ステンシルテスト

ステンシルテストは、フラグメントのウィンドウ座標系での座標にあるステンシルバッファの内容と参照値とを比較し、フラグメントを次のプロセスに通過させるのか棄却するのかを決定する機能です。

3DS では、ポリゴンの表裏を区別しないため、glStencilFuncSeparate()glStencilOpSeparate() は実装されていません。

13.2.1. 使用方法

ステンシルテストの使用方法は OpenGL と同じです。

ステンシルテストの有効・無効

ステンシルテストの有効・無効の制御は、capGL_STENCIL_TEST を渡して glEnable() または glDisable() を呼び出すことで行います。現在の設定を取得するには、capGL_STENCIL_TEST を渡して glIsEnabled() を呼び出してください。デフォルトではステンシルテストは無効になっています。無効に設定されている場合、ステンシルバッファの変更やフラグメントの棄却は行われません。フレームバッファにステンシルバッファが関連付けられていない場合、ステンシルテストは無効に設定されているものとして処理されます。ステンシルテストとデプステストは、どちらも有効・どちらか一方が有効のいずれの場合でも、性能の差はありません。

比較方法、参照値、マスク

ステンシルテストは glStencilFunc() で指定された比較方法、参照値、マスクの 3 要素をもとに行われます。

コード 13-1. glStencilFunc() の定義
void glStencilFunc(GLenum func, GLint ref, GLuint mask);

ref には比較で使用する参照値を整数で指定します。参照値は、ステンシルテストの比較時に符号なしの数値として扱われ、0 ~ 255(3DS のステンシルバッファが 8 bit 固定であるため)の範囲にクランプされます。デフォルトでは 0 が使用されます。

mask にはマスキング値を指定します。比較時の参照値とステンシルバッファの内容には、マスキング値とビット単位での論理積を適用した値が使用されます。デフォルトでは 0xFFFFFFFF(全ビットが 1)が使用されます。

func には比較方法を設定します。設定することのできる値には、以下の 8 種類があります。

表 13-3. ステンシルテストの比較方法

設定値

比較内容

GL_NEVER

すべて棄却(すべて通過しない)

GL_ALWAYS(デフォルト)

すべて通過

GL_LESS

参照値がバッファの内容より小さければ通過 (reference < stencil buffer)

GL_LEQUAL

参照値がバッファの内容以下ならば通過 (reference <= stencil buffer)

GL_EQUAL

参照値がバッファの内容と等しければ通過 (reference == stencil buffer)

GL_GEQUAL

参照値がバッファの内容以上ならば通過 (reference >= stencil buffer)

GL_GREATER

参照値がバッファの内容より大きければ通過 (reference > stencil buffer)

GL_NOTEQUAL

参照値がバッファの内容と等しくなければ通過 (reference != stencil buffer)

テスト結果への対処

ステンシルテストでは、参照値とステンシルバッファの比較結果だけでなく、後述するデプステストの結果によってもステンシルバッファに対して値をどのように変化させるのかを glStencilOp() で設定することができます。

コード 13-2. glStencilOp() の定義
void glStencilOp(GLenum fail, GLenum zfail, GLenum zpass);

fail は、ステンシルテストの結果がフラグメントの棄却であった場合に、ステンシルバッファの内容をどのように変化させるのかを設定します。設定することのできる値には、以下の 8 種類があります。

表 13-4. ステンシルバッファの内容の変化

設定値

ステンシルバッファの内容

GL_KEEP(デフォルト)

そのままの値で変化しません。

GL_ZERO

0 に設定します。

GL_REPLACE

参照値に置き換えます。

GL_INCR

1 増加させます。255 を超えることはありません。

GL_DECR

1 減少させます。0 未満になることはありません。

GL_INVERT

ビット反転させます。

GL_INCR_WRAP

1 増加させます。255 の次は 0 になります。

GL_DECR_WRAP

1 減少させます。0 の次は 255 になります。

zfail はデプステストでフラグメントが棄却されたとき、zpass はデプステストでフラグメントが通過したときにステンシルバッファの内容がどのように変化するのかを設定します。設定することのできる値は fail と同じです。

13.3. デプステスト

デプステストは、フラグメントのデプス値とフラグメントのウィンドウ座標系での座標にあるデプスバッファの内容とを比較し、フラグメントを次のプロセスに通過させるのか棄却するのかを決定する機能です。ステンシルバッファでも述べたように、デプステストの結果でステンシルバッファの内容を変化させることもできます。

13.3.1. 使用方法

デプステストの使用方法は OpenGL と同じです。

デプステストの有効・無効

デプステストの有効・無効の制御は、capGL_DEPTH_TEST を渡して glEnable() または glDisable() を呼び出すことで行います。現在の設定を取得するには、capGL_DEPTH_TEST を渡して glIsEnabled() を呼び出してください。デフォルトではデプステストは無効になっています。無効に設定されている場合、デプスバッファの変更やフラグメントの棄却は行われません。フレームバッファにデプスバッファが関連付けられていない場合、デプステストは無効に設定されているものとして処理されます。デプステストとステンシルテストは、どちらも有効・どちらか一方が有効のいずれの場合でも、性能の差はありません。

比較方法

比較方法は glDepthFunc() で設定します。

コード 13-3. glDepthFunc() の定義
void glDepthFunc(GLenum func);

func に設定することのできる値には、以下の 8 種類があります。

表 13-5. デプステストの比較方法

設定値

比較内容

GL_NEVER

すべて棄却(すべて通過しない)

GL_ALWAYS

すべて通過

GL_LESS(デフォルト)

デプス値がバッファの内容より小さければ通過 (fragment depth < depth buffer)

GL_LEQUAL

デプス値がバッファの内容以下ならば通過 (fragment depth <= depth buffer)

GL_EQUAL

デプス値がバッファの内容と等しければ通過 (fragment depth == depth buffer)

GL_GEQUAL

デプス値がバッファの内容以上ならば通過 (fragment depth >= depth buffer)

GL_GREATER

デプス値がバッファの内容より大きければ通過 (fragment depth > depth buffer)

GL_NOTEQUAL

デプス値がバッファの内容と等しくなければ通過 (fragment depth != depth buffer)

比較の結果、フラグメントが棄却されるときはデプスバッファに変化はありません。フラグメントが通過するときはデプスバッファの内容がフラグメントのデプス値で上書きされます。

13.4. ブレンディング

ブレンディングは、フラグメントの持つカラー(ソースカラー)とフラグメントのウィンドウ座標系での座標にあるフレームバッファのカラー(ディスティネイションカラー)を合成する機能です。ブレンディングの結果は、フラグメントの持つカラーとして次のプロセスに渡されます。

13.4.1. 使用方法

ブレンディングの使用方法は OpenGL と同じです。

ブレンディングの有効・無効

ブレンディングの有効・無効の制御は、capGL_BLEND を渡して glEnable() または glDisable() を呼び出すことで行います。現在の設定を取得するには、capGL_BLEND を渡して glIsEnabled() を呼び出してください。デフォルトではブレンディングは無効になっています。無効に設定されている場合、ブレンディングは行われません。

フレームバッファにカラーバッファが関連付けられていない場合、または後述する論理演算が有効になっている場合、ブレンディングは無効に設定されているものとして処理されます。

ブレンディングの計算式(合成方法)

フラグメントの持つカラー(ソースカラー)とフレームバッファのカラー(ディスティネーションカラー)をどのように合成するかは、glBlendEquation() または glBlendEquationSeparate() で設定することができます。

コード 13-4. glBlendEquation*() の定義
void glBlendEquation(GLenum mode);
void glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha);

glBlendEquation() は、mode で RGB 成分とアルファ成分の計算式をまとめて設定することができます。

glBlendEquationSeparate() は、modeRGB で RGB 成分の、modeAlpha でアルファ成分の計算式を個別に設定することができます。それぞれに設定する値は共通で、以下の 5 種類があります。

表 13-6. ブレンディングの計算式

設定値

RGB 成分

アルファ成分

GL_FUNC_ADD(デフォルト)

R = Rs * Sr + Rd * Dr
G = Gs * Sg + Gd * Dg
B = Bs * Sb + Bd * Db

A = As * Sa + Ad * Da

GL_FUNC_SUBTRACT

R = Rs * Sr - Rd * Dr
G = Gs * Sg - Gd * Dg
B = Bs * Sb - Bd * Db

A = As * Sa - Ad * Da

GL_FUNC_REVERSE_SUBTRACT

R = Rd * Sr - Rs * Dr
G = Gd * Sg - Gs * Dg
B = Bd * Sb - Bs * Db

A = Ad * Sa - As * Da

GL_MIN

R = min( Rs, Rd )
G = min( Gs, Gd )
B = min( Bs, Bd )

A = min( As, Ad )

GL_MAX

R = max( Rs, Rd )
G = max( Gs, Gd )
B = max( Bs, Bd )

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() で設定することができます。

コード 13-5. glBlendFunc*() の定義
void glBlendFunc(GLenum sfactor, GLenum dfactor);
void glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha,
                         GLenum dstAlpha);

glBlendFunc() は、sfactordfactor でソースとディスティネーションの重み係数をまとめて設定することができます。glBlendFuncSeparate() は、srcRGBsrcAlpha でソースの RGB 成分とアルファ成分の重み係数を、dstRGBdstAlpha でディスティネーションの RGB 成分とアルファ成分の重み係数を個別に設定することができます。それぞれに設定する値は共通で、以下の 15 種類があります。

表 13-7. ソースとディスティネーションの重み係数

設定値

カラーの重み係数
(Sr, Sg, Sb) or (Dr, Dg, Db)

アルファの重み係数
Sa or Da

GL_ZERO(デフォルト dstRGB, dstAlpha

(0, 0, 0)

0

GL_ONE(デフォルト srcRGB, srcAlpha

(1, 1, 1)

1

GL_SRC_COLOR

(Rs, Gs, Bs)

As

GL_ONE_MINUS_SRC_COLOR

(1, 1, 1) - (Rs, Gs, Bs)

1 - As

GL_DST_COLOR

(Rd, Gd, Bd)

Ad

GL_ONE_MINUS_DST_COLOR

(1, 1, 1) - (Rd, Gd, Bd)

1 - Ad

GL_SRC_ALPHA

(As, As, As)

As

GL_ONE_MINUS_SRC_ALPHA

(1, 1, 1) - (As, As, As)

1 - As

GL_DST_ALPHA

(Ad, Ad, Ad)

Ad

GL_ONE_MINUS_DST_ALPHA

(1, 1, 1) - (Ad, Ad, Ad)

1 - Ad

GL_CONSTANT_COLOR

(Rc, Gc, Bc)

Ac

GL_ONE_MINUS_CONSTANT_COLOR

(1, 1, 1) - (Rc, Gc, Bc)

1 - Ac

GL_CONSTANT_ALPHA

(Ac, Ac, Ac)

Ac

GL_ONE_MINUS_CONSTANT_ALPHA

(1, 1, 1) - (Ac, Ac, Ac)

1 - Ac

GL_SRC_ALPHA_SATURATE

(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() で設定することができます。

コード 13-6. glBlendColor() の定義
void glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);

red greenbluealpha で RGB とアルファの各成分を指定します。各成分値は 0.0 ~ 1.0 の浮動小数点数で指定します。デフォルトでは、すべて 0.0(0.0, 0.0, 0.0, 0.0)に設定されています。

13.5. 論理演算

論理演算は、フラグメントのカラーとフレームバッファのカラーに対して、パーフラグメントオペレーションの最後に適用される、画像の論理演算を行う機能です。論理演算の結果は、ウィンドウ座標系でのフラグメントの座標に対応するフレームバッファに書き込まれます。

13.5.1. 使用方法

論理演算の使用方法は OpenGL ES 1.1 と同じです。

論理演算の有効・無効

論理演算の有効・無効の制御は、capGL_COLOR_LOGIC_OP を渡して glEnable() または glDisable() を呼び出すことで行います。現在の設定を取得するには、capGL_COLOR_LOGIC_OP を渡して glIsEnabled() を呼び出してください。デフォルトでは論理演算は無効になっています。無効に設定されている場合、論理演算は行われませんが、フレームバッファにはフラグメントのカラーが書き込まれます。論理演算を有効に設定すると、ブレンディングは無効となります。

演算方法

フラグメントのカラー(ソース)とフレームバッファのカラー(ディスティネーション)をどのように論理演算するのかは、glLogicOp() で設定します。現在の設定を取得するには、pnameGL_LOGIC_OP_MODE を渡して glGetIntegerv() を呼び出してください。デフォルトでは GL_COPY が設定されています。

コード 13-7. glLogicOp() の定義
void glLogicOp(GLenum opcode);

opcode には、RGB とアルファの各成分に対する演算方法をまとめて指定します。

表 13-8. 論理演算の演算方法

設定値

演算方法

C スタイルでの表記

GL_CLEAR

0

0

GL_AND

s ∧ d

s & d

GL_AND_REVERSE

s ∧ ¬ d

s & ~d

GL_COPY(デフォルト)

s

s

GL_AND_INVERTED

¬ s ∧ d

~s & d

GL_NOOP

d

d

GL_XOR

s xor d

s ^ d

GL_OR

s ∨ d

s | d

GL_NOR

¬ (s ∨ d)

~(s | d)

GL_EQUIV

¬ (s xor d)

~(s ^ d)

GL_INVERT

¬ d

~d

GL_OR_REVERSE

s ∨ ¬ d

s | ~d

GL_COPY_INVERTED

¬ s

~s

GL_OR_INVERTED

¬ s ∨ d

~s | d

GL_NAND

¬ (s ∧ d)

~(s & d)

GL_SET

all 1

pow(2, n) - 1

n は各成分でのビット数

13.6. フレームバッファのマスク

パーフラグメントオペレーションで行われる、フレームバッファへのカラー(RGBA)、ステンシル、デプスの書き込みに対してマスキングを行うことができます。それぞれ、glColorMask()glStencilMask()glDepthMask() で設定することができます。

コード 13-8. フレームバッファのマスキング関数
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)が設定されています。