かなり単純なピクセル シェーダーを用意しました。アルファ チャネルを 0 に設定して元に戻します。
sampler2D tex : register(s0);
float4 PS(float2 uv : TEXCOORD) : COLOR
{
float4 color = tex2D(tex, uv);
color.a = 0;
return color;
}
これにより、適用された画像が完全に見えなくなると思います。しかし、それは起こっているように見えることではありません。代わりに、結果の画像は白い背景では見えなくなりますが、黒い背景では変更されません。このシェーダーが原因で、フォアグラウンドとバックグラウンドの間で "add" 関数が呼び出されているようです。
たとえば、次のコードは前景と背景の画像を読み込み、上記のシェーダー効果を前景に適用し、それらをビットマップにレンダリングし、ビットマップをファイルに書き込みます。
public sealed partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
}
void Button_Click(object sender, RoutedEventArgs e)
{
const int width = 1024;
const int height = 768;
var sz = new Size(width, height);
var background = new Image { Source = new BitmapImage(new Uri(@"c:\background.jpg")) };
background.Measure(sz);
background.Arrange(new Rect(sz));
var foreground = new Image { Source = new BitmapImage(new Uri(@"c:\foreground.jpg")), Effect = new Alpha() };
foreground.Measure(sz);
foreground.Arrange(new Rect(sz));
var target = new RenderTargetBitmap(width, height, 96d, 96d, PixelFormats.Default);
target.Render(background);
target.Render(foreground);
var jpg = new JpegBitmapEncoder();
jpg.Frames.Add(BitmapFrame.Create(target));
using (var fileStream = File.OpenWrite(@"c:\output.jpg"))
{
jpg.Save(fileStream);
}
}
}
// Standard ShaderEffect stuff here, nothing exciting.
public sealed class Alpha : ShaderEffect
{
static readonly PixelShader Shader = new PixelShader{UriSource = new Uri("pack://application:,,,/Alpha.ps", UriKind.RelativeOrAbsolute)};
public static readonly DependencyProperty InputProperty = RegisterPixelShaderSamplerProperty("Input", typeof(Alpha), 0);
public Alpha()
{
PixelShader = Shader;
UpdateShaderValue(InputProperty);
}
public Brush Input
{
get { return (Brush)GetValue(InputProperty); }
set { SetValue(InputProperty, value); }
}
}
これを 2 つの Win7 サンプル画像に適用すると、次のようになります。
Image
これは、 XAML で効果を適用したときに画面に表示される動作と同じImage
です。
前景と背景が逆の場合、画像は同じであることに注意してください。したがって、「追加」でない場合は、少なくとも交換可能です。「追加」だと思います。
コンピュータは通常正しいので、これはユーザー エラーだと思いますが、アルファをゼロに設定しても透明な画像が得られないのはなぜですか? もしそうなら、どうすれば透明な画像を取得できますか?(最終的にシェーダーでもっと複雑なことをしたいのは明らかですが (特にグリーンスクリーン)、それを機能させるには、まずこのシェーダーを機能させる必要があるため、「不透明度プロパティを設定する」とだけ言ってはいけません)。