Thread: [Algorithms] Undershooting in spherical harmonics generated by cubemap convolution
Brought to you by:
vexxed72
|
From: Alen L. <ale...@cr...> - 2009-04-28 07:30:55
|
Hi all, When generating 2nd order SHs by convolving environment cubemaps, In some rare cases I get some strange artefacts that seem as if that is just a limitation of 2nd order SHs, but I'm not sure, so I figured I'd ask... The problematic case is where there is only a handful of very bright (~2000x the cubemap average) pixels in one narrow direction (~0.5 deg). (This example is generated by a sun disk in the skies, when seen through a small window in a dark room). In this case I get large undershooting (manifesting as a black spot) in some other direction. Depending on the bright direction, the black spot is sometimes on the opposite side, but sometimes it is e.g. 90 or 135 degrees from the bright side, etc. I was expecting to see something like this in the exact opposite direction, but I'm a bit surprised to see it move around. Then again, I'm not an SH expert, so I'm probably wrong. So to ask a concrete question: Is it normal for SH approximation errors in such "spiky" cases to generate undershooting in directions that are not directly opposite to the brightest point? Thanks, Alen |
|
From: Sam M. <sam...@ge...> - 2009-04-28 09:10:53
|
Hi Alan, SH can suffer from ringing and that really bright sun isn't going to help, but there's a myriad of other things that can go wrong and produce the same problems. Ringing is usually less of a problem for representing irradiance as its low frequency (as opposed to radiance or visibility). >From your description it sounds like you could well have other problems so it's worth ruling those out first. Some suggestions on things to check: - Check your maths and implementation to make sure your coeffs are scaled appropriately. It can be helpful to project cube maps with the single SH basis elements in them to ensure you get the coeffs out you expect and at the right scale. - Check you are including the scaling for the cosine convolution. If you are missing it your L2 SH will be too bright and can produce this kind of artefact. - Check for bugs by testing the rotational invariance. Ie. rotate your cube map and ensure the projection rotates as expected. I guess you could also test a known cubemap + SH coeffs to compare your output with other peoples? Hope that helps, Sam -----Original Message----- From: Alen Ladavac [mailto:ale...@cr...] Sent: 28 April 2009 08:31 To: Game Development Algorithms Subject: [Algorithms] Undershooting in spherical harmonics generated bycubemap convolution Hi all, When generating 2nd order SHs by convolving environment cubemaps, In some rare cases I get some strange artefacts that seem as if that is just a limitation of 2nd order SHs, but I'm not sure, so I figured I'd ask... The problematic case is where there is only a handful of very bright (~2000x the cubemap average) pixels in one narrow direction (~0.5 deg). (This example is generated by a sun disk in the skies, when seen through a small window in a dark room). In this case I get large undershooting (manifesting as a black spot) in some other direction. Depending on the bright direction, the black spot is sometimes on the opposite side, but sometimes it is e.g. 90 or 135 degrees from the bright side, etc. I was expecting to see something like this in the exact opposite direction, but I'm a bit surprised to see it move around. Then again, I'm not an SH expert, so I'm probably wrong. So to ask a concrete question: Is it normal for SH approximation errors in such "spiky" cases to generate undershooting in directions that are not directly opposite to the brightest point? Thanks, Alen ------------------------------------------------------------------------ ------ Register Now & Save for Velocity, the Web Performance & Operations Conference from O'Reilly Media. Velocity features a full day of expert-led, hands-on workshops and two days of sessions from industry leaders in dedicated Performance & Operations tracks. Use code vel09scf and Save an extra 15% before 5/3. http://p.sf.net/sfu/velocityconf _______________________________________________ GDAlgorithms-list mailing list GDA...@li... https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list Archives: http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-lis t |
|
From: Alen L. <ale...@cr...> - 2009-04-28 12:24:50
|
Fabian wrote at 4/28/2009:
> The second order SH basis functions aren't (and their symmetries are
> rotations by multiplies of 90 degrees, not 180, around the Z axis),
> so you'll get undershooting in other places too.
That makes sense. Thanks!
Sam wrote at 4/28/2009:
> - Check your maths and implementation to make sure your coeffs are
> scaled appropriately. It can be helpful to project cube maps with the
> single SH basis elements in them to ensure you get the coeffs out you
> expect and at the right scale.
Do you mean to generate a cubemap by evaluating SHs with synthetic
values like (1, 0, 0,..., 0) and see if they transform back to
themselves? Sounds interesting. Will have to try that.
> - Check you are including the scaling for the cosine convolution. If you
> are missing it your L2 SH will be too bright and can produce this kind
> of artefact.
Hm, the current result seems to be of correct brightness so perhaps,
that is not it. When integrating across a cubemap, I use these
coefficients:
static const FLOAT c[5] = {
0.282095f*0.282095f * 1.0f,
0.488603f*0.488603f * 2.0f/3.0f,
1.092548f*1.092548f * 1.0f/4.0f,
0.315392f*0.315392f * 1.0f/4.0f,
0.546274f*0.546274f * 1.0f/4.0f
};
in these equations:
FLOAT SHC[9] = {
c[0],
c[1] * v.x,
c[1] * v.y,
c[1] * v.z,
c[2] * v.x * v.z,
c[2] * v.z * v.y,
c[2] * v.y * v.x,
c[3] * (3.0f* v.z*v.z -1.0f),
c[4] * (v.x*v.x - v.y*v.y)
}
integrated over the cube and additionally weight each pixel by
differential angle expressed as R^(-3/2) (to compensate for the cube
shape).
When approximating just one directional light, I use these
coefficients:
static const FLOAT c[5] = {
0.282095f*0.282095f * PI*16.0f/17.0f * 1.0f,
0.488603f*0.488603f * PI*16.0f/17.0f * 2.0f/3.0f,
1.092548f*1.092548f * PI*16.0f/17.0f * 1.0f/4.0f,
0.315392f*0.315392f * PI*16.0f/17.0f * 1.0f/4.0f,
0.546274f*0.546274f * PI*16.0f/17.0f * 1.0f/4.0f
}
But that is just a fixed multiplier for all coeficients, and that
should be covered as the current brightness seems correct (testing
with simple blue/red cubemaps etc.)
> - Check for bugs by testing the rotational invariance. Ie. rotate your
> cube map and ensure the projection rotates as expected.
Checked, seems correct.
> I guess you could also test a known cubemap + SH coeffs to compare your
> output with other peoples?
Sounds like a good idea. Do you know of any such examples? Google
didn't find anything useful.
Thanks,
Alen
|
|
From: Sam M. <sam...@ge...> - 2009-04-28 13:22:13
|
Hi Alen, > Do you mean to generate a cubemap by evaluating SHs with synthetic > values like (1, 0, 0,..., 0) and see if they transform back to > themselves? Sounds interesting. Will have to try that. Yep, exactly. You can turn this into a proper unit test. > Hm, the current result seems to be of correct brightness so perhaps, > that is not it. Worth noting that the overall brightness is controlled by just the L0 (ambient) value. The others all integrate to zero and just 'add shape' to the signal. So it's possible to get the ambient value correct and the others wrong. If they are too low in general the lighting will be too directionless. If they are too high you exaggerate the shape (and ringing). Btw, if it does turn out to be ringing, the easiest way to reduce this is to simply scale down the L1 and L2 terms :). > When integrating across a cubemap, I use these > coefficients: Off the top of my head, these look ok - the cosine term is the rational on the right hand side. I note they are identical to the Ramamoorthi paper: http://graphics.stanford.edu/papers/envmap/. Did you learn about SH through a different paper to this? If so I'd recommend reading the Ramamoorthi paper in some detail. For one, I just noticed it happens to have some numerical SH values in it for Paul Debevec's light probes, which you can grab online. Cheers, Sam -----Original Message----- From: Alen Ladavac [mailto:ale...@cr...] Sent: 28 April 2009 13:25 To: Sam Martin; Fabian Giesen Cc: Game Development Algorithms Subject: Re: [Algorithms] Undershooting in spherical harmonics generated bycubemap convolution Fabian wrote at 4/28/2009: > The second order SH basis functions aren't (and their symmetries are > rotations by multiplies of 90 degrees, not 180, around the Z axis), > so you'll get undershooting in other places too. That makes sense. Thanks! Sam wrote at 4/28/2009: > - Check your maths and implementation to make sure your coeffs are > scaled appropriately. It can be helpful to project cube maps with the > single SH basis elements in them to ensure you get the coeffs out you > expect and at the right scale. Do you mean to generate a cubemap by evaluating SHs with synthetic values like (1, 0, 0,..., 0) and see if they transform back to themselves? Sounds interesting. Will have to try that. > - Check you are including the scaling for the cosine convolution. If you > are missing it your L2 SH will be too bright and can produce this kind > of artefact. Hm, the current result seems to be of correct brightness so perhaps, that is not it. When integrating across a cubemap, I use these coefficients: static const FLOAT c[5] = { 0.282095f*0.282095f * 1.0f, 0.488603f*0.488603f * 2.0f/3.0f, 1.092548f*1.092548f * 1.0f/4.0f, 0.315392f*0.315392f * 1.0f/4.0f, 0.546274f*0.546274f * 1.0f/4.0f }; in these equations: FLOAT SHC[9] = { c[0], c[1] * v.x, c[1] * v.y, c[1] * v.z, c[2] * v.x * v.z, c[2] * v.z * v.y, c[2] * v.y * v.x, c[3] * (3.0f* v.z*v.z -1.0f), c[4] * (v.x*v.x - v.y*v.y) } integrated over the cube and additionally weight each pixel by differential angle expressed as R^(-3/2) (to compensate for the cube shape). When approximating just one directional light, I use these coefficients: static const FLOAT c[5] = { 0.282095f*0.282095f * PI*16.0f/17.0f * 1.0f, 0.488603f*0.488603f * PI*16.0f/17.0f * 2.0f/3.0f, 1.092548f*1.092548f * PI*16.0f/17.0f * 1.0f/4.0f, 0.315392f*0.315392f * PI*16.0f/17.0f * 1.0f/4.0f, 0.546274f*0.546274f * PI*16.0f/17.0f * 1.0f/4.0f } But that is just a fixed multiplier for all coeficients, and that should be covered as the current brightness seems correct (testing with simple blue/red cubemaps etc.) > - Check for bugs by testing the rotational invariance. Ie. rotate your > cube map and ensure the projection rotates as expected. Checked, seems correct. > I guess you could also test a known cubemap + SH coeffs to compare your > output with other peoples? Sounds like a good idea. Do you know of any such examples? Google didn't find anything useful. Thanks, Alen |
|
From: Alen L. <ale...@cr...> - 2009-05-05 08:56:30
|
Sam wrote at 4/28/2009: >> Do you mean to generate a cubemap by evaluating SHs with synthetic >> values like (1, 0, 0,..., 0) and see if they transform back to >> themselves? Sounds interesting. Will have to try that. > Yep, exactly. You can turn this into a proper unit test. Unfortunately, it seems that this is not a correct test for my case. Perhaps I haven't specifically mentioned a "slight" detail: this used to specify diffuse radiance, not irradiance. As this includes the cosine term, I believe that such two-way transformation is not possible. Right? Alen |
|
From: Sam M. <sam...@ge...> - 2009-05-05 12:10:13
|
Hi Alen, I'm not quite sure what you mean by diffuse radiance? There are roughly 3 diffuse values that I think about: - incoming radiance (ie. an environment cube map) - irradiance (ie. a blurry cube map: the radiance convolved with the cosine) - exit radiance (ie. irradiance multiplied by the surface albedo) I definitely left off those details in my email :) If you start with a SH function in a cube map (say, an L1 term), "do your thing" to get it into SH, and then regenerate a cube map (or similar) from your generated SH data you can still check whether it's correct as the end result should just be a scaled version of the original. The scaling should depend on which of the 3 of the above you are working with in the "do your thing" step. If it's radiance it should be exactly the same, if it's irradiance it should be scaled by the cosine terms (see the ramamoorthi paper) and if it's exit radiance it'll be the irradiance * albedo. Even if you ignore scaling you should still be able to check that if you put a single SH term in you get a single SH term back - all other terms should remain 0. Cheers, Sam -----Original Message----- From: Alen Ladavac [mailto:ale...@cr...] Sent: Tue 05/05/2009 09:56 To: Sam Martin Cc: Game Development Algorithms Subject: Re: [Algorithms] Undershooting in spherical harmonics generated bycubemap convolution Sam wrote at 4/28/2009: >> Do you mean to generate a cubemap by evaluating SHs with synthetic >> values like (1, 0, 0,..., 0) and see if they transform back to >> themselves? Sounds interesting. Will have to try that. > Yep, exactly. You can turn this into a proper unit test. Unfortunately, it seems that this is not a correct test for my case. Perhaps I haven't specifically mentioned a "slight" detail: this used to specify diffuse radiance, not irradiance. As this includes the cosine term, I believe that such two-way transformation is not possible. Right? Alen |
|
From: Alen L. <ale...@cr...> - 2009-05-05 13:56:47
|
Sam wrote at 5/5/2009: > I'm not quite sure what you mean by diffuse radiance? Eh, sorry. This radiometry terminology always gets somehow mixed up in my head. :) I was refering to irradiance, whereas I think that method of testing would work e.g. for incoming radiance. > If you start with a SH function in a cube map (say, an L1 term), > "do your thing" to get it into SH, and then regenerate a cube map > (or similar) from your generated SH data you can still check whether > it's correct as the end result should just be a scaled version of > the original. The scaling should depend on which of the 3 of the > above you are working with in the "do your thing" step. Am I wrong to think that the difference is not just a scaler in some of those cases? When trying to get irradiance SH from a cubemap which represents radiance, I'm convolving not just by the SH, but also by clamped cosine. When convolving with cosine, I'm effectively generating a "blurry" SH from a "non-blurry" cubemap. Converting that "blurry" SH into a cubemap will generate a "blurry" cubemap, which cannot be easily compared to the "non-blurry" original (save for doing O(P^2) convolution in the cubemap space and comparing to that). I'm not very proficient with SHs, so it's all a bit hand-wavy on my side, but... Such test passes if I use the c0-c4 coefficients as intended for irradiance (without the 2/3 and 1/4 parts), but not if I use the coefficients that incorporate cosine convolution (those with 2/3 and 1/4). This leads me to believe that my hunch makes sense. Granted, I could generate a cubemap from synthetic SHs, convolve them back and check that the result is exactly different by the 2/3 and 1/4 factors in the correct places. But I fear it kind of defeats the purpose of testing. > If it's radiance it should be exactly the same, if it's irradiance > it should be scaled by the cosine terms (see the ramamoorthi paper) > and if it's exit radiance it'll be the irradiance * albedo. > Even if you ignore scaling you should still be able to check that if > you put a single SH term in you get a single SH term back - all > other terms should remain 0. That passes. But it seems like (and is intuitive to be that way) this kind of test covers only existence of correct x/y/z powers in the polynomials. Putting any coefficients in front passes the test. (E.g. if c0-c4 are all 1, this test passes.) Or am I missing something? In general I'd be very happy if I could test whether the convolution actually generates SHs that are equivalent (to within approximation error) to the source cubemap _with_ cosine term already included. I guess there is no other way than to convolve the old-fashioned way? Thanks, Alen |
|
From: Sam M. <sam...@ge...> - 2009-05-06 16:41:13
|
Hi Alen, <snip> Am I wrong to think that the difference is not just a scaler in some of those cases? When trying to get irradiance SH from a cubemap which represents radiance, I'm convolving not just by the SH, but also by clamped cosine. When convolving with cosine, I'm effectively generating a "blurry" SH from a "non-blurry" cubemap. Converting that "blurry" SH into a cubemap will generate a "blurry" cubemap, which cannot be easily compared to the "non-blurry" original (save for doing O(P^2) convolution in the cubemap space and comparing to that). </snip> It really is just a scalar - this is one of the very cool things about SH. When represented in SH, the blurry version is just a scaled version of the non-blurry version. This is true when convolving against any radially symmetric function. The radially symmetic bit effectively means the result doesn't depend on the m-components of the function, and turns into just one scalar for each L. Incidentally, the fact all the odd bands from L3 upwards disappear is the main proof you can't invert this convolution - it does actually lose information. You should think of the L-bands in SH as frequencies. When you convolve with the clamped cosine you remove a load of high frequencies - but not all due to the presence of the clamp. So when you blur your SH version of the cubemap all you need to do is scale the frequencies appropriately. (This scaling is the A terms in the paper). <snip> That passes. But it seems like (and is intuitive to be that way) this kind of test covers only existence of correct x/y/z powers in the polynomials. Putting any coefficients in front passes the test. (E.g. if c0-c4 are all 1, this test passes.) Or am I missing something? </snip> Providing you test each coefficient in isolation, sure, it only tests that something else isn't getting into your code causing 'talk' between the coefficients. Testing you haven't made a mistake with the scaling is harder. Cheers, Sam |
|
From: Alen L. <ale...@cr...> - 2009-05-07 10:50:35
|
Sam wrote at 5/6/2009: > It really is just a scalar - this is one of the very cool things > about SH. When represented in SH, the blurry version is just a > scaled version of the non-blurry version. This is true when > convolving against any radially symmetric function. The radially > symmetic bit effectively means the result doesn't depend on the > m-components of the function, and turns into just one scalar for > each L. Ah, scalar _per band_! Yes, that makes sense. I originally thought you ment scaling all the factors by the same scalar, which sounded weird. > You should think of the L-bands in SH as frequencies. Indeed. I somehow skipped over that part. It makes the whole concept much easier to digest. :) Thanks, Alen |
|
From: Jarkko L. <al...@gm...> - 2009-05-07 11:52:10
|
FWIW, radially symmetric SH is called zonal harmonics. Cheers, Jarkko -----Original Message----- From: Alen Ladavac [mailto:ale...@cr...] Sent: Thursday, May 07, 2009 1:50 PM To: Sam Martin Cc: Game Development Algorithms Subject: Re: [Algorithms] Undershooting in spherical harmonics generatedbycubemap convolution Sam wrote at 5/6/2009: > It really is just a scalar - this is one of the very cool things > about SH. When represented in SH, the blurry version is just a > scaled version of the non-blurry version. This is true when > convolving against any radially symmetric function. The radially > symmetic bit effectively means the result doesn't depend on the > m-components of the function, and turns into just one scalar for > each L. Ah, scalar _per band_! Yes, that makes sense. I originally thought you ment scaling all the factors by the same scalar, which sounded weird. > You should think of the L-bands in SH as frequencies. Indeed. I somehow skipped over that part. It makes the whole concept much easier to digest. :) Thanks, Alen ---------------------------------------------------------------------------- -- The NEW KODAK i700 Series Scanners deliver under ANY circumstances! Your production scanning environment may not be a perfect world - but thanks to Kodak, there's a perfect scanner to get the job done! With the NEW KODAK i700 Series Scanner you'll get full speed at 300 dpi even with all image processing features enabled. http://p.sf.net/sfu/kodak-com _______________________________________________ GDAlgorithms-list mailing list GDA...@li... https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list Archives: http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list |
|
From: Fabian G. <f.g...@49...> - 2009-04-28 09:16:49
|
Hi Alen, > So to ask a concrete question: Is it normal for SH approximation > errors in such "spiky" cases to generate undershooting in directions > that are not directly opposite to the brightest point? If you look at the basis functions for l=2: http://web.uniovi.es/qcg/harmonics/harmonics.html you should see what's going on. For first order SH, you will indeed only get undershooting in the opposite direction, since all the functions are point-symmetric around zero. The second order SH basis functions aren't (and their symmetries are rotations by multiplies of 90 degrees, not 180, around the Z axis), so you'll get undershooting in other places too. Kind regards, -Fabian Giesen |