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午後! ;)



All Articles