2012-08-29 15 views
8

質問が回答されました。詳細については、このテキストの最後にあるEDIT#4を参照してください。添加剤ブレンドによる描画イメージ

私たちは現在、かなりうまく行っているゲームメーカーエンジンに取り組んでいます。私はアニメーションクリエイターに取り組んでおり、追加ブレンドでイメージを描くことが可能かどうか疑問に思っていました。

私を説明しましょう。

私たちはC#のSystem.Drawingライブラリを使用し、Windowsフォームで作業します。今のところ、ユーザは、フレーム化されたアニメーション画像(アニメーションの各フレームを含む画像)をインポートすることによって、自分のアニメーションを作成することができ、ユーザは、所望の場所にこれらのフレームをドラッグアンドドロップすることができる。

実際の問題は、追加ブレンディングでフレームを描画する方法を理解できないことです。

ここでは、それが得られない場合の添加剤ブレンドの例を示します。私はあなたを責めません、私は英語で書くのは難しいです。 Additive blending exemple

次の方法を使用して、パネルに描画するか、フォームに直接描画します。例として、地図エディタ用のタイルマップを描画するコードを示します。 AnimationManagerのコードは混乱しているので、この例ではより明確になります。

 using (Graphics g = Graphics.FromImage(MapBuffer as Image)) 
     using (Brush brush = new SolidBrush(Color.White)) 
     using (Pen pen = new Pen(Color.FromArgb(255, 0, 0, 0), 1)) 
     { 
      g.FillRectangle(brush, new Rectangle(new Point(0, 0), new Size(CurrentMap.MapSize.Width * TileSize, CurrentMap.MapSize.Height * TileSize))); 

      Tile tile = CurrentMap.Tiles[l, x, y]; 
      if (tile.Background != null) g.DrawImage(tile.Background, new Point(tile.X * TileSize, tile.Y * TileSize)); 

      g.DrawRectangle(pen, x * TileSize, y * TileSize, TileSize, TileSize); 
     } 

添加剤の図面に画像を描画する可能な方法はありますし、もしそうなら、誰かがどのように私を指摘することができれば、私は永遠に感謝するでしょう。ありがとうございました。

EDIT#1:

画像を描画するため、我々はこのような色相とALPH(不透明度)を設定するカラーマトリックスを使用している:

ColorMatrix matrix = new ColorMatrix 
(
    new Single[][] 
    { 
     new Single[] {r, 0, 0, 0, 0}, 
     new Single[] {0, g, 0, 0, 0}, 
     new Single[] {0, 0, b, 0, 0}, 
     new Single[] {0, 0, 0, a, 0}, 
     new Single[] {0, 0, 0, 0, 1} 
    } 
); 

多分カラー行列がのために使用することができます添加ブレンド?

EDIT#2:

ちょうどマヘシュチャンドによってthis記事を見つけました。

さらに色の変換に関して多くのことを達成することはできますが、さらにブラウズしてもカラーマトリックスでは不可能な場合があります。 解決策が見つかったら私自身の質問に答えます。

ありがとうございました。

EDIT#3:

XNAは、ブレンドに関するドキュメントhereをたくさん持っています。画像の各ピクセルに加法混色を達成するために使用された式が見つかりました。 =

PixelColor(ソース*の[1、1、1、1])+(先* [1、1、1、1])

多分現在のコンテキストでは、この式を使用する方法がありますか? 私は次回の編集で50の賞金を払うつもりです。

もう一度お返事ありがとうございます。軸索へ

EDIT#4

おかげで、今の問題が解決されます。 XNAとそのSpritebatchを使用して、あなたはそうする添加剤の配合を達成することができます:あなたはのGraphicsDeviceを作成するすべてとSpriteBatch

// In the following example, we want to draw inside a Panel called PN_Canvas. 
// If you want to draw directly on the form, simply use "this" if you 
// write the following code in your form class 

PresentationParameters pp = new PresentationParameters(); 

// Replace PN_Canvas with the control to be drawn on 
pp.BackBufferHeight = PN_Canvas.Height; 
pp.BackBufferWidth = PN_Canvas.Width; 
pp.DeviceWindowHandle = PN_Canvas.Handle; 
pp.IsFullScreen = false; 

device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, GraphicsProfile.Reach, pp); 
batch = new SpriteBatch(device); 

まず、それがコントロールまたはフォーム上に描画する時が来たときに( )例えばOnPaintイベントで、次のコードブロック

// You should always clear the GraphicsDevice first 
device.Clear(Microsoft.Xna.Framework.Color.Black); 

// Note the last parameter of Begin method 
batch.Begin(SpriteSortMode.BackToFront, BlendState.Additive); 
batch.draw(/* Things you want to draw, positions and other infos */); 
batch.End(); 

// The Present method will draw buffer onto control or form 
device.Present(); 
+1

これは、ピクセル値自体を操作することなく、まっすぐなwinformsで可能かどうかわかりません。図面用のWPFホストコンポーネントを使用するのはオプションですか?WPFにはブレンドモードを設定するのがはるかに簡単です。 – Dervall

+0

@Dervallもっと検索するほど、WPFホストされたコンポーネントを使用することは非常に良いアイデアだと思うようになります。たぶん、Winformsで直接ピクセル単位のalgoを使用しないと解決策はありません。あるいは、誰かが何らかの奇跡を思いつくだろうか? –

+0

[.DrawImage with opacity?](http://stackoverflow.com/questions/5519956/drawimage-with-opacity) –

答えて

7

速度に推奨1)XNA()を使用するか、又は2)C#でピクセル操作を使用を使用することができます。他の方法もあるかもしれませんが、これらのいずれかが働いています(私は3D効果と画像解析アプリケーションのためにそれぞれを使用しています)。

C#でのピクセル操作: 3つのビットマップの使用。 bmpA、bmpB、bmpC、bmpCにbmpA + bmpBを保存したい場所。

for (int y = 0; y < bmp.Height; y++) 
{ 
    for (int x = 0; x < bmp.Width; x++) 
    { 
     Color cA = bmpA.GetPixel(x,y); 
     Color cB = bmpB.GetPixel(x,y); 
     Color cC = Color.FromArgb(cA.A, cA.R + cB.R, cA.G + cB.G, cA.B + cB.B); 
     bmpC.SetPixel(x, y, cC); 
    } 
} 

上記のコードは非常に遅いです。 C#でのより高速なソリューションは、このようなポインタを使用できます。

// Assumes all bitmaps are the same size and same pixel format 
    BitmapData bmpDataA = bmpA.LockBits(new Rectangle(0, 0, bmpA.Width, bmpA.Height), ImageLockMode.ReadOnly, bmpA.PixelFormat); 
    BitmapData bmpDataB = bmpB.LockBits(new Rectangle(0, 0, bmpA.Width, bmpA.Height), ImageLockMode.ReadOnly, bmpA.PixelFormat); 
    BitmapData bmpDataC = bmpC.LockBits(new Rectangle(0, 0, bmpA.Width, bmpA.Height), ImageLockMode.WriteOnly, bmpA.PixelFormat); 
    void* pBmpA = bmpDataA.Scan0.ToPointer(); 
    void* pBmpB = bmpDataB.Scan0.ToPointer(); 
    void* pBmpC = bmpDataC.Scan0.ToPointer(); 
    int bytesPerPix = bmpDataA.Stride/bmpA.Width; 
    for (int y = 0; y < bmp.Height; y++) 
    { 
     for (int x = 0; x < bmp.Width; x++, pBmpA += bytesPerPix, pBmpB += bytesPerPix, pBmpC += bytesPerPix) 
     { 
      *(byte*)(pBmpC) = *(byte*)(pBmpA) + *(byte*)(pBmpB); // R 
      *(byte*)(pBmpC + 1) = *(byte*)(pBmpA + 1) + *(byte*)(pBmpB + 1); // G 
      *(byte*)(pBmpC + 2) = *(byte*)(pBmpA + 2) + *(byte*)(pBmpB + 2); // B 
     } 
    } 
    bmpA.UnlockBits(bmpDataA); 
    bmpB.UnlockBits(bmpDataB); 
    bmpC.UnlockBits(bmpDataC); 

上記の方法は、ポインタを必要とするので、「危険な」指令でコンパイルする必要があります。また、R、G、Bごとに1バイトと仮定します。ピクセル形式に合わせてコードを変更します。

XNAを使用するは、(GPUによって)ハードウェアアクセラレーションが強化されているため、より高速(パフォーマンス)です。基本的に次のもので構成されています。 1.画像を描画するために必要なジオメトリを作成します(長方形、おそらく全画面クワッド)。 2.頂点シェーダーとピクセルシェーダーを作成します。頂点シェーダは、変更されていないジオメトリを単純にパススルーすることができます。または、直交射影を適用することもできます(四重線に対してどの座標を使用するかによって異なります)。ピクセルシェーダには次の行(HLSL)があります。

float4 ps(vertexOutput IN) : COLOR 
{ 
    float3 a = tex2D(ColorSampler,IN.UV).rgb; 
    float3 b = tex2D(ColorSampler2,IN.UV).rgb; 
    return float4(a + b,1.0f); 
} 

テクスチャにアクセスするには、さまざまな方法があります。以下は、(あなたがXNAコードはシェーダパラメータにバインドする方法に応じて)動作します:

float4 ps(vertexOutput IN) : COLOR 
{ 
    float3 a = texA.Sample(samplerState, IN.UV).xyz; 
    float3 b = texB.Sample(samplerState, IN.UV).xyz; 
    return float4(a + b,1.0f); 
} 

を、あなたが「sampler2D」または "を使用するかどうかによって異なります使用上のシェーダのどちらテクスチャ "HLSLはテクスチャにアクセスするためのインターフェイスです。

適切なサンプラー設定を使用して、色の値を調べるときに標本化(線形補間など)が使用されないように注意する必要があります(その場合は、高品質/高次)。

XNAには、組み合わされたテクスチャの結合方法を指定するためのBlendStatesも組み込まれています。私。 BlendState.Additive(更新されたオリジナルの記事を参照)。

+0

明日私がチームに入るとすぐに試してみましょう。それはたくさんの意味があります。描画するピクセルとピクセルをブレンドするには、ソースイメージが必要です。私たちはXNAを使用しないことに決めましたが、私があなたに提供したこの非常にうまくいった答えで彼らを納得させるかもしれません。 –

+0

さて、チームは最終的にWinFormsでXNAを使用することに決めました。先生、あなたはちょうどその日を救った。ありがとうございました!私はあなたに50ptsを与えることができるまで14時間待つようになった。 –

+0

いいえ問題。運が良かった! – axon

関連する問題