Problem texture coordinates in pixel shader

Hi everyone, I’m working on a radial distortion shader but for some reason, even though I’m passing it the coordinates of my mouse, the distortion area moves slightly slower than the mouse is, as you can see in this video.

Here’s the code where I pass in parameters for the shader:
shockwave.Parameters["res"].SetValue(Screen.Size.ToVector2()); shockwave.Parameters["center"].SetValue(new Vector2(mouse.X / Screen.Width, mouse.Y / Screen.Height));

And here’s the code for the pixel shader function:
float4 PixelShaderFunction(float2 UV : TEXCOORD0) : COLOR0
{
float ratio = res.x / res.y;
float2 scaled_UV = (UV - float2(0.5, 0)) * float2(ratio, 1) + float2(0.5, 0);
float mask = (1 - smoothstep(radius - feather, radius, length(scaled_UV - center))) *
smoothstep(radius - thickness - feather, radius - thickness, length(scaled_UV - center));
float2 disp = normalize(scaled_UV - center) * force * mask;
float4 color = tex2D(samp, UV - disp);
return color;
}

If anyone knows why it’s not following the mouse correctly I’d really appreciate that!

Yep i have seen this behavior before myself its really weird.

The only thing i can think of is that this is because the actual mouse code we use thru mouse.GetState lags behind what the windows mouse sees as the current position i guess you could try to prove that with regular spritebatch if thats not the reason then i have no idea how or what why it could be.

I don’t think it lags behind though, because even if I pass Vector2.Zero into the shader, it draws it as if it’s “origin” is it’s center left, rather than just the center.

Yea this doesn’t look like a lag issue, it looks like a scale issue. At the edges of the screen, your mouse out-paces where the shader thinks it is.

I notice in your code you’re passing Screen.Size for “res” but you’re using Screen.Width and Screen.Height to calculate “center”. Is there any difference in value between these two?

This looks familiar to me, but it’s late and I can’t put my finger on it. Check your values and math :slight_smile:

I just checked, unfortunately that wasn’t the problem. :frowning_face: Screen is just a Rectangle, so so the size is just the width and height.

Oh he is right looking at your video yours really is that the mouse is off by scale.

I was talking about a slight actual delay for the position to catch the mouse.

center.x goes from 0 to 1. UV.x also goes from 0 to 1.
scaled_UV.x doesn’t go from 0 to 1 anymore, because you multiply and shift it. That’s why (scaled_UV - center) doesn’t make much sense anymore.

What if you just use UV everywhere instead of scaled_UV?

I see your point, but then the entire effect is stretched. How could I fix that?

(UV - center) will give you the distance from the center in UV-coordinates. As you rightly pointed out, this will be stretched, because the UV-coordinates are stretched. If you just “unstretch” this distance, and use it in your distortion calculations, you should be fine.

float2 distFromCenter = UV - center;
distFromCenter.x *= ratio;

Thanks. You said use it in my distortion calculations. would you mind showing me where in my code I should implement that?

I see 3 occurrences of (scaled_UV - center) in your code right now. Replacing each of them with distFromCenter from my code example probably does it.

Ok, now it looks like this. It’s being offset by the top right.

That seems weird. Can you post the entire pixel shader code again?

Here (sorry I changed the name of UV to coords) :

float4 PixelShaderFunction(float2 coords : TEXCOORD0) : COLOR0
{
    float ratio = res.x / res.y;
    float2 dist = coords - center;
    dist.x *= ratio;
    float mask = (1 - smoothstep(radius - feather, radius, length(dist - center))) *
    smoothstep(radius - thickness - feather, radius - thickness, length(dist - center));
    

    float2 disp = normalize(dist - center) * force * mask;
    float4 color = tex2D(samp, coords - disp);
    
    return color;

Ah I see. I meant it differently: dist - center should be just dist.

float4 PixelShaderFunction(float2 coords : TEXCOORD0) : COLOR0
{
    float ratio = res.x / res.y;
    float2 dist = coords - center;
    dist.x *= ratio;
    float mask = (1 - smoothstep(radius - feather, radius, length(dist))) *
    smoothstep(radius - thickness - feather, radius - thickness, length(dist));
    

    float2 disp = normalize(dist) * force * mask;
    float4 color = tex2D(samp, coords - disp);
    
    return color;

That worked! Thanks so much for the help.

No problem, you’re welcome.

1 Like