Page MenuHome

Cycles X: Support OIDN with guiding pass prefiltering
ClosedPublic

Authored by Sergey Sharybin (sergey) on Jul 27 2021, 7:21 PM.
Tags
None
Subscribers
Tokens
"Burninate" token, awarded by AlexeyAdamitsky."Love" token, awarded by benkl."Burninate" token, awarded by Roggii."Party Time" token, awarded by marcog."Love" token, awarded by HEYPictures."Love" token, awarded by Raimund58."Love" token, awarded by kursadk."Love" token, awarded by YAFU."Love" token, awarded by Alaska.

Details

Summary

Straightforward implementation from the OIDN 1.4 example use.

Has a separate option for viewport and final rendering, as pre-filter
is not coming for free and for viewport we want to be as interactive
as possible by default.

The final render has the option enabled by default to help with cases
when the result is tricky and noisy. If the passes are known to be
noise free is better to disable filtering manually. Can re-iterate
over the default value after gaining some more statistics.

Test file: F10242785
Ground truth:

SamplesNLMOIDN OldOIDN new no filterOIDN new with filter
64
256

Extra result with the pvt_flat.blend scene:

SamplesNLMOIDN OldOIDN new no filterOIDN new with filter
256
512
NOTE: NLM is done in the master branch, where lighting is handled a bit different. Hence the difference in the light condition.

Diff Detail

Repository
rB Blender
Branch
cycles-x_oidn_clean_aux (branched from master)
Build Status
Buildable 16090
Build 16090: arc lint + arc unit

Event Timeline

Sergey Sharybin (sergey) requested review of this revision.Jul 27 2021, 7:21 PM
Sergey Sharybin (sergey) created this revision.

Addressed TODOs. Should be ready for review and tests.

The "cleanAux" seems to make OIDN result more better, but it still over-blurs details on the floor in comparison with NLM. Tried to disable filtering of guiding passes while giving a hit that guiding passes are noise-free but it didn't give any measurable difference.

In any case, while the result is still not perfect, it is improved, so think it does make sense to expose it.

Brecht Van Lommel (brecht) requested changes to this revision.Jul 28 2021, 3:29 PM

The OIDN API docs recommend using prefilter for final renders but not interactive denoising, since it's much more expensive. To me that seems reasonable but I have not done measurements.

The Prefilter is in the Viewport panel now but affects both. If we make it only affect final renders, we can move it to the Render panel. Also, when the OptiX denoiser is selected we should hide the option, not gray it out.

For completeness we should also add this option to the compositing node (not necessarily as part of this patch).

This revision now requires changes to proceed.Jul 28 2021, 3:29 PM

Hide prefilter options when OptiX denoiser is used.

The OIDN API docs recommend using prefilter for final renders but not interactive denoising, since it's much more expensive. To me that seems reasonable but I have not done measurements.

It is actually about 0.002sec to prefilter both passes for full-hd frame. Not sure if it depends on noise level though. So might try enabling prefilter for viewport as well.

The Prefilter is in the Viewport panel now but affects both

I can not confirm this on neither user level nor on the code. The F12 render is controlled by pre-filter option in the render layer settings panel, next to the guiding passes menu.

From the BlenderSync::get_denoise_params: background cases uses denoising.use_prefilter = get_boolean(clayer, "use_denoising_prefilter");, viewport case used denoising.use_prefilter = get_boolean(cscene, "use_preview_denoising_prefilter");.

Don't think it is more clear/better to move option to Render panel. Depending on a pass you might or might not want to prefilter guiding passes.

when the OptiX denoiser is selected we should hide the option, not gray it out.

This is done with this update.

For completeness we should also add this option to the compositing node (not necessarily as part of this patch).

Sure, but ideally would be done by compositor module, and directly in the master branch (no in the Cycles X).

One thing I keep forgetting to mention is that maybe we should always specify cleanAux, and use the newly introduced prefilter option to inform Cycles that the guiding passes are noisy. So basically, maybe:

  • Filter guiding passes if user specified they are noisy
  • Beauty pass denoising always considers guiding passes noise-free (cleanAux=true).

It is actually about 0.002sec to prefilter both passes for full-hd frame. Not sure if it depends on noise level though. So might try enabling prefilter for viewport as well.

Ok, seems reasonable then. I could not really notice a difference in the viewport either. It's a bit odd that it's so fast.

I can not confirm this on neither user level nor on the code. The F12 render is controlled by pre-filter option in the render layer settings panel, next to the guiding passes menu.

You're right, I was confused.

One thing I keep forgetting to mention is that maybe we should always specify cleanAux, and use the newly introduced prefilter option to inform Cycles that the guiding passes are noisy. So basically, maybe:

  • Filter guiding passes if user specified they are noisy
  • Beauty pass denoising always considers guiding passes noise-free (cleanAux=true).

That makes sense to me.

Implemented the idea of always using cleanAux, and filtering guiding passes when requested by user.

This makes comparison a bit harder to make, because the old behavior is not possible to replicate with the new code, so really need to compare previous build with the newer one.
The effect of pre-filtering seems to be minimal in the test scenes I've tried so far, not sure what to make of it yet. Having cleanAux does improve things quite a bit.

Will update description with updated and new comparisons after posting this update.

Sergey Sharybin (sergey) edited the summary of this revision. (Show Details)

Note that macOS Intel does not have OIDN 1.4 yet, so this can't be committed yet.

This revision is now accepted and ready to land.Jul 29 2021, 5:42 PM

Edit: Ignore this comment, I miss understood something.

Alaska (Alaska) added a comment.EditedJul 30 2021, 8:42 AM

This will require further investigation, and I'm willing to do that if you want, but exposing CleanAux as an option for users could be useful.

The blurred look of OIDN with CleanAux off may produce an image that looks more temporally stable than OIDN with CleanAux on.

CleanAux on can also produce some artifacts at really low sample counts in specific scenarios that OIDN with CleanAux off seem to just blur over. So disabling it and getting a blurrier look may be better for the end user.

For the temporal stability would be much better if that becomes a "built-in" feature of OIDN (similar to how it was introduced to OptiX).
For the low number of samples artifacts are always possible.

When exposing option to the interface it needs to have clear semantic meaning and usecases for artists. We should not expose setting in the interface just because it exist in some underlying algorithm. Generally, we should avoid situations like "try this option and see if things are better or worse when it's ON or OFF" (as it is not practical when working on animation).

That being said, if you'll find that in some identifyable set of cases exposing option gives better result we'll re-iterate over exposing the option.

P.S. For the low number of samples situation wonder whether blue nosie will be a better way to go.

...
That being said, if you'll find that in some identifyable set of cases exposing option gives better result we'll re-iterate over exposing the option.

I'm going to start off by saying this. CleanAux on assumes you have clean auxiliary passes. As such, it works best when working with a clean auxiliary pass, hence I will focus most of this comment on scenarios where you may not have a clean auxiliary pass, hence low sample counts.
At this point, I should be using the Pre-filtering option as it should help in these situations, however pre-filtering didn't seem to do anything (as discussed later on). Maybe pre-filtering isn't working in this patch? If so, then my results and findings are invalid.


I know that some people use the blurry nature of denoisers at low sample counts as a means to give a render a "painterly look". An example of this can be found in the "Still life" scene that is used as the splash screen for Blender 2.93: https://www.blender.org/download/demo-files/
By using CleanAux in all cases, it means the "painterly effect" is less pronounced.
Arguably, this is a side effect of the denoiser and probably shouldn't be considered a "feature" that should be kept inside Blender. Also, as the various denoisers improve with each update, the ability to get a "painterly look" from the denoiser will become harder and harder achieve unless Blender is designed around having a legacy version of each denoiser for that specific use case, which once again, isn't an "official" use case for the denoiser.
Also, if the user wants a "painterly look" to their renders, they can still export it to an external program and apply a filter to it or skip including guiding passes in the denoising step.

Here's a comparison of CleanAux on and CleanAux off on the "Still life" scene (Using colour, albedo, and normals in denoising). The file is un-modified apart from the switch to OIDN for denoising and compositing disabled.

CleanAux offCleanAux on

Note: The results from still life can not be extrapolated to other scenes that attempt to get the "painterly look" from the denoiser.


Looking at other scenes, rendering with CleanAux on can result in noise appearing in reflections, refractions, out of focus parts of renderings, and motion blur, when rendered at a low enough sample counts, something that is blurred over with CleanAux off resulting in a "nicer" image. Presumably this should be helped out by enabling the Pre-filtering but I can't find a difference. Maybe pre-filtering isn't working? As you said in a earlier comment, "pre-filtering takes 0.002 seconds at fullHD", this seems odd if Intel recommends against using it in the viewport due to interactivity concerns. If Intel has concerns over interactivity then presumably pre-filtering should probably take longer than 0.002 seconds at fullHD, of course, hardware can have an impact on this.

So although CleanAux off seems to resolve the issue of noisy reflections, refractions, DOF, and motion blur, it seems like the issue is more likely to be related to pre-filtering potentially not working.

Here's an example of noisy reflections. I used the Agent 347 barbershop scene rendered at 16 samples (Using colour, albedo, and normals in denoising). (If you look at the full size image, you can also see issues around the window area)

CleanAux offCleanAux onCleanAux off cropped to affected areaCleanAux on cropped to affected area

Here's a render show casing motion blur. The scene is one I made, it contains a ball, made with a brick material, rolling over mounds with grass (3D models of grass) with trees in the background. The scene was rendered at 128 and 256 samples. (Using colour, albedo, and normals during denoising). If you look at the renders closely, the CleanAux on render produces patches of noise in parts of the grass (specifically in the shadows on the right of the frame). This is not here when CleanAux is turned off as the image is overall blurrier. The effect is rather subtle, and with this being a frame from an animation, the effect will probably be covered up with motion and/or compression artifacts if posted websites that take advantage of compression. Once again, pre-filtering could help here, but there was no perceivable difference.

CleanAux off 128 samplesCleanAux on 128 samplesCleanAux off 256 samplesCleanAux on 256 samples

Here's a show case of DOF. This is a render from the pvt_flat.blend file at 32 samples. As you can see, with CleanAux on, noise is reintroduced into the blurred background of the scene. Once again, pre-filtering might help? But could be not working at the moment? (Uses colour, albedo, and normals in denoising):

CleanAux onCleanAux off

Here's another example with DOF and refraction. This scene consists of a "glass" cube placed inside a bowl shaped object. It's surrounded by little light emitting objects and the scene has a very strong DOF effect to get a strong bokeh. I have rendered the scene at 128 and 256 samples using the colour, albedo, and normals pass. Once again, you can see that the CleanAux on render has noise in bits of the refractive glass cube. And the bokeh on some of the lights are a bit more mis-shapened with CleanAux on. Pre-filtering could help, but I saw no difference, might not be working?

CleanAux off 128 samplesCleanAux on 128 samplesCleanAux off 256 samplesCleanAux on 256 samples

I'm personally in favor of having the CleanAux setting exposed, as it can resolve some issues with noise showing up in denoised renders. However, it seems this issue is caused by pre-filtering potentially not working.
I would try rendering these scenes out as EXR and process them with a standalone version of OIDN to make sure it's not a issue with Blender's pre-filtering implementation, but I can't get it to work properly.

The cleanAux indeed expects guiding passes to be clean. If those passes are not clean that's when the Prefilter option is supposed to be used.
If disabling cleanAux with noise-free guiding passes improves the quality, I'd say that is something up to OIDN to improve. Same goes to prefilter option: if prefilter+cleanAux is worse than filter without cleanAux then it also smells something to be investigated from OIDN side (a bit tricky permutation, but hope you know what I mean to say :)

Now, there are 2 news.
I'll start with the bad one. Afraid you'd need to do the investigation/comparison again :(

On a good news: you was right about pre-filter not doing anything. I've fixed it in the follow-up commit rBfd9c4f166b6.

P.S. Thanks for the investigation, it really does help :)

Alaska (Alaska) added a comment.EditedJul 30 2021, 1:50 PM

The cleanAux indeed expects guiding passes to be clean. If those passes are not clean that's when the Prefilter option is supposed to be used.
If disabling cleanAux with noise-free guiding passes improves the quality, I'd say that is something up to OIDN to improve. Same goes to prefilter option: if prefilter+cleanAux is worse than filter without cleanAux then it also smells something to be investigated from OIDN side (a bit tricky permutation, but hope you know what I mean to say :)

Now, there are 2 news.
I'll start with the bad one. Afraid you'd need to do the investigation/comparison again :(

On a good news: you was right about pre-filter not doing anything. I've fixed it in the follow-up commit rBfd9c4f166b6.

P.S. Thanks for the investigation, it really does help :)

For the investigation, what would you like me to focus on? Re-run the same tests I did before just to see how well pre-filtering works now? And run tests with higher sample counts (thus resulting in clean auxiliary passes without pre-filtering) and see how well it works?

I'll probably start work into investigating it again tomorrow my time (UTC+12)

Guess start with verifying that things do work as expected now. And see if there are still cases when cleanAux is something you don't desire.

No rush with that though, so don't feel pressured. Also, we should move discussion outside of the code review section. render-cycles-module on blender.chat perhaps?

Alaska (Alaska) added a comment.EditedJul 31 2021, 3:12 AM

For explanation check here: https://blender.chat/channel/render-cycles-module?msg=zbkna28XjADZWDP6R

I'm posting the images here because there was a issue with visibility for other people and this was the easiest way I could think of to get around it. I now know of a better way and will do that in the future.

Key:
CA = CleanAux
PF = Prefilter


Barbershop interior (testing reflections at 16 samples):

CA = off, PF = offCA = off, PF = onCA = on, PF = offCA = on, PF = on

Ball rolling through grass scene (motion blur test at 128 samples):

CA = off, PF = offCA = off, PF = onCA = on, PF = offCA = on, PF = on

Ball rolling through grass scene (motion blur test at 256 samples):

CA = off, PF = offCA = off, PF = onCA = on, PF = offCA = on, PF = on

pvt_flat scene (DOF test at 32 samples):

CA = off, PF = offCA = off, PF = onCA = on, PF = offCA = on, PF = on

Bokeh scene (Bokeh and refraction test at 128 samples):

CA = off, PF = offCA = off, PF = onCA = on, PF = offCA = on, PF = on

Bokeh scene (Bokeh and refraction test at 256 samples):

CA = off, PF = offCA = off, PF = onCA = on, PF = offCA = on, PF = on

pvt_flat high sample count (512) showing artifacts on cushion with CleanAux:

CA = off, PF = offCA = off, PF = onCA = on, PF = offCA = on, PF = onReference (32,768 samples without denoising)

pvt_flat high sample count (1024) showing artifacts on cushion with CleanAux:

CA = off, PF = offCA = off, PF = onCA = on, PF = offCA = on, PF = onReference (32,768 samples without denoising)