[video output=day652 member=cmuratori stream_platform=twitch stream_username=handmade_hero  project=code title="Stochastic Ray Origins" vod_platform=youtube id=SuvSMkf9-i8 annotator=Miblo]
[0:00][Recap and set the stage for the day handling light emitters overlapping light probes][:lighting :speech]
[2:41][@comrademaria][Q: Scene is wrong]
[3:01][Illustrate our overlapped light emitter-probe dimming bug][:lighting :run]
[3:56][Note how FullCast() doesn't cast rays from overlapped light probes][:lighting :research]
[4:28][Toggle on DebugDrawOctahedralValues() and DebugDrawSpatialGrid() in UpdateLighting()][:"debug visualisation" :lighting]
[4:49][Illustrate our overlapped light emitter-probe dimming bug][:"debug visualisation" :lighting :run]
[8:12][Possible overlapped emitter-probe solutions: 1. Rasterise light into overlapped probes as a pre-pass][:"debug visualisation" :lighting :run]
[10:52][Possible overlapped emitter-probe solutions: 2. Jitter sampling locations][:"debug visualisation" :lighting :run]
[11:12][Possible overlapped emitter-probe solutions: 3. Disallow overlapping of emitters and probes][:"debug visualisation" :lighting :run]
[13:51][Consider how to handle overlapped light emitters and probes, admiring our specular lighting][:"debug visualisation" :lighting :run]
[17:06][Toggle off DebugDrawOctahedralValues() and DebugDrawSpatialGrid() in UpdateLighting()][:"debug visualisation" :lighting]
[17:14][Consider trying jittering the sampling locations][:lighting :run]
[18:52][Possible overlapped emitter-probe solutions: 4. Permit rays to hit geometry they're inside of][:"debug visualisation" :lighting :research]
[19:54][Reacquaint ourselves with the intersection testing code in GridRayCast()][:lighting :research]
[23:54][Let GridRayCast() cast rays from inside everything][:lighting]
[24:19][Embedded probes now see light][:lighting :run]
[25:19][Enable GridRayCast() to track if a light probe was inside geometry][:lighting]
[26:56][Embedded probes still see light][:lighting :run]
[27:51][Toggle on DebugDrawOctahedralValues() in UpdateLighting()][:"debug visualisation" :lighting]
[27:59][Light probes do not gather light from overlapping emitters][:"debug visualisation" :lighting :run]
[28:28][Our light probe's rays must be hitting the overlapping emitter][:lighting :research]
[29:36][@psarokroketa][That tInside variable doesn't seem to be used, in case you assume it is?][:lighting]
[29:53][Investigate why GridRayCast() doesn't light up our overlapped light probe][:lighting :research]
[33:23][Make GridRayCast() clamp the tMin to 0 and above][:lighting]
[34:29][Light probes gather light from overlapping emitters, but too brightly][:"debug visualisation" :lighting :run]
[36:07][Toggle on room lights in StandardLightingPattern()][:lighting :"procedural generation"]
[36:26][We happily lack light bleed][:lighting :run]
[37:08][Comment tInside as intentionally not used in GridRayCast()][:lighting]
[38:24][Note our overly bright eclipsed probes, also with square artifacting][:lighting :run]
[41:44][Consider jittering light ray origins in X and Y][:lighting :research]
[43:36][Weld FullCast() and GridRayCast() together][:lighting]
[46:38][We :run just as before][:lighting]
[46:54][Toggle off DebugDrawOctahedralValues() in UpdateLighting()][:"debug visualisation" :lighting]
[47:05][Consider jittering light ray origins in X and Y][:lighting :run]
[47:45][Rename Pick to DebugPick in FullCast()][:lighting]
[49:57][Determine to jitter light ray origins in X and Y][:lighting :run]
[50:47][Make FullCast() jitter light ray origins in X and Y][:lighting]
[52:45][Our :lighting system is still doing something][:run]
[53:35][Make FullCast() keep jittered rays within their original tile][:lighting]
[54:55][Our :lighting looks a little wrong][:run]
[55:42][Consider how to proceed][:lighting :research]
[56:53][Reduce the JitterRadius in FullCast()][:lighting]
[57:04][We have a little bit of light bleed][:lighting :run]
[58:06][Consider what could be wrong with the jittered :lighting][:run]
[59:08][@steadygoa][Not backface culling rays][:lighting]
[59:38][Enable GRID_RAY_CAST_DEBUGGING][:lighting]
[1:00:12][Our debug overlay is now over-bright][:lighting :run :ui]
[1:00:32][Our ray casting isn't obviously wrong][:"debug visualisation" :lighting :run]
[1:01:52][Make FullCast() draw our ray's starting location][:"debug visualisation" :lighting]
[1:02:56][Check out a ray's starting locations][:"debug visualisation" :lighting :run]
[1:04:33][Change FullCast() to clamp the tRay to 0 as tClampedCompare, to retain the negatives][:lighting]
[1:06:32][Our embedded ray casting looks technically correct][:"debug visualisation" :lighting :run]
[1:08:47][The jittering looks okay, but doesn't behave well when moving between probes][:lighting :run]
[1:10:55][@steadygoa][It looks like water reflecting light rays][:lighting]
[1:11:29][Make SampleLighting() use a pure diffuse material][:lighting]
[1:11:34][Demo our pure diffuse light][:lighting :run]
[1:12:01][Make SampleLighting() use a pure specular material][:lighting]
[1:12:08][Demo our pure specular light][:lighting :run]
[1:13:12][Make SampleLighting() use a half-and-half specular / diffuse material][:lighting]
[1:13:25][Demo our half-and-half specular / diffuse light][:lighting :run]
[1:14:01][Illustrate our square artifacting around overlapped light probes][:lighting :run]
[1:15:07][Make AddPlayer() shrink the glove's light from 0.5 to 0.25][:lighting :"procedural generation"]
[1:15:52][Our glove's smaller light almost disappears][:lighting :run]
[1:17:25][Make AddPlayer() brighten the glove's light from 0.2 to 0.5][:lighting :"procedural generation"]
[1:17:32][Our glove's smaller but brighter light still almost disappears][:lighting :run]
[1:20:25][Make AddPlayer() enlarge the glove's light from 0.25 to 2][:lighting :"procedural generation"]
[1:20:39][Our glove's larger light works][:lighting :run]
[1:21:06][Make AddPlayer() darken the glove's light from 0.5 to 0.125][:lighting :"procedural generation"]
[1:21:29][Our glove's larger and darkened light looks just right][:lighting :run]
[1:21:58][Make AddPlayer() darken the glove's light from 0.125 to 0.05][:lighting :"procedural generation"]
[1:22:07][Our glove's larger and darkened light looks as expected][:lighting :run]
[1:23:53][Make AddPlayer() shrink the glove's light from 2 to 1, and brighten it from 0.05 to 0.1][:lighting :"procedural generation"]
[1:24:08][Our glove's light remains][:lighting :run]
[1:25:12][Make AddPlayer() shrink the glove's light from 1 to 0.5][:lighting :"procedural generation"]
[1:25:25][Our glove's light remains][:lighting :run]
[1:26:00][Make AddPlayer() shrink the glove's light from 0.5 to 0.4][:lighting :"procedural generation"]
[1:26:12][Our glove's light blinks][:lighting :run]
[1:28:03][Consider stratifying the light sampling][:lighting :run]
[1:29:25][@deggua][Is this because it's so small the probability of a sample ray intersecting the emissive source starts to become heavily affected by the random rays' distribution and whether they actually hit the emissive object? Seems like some kind of temporal averaging or a finer resolution grid would help][:lighting]
[1:29:58][Clean out cruft from UpdateLighting()][:lighting]
[1:33:10][We still :run][:lighting]
[1:33:12][Make FullCast() stratify the samples into a 4×4 grid][:lighting]
[1:36:46][Our glove's light still blinks][:lighting :run]
[1:38:55][Temporarily make FullCast() seed its random series with a constant value, to fix the rays][:lighting :prng]
[1:39:24][Our glove's light still pulsates with fixed rays, but why?][:lighting :run]
[1:44:06][Scour FullCast() for sources of noise][:lighting :prng :research]
[1:45:07][@mtsmox][Maybe the position of the glove, the bobbing, turn that off?]
[1:45:11][The glove doesn't bob][:lighting :run]
[1:45:38][Increase tUpdateBlend from 12/60 to 1 in UpdateLighting()][:lighting]
[1:46:24][Our glove's light blinks vigorously][:lighting :run]
[1:48:16][@fat_dratini][Runaway NaNs]
[1:48:46][Our glove's light blinks vigorously (cont.)][:lighting :run]
[1:49:46][Toggle off room lights in StandardLightingPattern()][:lighting :"procedural generation"]
[1:50:03][Only overlapped light probes have the blinking bug][:lighting :run]
[1:51:10][Temporarily prevent GridRayCast() from casting rays from inside geometry][:lighting]
[1:51:41][Our light still blinks, but less vigorously][:lighting :run]
[1:52:09][Let GridRayCast() cast rays from inside geometry][:lighting]
[1:52:14][Consider how to approach our blinking bug][:lighting :research]
[1:54:14][@snoringtortoise][Could you turn on NaN exceptions so if we hit a NaN the program will halt?]
[1:54:19][Check our tUpdate and JitterRadius][:lighting :research]
[1:55:21][Decrease the JitterRadius multiplier from 0.45 to 0.4 in FullCast()][:lighting]
[1:55:30][Our light still blinks][:lighting :run]
[1:55:34][Decrease the JitterRadius multiplier from 0.4 to 0.1 in FullCast()][:lighting]
[1:55:36][Our light blinks more sporadically][:lighting :run]
[1:56:10][Increase the JitterRadius multiplier from 0.1 to 0.45 in FullCast()][:lighting]
[1:56:31][Determine to get snacks and enable NaN exceptions][:speech]
[1:56:53][@fnaarp][Maybe try just setting tUpdateBlend to 1 in both clauses of that if?]
[1:57:02][Remove the tUpdateBlend modification branch from UpdateLighting(), and remove Accumulating, AccumulationCount and FrameOdd from lighting_solution][:lighting]
[1:57:35][Our light continues to blink][:lighting :run]
[1:58:09][Determine to get snacks and enable NaN exceptions][:speech]
[1:58:47][Grab snacks][:admin]
[1:58:57][:afk]
[2:03:06][Return with snacks][:admin]
[2:03:42][@snoringtortoise][[@cmuratori Casey]: Just wondering if removing the (tMin < tMax) expression from the Mask calculation will have an effect? That part of the expression was added this stream][:lighting]
[2:04:11][@snoringtortoise][[@cmuratori Casey]: If the ray can be negative, then couldn't tMin be > tMax some of the time?][:lighting]
[2:04:42][@fnaarp][Why'd it change from a throb to a blink?][:lighting]
[2:05:04][Demo the blinking light][:lighting :run]
[2:05:12][Toggle on room lights in StandardLightingPattern()][:lighting :"procedural generation"]
[2:05:22][Demo the blinking, with stable lighting][:lighting :run]
[2:06:14][Revert FullCast() to seed its random series randomly][:lighting :prng]
[2:06:33][Demo the blinking with noisy lighting][:lighting :run]
[2:07:14][@yuika_lamonting][The blinking?][:lighting]
[2:07:31][Demo the flickery lighting (cont.)][:lighting :run]
[2:09:51][@fnaarp][So temporal averaging made the blink into a throb, got it][:lighting]
[2:10:41][Wonder why the glove light blinks when small enough][:lighting :run]
[2:11:07][Make AddPlayer() enlarge the glove's light from 0.4 to 0.5][:lighting :"procedural generation"]
[2:11:36][Our glove's larger light rarely blinks][:lighting :run]
[2:12:09][@mtsmox][Can you see if the gameplay speed is related by slowing down the clock?]
[2:12:21][Slowing the timestep stops the light from blinking (even after speeding it back up again)][:run]
[2:14:48][Toggle on DebugDrawOctahedralValues() and DebugDrawSpatialGrid() in UpdateLighting()][:"debug visualisation" :lighting]
[2:14:51][Our light probe is suspiciously positioned in Z relative to the glove][:lighting :run]
[2:15:57][Toggle off DebugDrawOctahedralValues() and DebugDrawSpatialGrid() in UpdateLighting()][:"debug visualisation" :lighting]
[2:16:16][Halve the JitterRadius along Z, and make FullCast() jitter light ray origins in Z][:lighting]
[2:16:41][Our glove's light flickers more sporadically][:lighting :run]
[2:17:31][Increase the JitterRadius multiplier from 0.45 to 0.5 in FullCast()][:lighting]
[2:17:44][Our glove's light still flickers sporadically][:lighting :run]
[2:18:56][Decrease tUpdateBlend from 1 to 12/60 in UpdateLighting()][:lighting]
[2:18:59][The glove's light now barely flickers][:lighting :run]
[2:20:05][Light leaks to the outdoors][:lighting :run]
[2:21:13][Admire the :lighting, and consider putting in an exposure curve and a notion of brightness (for bloom)][:run]
[2:23:47][Make AddPlayer() shrink the glove's light from 0.4 to 0.25, and brighten it from 0.1 to 0.2][:lighting :"procedural generation"]
[2:24:08][The glove's smaller light varies more][:lighting :run]
[2:24:39][Make AddPlayer() enlarge the glove's light from 0.25 to 0.75, and darken it from 0.2 to 0][:lighting :"procedural generation"]
[2:25:03][Our glove's light is dark][:lighting :run]
[2:25:10][Make AddPlayer() brighten the glove's light from 0 to 0.1][:lighting :"procedural generation"]
[2:25:28][The glove's larger light is pretty stable][:lighting :run]
[2:26:26][Consider adding spheres][:geometry :lighting :run]
[2:31:36][Make AddPlayer() shrink the glove's light from 0.75 to 0.25][:lighting :"procedural generation"]
[2:31:46][Our glove's smaller light is dimmer][:lighting :run]
[2:31:59][Make AddPlayer() brighten the glove's light from 0.1 to 1][:lighting :"procedural generation"]
[2:32:11][Our glove's small and bright light is not too noisy][:lighting :run]
[2:33:19][Consider how to proceed][:lighting :run]
[2:34:07][Real-time global illumination: General purpose engines (using global illumination only for secondary indirect lighting) vs ours (using it for both direct and indirect lighting)][:lighting :run]
[2:39:27][@mtsmox][How do the other engines "skip" the direct light and only use secondary bounces?][:lighting]
[2:41:28][@fnaarp][Crazy idea - since all your surfaces are xy / xz / yz planes, could you look at a circle around a projection of the light source onto the surface rather than spherical intersection?][:lighting]
[2:43:06][@deggua][So you either have to do all sphere lights or all AABB lights?][:geometry :lighting]
[2:43:12][Describe the changes to FullCast() required to support spherical lights][:geometry :lighting :research]
[2:45:59][@spacenaming][But shouldn't a small enough box give a spherical falloff as well?][:lighting]
[2:46:31][Consider how to proceed][:lighting :run]
[2:47:53][Increase RayCount from 16 to 256 in GridRayCast()][:lighting]
[2:48:20][The light still doesn't look great around the light source][:lighting :run]
[2:48:49][Decrease RayCount from 256 to 16 in GridRayCast()][:lighting]
[2:48:59][Our glove's light is noisier][:lighting :run]
[2:49:06][Make AddPlayer() shrink the glove's light from 0.25 to 0.1][:lighting :"procedural generation"]
[2:49:21][:Run the game][:lighting]
[2:49:24][Make AddPlayer() shrink the glove's light from 0.1 to 0.05][:lighting :"procedural generation"]
[2:49:28][Our glove's light is barely visible][:lighting :run]
[2:49:48][Increase RayCount from 16 to 1024 in GridRayCast()][:lighting]
[2:49:56][Our glove's light is barely visible][:lighting :run]
[2:50:59][Make AddPlayer() brighten the glove's light from 1 to 10, and decrease the RayCount from 1024 to 16 in GridRayCast()][:lighting :"procedural generation"]
[2:51:23][Our light flickers][:lighting :run]
[2:51:43][Increase RayCount from 16 to 1024 in GridRayCast()][:lighting]
[2:51:51][Our light no longer flickers][:lighting :run]
[2:53:08][Decrease RayCount from 1024 to 16 in GridRayCast(), and make AddPlayer() brighten the glove's light from 10 to 20][:lighting]
[2:53:21][Our light flickers][:lighting :run]
[2:53:45][Increase RayCount from 16 to 1024 in GridRayCast()][:lighting]
[2:53:49][Our light no longer flickers][:lighting :run]
[2:54:12][Make AddPlayer() brighten the glove's light from 20 to 100, and decrease the RayCount from 1024 to 64 in GridRayCast()][:lighting :"procedural generation"]
[2:54:34][Our :performance has degraded][:lighting :run]
[2:54:51][Decrease RayCount from 64 to 16 in GridRayCast()][:lighting]
[2:55:01][Our light flickers][:lighting :run]
[2:55:21][Increase RayCount from 16 to 1024 in GridRayCast()][:lighting]
[2:55:27][Our light no longer flickers][:lighting :run]
[2:55:57][Make AddPlayer() enlarge the glove's light from 0.05 to 0.4 and darken it from 100 to 1, and decrease RayCount from 1024 to 16 in GridRayCast()][:lighting :"procedural generation"]
[2:56:33][Our glove's light has a square falloff][:lighting :run]
[2:56:48][Increase RayCount from 16 to 1024 in GridRayCast()][:lighting]
[2:56:55][Our glove's light still has a square falloff][:lighting :run]
[2:57:17][Decrease RayCount from 1024 to 16 in GridRayCast()][:lighting]
[2:57:27][Our glove's light still has a square falloff][:lighting :run]
[2:57:55][@mtsmox][Could you then also remove the temporal smooth?][:lighting]
[2:58:08][Increase tUpdateBlend from 12/60 to 1 in UpdateLighting()][:lighting]
[2:58:12][Our light flickers][:lighting :run]
[2:58:20][Increase RayCount from 16 to 1024 in GridRayCast()][:lighting]
[2:58:26][Our glove's light still has a square falloff][:lighting :run]
[2:59:03][Decrease RayCount from 1024 to 16 in GridRayCast()][:lighting]
[2:59:21][Our light flickers][:lighting :run]
[2:59:39][Start to enable FullCast() to handle spherical lights][:lighting]
[3:02:27][Switch to the lightboard][:admin]
[3:03:56][Sphere vs. Ray][:blackboard :collision :geometry :lighting :mathematics]
[3:08:42][Sphere vs. Ray intersection equation, Take 1][:blackboard :collision :geometry :lighting :mathematics]
[3:16:36][Sphere vs. Ray intersection equation, Take 2][:blackboard :collision :geometry :lighting :mathematics]
[3:19:59][Switch to the code][:admin]
[3:20:12][@sagian2005][Do we need the coordinates? Or do we just need to know if it intersects?][:collision :geometry :lighting :mathematics]
[3:20:51][Reacquaint ourselves with the sphere intersection code in CastSampleRays() from ray.cpp][:collision :geometry :lighting :mathematics :research]
[3:24:32][SQRTPS() and DIVPS() are on ports 0, and cost 3 cycles[ref
    site=uops.info
    url=https://uops.info/table.html]][:performance :research]
[3:27:39][Enable FullCast() to handle spherical lights based on CastSampleRays() from ray.cpp][:lighting]
[3:42:12][Introduce SquareRoot()][:mathematics]
[3:42:41][Enable FullCast() to handle spherical lights based on CastSampleRays() from ray.cpp (cont.)][:lighting]
[3:44:58][Our sphere code is running][:lighting :run]
[3:45:04][Toggle off the spherical intersection in FullCast()][:lighting]
[3:46:05][Our glove's light has a square falloff][:lighting :run]
[3:46:18][Toggle on the spherical intersection in FullCast()][:lighting]
[3:46:26][Our light is doing something different][:lighting :run]
[3:46:36][Enable GridBuildSpatialPartition() to handle spherical lights][:lighting]
[3:50:23][Our glove's light looks less square][:lighting :run]
[3:51:01][Decrease tUpdateBlend from 1 to 12/60 in UpdateLighting()][:lighting]
[3:51:07][Our glove's light looks even less square][:lighting :run]
[3:51:33][Increase RayCount from 16 to 1024 in GridRayCast()][:lighting]
[3:51:58][Our glove's light is centred wrong][:lighting :run]
[3:52:47][Decrease RayCount from 1024 to 16 in GridRayCast(), and make AddPlayer() darken the glove's light from 1 to 0.25][:lighting :"procedural generation"]
[3:53:10][Our glove's light is centred wrong][:lighting :run]
[3:54:13][Double-check the spherical light code in GridBuildSpatialPartition() and GridRayCast()][:lighting :research]
[3:58:25][Eyeball our spherical light][:lighting :run]
[3:59:10][Make AddPlayer() add a light to the hero's head rather than the glove][:lighting :"procedural generation"]
[4:00:08][We may be detecting intersections where the sphere doesn't actually touch][:lighting :run]
[4:01:50][@deggua][Probably NaN I would guess]
[4:02:25][Fix the RootTerm computation in GridRayCast(), and test it before square rooting it][:lighting]
[4:04:42][Our spherical light looks better][:lighting :run]
[4:05:41][Make AddPlayer() brighten the glove's light from 0.25 to 0.5][:lighting :"procedural generation"]
[4:06:03][Our light still looks a bit square][:lighting :run]
[4:06:40][Increase RayCount from 16 to 1024 in GridRayCast()][:lighting]
[4:06:53][Our light still looks a bit square][:lighting :run]
[4:08:26][Disable LIGHTS_ARE_SPHERES][:lighting]
[4:08:40][Our light looks brighter and more prominently square][:lighting :run]
[4:09:31][@sagian2005][Yeah, it looks like it's just being clipped to the voxel somehow][:lighting]
[4:09:50][Enable LIGHTS_ARE_SPHERES][:lighting]
[4:09:55][Our light looks dimmer and less square][:lighting :run]
[4:11:29][Decrease RayCount from 1024 to 16 in GridRayCast()][:lighting :"procedural generation"]
[4:11:41][Our light trails behind us][:lighting :run]
[4:11:59][Increase tUpdateBlend from 12/60 to 20/60 in UpdateLighting()][:lighting]
[4:12:22][Our light trails less, but flickers][:lighting :run]
[4:12:48][Increase tUpdateBlend from 20/60 to 1 in UpdateLighting()][:lighting]
[4:12:54][Our light flickers, and seems to have a frame of lag][:lighting :run]
[4:14:20][Increase tUpdateBlend from 1 to 12/60 in UpdateLighting()][:lighting]
[4:14:31][Determine to make the light interpolation less square][:lighting :run]
[4:15:31][Disable LIGHTS_ARE_SPHERES][:lighting]
[4:15:37][Our light looks brighter and more prominently square][:lighting :run]
[4:16:08][That's it for today, with a plug of Molly Movie Club[ref
    site="Molly Movie Club"
    url=https://www.mollymovieclub.com/]][:speech]
[/video]
