[video member=cmuratori stream_platform=twitch stream_username=handmade_hero project=code title="Distinguishing Between Lights and Occluders" vod_platform=youtube id=_dVntlUp4eM annotator=Miblo] [0:01][Demo the current state of our light probe-based ray cast :lighting][:run] [1:59][:Lighting improvements: 1. Averaging across frames][:run] [2:57][:Lighting improvements: 2. Real indirect bounce and convection][:run] [3:34][:Lighting improvements: 3. How best to store and update our information][:run] [8:22][Reacquaint ourselves with TestCastFromProbes()][:lighting :research] [9:55][Reacquaint ourselves with ComputeLightPropagation()][:lighting :research :threading] [10:49][Turn the lighting_work version of ComputeLightPropagation() into a ComputeLightPropagationWork() PLATFORM_WORK_QUEUE_CALLBACK][:lighting :threading] [13:22][Prepare to update ComputeLightPropagationWork() to work with voxel-based :lighting][:research] [17:51][Set up ComputeLightPropagationWork() to handle multiple light sources][:lighting] [20:55][Continue to reacquaint ourselves with ComputeLightPropagationWork(), its stochastic spherical :sampling and ambient light][:lighting :research] [23:53][Consider getting ambient light from the probes][:lighting] [24:56][Continue to reacquaint ourselves with ComputeLightPropagationWork(), :sampling hits][:lighting :research] [26:52][Set up ComputeLightPropagationWork() to sample from our voxel-based :lighting, removing light_probe_irradiance and introducing ComputeVoxelIrradianceAt()][:sampling] [31:19][Make ComputeLightPropagationWork() call SpamVoxel() renaming the existing SpamVoxel() to SpamVoxelSlice()][:lighting] [35:52][Clean up compile errors][:lighting] [40:55][Set up ComputeLightPropagationWork() to compute falloff based on the light source position][:lighting] [43:02][Make ComputeLightPropagationWork() weight the incoming light by its intensity and location][:lighting] [46:11][Consider how to average higher fidelity :lighting with multiple light fields][:research] [48:23][Make ComputeLightPropagationWork() initialise a consistent MoonP, and SpamVoxelSlice() and SpamVoxel() take a LightFalloff which may be 0.0f for the moon][:lighting] [54:37][Introduce a stubbed out ComputeVoxelIrradianceAt()][:lighting] [55:38][Traverse the world with the determination to put lights into the casting hierarchy][:lighting :run] [56:29][Determine to distinguish between lights and occluders][:lighting :speech] [57:59][Spatial Partitioning of Lights][:blackboard :geometry :lighting] [1:03:17][Upgrade our lighting_box spatial hierarchy for gathering four lights and distinguish between lights and occluders, replacing its Emission and TextureIndex values with a LightBoxD array in lighting_solution][:"data structure" :geometry :lighting] [1:11:41][Make PushOccluder() set IsLight to 0, and redo PushLight() based on that function instead setting IsLight to 1][:lighting] [1:13:40][Fix compile errors in SplitBox() and UpdateAndRenderEntities()][:"entity system" :geometry :lighting] [1:16:16][Make RayCast() conditionally set the HitEmission to 1.0 or 0.0f for lights and occluders respectively, with deep considerations on efficiency][:lighting] [1:24:05][Find that all remains well][:lighting :run] [1:24:23][Toggle on the PushLight() call in UpdateAndRenderWorld()][:lighting] [1:25:12][Check out our pushed light, being occluded at the top of the hero's hop][:lighting :run] [1:25:50][Set up TestCastFromProbes() to distinguish between lights and occluders][:lighting] [1:27:10][Find that our light–occluder distinguishing does not work][:lighting :run] [1:27:31][Enable IsTestCast in TestCastFromProbes() to highlight ray hits][:"debug visualisation" :lighting] [1:30:06][Find that our light–occluder distinguishing now works][:lighting :run] [1:31:17][Introduce GetSpatialLeafForP() to gather light from the spatial hierarchy][:geometry :lighting] [1:38:29][Make TestCastFromProbes() call GetSpatialLeafForP(), and rename LightBoxP to LightBoxTargetP in lighting_solution][:"data structure" :geometry :lighting] [1:41:04][Slightly rewrite GetSpatialLeafForP() to return a u32 rather than a lighting_box pointer][:geometry :lighting] [1:42:39][Fix compile error in TestCastFromProbes()][:geometry :lighting] [1:43:12][Determine to gather our light from the spatial hierarchy][:geometry :lighting :speech] [1:43:47][Check out our uninitialised light][:geometry :lighting :run] [1:43:59][Investigate why we saw the light move][:geometry :lighting :research] [1:44:43][Consider our :lighting to be buggy][:geometry :run] [1:45:02][Begin to enable BuildSpatialPartitionForLighting() to insert lights into the hierarchy, introducing InsertLight()][:geometry :lighting] [1:52:21][Consider tabling our spatial hierarchy :lighting gather for tomorrow][:geometry :speech] [1:53:55][Make BuildSpatialPartitionForLighting() fill LightBoxTargetP with the DebugLightP][:geometry :lighting] [1:55:01][Verify that the LightBoxTargetP filling works][:geometry :lighting :run] [1:55:09][Disable IsTestCast in TestCastFromProbes()][:"debug visualisation" :lighting] [1:55:34][See our test :lighting, without the spatial hierarchy lookup][:geometry :run] [1:55:56][Q&A][:speech] [1:57:23][@0lpbm][Q: You're returning 0 instead of Result in the function you created to find the box][:geometry :lighting] [1:57:45][Fix GetSpatialLeafForP() to return Result][:geometry :lighting] [1:58:03][@ymm0][Q: Not sure how relevant, but the problem seems related to importance :sampling lights in Monte Carlo ray tracers][:lighting] [1:59:43][@jessem3y3r][Q: What lessons did you learn from implementing [~hero Handmade Hero]'s debug inspection system?][:"debug system"] [2:01:15][@jessem3y3r][Q: Yes! Follow up question incoming...] [2:02:09][@devsigner][Q: Are there any :performance impacts to storing large arrays of data as static global constants?] [2:04:10][@jessem3y3r][Q: Is a non-trivial part of the difficulty the inherent limitations of C (you originally had to implement various metaprogramming tooling) or is the ideal system you want just inherently complex?][:language] [2:04:52][@panostrak][Q: Do you use OpenGL?] [2:06:42][@0lpbm][Q: Will you add lights separately, or bundle it with other objects in the scene (like lamps, for example)?][:"entity system" :lighting] [2:08:14][@berlin84][Q: Not a question, but just wanted to tell you. Lost two daughters (twins) due to a freak accident, and binging [~hero Handmade Hero] helped a lot with managing the loss during the hardest time. You help with more than you probably think] [2:10:23][@jessef][Q: Do you think the current trend of dedicated ray tracing :hardware is the right way to go for GPUs solving the :lighting problem? Is there another route you would like to see?] [2:14:36][@bulmanator][Q: I really like the platform and renderer setup you have. If your renderer needed to load files – for shaders or something, or had to allocate a lot of stuff – would you reimplement the platform specific functions in the renderer, or would you pass your platform :API struct to the renderer initialise and use the ones your main executable implemented?][:"file io" :library :memory] [2:16:17][Wrap it up][:speech] [/video]