
このパートでは:
- ピクセルシェーダーとは何ですか?
- 後処理とは
- 簡単に説明すると、 RenderTarget2Dとは何ですか?
- Displacemenet-mapを使用したシェーダーの歪み
- 練習:パーティクルシステムの変更
シェーダー
シェーダーについて少し話しましょう。 シェーダーには2つのタイプがあります(使用するShader Model 2.0では)。頂点とピクセル。
頂点シェーダーは、多面体の頂点にマッピングされたデータを操作します。 このようなデータには、特に、空間内の頂点の座標、テクスチャ座標、接線ベクトル、従法線ベクトル、法線ベクトルが含まれます。 頂点シェーダーは、頂点の種と透視変換、テクスチャ座標の生成、照明の計算などに使用できます。
ピクセルシェーダーは、三角形のラスタライズのフェーズで各フラグメントに対して実行されます。 フラグメント(またはピクセル)は、一連の操作を実行した後にラスタライザーによって取得された、ウィンドウ座標を持つポイントです。 単純に、結果のポイントをフレームバッファーに配置し、これらのポイントの組み合わせが画像を形成します。 ピクセルシェーダーは、最終段階、つまり 深度テスト、アルファおよびステンシル。 ピクセルシェーダーは、頂点シェーダーから補間データ(色、テクスチャ座標)を受け取ります。

ピクセルシェーダーについて非常に簡単に言うと、これが完成した画像プロセッサです。
ディスプレイスメントシェーダーの場合、頂点シェーダーは必要ありません。 ピクセルシェーダーを考えてみましょう 。
後処理
-結局のところ、spriteBatch.Beginにはパラメーター、エフェクトがあります。シェーダーをすぐに適用する方が簡単ではないでしょうか、どのように描画しますか?
私は答えます:まさにそのようなシェーダーが単一のスプライトに適用されることです。その結果、変位シェーダーは曲がって機能します。
ポストプロセス処理を作成するには、まず画面に描画するものを別のテクスチャに描画し、次にポストプロセスシェーダーを使用してこのテクスチャを描画する必要があります。 したがって、シェーダーは単一のスプライトではなく、画像全体に作用します。
-やめて、でも別のテクスチャに描く方法は?
答えは次の とおりです。RenderTarget2Dを満たす
RenderTarget2D
そして再び、こんにちは私の友人-簡潔さ。 RenderTarget2D-基本的には描画できるテクスチャです。
通常、シーンを描画する場所に移動し、クリーニングする前に挿入します。
GraphicsDevice.SetRenderTarget(renderTarget);
これですべてが画面上ではなく、RenderTarget2D上に描画されます。
画面に戻るには、次の構造を使用します。
GraphicsDevice.SetRenderTarget(null);
描画する前に必ずRenderTargetをクリアしてください。
Displacemenet-mapを使用したシェーダーの歪み
このようなピクセルシェーダーのアイデアは非常に単純です。入力は「曲げる」必要があるテクスチャであり、2番目の入力は曲げ方に関するマップです。
実際に-どのようにマップを生成します。
ところで、地図について。 マップは、おそらく、描画された画像が表示されないことを除いて、シーンのテクスチャと同じサイズの画像です。
マップとシェーダーの仕組みにさらに似ています:
画像処理のプロセスでは、現在のピクセル位置を取得し、色を取得します。 カードについても同じことを行います。 つまり 最終的に、画像の対応するピクセル位置のマップ上のピクセル色、ピクセル位置、ピクセル色を変更できるようになります。
マップの色を使用して、ピクセルを曲げる方法をシェーダーに伝えます。
たとえば、Rチャネル(赤)は0fから1fまでの値を受け取ります。 マップに歪みR = 0.5fが表示されている場合、画像のピクセルの位置を10f * 0.5fピクセルだけシフトします。 10fは私たちが移動する力です。
したがって、RチャネルはX座標に対応し、GチャネルはYに対応します。
写真が必要な場合は入手してください:
元の画像:

地図:

最終画像:

そこで、理論を整理し、コードですべてを実装してみましょう。
行動計画:
- シェーダーをプログラムします。
- 後処理を実装します
- パーティクルの別のシステムを作成しますが、今回は珍しいことですが、これらのパーティクルはシェーダーのマップに描画されます。
- マップをシェーダーに渡し、ポストプロセス描画で適用します。
- ???
- 利益!
練習:パーティクルシステムの変更
前の記事のソースコードを完成させています 。
すぐにいくつかの画像を追加して、歪みが目立つようにします。たとえば次のように:

ParticleControllerをコピーしてShaderControllerと呼びます。その中で、パーティクル自体の作成プロセスのみを変更する必要があります。具体的には次のとおりです。
public void EngineRocketShader(Vector2 position) // , { for (int a = 0; a < 2; a++) // 2 { Vector2 velocity = AngleToV2((float)(Math.PI * 2d * random.NextDouble()), 1.6f); float angle = (float)(Math.PI * 2d * random.NextDouble()); float angleVel = 0; Vector4 color = new Vector4((float)random.NextDouble(), (float)random.NextDouble(), 1f, (float)random.NextDouble()); // R G A . float size = 1f; int ttl = 80; float sizeVel = 0; float alphaVel = 0.01f; GenerateNewParticle(smoke, position, velocity, angle, angleVel, color, size, ttl, sizeVel, alphaVel); } }
後処理を実装し、新しい変数を作成します。
RenderTarget2D shader_map; // RenderTarget2D renderTarget; //
それらを初期化します。
shader_map = new RenderTarget2D(GraphicsDevice, 800, 600); renderTarget = new RenderTarget2D(GraphicsDevice, 800, 600);
メインクラスのDrawメソッドに移動して、次のように記述します。
protected override void Draw(GameTime gameTime) { GraphicsDevice.SetRenderTarget(renderTarget); // renderTarget GraphicsDevice.Clear(Color.Black); spriteBatch.Begin(); spriteBatch.Draw(background, new Rectangle(0, 0, 800, 600), Color.White); spriteBatch.End(); part.Draw(spriteBatch); GraphicsDevice.SetRenderTarget(shader_map); // GraphicsDevice.Clear(Color.Black); shad.Draw(spriteBatch); GraphicsDevice.SetRenderTarget(null); // GraphicsDevice.Clear(Color.Black); spriteBatch.Begin(); spriteBatch.Draw(renderTarget, new Rectangle(0, 0, 800, 600), Color.White); spriteBatch.End(); base.Draw(gameTime); }
後処理の準備ができたら、 シェーダーを作成します。
新しいエフェクト (fx)ファイル( これはHLSLで記述されたシェーダーファイルです )を作成し、そこに入力します。
texture displacementMap; // sampler TextureSampler : register(s0); // , sampler DisplacementSampler : samplerState{ // TextureAddress Texture = displacementMap; MinFilter = Linear; MagFilter = Linear; AddressU = Clamp; AddressV = Clamp; }; float4 main(float4 color : COLOR0, float2 texCoord : TEXCOORD0) : COLOR0 { /* PIXEL DISTORTION BY DISPLACEMENT MAP */ float3 displacement = tex2D(DisplacementSampler, texCoord); // R,G,B // Offset the main texture coordinates. texCoord.x += displacement.r * 0.1; // texCoord.y += displacement.g * 0.1; // float4 output = tex2D(TextureSampler, texCoord); // return color * output; } technique DistortionPosteffect { pass Pass1 { PixelShader = compile ps_2_0 main(); // } }
シェーダーが作成され、タイプがTexture2DではなくEffectであることを除いて、通常のテクスチャと同じ方法でロードできます。
Drawを更新します。
effect1.Parameters["displacementMap"].SetValue(shader_map); // spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.Opaque, SamplerState.LinearClamp, DepthStencilState.None, RasterizerState.CullCounterClockwise, effect1); // spriteBatch.Draw(renderTarget, new Rectangle(0, 0, 800, 600), Color.White); spriteBatch.End();
まず、美しくリアルな

実際、このパーティクルシステム(シェーダーではなく、最初のレッスンの内容)の実装は、全体としてパフォーマンスに完全に適しているわけではありません。 理解するのがより難しい他の方法があります。それらについては後で説明します。
ソースコードとデモを適用します(今回は、XNA 4.0およびハードウェアサポートDirectX9、inc sh 2.0を搭載したコンピューターで実行します)
今週かもしれませんが、 UpdateメソッドとBox2Dを使用して物理を実装する方法について説明します。
幸運を祈ります。