Microfacet (RoughGlass) and Multiple Importance Sampling back
Board:
Board index
Raytracing
General Development
(L) [2014/03/20] [tby Chaos] [Microfacet (RoughGlass) and Multiple Importance Sampling] Wayback!Hi,
I'm currently working on some RoughGlass shader implementation, and when trying to 'validate' the MIS, I encountered some problem.
Basically, I take the assumption that when I 'generate' a direction for my bsdf, if I 'evaluate' my bxdf for the same direction, I should get identical values for the pdf and the bsdf response, am I right?
Sadly, the implementation I was looking at doesn't satisfy this assumption. I think this is because in the 'evaluate' method, this implementation never consider the possibility that a given direction could have been generated by a refraction *and* a reflection even. This is similar to what seems to happen in the mitsuba-renderer (can we post direct link to the repos? [LINK https://www.mitsuba-renderer.org/repos/mitsuba/files/88b82d613feb5efac3b89cc7e513c14695a372d6/src/bsdfs/roughdielectric.cpp#L267]). Line 267 implies that only one even was able to generate this direction.
However, when running some render for non-zero roughness, I can confirm there are some cases where for a given set of wi, wo and n, we can find at least one vector h/m (microfacet orientation) for each of the event. Actually it even looks like in certain cases you can find a h/m vector for 1) a reflection, 2) a refraction with eta and 3) another refraction with 1/eta (when the original h/m vector points in the other direction to wi).
Granted, for each of these cases, the bsdf response has previously been clamped (see [LINK https://www.mitsuba-renderer.org/repos/mitsuba/files/88b82d613feb5efac3b89cc7e513c14695a372d6/src/bsdfs/roughdielectric.cpp#L463] and [LINK https://www.mitsuba-renderer.org/repos/mitsuba/files/88b82d613feb5efac3b89cc7e513c14695a372d6/src/bsdfs/roughdielectric.cpp#L478]), but shouldn't we still be taken the probability of generating these cases into account to make sure the MIS will be correct?
Cheers,
Jon
(L) [2014/03/21] [tby ypoissant] [Microfacet (RoughGlass) and Multiple Importance Sampling] Wayback!>> Chaos wrote:... when I 'generate' a direction for my bsdf, if I 'evaluate' my bxdf for the same direction, I should get identical values for the pdf and the bsdf response, am I right?
It depends on the microfacet BRDF model you are implementing. But generally, the pdf and the bsdf are not the same function. The complete BSDF should include the microfacet distribution D, the masking/shadowing function G and some foreshortening factor while the pdf is based on D only plus a transformation from microfacet distribution to a Wo -> Wi distribution. The D function gives the microfacet normal distribution but when sampling the BRDF, the pdf should be w.r.t.Wi because Wi is generated by reflecting Wo on the microfacet normal.
 >> ... the implementation I was looking at doesn't satisfy this assumption. I think this is because in the 'evaluate' method, this implementation never consider the possibility that a given direction could have been generated by a refraction *and* a reflection event. ...
I'm not familiar with Mitsuba. The sited code seems to verify if both Wo and Wi are in the same hemisphere or are both on the same side of the macrosurface. If Wi and Wo are both on the same side of the macrosurface, the direction must have been a reflection while if Wi and Wo are on opposite sides, the direction must have been a refraction. On very rough microfaceet BSDF, it is not uncommon that a reflection direction goes on the other side of the macrosurface but when this hapens, the reflection si absorbed and its pdf is set to 0 because a reflection that goes on the other side of the macrosurface would bounce several times on the microfacets around and exit following a diffuse distribution. So because of that, at this point in the code, if Wi and Wo are found to be on both side of the macrosurface, then it must be a refraction.
Those are my two little cents.
(L) [2014/03/21] [tby Chaos] [Microfacet (RoughGlass) and Multiple Importance Sampling] Wayback!Ah I wasn't clear enough, sorry! I am aware that generally, the pdf and the bxdf response are different. I was asking about the pdf returned by generate() and the pdf returned by evaluate() (same for bsdf response).
The way I understand it, if you were to generate a direction with generate() (getting a direction, a bsdf response and a pdf), you should be able to directly call evaluate() (which would give you a 'new' bsdf response and pdf), and I would expect this to have no effect at all (the values returned by evaluate() should be the same as the one returned by generate()).
 >> On very rough microfaceet BSDF, it is not uncommon that a reflection direction goes on the other side of the macrosurface but when this hapens, the reflection si absorbed and its pdf is set to 0 because a reflection that goes on the other side of the macrosurface would bounce several times on the microfacets around and exit following a diffuse distribution.
But that would require you to actually never generate this direction in the first place, wouldn't it? You would have to reject it and generate another one? In the mitsuba code for example, I can't find where they would actually prevent the generation of such directions (they only set the bsdf response to zero). Note that I'm not familiar with mitsuba either, so maybe later in the code they actually do something akin to that :/
So, if in the end you are still generating this zero-response bsdf, they have to have a non-null pdf, and then the evaluate() has to take this into account. Or, I suppose, you could change the sample generation so that you actually reject these directions and draw a new one, but that may be more complicated when it comes to find the associated pdf?
Cheers,
Jon
(L) [2014/03/21] [tby ypoissant] [Microfacet (RoughGlass) and Multiple Importance Sampling] Wayback!>> Chaos wrote:The way I understand it, if you were to generate a direction with generate() (getting a direction, a bsdf response and a pdf), you should be able to directly call evaluate() (which would give you a 'new' bsdf response and pdf), and I would expect this to have no effect at all (the values returned by evaluate() should be the same as the one returned by generate()).
In theory, that is what I would expect too. But in practice I found that the microfacet sampling mechanism is not perfect especially near grazing angles and that there is a need to introduce a "renormalizing hack" somewhere. And since we don't want to mess with the pdf because of issues this might introduce with MIS, then the "renormalization" is better done on the bsdf response. Maybe, this is a similar renormalization effect that you are observing?
Note that I'm a practitioner. Not a theoretician. But I had a fair share of fights with microfacet BSDF implementations so I have a few opinions.
 >> But that would require you to actually never generate this direction in the first place, wouldn't it? You would have to reject it and generate another one?
With the way Wi directions are generated in the microfacet model, there are no ways you can "never generate this direction in the first place". Those directions will be generated for sure and the question is what to do with them. Setting their pdf to 0 means that they are rejected and we just wait for another direction to be eventually generated. Regenerating another direction in-situ is something I tried and didn't work too well. The intuitive reason why it doesn't work is because it changes the distribution. It actually generates more rays in the region above the surface than it should but the pdf does not reflect that.
 >> So, if in the end you are still generating this zero-response bsdf, they have to have a non-null pdf, and then the evaluate() has to take this into account.
I agree. However, this is, in itself, a good subject of research IMO.
Simply not accounting for those directions means that some energy is lost. And this is recognized as one of the many limitations of the microfacet model.
When observing the behavior of several MERL BRDF, it is clear that some energy is scattered in a different ways than the glossy lobe of the microfacet models. This other scattering component have different forms: diffuse, backscattering, subsurface scattering, Oren-Nayar kind of scattering, and other more exotic scattering patterns. The microfacet BRDF is incomplete in the sense that it only models the glossy component.
 >> Or, I suppose, you could change the sample generation so that you actually reject these directions and draw a new one, ...
If the rejected directions were recuperated and new directions generated, then those new directions should be taken from this other scattering component distribution. Not from the same microfacet distribution. This sample direction must transport with itself the fact that it was taken from a different distribution so that the bsdf response is also from this other distribution.
This is an idea I've been toying with for a while but so far haven't had the time to implement and try. Would this work?
 >> ... but that may be more complicated when it comes to find the associated pdf?
Exactly.
Although, maybe not that complicated. My idea is use the microfacet distribution pdf for directions generated and accepted from microfacet generation and use diffuse (for example) pdf for the other rays that were rejected and regenerated from the diffuse distribution. Their respective weights implicitly come from the acceptance vs rejection mechanism.
Note that there are other nooks with the microfacet selection mechanism. Sometime the selected microfacet if on the wrong side of Wo. The usual trick in this case is to select the facing microfacet by flipping the microfacet normal. But this biases the microfacet distribution toward the microfacets facing the Wo direction and can become troublesome for primary rays from the camera. To correct that the generated or the facing microfacet must be probabilistically selected and weighted when both are visible to Wo.
(L) [2014/03/23] [tby ypoissant] [Microfacet (RoughGlass) and Multiple Importance Sampling] Wayback!>> ypoissant wrote:Although, maybe not that complicated. My idea is use the microfacet distribution pdf for directions generated and accepted from microfacet generation and use diffuse (for example) pdf for the other rays that were rejected and regenerated from the diffuse distribution. Their respective weights implicitly come from the acceptance vs rejection mechanism.
Thinking about this some more, the above would work for the SampleBSDF function but not for the EvaluateBSDF function. The EvaluateBSDF function still needs a function that provides the probability that for given roughness, Wo and Wi, what is the proportion of the reflectance that comes from the glossy lobe vs the diffuse lobe. Essentially, this proportion is the proportion of Wi that falls over vs under the macrosurface, or
Integrate(D(alpha, Wo, Wi+) N.dot.M / (4 M.dot.Wo)) / Integrate(D(alpha, Wo, Wi) N.dot.M / (4 M.dot.Wo))
where Wi+ is the set of all Wi above the macrosurfce ie N.dot.Wi > 0
(L) [2014/03/24] [tby Chaos] [Microfacet (RoughGlass) and Multiple Importance Sampling] Wayback!Hi,
I'm still struggling to have my microfacets working together, but it may be that I'm too picky...
One thing I was reluctant to do is generating zero-pdf directions from the equivalent to bsdf->sample() method, because in my mind, it didn't make sense to generate a direction with a zero pdf (if you generate it, then surely its pdf is not zero) and/or simply fail to generate (since the next time you will manage to generate a direction). But that is probably because I'm using Pixar's Renderman plausible shading framework, which I think doesn't always work really well with zero-pdf samples [SMILEY :)]
Second, I was explained that to avoid the need to cross-evaluate reflection and refractions for some directions, some implementations actually force the following: reflections can only generate samples on the same hemisphere as w_i, where refractions can only generate samples on the opposite hemisphere to w_o. They then set non-compliant samples to 'invalid' (it depends on the integrator what is considered invalid, I suppose in most cases pdf = 0 is enough). This solves the issue of generating a reflected sample on a far-from-the-normal-microfacet, that ends up on the other side of the hemisphere. I still feel its weird, but I clearly haven't spend enough time on this topic yet.
I was also able to find cases where, for a given couple (w_i, w_o), there can be *two* microfacet orientations, both valid (i.e. H.N > 0), one with using 'eta' (because H_a . w_i > 0), the second one using '1/eta' (because H_b . w_i < 0). For me, this would mean that when computing the pdf associated with (w_i,w_o), you need to consider both events and add up their individual probabilities (and contributions), which I haven't seen done yet. At the same time, since no one does it, it is probably not a big issue [SMILEY :)]
About the management of 'wrong' directions, I was actually thinking about the following: why not consider that a 'wrong' reflection, reflected toward the surface (w_i . N > 0, H . N > 0, w_i . N > 0, but w_o . N < 0) is actually a new w_i_bis, and apply the microfacet model again? Since microfacet models are probabilistic models, considering the behaviour of a bunch of micro-facets, why not consider a recursive interpretation? Of course, that is exponentially costly, and I have no idea how to evaluate the probabilities for a given (w_i,w_o)! I suppose that as soon as you convolve two models in that way, you need to compute integrals everytime indeed, which may not be practical for many models...
Cheers,
Jonathan
(L) [2014/03/24] [tby ypoissant] [Microfacet (RoughGlass) and Multiple Importance Sampling] Wayback!>> Chaos wrote:One thing I was reluctant to do is generating zero-pdf directions from the equivalent to bsdf->sample() method, because in my mind, it didn't make sense to generate a direction with a zero pdf (if you generate it, then surely its pdf is not zero) and/or simply fail to generate (since the next time you will manage to generate a direction).
Indeed, if the direction is generated, then it does have a pdf. That is the pdf function will return a value. Setting its pdf to zero is only a mean to have this direction rejected (not being considered).
 >> But that is probably because I'm using Pixar's Renderman plausible shading framework, which I think doesn't always work really well with zero-pdf samples
That could be a problem. When we write our own renderer, then we can decide to ignore directions with zero pdf. But if the Pixar Framework don't know that zero pdf direction should be ignored and tries to use them anyway, then this could cause issues.
 >> About the management of 'wrong' directions, I was actually thinking about the following: why not consider that a 'wrong' reflection, reflected toward the surface (w_i . N > 0, H . N > 0, w_i . N > 0, but w_o . N < 0) is actually a new w_i_bis, and apply the microfacet model again? Since microfacet models are probabilistic models, considering the behaviour of a bunch of micro-facets, why not consider a recursive interpretation? Of course, that is exponentially costly, and I have no idea how to evaluate the probabilities for a given (w_i,w_o)! I suppose that as soon as you convolve two models in that way, you need to compute integrals everytime indeed, which may not be practical for many models...
I also considered re-reflecting a penetrating ray on other microfacets until it gets out. But decided upfront that this would be too expensive both in render time and in R&D time. For most realistic material, the extinction would happen rather quickly and all this bouncing work would be done for nothing.
(L) [2014/03/25] [tby ypoissant] [Microfacet (RoughGlass) and Multiple Importance Sampling] Wayback!Since you are using Pixar Renderman Framework, Are you aware of the following resources:
[LINK http://blog.selfshadow.com/publications/s2013-shading-course/]
In particular the course notes "Physically Based Shading at Pixar"
And in Pixar RPS documentation:
[LINK http://renderman.pixar.com/resources/current/rps/physicallyPlausibleShadingInRSL.html]
(L) [2014/03/25] [tby Chaos] [Microfacet (RoughGlass) and Multiple Importance Sampling] Wayback!Hi,
I have been working with prman RSL for some years now, so I know about these [SMILEY :)] Sadly, there are many many many subtleties at all levels in prman, so generally the documentation will be lacking, if you're encountering a non-trivial issue.
To be fair, plausible shading works nicely, but edge cases fail hard. Most of it is due to the RSL particularities (uniform vs. varying). The provided integrator actually manage zero-pdf, provided they are not too exotic (i.e. if using multiple lobes, they have to generate a 'uniform' number of samples, some of them can be zero, but you can't have 'zero-pdf' in the middle of the array section for a given lobe for example....). Lots of fun :p
I am still struggling to get my micro facet working, and I'm starting to despair now ^^' For some reason, light sampling and brdf sampling work nicely for the direct reflection, but not for direct refraction ><. However, for the direct refraction, when I use brdf sampling (->sample()) *and* evaluate the brfd (->eval() / ->f()), then it's working! So clearly, the eval() method is not completely wrong...
(L) [2014/03/25] [tby ypoissant] [Microfacet (RoughGlass) and Multiple Importance Sampling] Wayback!And also the paper by Walter et al "Microfacet Models for Refraction through Rough Surfaces"
[LINK https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.html]
Since you are doing refraction through microfacet BSDF, this seems to be exactly the same situation.
back