WPFPixelShaderLibrary icon indicating copy to clipboard operation
WPFPixelShaderLibrary copied to clipboard

How to save Visual of framework element with these shader effects?

Open Milkitic opened this issue 4 years ago • 5 comments

a I tried to use RenderTargetBitmap to save the result of the effect, but it doesn't work. And after my consult I saw https://stackoverflow.com/questions/3847097/cant-render-pixel-shader-to-rendertargetbitmap-please-help this question but I don't know if the problems are the same. Is there any solution to resolve this?

Milkitic avatar Nov 30 '20 13:11 Milkitic

image And here is the direct screenshot

Milkitic avatar Nov 30 '20 13:11 Milkitic

Thank you very much for submitting the issue! Unfortunately, I'm currently working on my final university thesis, which takes up all my free time and energy. I expect to have more free time after Christmas (2020-12-24).

I am not completely sure, why RenderTargetBitmap does not work on pixel shaders. Have you tried using in on WPF's default 'Blur'-effect? Did it work there?

I'll try to track down the bug as soon as possible. Might I suggest in the meantime that you try to create a screenshot of the WPF window using https://stackoverflow.com/q/37931433/3902603 . This solution is far from optimal, but it was the first solution I could think of. An alternative would be to dig into WPF's D3D-pipeline, but that is rather difficult to pull of.

Unknown6656 avatar Nov 30 '20 17:11 Unknown6656

Thank you very much for submitting the issue! Unfortunately, I'm currently working on my final university thesis, which takes up all my free time and energy. I expect to have more free time after Christmas (2020-12-24).

I am not completely sure, why RenderTargetBitmap does not work on pixel shaders. Have you tried using in on WPF's default 'Blur'-effect? Did it work there?

I'll try to track down the bug as soon as possible. Might I suggest in the meantime that you try to create a screenshot of the WPF window using https://stackoverflow.com/q/37931433/3902603 . This solution is far from optimal, but it was the first solution I could think of. An alternative would be to dig into WPF's D3D-pipeline, but that is rather difficult to pull of.

Yes as the image I uploaded shows, the internal Blur effect works. Screenshot can be a solution but there will be more problems like how to locate the actual FrameworkElement after RenderTransforms(etc. ). I think it's only a hack and may be slower to generate images. By the way I'm not in a hurry and thanks to reply immediately.

Milkitic avatar Dec 01 '20 08:12 Milkitic

Yes as the image I uploaded shows, the internal Blur effect works

Yep sorry, I missed that.'

I think it's only a hack and may be slower to generate images.

You are completely right. It is overkill and takes way more time (furthermore, it might capture the mouse cursor or other windows accidentally).


I'll try to look into this issue as soon as I can.

Unknown6656 avatar Dec 01 '20 12:12 Unknown6656

I had a look at the problem, and I did not find a really good alternative to taking screenshots.

However, I stumbled across RWStructuredBuffer<...> which are read-write buffers. It may be possible to store a combination of UV-/Color-Information in such a buffer. However, you'd have to interpolate between the individual values to reconstruct the original frame buffer. I'm furthermore unsure whether control transformations etc. would be taken into account.

I tried to compile the following modification of https://github.com/Unknown6656/WPFPixelShaderLibrary/blob/master/wpfpslib/ps-hlsl/Pixelation.fx, but it failed to compile (I used ps_3_0):

sampler2D input : register(s0);
float2 count : register(C0);

struct OUTPUT
{
	float2 uv : TEXCOORD;
	float4 color : COLOR;
};
uniform RWStructuredBuffer<OUTPUT> buffer : register(u1);
uniform RWStructuredBuffer<int> buffer_index : register(u2);


float4 main(float2 uv : TEXCOORD) : COLOR
{
    float2 sz = 1.0 / count;
    float2 offs = uv;

    if ((floor(offs.y / sz.y) % 2 >= 1) && false)
        offs.x += sz / 2.0;

    float2 pos = floor(offs / sz);
    float2 cnt = pos * sz + sz / 2;

    cnt = clamp(cnt, 0, 1);

    float4 color = tex2D(input, cnt);
    
    buffer[buffer_index[0]].uv = uv;
    buffer[buffer_index[0]].color = color;
    ++buffer_index[0];
    
    return color;
}

The idea is to register an uniform RWStructuredBuffer for the output data (represented by a tuple of coordinates and colors), as well as a 1-element RWStructuredBuffer for keeping track of the current output data index.

Unknown6656 avatar Jan 04 '21 10:01 Unknown6656