Weitere ähnliche Inhalte
Ähnlich wie シェーダー伝道師 第一回 (20)
Kürzlich hochgeladen (12)
シェーダー伝道師 第一回
- 5. 当講座について
• C++
• DirectX 11
• DirectX HLSL
• Visual Studio 2015 (2013)
開発環境はここに示しているものです。
私は2015ですが…
プロジェクト自体は2013です。
- 46. 画像処理フィルタ (DirectX HLSL)
• ShaderFiles/2DShaders.hlsl
書き換えるということで、まず確認。
プロジェクト内にhlslファイルがあります。
その中にこのような記述があります。
//===================================
// ピクセルシェーダ
//===================================
float4 mainPS(PSINPUT input) : SV_TARGET
{
float4 Out;
float4 Samp;
int width, height;
g_Tex0.GetDimensions(width, height);
int2 size = int2(width, height);
int3 sp = int3(input.tex * size, 0);
Samp = g_Tex0.Load(sp);
Out.rgb = Samp.rgb;
Out.a = 1;
return Out;
}
- 47. 画像処理フィルタ (DirectX HLSL)
• ShaderFiles/2DShaders.hlsl
ピクセルシェーダー…ですね。
これは、実行直後の標準のシェーダーです。
つまりそのままの描画です。
//===================================
// ピクセルシェーダ
//===================================
float4 mainPS(PSINPUT input) : SV_TARGET
{
float4 Out;
float4 Samp;
int width, height;
g_Tex0.GetDimensions(width, height);
int2 size = int2(width, height);
int3 sp = int3(input.tex * size, 0);
Samp = g_Tex0.Load(sp);
Out.rgb = Samp.rgb;
Out.a = 1;
return Out;
}
- 48. 画像処理フィルタ (DirectX HLSL)
• ShaderFiles/2DShaders.hlsl
記述、に関してですが…
普通の関数という認識で構いません。
float4(rbga)を返すmainPSという関数です。
//===================================
// ピクセルシェーダ
//===================================
float4 mainPS(PSINPUT input) : SV_TARGET
{
float4 Out;
float4 Samp;
int width, height;
g_Tex0.GetDimensions(width, height);
int2 size = int2(width, height);
int3 sp = int3(input.tex * size, 0);
Samp = g_Tex0.Load(sp);
Out.rgb = Samp.rgb;
Out.a = 1;
return Out;
}
- 49. 画像処理フィルタ (DirectX HLSL)
• ShaderFiles/2DShaders.hlsl
rgbaを1つしか返さない関数…
ということで、このピクセルシェーダーは、
描画する各ピクセルで実行される関数です。
//===================================
// ピクセルシェーダ
//===================================
float4 mainPS(PSINPUT input) : SV_TARGET
{
float4 Out;
float4 Samp;
int width, height;
g_Tex0.GetDimensions(width, height);
int2 size = int2(width, height);
int3 sp = int3(input.tex * size, 0);
Samp = g_Tex0.Load(sp);
Out.rgb = Samp.rgb;
Out.a = 1;
return Out;
}
- 50. 画像処理フィルタ (DirectX HLSL)
• ShaderFiles/2DShaders.hlsl
今回の書き換えは、このピクセルシェーダー
に限定したものとなります。
次回以降、テクスチャの生成やシェーダー
追加などに触れていきますのであしからず。
//===================================
// ピクセルシェーダ
//===================================
float4 mainPS(PSINPUT input) : SV_TARGET
{
float4 Out;
float4 Samp;
int width, height;
g_Tex0.GetDimensions(width, height);
int2 size = int2(width, height);
int3 sp = int3(input.tex * size, 0);
Samp = g_Tex0.Load(sp);
Out.rgb = Samp.rgb;
Out.a = 1;
return Out;
}
- 51. 画像処理フィルタ (DirectX HLSL)
• ShaderFiles/2DShaders.hlsl
では、この関数について簡単に解説します。
まず入力したテクスチャの解像度を取得。
(g_Tex0が入力テクスチャ)
//===================================
// ピクセルシェーダ
//===================================
float4 mainPS(PSINPUT input) : SV_TARGET
{
float4 Out;
float4 Samp;
int width, height;
g_Tex0.GetDimensions(width, height);
int2 size = int2(width, height);
int3 sp = int3(input.tex * size, 0);
Samp = g_Tex0.Load(sp);
Out.rgb = Samp.rgb;
Out.a = 1;
return Out;
}
- 52. 画像処理フィルタ (DirectX HLSL)
• ShaderFiles/2DShaders.hlsl
解像度と描画する座標(input.tex)より、
テクスチャの画素を読み取る座標を
計算します。
//===================================
// ピクセルシェーダ
//===================================
float4 mainPS(PSINPUT input) : SV_TARGET
{
float4 Out;
float4 Samp;
int width, height;
g_Tex0.GetDimensions(width, height);
int2 size = int2(width, height);
int3 sp = int3(input.tex * size, 0);
Samp = g_Tex0.Load(sp);
Out.rgb = Samp.rgb;
Out.a = 1;
return Out;
}
- 53. 画像処理フィルタ (DirectX HLSL)
• ShaderFiles/2DShaders.hlsl
変数に値を読み取ります。
//===================================
// ピクセルシェーダ
//===================================
float4 mainPS(PSINPUT input) : SV_TARGET
{
float4 Out;
float4 Samp;
int width, height;
g_Tex0.GetDimensions(width, height);
int2 size = int2(width, height);
int3 sp = int3(input.tex * size, 0);
Samp = g_Tex0.Load(sp);
Out.rgb = Samp.rgb;
Out.a = 1;
return Out;
}
- 54. 画像処理フィルタ (DirectX HLSL)
• ShaderFiles/2DShaders.hlsl
今回の場合はそのまま描画ですね。
(α値だけ1に固定)
//===================================
// ピクセルシェーダ
//===================================
float4 mainPS(PSINPUT input) : SV_TARGET
{
float4 Out;
float4 Samp;
int width, height;
g_Tex0.GetDimensions(width, height);
int2 size = int2(width, height);
int3 sp = int3(input.tex * size, 0);
Samp = g_Tex0.Load(sp);
Out.rgb = Samp.rgb;
Out.a = 1;
return Out;
}
- 55. 画像処理フィルタ (DirectX HLSL)
• ShaderFiles/2DShaders.hlsl
最後にreturnですね。
では、平滑化フィルタに参りましょう。
//===================================
// ピクセルシェーダ
//===================================
float4 mainPS(PSINPUT input) : SV_TARGET
{
float4 Out;
float4 Samp;
int width, height;
g_Tex0.GetDimensions(width, height);
int2 size = int2(width, height);
int3 sp = int3(input.tex * size, 0);
Samp = g_Tex0.Load(sp);
Out.rgb = Samp.rgb;
Out.a = 1;
return Out;
}
- 56. 画像処理フィルタ (DirectX HLSL)
• ShaderFiles/2DShaders.hlsl
先程の1つ下にぼかしフィルタがあります。
こちらについても解説していきます。
//===================================
// ピクセルシェーダ ぼかし
//===================================
float4 blurPS(PSINPUT input) : SV_TARGET
{
~~~~~~~~~~~~~~~~~~略~~~~~~~~~~~~~~~~
float dw = 1.0f / width;
float dh = 1.0f / height;
float2 ei[9] = { float2(-dw, -dh), float2(0, -dh), float2(dw, -dh), float2(-dw, 0), float2(0, 0), float2(dw, 0), float2(-dw, dh), float2(0, dh), float2(dw, dh) };
float2 center = input.tex ;
float3 s = float3(0, 0, 0);
for (i = 0; i < 9; i++)
s += g_Tex0.Sample(g_Sampler, center + ei[i]).rgb;
Out = float4(s / 9.0f, 1);
return Out;
}
- 57. 画像処理フィルタ (DirectX HLSL)
• ShaderFiles/2DShaders.hlsl
略、に関しては解像度の取得です。
//===================================
// ピクセルシェーダ ぼかし
//===================================
float4 blurPS(PSINPUT input) : SV_TARGET
{
~~~~~~~~~~~~~~~~~~略~~~~~~~~~~~~~~~~
float dw = 1.0f / width;
float dh = 1.0f / height;
float2 ei[9] = { float2(-dw, -dh), float2(0, -dh), float2(dw, -dh), float2(-dw, 0), float2(0, 0), float2(dw, 0), float2(-dw, dh), float2(0, dh), float2(dw, dh) };
float2 center = input.tex ;
float3 s = float3(0, 0, 0);
for (i = 0; i < 9; i++)
s += g_Tex0.Sample(g_Sampler, center + ei[i]).rgb;
Out = float4(s / 9.0f, 1);
return Out;
}
- 58. 画像処理フィルタ (DirectX HLSL)
• ShaderFiles/2DShaders.hlsl
こちらは解像度から、
1ピクセル分のテクスチャ座標を求めます。
つまり、1つ隣の移動量を算出します。
//===================================
// ピクセルシェーダ ぼかし
//===================================
float4 blurPS(PSINPUT input) : SV_TARGET
{
~~~~~~~~~~~~~~~~~~略~~~~~~~~~~~~~~~~
float dw = 1.0f / width;
float dh = 1.0f / height;
float2 ei[9] = { float2(-dw, -dh), float2(0, -dh), float2(dw, -dh), float2(-dw, 0), float2(0, 0), float2(dw, 0), float2(-dw, dh), float2(0, dh), float2(dw, dh) };
float2 center = input.tex ;
float3 s = float3(0, 0, 0);
for (i = 0; i < 9; i++)
s += g_Tex0.Sample(g_Sampler, center + ei[i]).rgb;
Out = float4(s / 9.0f, 1);
return Out;
}
- 59. 画像処理フィルタ (DirectX HLSL)
• ShaderFiles/2DShaders.hlsl
そして、9方向分の移動を配列に格納します。
ちょうど[4]がfloat2(0,0)で中心です。
//===================================
// ピクセルシェーダ ぼかし
//===================================
float4 blurPS(PSINPUT input) : SV_TARGET
{
~~~~~~~~~~~~~~~~~~略~~~~~~~~~~~~~~~~
float dw = 1.0f / width;
float dh = 1.0f / height;
float2 ei[9] = { float2(-dw, -dh), float2(0, -dh), float2(dw, -dh), float2(-dw, 0), float2(0, 0), float2(dw, 0), float2(-dw, dh), float2(0, dh), float2(dw, dh) };
float2 center = input.tex ;
float3 s = float3(0, 0, 0);
for (i = 0; i < 9; i++)
s += g_Tex0.Sample(g_Sampler, center + ei[i]).rgb;
Out = float4(s / 9.0f, 1);
return Out;
}
- 60. 画像処理フィルタ (DirectX HLSL)
• ShaderFiles/2DShaders.hlsl
テクスチャ座標(center)と配列の値より
周囲のピクセルの値をサンプリングします。
//===================================
// ピクセルシェーダ ぼかし
//===================================
float4 blurPS(PSINPUT input) : SV_TARGET
{
~~~~~~~~~~~~~~~~~~略~~~~~~~~~~~~~~~~
float dw = 1.0f / width;
float dh = 1.0f / height;
float2 ei[9] = { float2(-dw, -dh), float2(0, -dh), float2(dw, -dh), float2(-dw, 0), float2(0, 0), float2(dw, 0), float2(-dw, dh), float2(0, dh), float2(dw, dh) };
float2 center = input.tex ;
float3 s = float3(0, 0, 0);
for (i = 0; i < 9; i++)
s += g_Tex0.Sample(g_Sampler, center + ei[i]).rgb;
Out = float4(s / 9.0f, 1);
return Out;
}
- 61. 画像処理フィルタ (DirectX HLSL)
• ShaderFiles/2DShaders.hlsl
「あれ?さっきはLoadじゃなかった?」
という点については後ほど解説致します。
//===================================
// ピクセルシェーダ ぼかし
//===================================
float4 blurPS(PSINPUT input) : SV_TARGET
{
~~~~~~~~~~~~~~~~~~略~~~~~~~~~~~~~~~~
float dw = 1.0f / width;
float dh = 1.0f / height;
float2 ei[9] = { float2(-dw, -dh), float2(0, -dh), float2(dw, -dh), float2(-dw, 0), float2(0, 0), float2(dw, 0), float2(-dw, dh), float2(0, dh), float2(dw, dh) };
float2 center = input.tex ;
float3 s = float3(0, 0, 0);
for (i = 0; i < 9; i++)
s += g_Tex0.Sample(g_Sampler, center + ei[i]).rgb;
Out = float4(s / 9.0f, 1);
return Out;
}
- 62. 画像処理フィルタ (DirectX HLSL)
• ShaderFiles/2DShaders.hlsl
あとは9分の1にして描画ですね。
//===================================
// ピクセルシェーダ ぼかし
//===================================
float4 blurPS(PSINPUT input) : SV_TARGET
{
~~~~~~~~~~~~~~~~~~略~~~~~~~~~~~~~~~~
float dw = 1.0f / width;
float dh = 1.0f / height;
float2 ei[9] = { float2(-dw, -dh), float2(0, -dh), float2(dw, -dh), float2(-dw, 0), float2(0, 0), float2(dw, 0), float2(-dw, dh), float2(0, dh), float2(dw, dh) };
float2 center = input.tex ;
float3 s = float3(0, 0, 0);
for (i = 0; i < 9; i++)
s += g_Tex0.Sample(g_Sampler, center + ei[i]).rgb;
Out = float4(s / 9.0f, 1);
return Out;
}
- 63. 画像処理フィルタ (DirectX HLSL)
• 例題1
標準シェーダーを変更
rgb=argに
• 例題2
ぼかしシェーダーを変更
周囲の平均r値より自身のr値が高ければ白
そうでなければ黒に
ということで実際のコードに触れてみましょう。
触れるには書き換えが一番です。
これらの例題の解説をします。
- 64. 画像処理フィルタ (DirectX HLSL)
• 例題1
まず例題1ですが、ここを書き換えてください。
HLSLの面白い記述方法の一つです。
Aはαチャンネルですね。
//===================================
// ピクセルシェーダ
//===================================
float4 mainPS(PSINPUT input) : SV_TARGET
{
float4 Out;
float4 Samp;
int width, height;
g_Tex0.GetDimensions(width, height);
int2 size = int2(width, height);
int3 sp = int3(input.tex * size, 0);
Samp = g_Tex0.Load(sp);
Out.rgb = Samp.arg;
Out.a = 1;
return Out;
}
- 70. 画像処理フィルタ (DirectX HLSL)
• 例題2
次に例題2ですが、このような感じでしょうか。
//===================================
// ピクセルシェーダ ぼかし
//===================================
float4 blurPS(PSINPUT input) : SV_TARGET
{
~~~~~~~~~~~~~~~~~~略~~~~~~~~~~~~~~~~
float dw = 1.0f / width;
float dh = 1.0f / height;
float2 ei[9] = { float2(-dw, -dh), float2(0, -dh), float2(dw, -dh), float2(-dw, 0), float2(0, 0), float2(dw, 0), float2(-dw, dh), float2(0, dh), float2(dw, dh) };
float2 center = input.tex;
float3 s = float3(0, 0, 0);
for (i = 0; i < 9; i++)
s += g_Tex0.Sample(g_Sampler, center + ei[i]).rgb;
Out = s.r / 9.0f < g_Tex0.Sample(g_Sampler, center).r;
Out.a = 1;
return Out;
}
- 74. 画像処理フィルタ (DirectX HLSL)
• 実践1 (グレースケール変換)
変換式を調べる
ヒント : rgb = r * _ + g * _ + b * _;
• 実践2 (3成分ラプラシアンフィルタ)
ラプラシアンフィルタを調べる
ヒント : 先鋭化フィルタ
実践ということで、このような感じでしょうか。
余裕があればやってみてください。
- 75. DirectX HLSL
• 4成分変数の扱い方
o.rgb = i.bgr; // 順番
o.rgb = i.rrr; // 好きな成分
o.rgb = 0; // 一気に代入
o.a = 1; // 当然1つも
o.xyzw = i.xyzw; // xyzwでも
o.rgb *= 2.0f; // 3成分に同時
o = float4(i.rgb, 1); // 初期化が多彩
o = float4(i1.xy, i2.xy);// 初期化が多彩
さて、いかがでしたか?
簡単ですが書き換えは楽しかったですか?
hlslの書き方は特徴的?
- 78. P.S. LoadとSampleについて
• Load (ピクセル単位で取り出す)
よって整数型で指定する
• Sample (テクスチャ座標でサンプリング)
よって浮動小数点型で指定する
• なぜ周囲を見る時Sampleか
出力画像の解像度でフィルタ処理を行いたい
入力画像の解像度に依存しないSample
追伸、LoadとSampleの件。
Loadは配列の値を読み取るように、
整数の値によってピクセルを指定して
その色を取り出します。
- 79. P.S. LoadとSampleについて
• Load (ピクセル単位で取り出す)
よって整数型で指定する
• Sample (テクスチャ座標でサンプリング)
よって浮動小数点型で指定する
• なぜ周囲を見る時Sampleか
出力画像の解像度でフィルタ処理を行いたい
入力画像の解像度に依存しないSample
逆にSampleは適当な座標でも適切な値を算
出します。この時、サンプリングの設定で線
形補間などを選択できます。
- 80. P.S. LoadとSampleについて
• Load (ピクセル単位で取り出す)
よって整数型で指定する
• Sample (テクスチャ座標でサンプリング)
よって浮動小数点型で指定する
• なぜ周囲を見る時Sampleか
出力画像の解像度でフィルタ処理を行いたい
入力画像の解像度に依存しないSample
なぜSampleかと言うと、出力画像の解像度
でフィルタ処理を行いたいためです。
- 81. P.S. LoadとSampleについて
• Load (ピクセル単位で取り出す)
よって整数型で指定する
• Sample (テクスチャ座標でサンプリング)
よって浮動小数点型で指定する
• なぜ周囲を見る時Sampleか
出力画像の解像度でフィルタ処理を行いたい
入力画像の解像度に依存しないSample
入力画像の解像度によって、
フィルタが変わるのはナンセンスです。
ということでよろしいでしょうか。