XNAパーティクルシステムを描画または作成します。 パートII:シェーダー

すべてのゲーム開発者、およびゲーム開発に興味のある人々のみなさん、こんにちは。

ピクセルシェーダーと後処理の方法について説明します。 これは、 前回の記事の XNAのグラフィカルメソッドに関する記事の第2部です。spriteBatchのDrawメソッドとBeginメソッドを調べました。 例:スペースを歪めるピクセルシェーダーを追加して、パーティクルシステムを改善します。







このパートでは:

シェーダー



シェーダーについて少し話しましょう。 シェーダーには2つのタイプがあります(使用するShader Model 2.0では)。頂点とピクセル。

頂点シェーダーは、多面体の頂点にマッピングされたデータを操作します。 このようなデータには、特に、空間内の頂点の座標、テクスチャ座標、接線ベクトル、従法線ベクトル、法線ベクトルが含まれます。 頂点シェーダーは、頂点の種と透視変換、テクスチャ座標の生成、照明の計算などに使用できます。

ピクセルシェーダーは、三角形のラスタライズのフェーズで各フラグメントに対して実行されます。 フラグメント(またはピクセル)は、一連の操作を実行した後にラスタライザーによって取得された、ウィンドウ座標を持つポイントです。 単純に、結果のポイントをフレームバッファーに配置し、これらのポイントの組み合わせが画像を形成します。 ピクセルシェーダーは、最終段階、つまり 深度テスト、アルファおよびステンシル。 ピクセルシェーダーは、頂点シェーダーから補間データ(色、テクスチャ座標)を受け取ります。



ピクセルシェーダーについて非常に簡単に言うと、これが完成した画像プロセッサです。

ディスプレイスメントシェーダーの場合、頂点シェーダーは必要ありません。 ピクセルシェーダーを考えてみましょう

後処理


zyで簡潔な人であるために、ゲームの画像全体が既に描画されているときに後処理シェーダーが実行されます。シェーダーは、個別のスプライトではなく、画像全体にすぐに重ねられます。

-結局のところ、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を使用して物理を実装する方法について説明します。

幸運を祈ります。 ホリデープログラマー 0xFF + 1午後! ;)

Source: https://habr.com/ru/post/J128349/


All Articles