[video output=day553 member=cmuratori stream_platform=twitch stream_username=handmade_hero project=code title="Improved Sphere Distributions" vod_platform=youtube id=Sln28NSVacQ annotator=Miblo]
[0:01][Recap and set the stage for the day][:speech]
[1:27][Address the "Sphere generator alignment" issue[ref
    site=GitHub
    page="HandmadeHero / cpp / Sphere generator alignment"
    url=https://github.com/HandmadeHero/cpp/issues/110]][:language :metaprogramming]
[3:02][Show off our white noise :sampling sphere][:lighting :run]
[5:54][Blue Noise Slices][:blackboard :sampling :statistics]
[6:55][White noise][:blackboard :sampling :statistics]
[8:47][Blue noise, or Poisson distribution][:blackboard :sampling :statistics]
[10:48][Blue noise as an approximation of real-world tree distributions][:blackboard :sampling :statistics]
[15:19][Blue noise as a limiter (or sampler) of workload, computing the average colour of an intractably huge image][:blackboard :sampling :statistics]
[19:41][Structured–Unknown But Evenly-distributed :sampling continuum][:blackboard :statistics]
[24:59][Sphere :Sampling][:blackboard :statistics]
[31:54][Sphere :Sampling Tuning vs Repulsion][:blackboard :statistics]
[35:33][Sphere :Sampling Slicing][:blackboard :statistics]
[37:27][Make GenerateLightingPattern() apply repulsion to the white noise samples][:lighting :sampling]
[49:14][Distance-based repulsion around a sphere][:blackboard :lighting :sampling]
[50:40][Continue to make GenerateLightingPattern() apply distance-based repulsion to the white noise samples][:lighting :sampling]
[51:20][Hard clipping in purely distance-based repulsion][:blackboard :lighting :sampling]
[52:38][Continue to make GenerateLightingPattern() apply a smooth falloff to the repulsion][:lighting :sampling]
[58:49][Enable GenerateLightingPattern() to track the minimum and maximum distances between samples, to provide an exit condition][:lighting :sampling]
[1:06:23][Step through hhsphere][:lighting :run :sampling]
[1:08:16][Praise ~RemedyBG: The FLT_MAX display][:admin]
[1:08:57][Continue to step through hhsphere][:lighting :run :sampling]
[1:10:11][Fix GenerateLightingPattern() to initialise LastMinClosestPointDistance as 0.0f][:lighting :sampling]
[1:10:45][Step through hhsphere and watch the closest point distances slowly converge][:lighting :run :sampling]
[1:11:28][Increase the MaxDispPerStep in GenerateLightingPattern() to speed up the convergence][:lighting :sampling]
[1:12:02][Step through hhsphere and see the closest point distances converge quickly][:lighting :run :sampling]
[1:12:09][Make GenerateLightingPattern() set the MaxDispPerStep based on MaxClosestPointDistance][:lighting :sampling]
[1:14:29][Step through hhsphere and watch the closest point distances converge][:lighting :run :sampling]
[1:14:50][Decrease the computed MaxDispPerStep in GenerateLightingPattern()][:lighting :sampling]
[1:15:04][Step through hhsphere and watch the closest point distances converge][:lighting :run :sampling]
[1:16:17][@floorislava][RemedyBG 0.2.8.1[ref
    site=RemedyBG
    page="RemedyBG 0.2.8.1"
    url=https://remedybg.handmade.network/forums/t/7034-remedybg_0.2.8.1]]
[1:16:32][Copy handmade_sampling_spheres.inl in to place][:admin]
[1:18:01][Check out our (identical) :sampling sphere][:"debug visualisation" :lighting :run]
[1:20:00][Again copy handmade_sampling_spheres.inl in to place][:admin]
[1:20:20][Check out our wrong-looking :sampling sphere][:"debug visualisation" :lighting :run]
[1:21:22][Scrutinise our repulsion routine in GenerateLightingPattern()][:lighting :research :sampling]
[1:22:30][Prevent GenerateLightingPattern() from zeroing out the Displacement]
[1:23:11][Continue to scrutinise our repulsion routine in GenerateLightingPattern()][:lighting :research :sampling]
[1:23:56][Repulsion around the great arc][:blackboard :lighting :sampling]
[1:25:28][Continue to scrutinise and clean-up our repulsion routine in GenerateLightingPattern()][:lighting :programming :research :sampling]
[1:27:48][Invoke hhsphere overwriting the real handmade_sampling_spheres.inl][:admin :lighting :sampling]
[1:29:14][Make GenerateLightingPattern() print out the sampling directions][:lighting :sampling]
[1:30:52][Invoke hhsphere again and watch the distances converge][:admin :lighting :sampling]
[1:31:45][Make GenerateLightingPattern() track the MinMaxSeparation and bail if it ever increases][:lighting :sampling]
[1:33:34][Step through GenerateLightingPattern() until the MinMaxSeparation increases][:lighting :run :sampling]
[1:34:47][Give GenerateLightingPattern() a more distant exit condition][:lighting :sampling]
[1:35:04][Invoke hhsphere and watch the distances converge][:admin :lighting :sampling]
[1:35:29][Fix GenerateLightingPattern() to set the LastMinMaxSeparation in the correct place][:lighting :sampling]
[1:35:38][Invoke hhsphere and watch the distances supposedly converging][:admin :lighting :sampling]
[1:36:59][Consider how to improve our sample repulsion][:lighting :research :sampling]
[1:38:23][Tangential repulsion][:blackboard :lighting :sampling]
[1:39:35][Make GenerateLightingPattern() tangentially repulse the samples][:lighting :sampling]
[1:40:17][Invoke hhsphere and watch the distances converge][:admin :lighting :sampling]
[1:41:00][Check out our (identical) :sampling sphere][:"debug visualisation" :lighting :run]
[1:42:21][Give GenerateLightingPattern() a yet further distant exit condition][:lighting :sampling]
[1:42:40][Invoke hhsphere and watch the distances converge][:admin :lighting :sampling]
[1:42:56][Give GenerateLightingPattern() a yet further distant exit condition][:lighting :sampling]
[1:43:03][Invoke hhsphere and watch the distances converge][:admin :lighting :sampling]
[1:44:12][Check out our :sampling sphere to see that samples are clearly not equidistant][:"debug visualisation" :lighting :run]
[1:45:23][Fix GenerateLightingPattern() to compute the ForceLineLength before the tangent][:lighting :sampling]
[1:47:13][Invoke hhsphere to see that it struggles to converge][:admin :lighting :sampling]
[1:48:22][Decrease the MaxDispPerStep multiplier to 0.01f in GenerateLightingPattern()][:lighting :sampling]
[1:48:32][Invoke hhsphere to see that it seems to be converging more cleanly][:admin :lighting :sampling]
[1:50:24][Increase the MaxDispPerStep multiplier to 0.025f in GenerateLightingPattern()][:lighting :sampling]
[1:50:36][Invoke hhsphere and watch the distances converge][:admin :lighting :sampling]
[1:51:59][Increase the MaxDispPerStep multiplier to 0.05f in GenerateLightingPattern()][:lighting :sampling]
[1:52:09][Invoke hhsphere to see the distances start to oscillate][:admin :lighting :sampling]
[1:54:06][Make GenerateLightingPattern() exit once the MinMaxSeparation is 0.02f][:lighting :sampling]
[1:54:25][Invoke hhsphere until the distances converge][:admin :lighting :sampling]
[1:54:58][Check out our (still identical) :sampling sphere, to determine that we are possibly measuring or writing out something incorrectly][:"debug visualisation" :lighting :run]
[1:58:30][Q&A][:speech]
[1:58:54][@vaualbus][Q: You use two times the Min]
[1:59:01][Fix typo in the MaxClosestPointDistance computation in GenerateLightingPattern()][:lighting :sampling]
[1:59:14][Invoke hhsphere to see the distances oscillate more wildly][:admin :lighting :sampling]
[1:59:54][Decrease the MaxDispPerStep multiplier to 0.01f in GenerateLightingPattern()][:lighting :sampling]
[2:00:11][Invoke hhsphere and leave it hopefully converging][:admin :lighting :sampling]
[2:00:41][@drzool][Q: When will you start reading chat during the session?]
[2:02:15][Gauge the convergence of our distances][:admin :lighting :sampling]
[2:02:43][@somebody_took_my_name][Q: Could you use a function like gravity and just sum up all the forces applied by all other points, where the force is proportional to the distance squared?][:lighting :sampling]
[2:03:45][@somebody_took_my_name][Q: But it would remove the if statements, right][:lighting :sampling]
[2:04:16][@an0mal0caris][Q: Is something like a golden spiral method too deterministic? I missed the beginning][:lighting :sampling]
[2:05:13][@raulrita][Q: Is there any :"save / load" state of the entire game, e.g. for resume purposes? Serialization?]
[2:06:39][@xrxr13579][Q: How do you measure stalls that happen on a particular memory load? Is it even a good metric to measure?][:profiling]
[2:10:07][@chrysos42][Q: I only caught the end, so I may be misunderstanding. Won't the points get farther and farther from the sphere, since you only normalize at the end?][:lighting :sampling]
[2:10:44][@drzool][Q: What spatial partitioning method would you use on this problem?][:lighting :sampling]
[2:11:43][@worldsigniayt][Q: For a dedicated server using winsockets, how would you send the player data? Is like a JSON serialization possible or should I use other formats to send player / game state to all clients like every x ticks?][:networking]
[2:14:26][@mattiamanzati][Q: Converging to the situation where the closest point max and min distance are similar isn't something like trying to produce a regular solid polygon with N faces and than rotate it by arbitrary angles?][:lighting :sampling]
[2:15:02][Make GenerateLightingPattern() exit once the MinMaxSeparation is 0.03f][:lighting :sampling]
[2:15:16][Invoke hhsphere and leave it converging][:admin :lighting :sampling]
[2:16:56][@vaualbus][Q: On a shipping game you would hard-code the shaders in the game or have it in the asset file?]
[2:18:08][@nitrixen][@handmade_hero Do you have projects that are voxel / octree-based?]
[2:18:21][@mattiamanzati][Q: So another possible implementation would be starting by a regular polygon distribution, and then apply an initial random displacement force and continue simulating, right?][:lighting :sampling]
[2:18:35][Check out our (identical) :sampling sphere][:"debug visualisation" :lighting :run]
[2:19:43][Read through our :sampling sphere drawing code][:"debug visualisation" :lighting :research]
[2:21:14][Consider whether we are seeing 1,000 points][:"debug visualisation" :lighting :run]
[2:21:48][Invoke hhsphere to generate 1 batch of samples][:admin :lighting :sampling]
[2:23:12][Make GenerateLightingPattern() exit once the MinMaxSeparation is 0.08f][:lighting :sampling]
[2:23:43][Check out our sparse samplingd sphere, to see 18 points (not the desired 4 × 18)][:"debug visualisation" :lighting :run :sampling]
[2:26:14][Step in to LightingTest() to see that we have duplicated sampling points][:lighting :run :sampling]
[2:27:36][Force GenerateLightingPattern() to bundle up four consecutive sampling directions before incrementing past them][:lighting :sampling]
[2:29:38][Step in to LightingTest() to see that we now have non-duplicate sampling points][:lighting :run :sampling]
[2:30:27][Check out our more regular sampling sphere][:"debug visualisation" :lighting :run :sampling]
[2:30:43][Add a TODO to determine what the real convergence criteria is][:lighting :sampling]
[2:31:17][Invoke hhsphere to generate our full 16 batches of samples][:admin :lighting :sampling]
[2:31:48][@vaualbus][Q: So maybe C++ was right][:language]
[2:33:09][@xrxr13579][Q: Maybe you can convince [@naysayer88 Jon] to make arguments evaluate left to right in JAI][:language]
[2:34:03][Close the "Sphere generator alignment" issue[ref
    site=GitHub
    page="HandmadeHero / cpp / Sphere generator alignment"
    url=https://github.com/HandmadeHero/cpp/issues/110]][:admin :language :metaprogramming]
[2:34:49][@subspice][@handmade_hero Will you be in the JAI closed beta?][:language]
[2:35:31][Check out our beautiful new sampling sphere][:"debug visualisation" :lighting :run :sampling]
[2:37:53][@sdanna][Q: As you decrease that magic number, does this method converge towards a uniform distribution?][:lighting :sampling]
[2:38:37][Wrap it up][:speech]
[/video]
