erichlof / THREE.js-PathTracing-Renderer

Real-time PathTracing with global illumination and progressive rendering, all on top of the Three.js WebGL framework. Click here for Live Demo: https://erichlof.github.io/THREE.js-PathTracing-Renderer/Geometry_Showcase.html
Creative Commons Zero v1.0 Universal
1.94k stars 177 forks source link

Blue noise #69

Open JustLexxy opened 2 years ago

JustLexxy commented 2 years ago

Is it possible to remove the blue noise? I tried modifying a few things to try and remove the blue noise, but it either does nothing or the code doesn't compile. Do you know/have a fix to remove it? Thanks!

erichlof commented 2 years ago

Hello @JustLexxy , Yes it is possible to not use any blue noise at all. Locate this line inside the large main() function inside of the PathTracing fragment shader file (which is written in the glsl language): vec2 pixelOffset = uFrameCounter < 150.0 ? vec2( tentFilter(rand()), tentFilter(rand()) ) : vec2( tentFilter(rng()), tentFilter(rng()) ); And change it to read instead: vec2 pixelOffset = vec2( tentFilter(rng()), tentFilter(rng()) );

The rand() function relies on the BlueNoise texture to produce random numbers between 0.0 and 1.0, whereas the rng() function computes the random numbers (also in the range of 0.0 to 1.0) all on its own. It produces pretty high quality white noise. As above, you will need to go through all glsl shader code for your own particular demo/scene and do a search and replace from rand() to rng(). Most if not all rand() will be found in the main() function as well as the CalculateRadiance() function. Every demo/scene will have a shader with these 2 functions at least. The final image output of the white noise rng() functions should look very similar to the blue noise rand() functions, but maybe won't look as smooth on the first animation frame, or might not converge as fast.

If you successfully change all of the occurrences of rand() to rng(), you can then go through and comment out any lines dealing with the blue noise texture itself, such as the following line, also located in the PathTracing shader's main() function: randVec4 = texelFetch(tBlueNoiseTexture, ivec2(mod(gl_FragCoord.xy + floor(uRandomVec2 * 256.0), 256.0)), 0);

In InitCommon.js, you could also get rid of the following lines, in order to avoid loading in the supplied 256x256 RGBA blue noise texture: // blueNoise texture used in all demos blueNoiseTexture = new THREE.TextureLoader().load('textures/BlueNoise_RGBA256.png'); blueNoiseTexture.wrapS = THREE.RepeatWrapping; blueNoiseTexture.wrapT = THREE.RepeatWrapping; blueNoiseTexture.flipY = false; blueNoiseTexture.minFilter = THREE.NearestFilter; blueNoiseTexture.magFilter = THREE.NearestFilter; blueNoiseTexture.generateMipmaps = false;

Pardon me if you already know this but it has been shown over the last 5 years or so that blue noise is preferable to white noise in path tracing. Path tracing requires many random numbers (usually in the 0.0 to 1.0 range) at every step of the way, from camera ray spawning, to sampling the camera lens (for depth of field effects), to material sampling (like diffuse surfaces), to shadow-ray sampling (producing smoother soft shadows). Blue noise beats white noise in almost every category. Not sure why you would want to disable blue noise, but at any rate, what I outlined in the above paragraphs should do the trick.

Let me know if you have any more questions or issues compiling. :) -Erich

JustLexxy commented 2 years ago

Thanks for the answer! My question was more to disable any kind of noise in order to have a sharp image faster, but from what you're saying I understand that you need the blue noise for the path tracing, so I'm gonna leave it as it is!

erichlof commented 2 years ago

@JustLexxy Glad I could clarify! Yes, unfortunately all path tracers have to deal with noise in one form or another. Noise (randomness) is a curiosity because on one hand, it allows us to randomly sample (like a poll) all possible paths that light might take after interacting with a diffuse or rough specular surface, which results in photo-realistic materials and lighting. But on the other hand, since it is a truly random sample, the first samples that come back could be way off the mark, needing more time to settle down, and instead we get back a noisy image initially (not enough info or samples yet). This can be seen on a simple 2d graph of a Monte Carlo estimator (which all path tracers follow) which is trying to estimate the value of PI in a precise manner. The graph starts out all over the place (too high, too low), then slowly but surely, (and this is the magic and beauty of Monte Carlo-style integration), the estimates settle down and get closer and closer (more decimal places) to the actual value of PI. So if that same system is applied to figuring out how a 3D scene should look when lit a certain way (which is pretty much incalculable using normal closed-form equations), we have to be willing to put up with the initial noisy image, but in return we are guaranteed that when the estimates start to settle down and converge, we will get a truly physically-accurate result - which is really cool when you think about it!

Our human vision is extremely good at finding visual patterns, which sort of works against us when it comes to random number/ray path generation. If the random number generator is of low quality, we see the effects as blotchy or streaky light and dark patterns in the final image. White noise is truly random, so preventing these unwanted patterns, repetitions, and artifacts is a work of art on its own! Recently, Blue noise (which is built within certain spatial constraints, and has more high frequency than low frequency, which is better at dodging our excellent human pattern-matching skills, ha) has been found to be less distracting and smooth when used to generate random ray directions and randomly sampled light paths. But once again, whenever you introduce any kind of randomness, no matter how well it is generated, you get the noise baggage that comes along with it.

Noise reduction in path tracing is an active area of research in both academics and industry (like NVIDIA RTX). I have implemented a very basic denoiser in my project, so I hope that the noise is not too terrible (as it would be with a raw naive path tracer), but there are new AI-trained denoisers being developed these days that do what you mentioned you wanted in an earlier post - they magically remove most or all of the initial noise. But these are highly sophisticated denoisers and most are proprietary, so unfortunately my project is not at that level yet.

Hope this helps further clarify the double-edged sword of randomness and noise when it comes to physically-accurate rendering. 🙂

Let me know if you have any other questions or concerns. Best of luck! -Erich

JustLexxy commented 2 years ago

Oh wow that explained a lot, thank you! I started learning your path tracing a few weeks ago for work, and my only complain would be that there is no documentation to help learning or to use/implement it, but the examples helped a ton!

erichlof commented 2 years ago

@JustLexxy

Ah yes I don't really have documentation, but I did try to follow three.js when it was just starting out all those years ago, and instead have numerous small, focused examples that showcase different aspects of the renderer that might be useful to different people.

As always, if you are confused by how something works in my project, or ever need any of my examples clarified, please feel free to ask here in this thread if you like. 😊

JustLexxy commented 2 years ago

Yeah the examples were life savers There's a few things that i easily could copy from them, but there's also some features i had to do/research by myself, for example i'm currently working on a small add-on that allows to switch between a scene with path tracing scene and one without (like a sort of on/off), if you're interested i can post it here when it will be done!

erichlof commented 2 years ago

Oh that would be cool! Feel free to post here. Glad the examples were helpful!

dafhi commented 2 years ago

Hey dog. I was wondering if you're aware of bootstrapping. YTube's statquest w/ josh has great vid.

The idea is u have a small-ish Nr of samps, and pick from those at random. I skipped over important details.

another thing for your ridiculously performant renderer - an importance map (per-frame grayscale rgb delta)

ideas combined, bootstrapping top 20% noisiest pixels would .. well its an interesting ide. Ive been out of the programming game for a while but i do still come up w ideas. Bootstrapping is awesome


From: Erich Loftis @.> Sent: Tuesday, July 12, 2022 1:56 PM To: erichlof/THREE.js-PathTracing-Renderer @.> Cc: Subscribed @.***> Subject: Re: [erichlof/THREE.js-PathTracing-Renderer] Blue noise (Issue #69)

@JustLexxyhttps://github.com/JustLexxy

Ah yes I don't really have documentation, but I did try to follow three.js when it was just starting out all those years ago, and instead have numerous small, focused examples that showcase different aspects of the renderer that might be useful to different people.

As always, if you are confused by how something works in my project, or ever need any of my examples clarified, please feel free to ask here in this thread if you like. 😊

— Reply to this email directly, view it on GitHubhttps://github.com/erichlof/THREE.js-PathTracing-Renderer/issues/69#issuecomment-1182492918, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AH4374NFE4AYPPKNQPFJZ3TVTXLWXANCNFSM52TX7TTA. You are receiving this because you are subscribed to this thread.Message ID: @.***>