[video output=day568 member=cmuratori stream_platform=twitch stream_username=handmade_hero project=code title="Debugging the Raycaster" vod_platform=youtube id=vPc2gfdABSk annotator=Miblo] [0:01][Welcome to Handmade Coffee, roasted by [@iradicator Irad][ref site=Twitter page="Irad Ratmansky" url=https://twitter.com/IRADICATOR] and presented to [@cmuratori Casey] at Handmade Seattle][:speech] [3:05][Demo the current state of our raycast :lighting][:run] [8:13][Cursorily reacquaint ourselves with EndLightingComputation()][:lighting :research] [8:54][Switch from TEST_LIGHT_TRANSFER to TEST_LIGHT_SPHERE in EndLightingComputation()][:lighting] [9:05][Admire our radial falloff :lighting solution, mixing four lights][:run] [11:42][Switch from TEST_LIGHT_SPHERE to TEST_LIGHT_TRANSFER in EndLightingComputation(), and let it assume that all rays hit light sources][:lighting] [12:44][Admire our voxel-to-voxel interpolation][:lighting :run] [13:25][Make EndLightingComputation() draw a simple shadow if a light source is found to be occluded][:lighting] [14:54][See our anomalous shadows][:lighting :run] [15:35][Toggle on the ray cast debug lines in EndLightingComputation()][:"debug visualisation" :lighting] [15:56][See our rays][:"debug visualisation" :lighting :run] [16:28][Note that we are drawing a subset of 8³ out of 32³ rays][:lighting :research] [18:44][Disable :lighting in CompileZBiasProgram()] [19:14][Look at our rays in bright light, to see some which hit non-obvious objects][:"debug visualisation" :lighting :run] [22:52][Make EndLightingComputation() draw all the rays, coloured black if no hit, and yellow if hit][:"debug visualisation" :lighting] [25:34][Begin to reacquaint ourselves with RayCast()][:lighting :research] [27:43][Prevent RayCast() from initialising NegativeOne][:lighting] [28:06][Continue to reacquaint ourselves with RayCast()][:lighting :research] [36:56][Consider making RayCast() base tCloseEnough on the particular box, such that boxes at the root of the hierarchy are more likely to be entered than boxes near the leaves][:lighting] [39:31][Continue to reacquaint ourselves with RayCast()][:lighting :research] [41:34][Address the old early-out condition in RayCast() when all four rays hit][:lighting :research] [44:11][Delete the old all-hit early-out condition in RayCast(), and restrict the Box push to ones whose closest point it also closer than the current tRay][:lighting] [48:24][Finish reacquainting ourselves with RayCast()][:lighting :research] [50:41][Look at our rays, and pick a problem one to isolate][:"debug visualisation" :lighting :run] [51:56][Try to isolate our problem ray in EndLightingComputation()][:lighting] [53:40][See that we picked the wrong ray][:"debug visualisation" :lighting :run] [53:59][Fix our ray isolation in EndLightingComputation()][:lighting] [54:11][See that we picked our desired problem ray][:"debug visualisation" :lighting :run] [54:25][Add a BreakMePlease in EndLightingComputation()][:lighting] [55:03][Break on our BreakMePlease in EndLightingComputation() and inspect our test case][:lighting :run] [58:17][Make RayCast() initialise AnyInside and AnyCloseEnough][:lighting] [59:25][Break on our BreakMePlease in EndLightingComputation() and step through to RayCast()][:lighting :run] [1:00:03][Consider starting our :camera at a known good location][:speech] [1:01:05][Break on our BreakMePlease in EndLightingComputation(), skip the first frame, step through to RayCast() and inspect our test case][:lighting :run] [1:08:47][Our ray cast bug possibilities: 1) Erroneous box, correctly hit tested; 2) Correct box, erroneously hit tested][:lighting :run] [1:10:27][Enable RayCast() to draw its boxes, initially one ring of each][:"debug visualisation" :lighting] [1:16:33][Launch our debug build and see no ray cast box][:"debug visualisation" :lighting :run] [1:17:05][Make EndLightingComputation() pass IsTestCast to RayCast()][:"debug visualisation" :lighting] [1:17:39][Check out our ray cast boxes][:"debug visualisation" :lighting :run] [1:18:08][Make RayCast() draw the opposite ring of the boxes][:"debug visualisation" :lighting] [1:18:25][Check out our ray cast boxes][:"debug visualisation" :lighting :run] [1:19:04][Make RayCast() draw the final edges of its boxes][:"debug visualisation" :lighting] [1:19:47][Check out our complete ray cast boxes][:"debug visualisation" :lighting :run] [1:21:29][Make RayCast() colour hit boxes cyan if they are containers, and yellow if not][:"debug visualisation" :lighting] [1:22:45][Check out our ray cast boxes, noting the erroneously placed box, and the fact that our light probes are considered colliders][:"debug visualisation" :lighting :run] [1:23:41][Prevent light probes from being considered colliders, introducing PushOccluder() to perform the occlusion code from PushCube()][:lighting] [1:29:01][Check out our ray cast boxes, to see that our bad case has disappeared][:"debug visualisation" :lighting :run] [1:30:02][Enable :lighting in CompileZBiasProgram()] [1:30:22][See black][:lighting :run] [1:30:57][Make EndLightingComputation() draw a simple shadow if a light source is found to be occluded][:lighting] [1:31:24][See different erroneous shadows][:lighting :run] [1:32:28][Make EndLightingComputation() draw all our rays][:"debug visualisation" :lighting] [1:33:12][See some black (non-hitting) rays that apparently should be hitting something][:"debug visualisation" :lighting :run] [1:34:07][Disable :lighting in CompileZBiasProgram()] [1:34:44][Try to pick a problem ray][:"debug visualisation" :lighting :run] [1:37:28][Make EndLightingComputation() just draw a tick mark at the casting locations][:"debug visualisation" :lighting] [1:39:09][Check out our casting locations][:"debug visualisation" :lighting :run] [1:39:32][Make EndLightingComputation() colour the tick marks cyan, and draw the rays themselves][:"debug visualisation" :lighting] [1:40:14][See some tick marks lacking a ray, and vice versa][:"debug visualisation" :lighting :run] [1:41:17][Make EndLightingComputation() draw the direction in which each ray is pointing][:"debug visualisation" :lighting] [1:42:15][Again see some tick marks lacking a ray, and vice versa][:"debug visualisation" :lighting :run] [1:42:58][Wonder what could be wrong with our rays][:lighting :research] [1:43:54][Pick a problem ray to isolate][:"debug visualisation" :lighting :run] [1:44:47][Try to isolate our problem ray in EndLightingComputation()][:lighting] [1:44:57][See that we picked our desired problem ray][:"debug visualisation" :lighting :run] [1:46:07][Break on our BreakMePlease in EndLightingComputation(), and inspect our Cast to see that FLT_MAX may be causing the problem][:lighting :run] [1:47:02][Change EndLightingComputation() to set the CastP of non-hit rays to the light distance][:lighting] [1:48:53][See that our problem ray's check mark is now accompanied by its actual ray, and that it remains a problem ray][:"debug visualisation" :lighting :run] [1:49:22][Make EndLightingComputation() pass IsTestCast to RayCast()][:lighting] [1:49:30][See that our RayCast() failed to test the child boxes through which our ray passes][:"debug visualisation" :lighting :run] [1:50:12][Make RayCast() push all the child boxes into the system][:lighting] [1:50:42][See that we do correctly detect the intersection][:"debug visualisation" :lighting :run] [1:51:33][Prevent RayCast() from checking from AnyCloser before pushing on a box][:lighting] [1:52:17][See that we do not detect the intersection][:"debug visualisation" :lighting :run] [1:52:27][Prevent RayCast() from checking from AnyCloseEnough before pushing on a box][:lighting] [1:53:02][See that we do not detect the intersection][:"debug visualisation" :lighting :run] [1:53:09][Scrutinise the AnyInside value in RayCast()][:lighting :research] [1:55:34][Let RayCast() push on a box if AnyInside or AnyCloser][:lighting] [1:56:14][See that we do not detect the intersection][:"debug visualisation" :lighting :run] [1:56:44][Make RayCast() extend tInside to encompass FLT_MAX][:lighting] [1:57:08][See that we do correctly detect the intersection][:"debug visualisation" :lighting :run] [1:57:23][Restore our full checks in EndLightingComputation() before pushing a box][:lighting] [1:57:40][Look at our correct ray][:"debug visualisation" :lighting :run] [1:57:49][Make EndLightingComputation() draw all our rays, without boxes][:"debug visualisation" :lighting] [1:58:23][Find that our rays look a little more sane][:"debug visualisation" :lighting :run] [1:59:16][Disable the test drawing in EndLightingComputation(), and enable :lighting in CompileZBiasProgram()][:"debug visualisation"] [2:00:22][See our shadows, and determine to cast rays from light probe points][:"debug visualisation" :lighting :run] [2:01:20][Make EndLightingComputation() draw all our rays][:"debug visualisation" :lighting] [2:01:37][Admire our rays in the lit scene][:"debug visualisation" :lighting :run] [2:02:31][Q&A][:speech] [2:03:48][@eerrman1][Q: Where did you learn programming, like this :lighting stuff, previously?] [2:06:53][@smack_ssbm][Q: Which parts of the CRT do you think are the most poorly designed or unnecessary? What do you feel is missing?] [2:09:15][@euphius][Q: Did you learn new things about game programming while working on [~hero Handmade Hero]? If yes, what?] [2:10:36][@ablindorphan][Q: Can you imagine any debug tools that would make stuff like graphics programming and :lighting easier to debug (especially for beginners)?] [2:15:35][@bulmanator][Q: Is it possible to get cl.exe and msbuild without installing Visual Studio?] [2:16:07][@enemypanda][Q: How do you split your time between learning theory and practice?] [2:16:37][@erik_ava][Q: How many hours did you expect [~hero Handmade Hero] was going to be at the start?] [2:18:30][@mariaberry][Q: Are you planning to do another series after you're done with [~hero Handmade Hero]?] [2:18:34][@enemypanda][Q: Any plans for :physics?] [2:18:49][Wrap it up][:speech] [/video]