» チュートリアル エフェクト - 色操作
This site relies heavily on Javascript. You should enable it if you want the full experience. Learn more.

チュートリアル エフェクト - 色操作

English | Italian | Spanish | Mandarin

TOC: エフェクトとシェーダー
Back: ピクセルシェーダーの準備
Next: テクスチャ座標


今私たちが注目すべきコードは実際のピクセルシェーダー関数です:

  1. float4 PS(vs2ps In): COLOR
  2. {
  3.     return 1;
  4. }

あなたのシーンの中でメッシュが占有するスクリーンのすべてのピクセルから呼ばれるこの関数について考えます。

float4 = ピクセルの色

この関数の戻り値の型はfloat4です。PSは関数の名前で、ファイルの下部にあるtechniqueブロックのなかの記述に対応しています。

関数の戻り値であるfloat4はひとつのピクセルの色をつける4成分のベクトルです。4成分の項目順は次の通りです。

  • red
  • green
  • blue
  • alpha

よって、1の代わりにこのようにfloat4を返すと、

return float4(1, 0, 0, 1);

quadは完全に赤になるでしょう。
それぞれの成分の範囲は0から1の間(0から255ではない)です。

上記のようにfloat4を直接返す代わりに、始めにfloat4型の変数を定義し、何かを行ってから変数を返すこともできます。

float4 col;
col = float4(1, 0, 0, 1);
col /= 2;     //short syntax for: col = col / 2
return col;

これは2で割った後次の値を持つ変数colとして、暗い赤という結果となります:

 (0.5, 0, 0, 0.5)

float4での数学的操作(2で割るような)はすべてのベクトル成分で同時に適用されます。

個々の色成分/チャンネルへのアクセス

しかし、次の様に個々の成分を操作することもできます:

float4 col = float4(1, 0, 0, 1);
col.g = col.r / 2;
return col;

これは次の様な結果になります。:

 (1, 0.5, 0, 1)

swizzlingと呼ばれるものを使って、ベクトルの個々の成分にアクセスできます。
4つの色成分のための基本的なswizzlesは.r、.g、.b、そして.aです。しかし次の様に任意の組み合わせを使うこともできます:

 col = col.bgra;

これは次の様な結果として色成分を並び替えます:

 (0, 0.5, 1, 1)

実際、swizzlingでのすべての組み合わせが許されます。次の様なものでさえ可能です:
.rrgg
.rb
.abba
...you get the idea.
...あなたが思いついたアイデア。

テクスチャの表示

FileTexture (EX9.Texture)Filenameはあなたの好きな画像ファイルを選択します。

ピクセルシェーダーでテクスチャにアクセスし、そのピクセルの色を返すには、次の一行のコードが必要です:

return tex2D(Samp, In.TexCd);

tex2D関数の戻り値(float4)をピクセルの色として直接返しています。
この関数は第1引数としてsamplerを、第2引数としてテクスチャ座標をとります。

エディタ内のいずれかの単語をダブルクリックするとその単語がマークされます。よってsampler変数であるSampをダブルクリックすると、ファイルの上部に定義されているのが見つかるでしょう。samplerはテクスチャといくつかのsampler statesを結びつける構造体です。差し当たって、それについての詳しい説明は置いておいて、後述のテクスチャ座標についてのものだということだけ気に留めておきます。

では、テクスチャの色チャンネルで遊んでみましょう:

float4 col = tex2D(Samp, In.TexCd);
return col.bgra;

最初の画像の色のサンプリングはcolと呼ばれる変数に割り当てられます。
単純に現在のピクセル色としてcolを返す代わりに赤と青の色チャンネルを切り替えて返します。

float4 col = tex2D(Samp, In.TexCd);
return col.b;  //short syntax for: return float4(col.b, col.b, col.b, col.b)

または、画像の青成分だけを全ての4つの色チャンネルに適用したものを表示することもできます。

テクスチャを反転する

テクスチャを反転するためにアルファチャンネルを覗いた赤/緑/青成分だけを反転させたいときはこの様にします:

float4 col = tex2D(Samp, In.TexCd);
col.rgb = 1 - col.rgb;
return col;

テクスチャにコントラストをつける

画像のコントラストは0.5より大きい全ての色の値で増加され、0.5より小さい全ての値で減少されます。
最初に値の範囲を0.5に落とすために、コントラスト要因を用いた簡単な乗算を通して、両方の方向(0のまわり)に対称的にスケールすることができます。その結果、再び0..1の範囲になります。

float4 col = tex2D(Samp, In.TexCd);
col.rgb -= 0.5;
col.rgb *= Contrast;
col.rgb += 0.5;
return col;

これを保存すると次の様なエラーとなるでしょう:

 undeclared identifier 'Contrast'

まだ定義していないので、ピクセルシェーダー関数の真上に:

 float Contrast = 1;

と書き、Contrastと名付けられた変数を定義して値を1で初期化して保存します。
エフェクトノードにContrastと呼ばれる新しいピンが自動的に追加されます。
このピンの値を変えると画像のコントラストが変わります。

グレースケールに変換する

インターネットには3色のチャンネルそれぞれの知覚明度を考慮することによって色をそのグレースケールに相当する値に変換する簡単な公式が述べられています。
このアイデアは赤の値のの30%、緑の値の59%、青の値の11%を一緒に足すことです。
これは2つの方法があります:

float4 col = tex2D(Samp, In.TexCd);
col.rgb = col.r * 0.3 + col.g * 0.59 + col.b * 0.11;
return col;

2つのベクトルの内積を使うことはより洗練された方法です:

const float3 lumCoeff = {0.3, 0.59, 0.11};
col.rgb = dot(col.rgb, lumCoeff);

これは1つ目の方法と(数学的に)全く同じことです。

コードを再利用する

コードの中で一回より多くグレー相当の値にピクセルを変換したい時、同じコードを2回書く代わりに、分割された関数の中にグレースケールに変換するコードを自由に展開できます:

float4 ConvertToGray(float4 col)
{
    const float4 lumcoeff = {0.3, 0.59, 0.11, 0};
    return dot(col, lumcoeff);
}

メインのピクセルシェーダー関数の中でこの関数を使います:

float4 col = tex2D(Samp, In.TexCd);
return ConvertToGray(col);

出来上がり! ではシートベルトをしっかり締めましょう!


Next: テクスチャ座標
Back: ピクセルシェーダーの準備
TOC: エフェクトとシェーダー

anonymous user login

Shoutbox

~2d ago

joreg: vvvvTv S0204 is out: Custom Widgets with Dear ImGui: https://youtube.com/live/nrXfpn5V9h0

~2d ago

joreg: New user registration is currently disabled as we're moving to a new login provider: https://visualprogramming.net/blog/2024/reclaiming-vvvv.org/

~10d ago

joreg: vvvvTv S02E03 is out: Logging: https://youtube.com/live/OpUrJjTXBxM

~12d ago

~13d ago

joreg: Follow TobyK on his Advent of Code: https://www.twitch.tv/tobyklight

~17d ago

joreg: vvvvTv S02E02 is out: Saving & Loading UI State: https://www.youtube.com/live/GJQGVxA1pIQ

~17d ago

joreg: We now have a presence on LinkedIn: https://www.linkedin.com/company/vvvv-group

~24d ago

joreg: vvvvTv S02E01 is out: Buttons & Sliders with Dear ImGui: https://www.youtube.com/live/PuuTilbqd9w

~1mth ago

joreg: vvvvTv S02E00 is out: Sensors & Servos with Arduino: https://visualprogramming.net/blog/2024/vvvvtv-is-back-with-season-2/

~1mth ago