オフスクリーンビットマップにPixelShaderを適用する
-
08-07-2019 - |
質問
私は現在、.net 3.5 sp1で導入されたPixelShadersを使用して、画像処理のパフォーマンスを改善する実験を行っています。すべてがはるかに高速ですが、まだwpfフォームの一部の要素にエフェクトが適用されていたので、実際には回避したいです。
多数の画像処理機能があり、パフォーマンスを向上させるために、ピクセルシェーダーを使用して他のものをいくつか置き換えたいと思います。 このようなピクセルシェーダーを表示せずにImageSourceに適用する方法はありますか?
解決
これが必要な人のために: WPFで行う方法を示すこの記事を作成しました。 http://www.codeproject.com / Articles / 642151 / Pixel-shaders-in-a-background-thread-in-WPF
以下にコピーした関連コード。いくつかの保存された変数を持つクラスからのものです
- ソース:ImageSource
- DpiX、DpiY:ソースのDpiを含むdoubles
- img:WPFイメージコントロール
- viewbox:WPF ViewBoxコントロール
- WPF_DPI_X、WPF_DPI_Y:constは値96.0で倍増します
1。画像imgはViewboxに埋め込まれています(画面外でも)
//prepare images
img = new Image();
img.Stretch = Stretch.None;
viewbox = new Viewbox();
viewbox.Stretch = Stretch.None;
viewbox.Child = img; //control to render
2.imgとviewboxは正しい比率に合わせてサイズ調整され、またいくつかのレイアウト関数はviewboxで呼び出されます。これにより、シェーダーが適用された状態でコントロールがレンダリングされます。
/// <summary>
/// Loads the image and viewbox for off-screen rendering.
/// </summary>
public void LoadImage(double width, double height)
{
img.BeginInit();
img.Width = width;
img.Height = height;
img.Source = Source;
img.EndInit();
viewbox.Measure(new Size(img.Width, img.Height));
viewbox.Arrange(new Rect(0, 0, img.Width, img.Height));
viewbox.UpdateLayout();
}
3。そして、画像のコンテンツを取得するには、「スクリーンショット」する場合:
void SaveUsingEncoder(BitmapEncoder encoder, Stream stream)
{
RenderTargetBitmap bitmap = new RenderTargetBitmap((int)(img.Width * DpiX / WPF_DPI_X), (int)(img.Height * DpiY / WPF_DPI_Y), DpiX, DpiY, PixelFormats.Pbgra32);
bitmap.Render(viewbox);
BitmapFrame frame = BitmapFrame.Create(bitmap);
encoder.Frames.Add(frame);
encoder.Save(stream);
}
また、これを別のスレッドで実行する場合は、スレッドを作成する必要があります
thread.SetApartmentState(ApartmentState.STA);
詳細とデモプロジェクトについては、記事を参照してください。
他のヒント
C#の専門家からまだ答えが得られていないのを見て、C ++ DirectX開発者の観点からこれにアプローチしようとします。私の答えが役に立たない場合は、少なくとも正しい方向を指し示すことを望みます。私はC#についてほとんど知らず、PixelShaderがどのようにサポートされるかについても何も知らないため、チャンスは完全に間違っており、ここに書いた内容はまったく当てはまりません。そのような場合は、必要に応じて自由にコメントまたは投票を行ってください
これを実現するためにC ++ / DirectXで一般的に行われることは次のとおりです。
準備(1回実行)
- CreateRenderTargetを使用してレンダーターゲットを作成
- CreateOffscreenPlainSurfaceを使用してオフスクリーンサーフェスを作成
- SetRenderTargetを使用してレンダーターゲットサーフェスを設定する
- 必要な他の入力リソース(テクスチャ、頂点バッファなど)を作成します
レンダリング(複数回実行)
- 必要に応じて入力リソース(テクスチャ、バッファ)を更新します
- レンダリング
- GetRenderTargetを使用して、レンダーターゲットのコンテンツをオフスクリーンサーフェスにコピーします
- オフスクリーンサーフェスをロックし、CPUでコンテンツを読み取ります