[video member=cmuratori stream_platform=twitch stream_username=handmade_hero project=ray title="Making a Simple Raycaster" vod_platform=youtube id=pq7dV4sR7lg annotator=Miblo]
[0:05][Welcome to the stream, with a few words on the new computers]
[4:09][Embark on making a ray tracer, starting with a directory and build.bat]
[6:17][ray.cpp: Implement Hello World!]
[7:42][Build and run successfully]
[8:01][Ray tracer]
[9:40][ray.cpp: Introduce struct bitmap_header and a bitmap writer]
[13:22][A few words on malloc()]
[14:51][ray.cpp: Write colour values into memory, with a few words on our representation of this memory]
[18:35][ray.cpp: Initialise a bitmap Header]
[23:18][ray.cpp: Write to a file using fwrite()[ref
    site="cplusplus"
    page="fwrite"
    url="http://www.cplusplus.com/reference/cstdio/fwrite/"]]
[29:43][ray.cpp: typedef our types]
[31:17][Step through the code and try unsuccessfully to read our bitmap image]
[32:58][ray.cpp: Fill in the bitmap Header[ref
    site=Wikipedia
    page="BMP file format"
    url=https://en.wikipedia.org/wiki/BMP_file_format]]
[37:39][Run successfully, but receive find that our file is not well-formed]
[38:18][Step through the code and inspect our header]
[38:49][Draw a picture and save it out as a BMP file]
[39:45][ray.cpp: Load reference.bmp]
[40:23][Step through and inspect the header of the well-formed reference.bmp]
[42:02][ray.cpp: Fix up our header to be closer to the well-formed file[ref
    site=Wikipedia
    page="BMP file format"
    url=https://en.wikipedia.org/wiki/BMP_file_format]]
[44:29][Run and successfully read our bitmap file]
[45:09][ray.cpp: Write to all pixels in the image, and succesfully view it]
[45:24][ray.cpp: Add a red band to the image, to emphasise its directionality]
[45:52][Run and view our image]
[46:30][ray.cpp: Flip the sign of the Header.Height to draw the image from top to bottom]
[47:26][ray.cpp: Introduce struct image_32, WriteImage(), GetTotalPixelSize() and AllocateImage()]
[53:20][Run our program to recreate the bitmap file]
[54:04][Consider the next logical step for our ray tracer]
[55:11][ray.h: Pull out our types from ray.cpp and introduce structs material, plane, sphere and world]
[1:00:15][ray.cpp: Initialise a world and two materials]
[1:03:19][ray_math.h: Pull in structs v2, v3 and v4 from handmade_platform.h, and various functions from handmade_math.h]
[1:09:58][ray.cpp: Determine to initialise a plane]
[1:10:51][Blackboard: Defining planes, using the inner product]
[1:15:03][ray.cpp: Define a plane]
[1:15:29][ray.cpp: Introduce the notion of a camera]
[1:17:51][Blackboard: Camera axis coordinate system]
[1:18:57][ray.cpp: Continue to define the camera]
[1:21:35][Step through and inspect the camera values]
[1:23:04][ray.cpp: Hard set the CameraZ to 0, 1, 0 and step through to inspect the other axes]
[1:24:03][Blackboard: 3D coordinate system, following the right-hand rule]
[1:27:37][ray.cpp: Correctly define the camera axes]
[1:28:25][Step through and inspect the camera values]
[1:28:53][Blackboard: Shooting rays through a plane]
[1:30:42][ray.cpp: Convert our pixel positions to ratios across a film plane]
[1:34:58][ray.cpp: Shoot rays at our film]
[1:37:28][ray.cpp: Introduce RayCast(), testing first that it outputs the colours we expect]
[1:40:06][Blackboard: Ray hit detection]
[1:41:02][ray.cpp: Continue to implement RayCast()]
[1:44:28][Blackboard: Ray intersection]
[1:48:02][ray.cpp: Compute our intersection distance]
[1:48:48][Blackboard: Parallel ray and plane]
[1:49:49][ray.cpp: Make RayCast() test the Denominator against our Tolerance value]
[1:50:52][build.bat: Automatically open the image after building]
[1:52:22][Build, see our image and check that we are producing what we expect]
[1:54:20][Blackboard: Double-check our equations]
[1:56:47][ray.cpp: Set one material colour to grey, consider that we are exactly backwards and investigate why]
[1:59:05][Blackboard: Camera coordinates]
[1:59:32][Continue to investigate our inversion bug]
[2:03:27][Blackboard: Producing camera coordinates]
[2:04:18][ray.cpp: Set CameraX by crossing 0, 0, 1 and CameraZ the other way]
[2:05:20][View our correct image]
[2:05:38][ray.cpp: Add a sphere]
[2:08:01][ray.cpp: Enable RayCast() to handle spheres]
[2:08:48][Blackboard: Sphere Intersection[ref
    site="Wikipedia"
    page="Quadratic equation"
    url="https://en.wikipedia.org/wiki/Quadratic_equation"]]
[2:16:10][ray.cpp: Enable RayCast() to compute the nearest sphere interesection point]
[2:23:14][Run and view our image]
[2:23:36][Blackboard: Sphere origin]
[2:24:40][ray.cpp: Make RayCast() correctly account for the sphere origin]
[2:27:05][ray.cpp: Correctly compute FilmX]
[2:27:30][ray.cpp: Handle the aspect ratio]
[2:30:11][Blackboard: Aspect ratio]
[2:30:42][View our image in the correct aspect]
[2:31:42][ray.cpp: Output stats]
[2:32:47][Run our program in the console to see our stats]
[2:34:48][ray.cpp: Enable RayCast() to cast multiple rays from different origins]
[2:45:05][ray.h: Change the material struct to contain EmitColor and RefColor]
[2:46:17][ray.cpp: Enable RayCast() to use both of those material colours]
[2:47:22][Blackboard: Attenuating angles]
[2:48:30][ray.cpp: Make RayCast() attenuate ray angles to correctly propagate light back to the camera]
[2:51:53][View our scene]
[2:53:25][Blackboard: Surface reflectance]
[2:56:18][ray.h: Add Specular to the material struct]
[2:56:46][Blackboard: Reflecting a vector]
[2:57:28][ray.cpp: Enable RayCast() to bounce rays randomly (but not unbiased) around the scene, renaming Specular to Scatter]
[3:01:22][ray.cpp: Introduce RandomUnilateral() and RandomBilateral()]
[3:03:35][View our image, and see black dots around the scene]
[3:04:45][ray.cpp: Set RayDirection to PureBounce, and correctly set the NextOrigin]
[3:06:10][View our image, consider that it's not quite right and investigate why]
[3:07:32][ray.cpp: Correctly set PureBounce and NextNormal]
[3:09:57][View our image and consider that the sphere may be below the plane]
[3:12:09][ray.cpp: Make RayCast() use the RandomBounce, and view our image]
[3:13:25][ray.cpp: Enable RayCast() to cast multiple rays per pixel]
[3:14:50][Blackboard: Angular attenuation]
[3:15:15][ray.cpp: Enable RayCast() to account for cosine attenuation]
[3:17:32][View the image, and consider that it's sort of correct]
[3:17:48][ray.cpp: Toggle off the cosine attenuation in RayCast()]
[3:18:24][ray.cpp: Add more spheres and materials]
[3:21:12][View our image, with spheres reflecting light]
[3:22:34][ray.cpp: Handle gamma correct sRGB]
[3:23:41][View our gamma correct image]
[3:24:08][ray.cpp: Introduce ExactLinearTosRGB()[ref
    site="Jason Summers's web site"
    page="A close look at the sRGB formula"
    url="http://entropymine.com/imageworsener/srgbformula/"]]
[3:28:32][ray_math.h: Introduce Pow()]
[3:28:54][View our apparently correct sRGB image]
[3:29:44][ray.cpp: Add a fourth sphere]
[3:30:36][View our image]
[3:31:13][ray.cpp: Re-enable RayCast() to perform cosine attenuation, and turn the red sphere into an emitter]
[3:32:57][View our image and consider further developments]
[3:34:30][ray.cpp: Compute the RayOrigin and RayDirection every time, to facilitate anti-aliasing at higher sampling rates]
[3:35:14][View the aliasing where the spheres meet the planes]
[3:35:46][ray.cpp: Jitter the ray direction]
[3:37:33][View the image with less and less aliasing as the RaysPerPixel increases]
[3:38:41][Consider optimisations]
[3:39:25][Q&A][:speech]
[3:39:50][@mapem_87][Is this series for total beginners in game programming?]
[3:40:19][@Kknewkles][Is it possible, or how hard is it, to have a debug system built-into your project that completely eliminates the need for a dedicated side debugger?]
[3:40:51][@macielda][Your mic is bouncing on the metal ring on your hood]
[3:41:13][@byteblind][So I just saw an old video where it says "Project will go at least until 2016". How far along towards the end are you?]
[3:42:02][@drive137][Is this going to be uploaded with the normal Handmade Hero code as well?]
[3:42:11][@bestalloys][Bug in the denominator check]
[3:42:30][ray.cpp: Fix Denom check]
[3:43:22][@bestalloys][Shouldn't you initialize your materials so EmitColor and RefColor are initialized?]
[3:43:41][@desuused][Maybe instead of reinventing BRDF (what you call reflectance), use some well-known BRDF, like Disney's? You can look at the implementation of one in e.g. Blender]
[3:44:11][@genos3][Could we use ray casting to determine a scene in real time that would allow infinite visibility, like with sparse voxel octree as opposed to a rasterizer?]
[3:45:39][@Miblo][Whatever happened to owlbot?]
[3:45:44][@siltnamis][why not use std::thread?]
[3:45:51][@pythor][Is it just a coincidence that three of the spheres all have their top / bottom line up almost exactly on the horizon? Or is that an artifact of something we're doing?]
[3:46:16][@sirslani][Could you just insert pragma omp on the raycaster loop?]
[3:46:36][@flyingsolomon][Could you disable windows bells? I hate these sounds]
[3:47:04][@macielda][The anti-alias has "roping" artifacts. Why?]
[3:48:06][View the anti-aliasing of the image in Paint]
[3:49:24][@bouke285][Will the growing popularity of multi-threading make procedural programming harder?]
[3:50:08][@bestalloys][Can you make one of the spheres a mirror?]
[3:50:23][ray.cpp: Create a mirror ball]
[3:52:00][@bluebooger][Is this source code included with $15 for Handmade Hero source?]
[3:52:30][@hoshoyo][Materials\[6\] should be 7 now]
[3:53:18][@sir_pinecone][Can you share the question prompter code too? I missed some of the stream and would like to see it]
[3:53:43][@genos3][I meant before if we could use traditional ray casting like Wolfenstein used to determine mesh visibility in the distance just using diffuse lighting]
[3:54:15][View our mirror ball]
[3:54:33][That's it, with plans for the future of our raycaster][:speech]
[3:58:20][Recommend Physically Based Rendering[ref
    site="Matt Pharr and Greg Humphreys"
    page="Physically Based Rendering"
    url="http://pbrt.org/"]][:research]
[3:59:39][Plug @Miblo's Patreon[ref
    site="Patreon"
    page="Matt Mascarenhas is creating Annotations for the Handmade.Network"
    url="https://www.patreon.com/miblo"]][:research]
[/video]
