- Home /
HLSL Post Process Shader Fixing UV/Texcoord
Hey, I am trying to make a simple Wobble shader using HDRP and custom post processing in HLSL. However, I am getting black areas on the edges of the screen where texcoord's x value is not within the range of 0-1 (my assumption).
Here's the fragment:
float2 wobble(float2 uv, float amplitude, float frequence, float speed)
{
float offset = amplitude * sin(uv.y * frequence + _Time * speed);
return float2(uv.x + offset, uv.y);
}
float4 CustomPostProcess(Varyings input) : SV_Target
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
float2 uv = input.texcoord;
float amplitude = 0.0030;
float frequence = 25.00;
float speed = 10.0;
uv = wobble(uv,_Amplitude, _Frequence, _Speed);
float3 outColor = LOAD_TEXTURE2D_X(_InputTexture, uv * _ScreenSize.xy).xyz;
return float4(outColor, 1);
}
And here is the result:
Of course the image is getting bent by the Wobble effect, but I need to fit the uv in such a way that these areas will not be black. If I clip the uv's x like this:
if (uv.x < 0.0f)
uv.x = 0.0;
// OR
uv.x = frac(uv.x);
Then I get what I need for the left side of the screen, but I couldn't find a way to handle the other side.
This issue also happens with some other tests I run with different effects, whenever I try to mess with the uv (texcoord). So I kinda need some explanation of how that works properly, and how to recalculate the uv to make the image fit into the screen space properly.
Answer by Bunny83 · Mar 13, 2020 at 04:09 AM
Uhm, of course clamping the UV coordinates would prevent the black areas from being black, but the result would just be the outermost texels streched across those regions. You can't really fill those areas with meaningful data "properly" since there is no data in those regions.
You have several possibilities to "fix" those areas. Though not all might fit your requirements.
Of course the simplest solution is to just clamp the uv values between 0-1 after your wobble function:
uv = clamp(uv, 0, 1);
As mentioned above this would just stretch the outermost pixels sideways to fill the black areas. So the areas are not black anymore but doesn't really look great. Another option is to just repeat the texture. This is done with the line you already mentioned
uv = frac(uv);
That essentially means that the area that is shifted out of the screen on one side comes back in on the other side. This should work for both sides. The last "simple" solution is to artificially "zoom in" a bit which would cut off parts of the image. That way you have enough room to do the wobble without actually leaving the image area. This might not be a valid solution depending on your needs. Especially in stereoscopic view this probably won't work so I don't go into details on this one. Finally if you're just interested in a wobble of the image you could dynamically reduce the distortion and essentially fade it out the closer you get to the edges. This would essentially keep the edges in place and the wobble mainly takes place in the center region of the image. To pull that off you just need a scaling factor for your offset / amplitude that goes to 0 as closer you get to an edge. This can be done by using two clamps and appropriate scaling:
offset *= clamp(uv.x*10, 0, 1) * clamp((1-uv.x)*10, 0, 1);
Of course this would go into your wobble function between your two lines. The "10" inside the two clamps would linearly fade out the offset in the last 10% of the screen. So the wobble would take place in the middle 80% of the screen. A larger value would make the fading area smaller. However the fading area should be at least as large as your amplitude value.
Thank you for your detailed answer!
As you've mentioned, frac gets rid of the black areas, but since it's a full screen effect I wouldn't want the tiling it generates. And using clamp on the uv seems to fix only the left part of the screen, not the right, probably because uv is shifted with wobble and some parts of the right is already below 1.
I needed to know a proper technique on how to modify the math to make sure the sides aren't affected, and you've explained it perfectly! Reducing the distortion and fading it out works perfectly, and now I have a better understanding of how it works. Thank you!
Your answer
Follow this Question
Related Questions
Curved Screen Post Processing Effect 1 Answer
Why doesn't this shader work when using it with as a custom effect on the post processing stack 1 Answer
How is _WorldSpaceLightPos0 calculated for a directional light? 0 Answers
Can you process a color with postprocessing stack's color grading? 2 Answers