Temporal AA sharpening

Just some more test comparisons.

Notice the bark on the trees
Moving: Imgsli
Stationary vs default: Imgsli
Stationary vs no AA: Imgsli

Here you go! 4.15 version :cool:

https://github.com/hallatore/UnrealEngine/tree/TAA_Sharpen_4.15

Last test shot for today. Most of the change are on the bark of the trees since everything else is foliage which isn’t sharpened.

Default vs. Dynamic: Imgsli

Default 150% vs. Dynamic: Imgsli
It’s interesting to see that the bark stays pretty much the same sharpness even though one of the shots are with screen percentage 150.

Thanks!

It still complained about some function redefinitions on shader compile, but I just removed those functions and then it worked.

I tested it with my game in VR, and it definitely makes a very significant difference. I’ve tested different values, and 0.35 seems to look best.

When looking in the distance, I feel almost no difference between off and on, probably because the HMD resolution is so low then that it doesn’t really matter how sharp the textures are. But when looking at something up close, the difference is huge. With your dynamic sharpen the textures are way, way sharper and it just looks significantly better. It doesn’t actually look sharpened, it just looks higher res, so that’s very good.

The only negative thing I can find is if you try to use the tonemapper sharpen. Your dynamic sharpen makes textures sharper, the tonemapper sharpen makes everything sharper, including edges. A slight tonemapper sharpen to make edges less blurry is nice, but when used together with your dynamic sharpen the textures are sharpened twice, and that does not look good I think, it is sharpening an already sharpened texture then.

So having one sharpening pass that’s sharpening the textures and the edges and another one that’s sharpening the textures is not ideal. More ideal it would be if there would be one sharpening pass sharpening the textures, and another one sharpening only the edges so that textures are not sharpened twice. I think there is currently no sharpening available that only affects the edges though?

If you didn’t use the tonemapper sharpen before though, you should definitely use this dynamic sharpen if you use TAA in VR, everything up close just looks so much better.

I am actually wondering about what performance impact this has. Could you add some stat counters to this so that it shows up in the GPU profiler? What is this currently part of? I guess Temporal AA? I don’t see any difference in TAA time no matter if this is disabled or enabled. I think your code actually runs even if the sharpen amount is set to 0, right? So its not really possible to compare performance with off/on just based on the console variable. How much performance impact do you expect this to have?

Try setting it to 0.20 (or even 0.10) and then use the tonemapper. By using values like 0.35 you are already making the texture sharper than it was before TAA.

I haven’t manage to see any significant performance impact. It seems to be under 1 fps difference at 100fps.

You can try testing without any AA applied. Then you would see what it looks like by default in VR. The dynamic sharpen should’t be sharper than what you see without AA.

Hi hallatore, do I have to use a custom build, or is there a blueprint fix too, and will this improvement eventually be added to future releases?

It is a change to the core engine, so you need a custom build.

I’m hoping my pull request will be accepted. But if it is that might not be until 4.19 or even later.

I’ve submitted a pull request. Hopefully it gets accepted!

https://github.com/EpicGames/UnrealEngine/pull/3924

Can you please confirm that this only is the result of the adaptive sharpening from @hallatore and the motion based blending code path has nothing to do with the sharp textures? Since the two code have been merged it’s hard to tell the results of one or the another approach, but i really must know if the motion based blending is helps in VR, because that would be a proof of a concept for a larger project of mine targeting this and many other artifacts.

In case this line from the repo is part of the code modification you just installed, please remove it and recompile the shaders then let me know the differences and your experiences.

You will find clear explanation as to how to recompile the shaders succesfully. The end result of the successful recompilation will be shown in the output logs of the editor stating the relevant shader have been recompiled.

link to the repo line



float MovementFactor = 1.f;


@hallatore could you please confirm that the following change would disable the technique targeting the movement blur, and will not cause issues with the adaptive sharpen code path of the pull request?

I have tested your adaptive blending earlier, before I merged this dynamic sharpen from hallatore. So I did test with your line:

BlendFinal = clamp( BlendFinal + sqrt(sqrt(distance(BackN.xy, UV.xy))) * 1.0f , BlendFinal , 1.0f );

And I did not see any difference. I enabled and disabled it a few times, yes I recompiled shaders which luckily is quite fast with a change at that shader, and it just didn’t seem to change anything. I don’t have any noisy textures in my game though and it runs with 90 fps, so I also never noticed any blur when I turn my head. The image always appeared same sharp as if the head is still, even with TAA, probably because those blur issues of TAA are way more noticeable when you are around 20 or 30 fps, but at 90 fps not so much.

Also, your blending is always active with hallators change I think, so your blending doesn’t depend on if r.TemporalAADynamicSharpen is set to 0 or anything else, even at 0 your blending does run. And at r.TemporalAADynamicSharpen 0 textures are just as blurry as I’m used to, so the increase in sharpness I see is definitely coming from hallators sharpening, not from your blending.

I am sure your blending makes certain scenes a lot nicer with TAA, as seen in your video, but it doesn’t seem to have too much effect in VR with constant 90 fps and in scenes that aren’t noisy.

Thank you for the response, and the careful tests. I’m happy to hear you have found @hallatore 's sharpening algorithm to be useful! While this means the undoing of the motion bluring have little effects on some scenes, i’m still continue gathering responses to better conclude it’s effects on certain scenarios. Will hopefully get a HMD myself too, but this will be an another topic somewhere else :slight_smile:

It is, but to me looks like it’s effect depends on the results of ContrastFactor, that means if you set the console variable to 0 it will result in zero effect since the multiplication. Maybe the author can lighten us up on the equation to better understand it’s mechanism :slight_smile:

Did you comment out this part of my code? BlendFinal = clamp( BlendFinal + MovementFactor * ContrastFactor, BlendFinal , 1.0 );
You need to comment out that if you want to test without, or in combination with @Konflict code, since they do much of the same thing.
TemporalAADynamicSharpen only affects the general sharpen, not that code that combats some of the blur when moving.

His and my code behave a bit differently. His blends directly on movement, so it removes a lot of blur and is generally sharper. But I found it to also introduce some jitter in high noise stuff vs. standing still.
Mine is inspired by his and still blends on movement, but it takes into account the pixel contrast vs. neighbors. It tries to get as close as possible to “no AA”, but not further. It’s a bit gentler and leaves a bit of blur on high contrast stuff.

If you are testing this with VR it might be difficult to tell the difference between the two since the screen resolution is the biggest problem. But you should notice when you comment out both.


float MovementFactor = saturate(sqrt(sqrt(distance(BackN.xy, UV.xy) / 50)));
float ContrastFactor = saturate(1 - (NeighborContrast * NeighborContrast) * 25);
BlendFinal = clamp( BlendFinal + MovementFactor * ContrastFactor, BlendFinal , 1.0 );

MovementFactor is goes from 0 to 1 based on how fast you move. 50 is quite slow, so it only get a middle value when you move the mouse slowly.
ContrastFactor goes from 0 to 1 and is calculated higher up. It is the highest Luminance contrast of one of the 4 neighboring pixels. This means the higher the contrast the less it reduce blur.

The reason for the ContrastFactor is that I don’t want to make high contrast stuff “pop” when you move, so they should stay with about the same level of blurriness as before.

Some 1440p test screenshots taken with screen percentage set to 100. I think they look very sharp. :cool:
Remember 100% zoom to see the details.

I’ve been testing this in VR as well, and my conclusions are different from John’s. Blur reduction has a noticeable positive impact, especially in scenes with fine details or high contrast.

Here’s a set of cropped screenshots that compare the different methods. They were taken with an Oculus Rift at ScreenPercentage 100, sharpening disabled, and no intentional head movements. The frame time never dipped below 11 ms, AFAIK.

In my opinion, Konflict’s version works better in VR. Hallatore’s version does not seem to do much unless I multiply it by a large amount, and both of them reintroduce a lot of specular aliasing if you set it too high. I didn’t take any screenshots with sharpening on, but in my opinion, the difference between blur reduction on/off is somehow more pronounced when combined with a bit of sharpening.

Sharpening definitely has a more dramatic impact than blur reduction. You can instantly tell if it’s on or not, while blur reduction is something that’s harder to notice without flipping it on/off in realtime. But they both measurably improve VR image quality.

Thanks for the screenies and the tests, and i too am happy to hear that both have positive effects on the VR!

Yes, the specular aliasing is an expected side effect that is hard to combat by regular means. If you find it very problematic it might be possible to reduce the blendings on these areas but that would involve a bit of a coding works in the shader.



BlendFinal *= clamp( 3.f - distance(CenterPixel,(DDX(CenterPixel) + DDY(CenterPixel))/2.f) , 0.f, 1.f);


This currently the equation that i use which is my silly little attempt to quickly select the high gain specular aliased pixels, but this helps apparently to reduce the blending at these spots. You can perhaps apply this in a postprocess material too (before tonemapper) by reducing the pixel’s brightness, tho that would likely reduce the HDR ranges and you end up with an effect similar to a clamp(pixel,0,1).

If you wish to do it like a pro, try this instead: antialiasing - Fighting aliasing on specular highlights - Game Development Stack Exchange :slight_smile:

Those are some good comparisons! :slight_smile:
Are those with just the BlendFinal code, or with my dynamic sharpen but with mine or Konflict’s version of the BlendFinal? (And did you leave TemporalAADynamicSharpen at 0.25?)

The BlendFinal code in PostProcessTemporalCommon.ush should’t do much when the image is perfectly still. But it might be moving just a a little bit because of how the Rift works?
And my version should’t do much with such a high contrast material, since it tries to keep the same amount of specular aliasing while moving as with default TAA. So I think Konflict’s version might work better in many VR scenarios.

Question is how performant is this?

I’ve measured around 0.02 to 0.04ms in frame time. So not noticeable at all.