Unknown6656 / WPFPixelShaderLibrary

A Pixel Shader Library for WPF UI Controls written in HLSL
GNU General Public License v3.0
38 stars 3 forks source link

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

Open Milkitic opened 3 years ago

Milkitic commented 3 years ago

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 commented 3 years ago

image And here is the direct screenshot

Unknown6656 commented 3 years ago

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.

Milkitic commented 3 years ago

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.

Unknown6656 commented 3 years ago

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 commented 3 years ago

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.