2012-07-25 8 views
5

WPFでピクセルシェーダの奇妙な動作が発生しました。シェーダエフェクトを適用した後にぼかした画像

この問題は100%再現可能なので、私は小さなデモプログラムを書きました。ソースコードhereをダウンロードできます。下の線は永久的な座標を持っていますが、上の行はENDX依存関係プロパティに依存します:あなたはこのフレームワークの要素が2行をレンダリング見ることができるように

internal sealed class MyFrameworkElement : FrameworkElement 
{ 
    public double EndX 
    { 
     get 
     { 
      return (double)this.GetValue(MyFrameworkElement.EndXProperty); 
     } 
     set 
     { 
      this.SetValue(MyFrameworkElement.EndXProperty, value); 
     } 
    } 

    public static readonly DependencyProperty EndXProperty = 
     DependencyProperty.Register("EndX", 
      typeof(double), 
      typeof(MyFrameworkElement), 
      new FrameworkPropertyMetadata(0d, FrameworkPropertyMetadataOptions.AffectsRender)); 

    protected override void OnRender(DrawingContext dc) 
    { 
     dc.DrawLine(new Pen(Brushes.Red, 2), new Point(0, 0), new Point(this.EndX, 100)); 
     dc.DrawLine(new Pen(Brushes.Green, 3), new Point(10, 300), new Point(200, 10)); 
    } 
} 

諸悪の根源は、小さなクラス題しMyFrameworkElementです。

このフレームワーク要素は、ピクセルシェーダー効果のターゲットです。簡単にするために、私はグレースケールのシェーダ効果hereを使用しています。そこで私はGrayscaleEffectをMyFrameworkElementに適用しました。あなたは結果を見ることができます、それは素敵に見えます。

私は劇的ENDX性を高めるまで。

小さなラインがぼやけていると、大きなラインは大丈夫です!

グレースケールエフェクトを削除すると、すべての行が表示されるようになります。

誰がこのボケの理由です何かを説明することはできますか? さらに、この問題をどのように解決できますか?

+0

大きな値のBitmapEffectの制限のようです。 – LPL

+0

@LPL 2番目(下位)の行をEndXプロパティにバインドしてEndXを80000に設定すると、すべてがOKになります。私たちはまだ大きな値を持っていますが、どちらの線も非常に長いですが、効果は適切に機能します。または私はあなたのアイデアを得ていませんでしたか? –

答えて

1

カスタムピクセルシェーダでは、中間ビットマップを作成してから、そのテクスチャをピクセルシェーダでサンプリングしなければなりません。

大量のレンダリングを作成しているので、レンダリングパスにいくつかの制限があります。

Geometry clip = new RectangleGeometry(new Rect(0,0,this.ActualWidth, this.ActualHeight)); 

dc.PushClip(clip); 

dc.DrawLine(new Pen(Brushes.Red, 2), new Point(0, 0), new Point(this.EndX, 100)); 
dc.DrawLine(new Pen(Brushes.Green, 3), new Point(200, 10), new Point(10, 300)); 

dc.Pop(); 

UPDATE:

一説には、(最大テクスチャサイズを超えた場合、ビットマップを拡大縮小するためにフィルタを使用していますということです

クイックフィックスを使用すると、次のようにレンダリングしたいものをクリップすることですあなたのグラフィックカードのアーキテクチャに応じて変わる可能性があります)...それは異なるサイズでピクセルシェーダを通ります。そして、元のサイズに縮小されます。

このように、スケーリングフィルタは、ビットマップの内容に応じてアーチファクトを引き起こしています(水平線と垂直線は、縮尺通りで、対角線よりも優れています)。

.NET 4では、フィルタリングに使用するデフォルトのフィルタが低品質のフィルタに変更されました... Fant ...の代わりに双線形...これはおそらくあなたが取得する品質に影響します。

http://10rem.net/blog/2010/05/16/more-on-image-resizing-in-net-4-vs-net-35sp1-bilinear-vs-fant

アップデート2:私は上記の考えていたものを確認するの

この種。

Windowsパフォーマンスツールキット/スイート(Windows SDKの一部)を使用している場合、より大きな中間ビットマップテクスチャが作成されているため、スライダの値を増やしながらビデオメモリがオレンジ色のグラフに表示されます。それは、限界に達するまで増加を続け、次にそれは平らになります...そして、ピクセル化が明白になる時です。

enter image description here

Update3と:

あなたは「ソフトウェアレンダラ」(階層0)にレンダリングモードを設定した場合、あなたはそれを視覚的にこのような大規模なレンダリングに対処方法を見ることができます - アーティファクトが現れる開始おそらく、テクスチャのサイズの制限があなたのGPUよりも大きい/違うからです。しかし、アーティファクトは内部的にBilinearフィルタを使用しているため、引き続き表示されます。

RenderOptions.SetBitmapScalingModeを使用してフィルタをFantに設定しようとしても、レンダリングの品質が何らかの形で変更されているようには見えません(カスタムピクセルシェーダパスを通過したときに尊重されないためです)。

RenderOptions.ProcessRenderMode = RenderMode.SoftwareOnly; 
1

通常、画像は垂直方向にぼやけていますが、水平方向にはギザギザです。

シェーダはベクトルではなくラスタイメージに適用されるため、線はテクスチャにラスタライズされます。ハードウェアは、通常、8198 * 8192までのテクスチャをサポートします。 私の場合は、それを呼び出すと「ぼかし」がスライダの値16384に表示されます。したがって、私のvirtualBox仮想グラフィックスカードは16384 * 16384までをサポートします。 制限は異なる場合があります。 この値をそれより低く保つだけです。

しかし、WPFが全体の画像をラスタライズするのは奇妙です。なぜなら、画像の小さな部分しか表示されないからです。 シェーダ自体の中にある別の理由もありますが、バイナリにコンパイルされているため、チェックできません。

更新: 私の場合、それはこのようになります。それは、水平、垂直フィルタ処理ではなく、同じよう with shader applied

が見えます。

+0

私はあなたのイメージが私のものと違って見えるようになったことに気付きました。あなたの外見は、双線形にフィルタリングされた低解像度です。つまり、あなたは通常のGPUを持っているということです。正方形のテクスチャを使用しています。私の場合、画像は水平にしか伸ばされませんでした。 –

+0

私はすでにLVLに同様のコメントを投稿しています。両方の線が巨大であれば、効果は適切に適用されます。あなたはそれを説明できますか?画像をどこかにアップロードできますか? –

1

[OK]を、私はこれを持っている:ソフトウェアレンダラの結果を見るためにApplication_Startupでこれを入れて

! グレイスケールエフェクトでライブラリを逆コンパイルし、WCF PresentationCoreライブラリを逆コンパイルして、なぜBlurEffectが同じ状況で完璧に機能するかを確認しました。 そして私はそれがBlurEffect抽象メソッドEffect.GetRenderBoundsが存在しないことを発見しました。GrayscaleEffectにあります。また、GrayscaleEffectがPresentationCore v 3.0.0に対して構築されており、EffectにはGetRenderBoundがありません。

これは、3番目と4番目のバージョンのWPFの間に互換性がありません。 それを修正するには、3つの方法があります。

  1. あなたはGrayscaleEffectのソースコードを持っている場合 - 必要なメソッドを追加し、ランタイムの4.0.0バージョンに対してそれをコンパイルします。
  2. アプリケーションで使用するランタイムをバージョン3に切り替えることができます。*。
  3. あなたはGrayscaleEffectのソースを持っていませんが、効果(V4)を継承し、不在のメソッドを実装しGrayscaleEffectのラッパーを書き、実行時の第三版を使用できない場合。

私は2番目の方法を試しましたが、問題は消えました。

+0

_GetRenderBounds_は_ShaderEffect_に実装されています。これは_GrayscaleEffect_の基本クラスであり、その実装は_BlurEffect_の実装とかなり似ています。 .NET 4.0に対するGrayscaleEffectのコンパイルは役に立ちません。 .NET 3.5に対するアプリケーションのコンパイルは役に立ちますが、この方法は実際のアプリケーションでは受け入れられません。これはフレームワーク内の問題のように見えます。 –

0

古い質問ですが、カスタムシェイダーエフェクトを適用した後に画像のぼかしに問題がある人には便利です。

レンダリングされたコンテンツの縮尺に関連している可能性があります。 WPFShadersLibraryからShaderEffectsをビデオ、テキスト、およびその他のコンテンツに適用した後、ぼかしで同様の問題が発生しました。

私は、その画像がちょっとだけシフトして「ピクセル分割」を起こしていることにお気づきになりました。そのため、ShaderEffect:XOffsetとYOffsetの2つの新しいプロパティを作成し、HLSL(下のコードを参照) XAMLでスライダーにバインドさ:

float2 newPos; 
newPos.x = uv.x + offsetX; 
newPos.y = uv.y + offsetY; 

は、その後、私はいくつかの任意のオフセットで実験し、画像を再整合させることができました。依然として、わずかなぼやけ(または細部の喪失)がありますが、結果は著しく優れています。

現在のところ、この解決策の問題は、解像度やウィンドウサイズによってオフセットを予測する方法がわかりません。

関連する問題