Generate uniform spherical gaussians on the sphere or hemisphere
| 27 | |
| 28 | // Generate uniform spherical gaussians on the sphere or hemisphere |
| 29 | static void GenerateUniformSGs(SG* sgs, uint64 numSGs) |
| 30 | { |
| 31 | uint64 N = numSGs * 2; |
| 32 | |
| 33 | Assert_(numSGs <= uint64(AppSettings::MaxSGCount)); |
| 34 | |
| 35 | Float3 means[AppSettings::MaxSGCount * 2]; |
| 36 | |
| 37 | float inc = Pi * (3.0f - std::sqrt(5.0f)); |
| 38 | float off = 2.0f / N; |
| 39 | for(uint64 k = 0; k < N; ++k) |
| 40 | { |
| 41 | float y = k * off - 1.0f + (off / 2.0f); |
| 42 | float r = std::sqrt(1.0f - y * y); |
| 43 | float phi = k * inc; |
| 44 | means[k] = Float3(std::cos(phi) * r, std::sin(phi) * r, y); |
| 45 | } |
| 46 | |
| 47 | uint64 currSG = 0; |
| 48 | for(uint64 i = 0; i < N; ++i) |
| 49 | { |
| 50 | // For the sphere we always accept the sample point but for the hemisphere we only accept |
| 51 | // sample points on the correct side of the hemisphere |
| 52 | if(Float3::Dot(means[i].z, Float3(0.0f, 0.0f, 1.0f)) >= 0.0f) |
| 53 | { |
| 54 | SG sample; |
| 55 | sample.Axis = Float3::Normalize(means[i]); |
| 56 | sgs[currSG++] = sample; |
| 57 | } |
| 58 | } |
| 59 | |
| 60 | Float3 h = Float3::Normalize(sgs[1].Axis + sgs[0].Axis); |
| 61 | float sharpness = (std::log(0.65f) * numSGs) / ((Float3::Dot(h, sgs[0].Axis) - 1.0f)); |
| 62 | |
| 63 | for(uint32 i = 0; i < numSGs; ++i) |
| 64 | sgs[i].Sharpness = sharpness; |
| 65 | } |
| 66 | |
| 67 | void InitializeSGSolver(uint64 numSGs) |
| 68 | { |