#region OpenTK

OpenTKがGitHubで更新されるようになりました。NuGetから手に入れることができるようになりました。
現在は.NET Coreに対応する機運があるようです。

TextureEnvMode.Combine

より複雑なテクスチャの合成

テクスチャの合成で紹介したように、ポリゴンに対して複数の色情報をどう使うかという設定があります。

TextureEnvModeにはAdd、Blend、Decal、Modulate、Replace、そしてCombineがあり、今回はその中のCombineだけについての説明です。

Combineではとても複雑なこともできますが、その場合は素直にシェーダーを用いたほうが簡単です。(そもそも、固定機能自体が非推奨なのですが…)

今回はこれらの画像を合成します。ダミーのテクスチャにする画像のサイズは何でもいいのですが、他のものと同じサイズにしました。

Texture1Texture2Texture3

合成の工程

以前は特に言及していませんでしたが、テクスチャの合成はポリゴン色をベースとして、TextureUnitで数字が小さいものから順に行われていきます。

もしテクスチャの色情報だけを使いたい場合は、Unit0ではReplaceとしておく必要があるなど、注意が必要です。

複雑な合成でも、前のテクスチャ合成の結果を使ってさらに合成するということの繰り返しとなります。

また、ダミーのテクスチャを使ったUnitを使って合成を行うというテクニックもあるようです。

設定が面倒なCombine…

Combine
線形補完、減算

ソースコードは、Combineの設定にだけ注目してください。ちなみに、テクスチャの色は白です。

※列挙体(Enum)の一覧は途中に挿入すると見づらくなるため、ページの一番後ろに載せています。

			GL.ActiveTexture(TextureUnit.Texture0);
			GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)TextureEnvMode.Replace);

ここでは今までのモードのReplaceを使い、ベースにポリゴンの色を使わないという設定をします。

Unit0

			GL.ActiveTexture(TextureUnit.Texture1);
			GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)TextureEnvMode.Combine);
			GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvColor, new float[] { 1.0f, 1.0f, 1.0f, 0.6f });

			GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.CombineRgb, (int)TextureEnvModeCombine.Interpolate);
			GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.Source0Rgb, (int)TextureEnvModeSource.Previous);
			GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.Src1Rgb, (int)TextureEnvModeSource.Texture);
			GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.Src2Rgb, (int)TextureEnvModeSource.Constant);
			GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.Operand0Rgb, (int)TextureEnvModeOperandRgb.SrcColor);
			GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.Operand1Rgb, (int)TextureEnvModeOperandRgb.SrcColor);
			GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.Operand2Rgb, (int)TextureEnvModeOperandRgb.SrcAlpha);

			GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.CombineAlpha, (int)TextureEnvModeCombine.Modulate);
			GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.Src0Alpha, (int)TextureEnvModeSource.Previous);
			GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.Src1Alpha, (int)TextureEnvModeSource.Texture);
			GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.Operand0Alpha, (int)TextureEnvModeOperandAlpha.SrcAlpha);
			GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.Operand1Alpha, (int)TextureEnvModeOperandAlpha.SrcAlpha);

ここでようやくCombineを使います。

Combineでは、RGBとα(透明度)を別々に合成することになります。

CombineRgb(Alpha)で、合成に使う式を指定します。

Source?Rgb(Alpha)またはSrc?Rgb(Alpha)で、合成に使う色情報を指定します。

Operand?Rgb(Alpha)で、使う色情報への加工(と言っても1から減算など)を指定します。

ここのCombineの指定について、RgbはUnit0の結果(Previous)とUnit1のテクスチャを0.6(EnvColor.Alpha)で線形補間、AlphaはUnit0の結果(Previous)とUnit1のテクスチャを乗算、となります。

Unit1の出力は、CをRgb、AをAlphaとして、
CUnit1=CUnit0AEnv+CTex11-AEnv
AUnit1=AUnit0ATex1
となります。

Unit1

			GL.ActiveTexture(TextureUnit.Texture2);
			GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)TextureEnvMode.Combine);
			
			GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.CombineRgb, (int)TextureEnvModeCombine.Subtract);
			GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.Source0Rgb, (int)TextureEnvModeSource.PrimaryColor);
			GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.Src1Rgb, (int)TextureEnvModeSource.Previous);
			GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.Operand0Rgb, (int)TextureEnvModeOperandRgb.SrcColor);
			GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.Operand1Rgb, (int)TextureEnvModeOperandRgb.SrcColor);

			GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.CombineAlpha, (int)TextureEnvModeCombine.Modulate);
			GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.Src0Alpha, (int)TextureEnvModeSource.Previous);
			GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.Src1Alpha, (int)TextureEnvModeSource.Texture);
			GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.Operand0Alpha, (int)TextureEnvModeOperandAlpha.SrcAlpha);
			GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.Operand1Alpha, (int)TextureEnvModeOperandAlpha.SrcAlpha);

ここのCombineの指定について、Rgbはテクスチャ色(PrimaryColor)からUnit1の結果(Previous)を引いたもの、AlphaはUnit0の結果(Previous)とUnit1のテクスチャを乗算、となります。

Unit2の出力は、CをRgb、AをAlphaとして、
CUnit2=CPorygon-CUnit1
AUnit2=AUnit1ATex2
となります。

Unit2

Unit3以降は使っていないため、表示されるものはCUnit2とAUnit2になります。

よって、実際に処理される計算式は、CをRgb、AをAlphaとして、
Cout=CPorygon-CTex0AEnv+CTex11-AEnv
Aout=ATex0ATex1ATex2
となります。

各種列挙体

TextureEnvParameterの中でCombineに使う物をを以下に示します。(GL.TexEnvの第2引数)

TextureEnvMode
合成の方法を指定 Combineを使う場合はTextureEnvMode.Combineを指定
TextureEnvColor
Combineの場合、色情報にConstantを指定したときに使われる色
CombineRgb
CombineのRGBの合成で使う計算式を指定 TextureEnvModeCombineを参照してください
CombineAlpha
Combineのα値の合成で使う計算式を指定 TextureEnvModeCombineを参照してください
Source?Rgb,Src?Rgb
RGBの計算式のNo.?要素を指定 TextureEnvModeSourceを参照してください 使われ方はTextureEnvModeCombineを参照してください
Source?Alpha,Src?Alpha
α値の計算式のNo.?要素を指定 TextureEnvModeSourceを参照してください 使われ方はTextureEnvModeCombineを参照してください
Operand?Rgb
RGBの計算式のNo.?要素への加工を指定 TextureEnvModeOperandRgbを参照してください
Operand?Alpha
α値の計算式のNo.?要素への加工を指定 TextureEnvModeOperandAlphaを参照してください

GL.TextEnvの第3引数

CombineRgbとCombineAlphaで使われる、TextureEnvModeCombineを以下に示します。

Replace
No.0要素で置き換える
計算式:ColororAlpha=arg0
※TextureEnvMode.Replace相当
Modulate
No.0要素とNo.1要素で乗算合成
計算式:ColororAlpha=arg0arg1
※TextureEnvMode.Modulate相当
Add
No.0要素とNo.1要素で加算合成
計算式:ColororAlpha=arg0+arg1
※TextureEnvMode.Add相当
AddSigned
No.0要素とNo.1要素を加算して0.5を引く
計算式:ColororAlpha=arg0+arg1-0.5
Interpolate
No.0要素とNo.1要素でNo.2要素を係数とする線形補間
計算式:ColororAlpha=arg0arg2+arg11-arg2
Subtract
No.0要素とNo.1要素で減算合成
計算式:ColororAlpha=arg0-arg1
Dot3Rgba,Dot3Rgba
dot3バンプマッピングを実現するときに用いるようです
計算式:value=4arg0-0.5arg1-0.5

Source?RgbとSource?Alphaで使われるTextureEnvModeSourceを以下に示します。

Texture
今のUnitのテクスチャの色
Texture?
Unit?のテクスチャの色
Constant
EnvColorで設定した色
PrimaryColor
ポリゴンの色
Previous
前の段階で合成された色

Operand?RgbとOperand?Alphaで使われる、TextureEnvModeOperandRgbとTextureEnvModeOperandAlpha(※付)を以下に示します。

SrcColor
RGBをそのまま使う
OneMinusSrcColor
RGBを1から引いて使う(反転)
SrcAlpha※
α値をそのまま使う
OneMinusSrcAlpha※
α値を1から引いて使う(反転)

記事

外部リンク

Thanks