views:

26

answers:

1

Hello -

I wrote a very simple WPF application to test the ability to render a control that has an associated pixel shader to a RenderTargetBitmap. I then write the bitmap to file (jpeg). The control is rendered onto the bitmap, however the pixel shader effect is not applied to the control.

The code and the XAML is below:

namespace TestPixelShader
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void OnSaveSnapshot(object sender, RoutedEventArgs e)
        {
            SaveFileDialog dlg = new SaveFileDialog();
            dlg.DefaultExt = "jpg";

            if ((bool)dlg.ShowDialog() == true)
            {
                String fileName = dlg.FileName;

                int Height = (int)CanvasControl.ActualHeight;
                int Width = (int)CanvasControl.ActualWidth;

                RenderTargetBitmap bmp = new RenderTargetBitmap(
                    Width, Height, 96, 96, PixelFormats.Pbgra32);
                bmp.Render(CanvasControl);

                string Extension = System.IO.Path.GetExtension(fileName).ToLower();

                BitmapEncoder encoder;
                if (Extension == ".gif")
                    encoder = new GifBitmapEncoder();
                else if (Extension == ".png")
                    encoder = new PngBitmapEncoder();
                else if (Extension == ".jpg")
                    encoder = new JpegBitmapEncoder();
                else
                    return;

                encoder.Frames.Add(BitmapFrame.Create(bmp));
                using (Stream stm = File.Create(fileName))
                {
                    encoder.Save(stm);
                }
            }
        }
    }
}

XAML:

<Window x:Class="TestPixelShader.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:TestPixelShader"
    Height="400"
    Width="300"
    Title="Test Pixel Shader">

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Canvas Grid.Column="0" x:Name="CanvasControl" Margin="5"
                HorizontalAlignment="Stretch"
                VerticalAlignment="Stretch" >
            <Canvas.Effect>
                <local:TestPixelShaderEffect />
            </Canvas.Effect>
            <Canvas.Background>
                <ImageBrush ImageSource="/TestPixelShader;component/Images/DSCF0225.JPG" />
            </Canvas.Background>
        </Canvas>
        <Button x:Name="SaveSnapshotButton" Grid.Row="1" Click="OnSaveSnapshot" Height="40"
                Content="Take Snapshot" Margin="5"/>
    </Grid>
</Window>
+1  A: 

What Pixel Shader version are you targeting?

I tried your code and it saved the image correctly for a PS 2.0 shader. RenderTargetBitmap uses the software renderer and PS 3.0 doesn't have a software fallback so if your using a PS 3.0 shader it will be ignored.

Kris
That is very disappointing, I need some of the features of PS 3.0 but also need to be able to save a snap shot of an off screen rendered WPF control to a file. I thought RenderTargetBitmap was my best hope. Any suggestions? I suppose I could use DirectX somehow, but I would still need to render the WPF control off screen. This is very frustrating! Thanks for the help!
BigPrimate
If you didn't need to do it offscreen a screen capture would probably be simplest, but it seems like using D3D or doing it in software yourself is your best bet. I don't have much experience with D3D but you can access it with managed code using Slim Dx or the 'Windows API Code Pack'. How complex is your shader, could it be split it into multiple PS 2.0 shaders?
Kris