(#) Rendering Algorithms Final Project by Tanli Su and Jacob Chen (##) Motivational images The prompt for this year's rendering competition was "It's what's inside that counts" - which made us think of those charts showing eggs boiled for different lengths of time. We also thought that the varying levels of yolk done-ness would be interesting to render with subsurface scattering. Thus, our goal for this project was to render a few eggs boiled for different amounts of time.

an example egg chart

[(source)](https://downshiftology.com/recipes/perfect-soft-boiled-hard-boiled-eggs/)

[(source)](https://www.masterclass.com/articles/all-about-soft-boiled-eggs-how-long-to-boil-eggs-and-easy-recipe)
Different people have different preferences for how they enjoy their boiled eggs - hard-boiled, soft-boiled, or somewhere in between! You can never be sure if an egg is up to your standards just from the outside; it’s what’s on the inside that counts!
(##) Features We implemented the following features on top of the renderer which had been developed throughout the class so far: * Homogeneous volumetric path tracing * Custom yolk material: a homogeneous medium encased in a rough dielectric with custom refraction * Environment lighting: using an environment map image mapped onto a sky sphere * Normal mapping: using a normal map image to modify surface normals (##) Volumetric path tracer Our implementation of homogeneous volumetric path tracing includes the following features: * with multiple scattering * with index-matched or dielectric boundary * with scattering/absorption coefficients as colors * with next-event estimation (NEE) * with isotropic or Henyey-Greenstein phase function Below are the validation images for each feature.

volumetric reference
Validation of subsurface scattering (in the sphere on the right) against Jensen box reference.
Using a dielectric boundary and a medium with absorption/scattering coefficients set to 0.


index-matched boundary dielectric boundary
Validation of strongly absorbing vs strongly scattering media.


Validation of backward vs forward scattering media (using negative/positive values of g in the Henyey-Greenstein phase function).


Validation of grey vs colored media. For each scattering event, we use multiple importance sampling (MIS) to choose one of the three RGB color channels.


with NEE without NEE
Validation of next-event estimation (NEE). For each scattering event, we sample direct illumination from the light sources and add it to the indirect illumination.


(##) Custom yolk material We created a custom material to simulate an undercooked yolk. The yolk consists of a homogeneous medium encased in a rough dielectric boundary. We further customized the yolk by making light refract on the way in, but not on the way out. This allows for shadow connections from within the yolk, while still getting sharp specular highlights on the wet yolk.
custom yolk material dielectric yolk material

(##) Environment mapping We used a sky sphere with an environment map image for environment lighting. The material gets the albedo value from an image texture and only emits from the non-normal-facing side because it assumes it is applied to a surface that surrounds the scene (with normals facing outwards, but we want it to emit light inwards).
with environment map without environment map

(##) Normal mapping We implemented normal mapping because we originally planned to use it for the egg shells in our image; however, we decided not to use this feature in our final image because we didn't find a texture that looked good on our egg shells. We still implemented the feature, and the validation images are shown below.
no normal map with normal map
Validation of normal mapping.

no normal map with normal map
Validation of normal mapping.


no normal map with normal map
Validation of normal mapping for a sphere.

(##) Final image Below is our final image (please refresh the page if it doesn't show up).
Our final image consists of 3 eggs cooked at different consistencies. We rendered it on 30 cores with 100 samples per pixel for each, and then averaged them to obtain the final image. * All 3 egg whites consist of a forward-scattering medium with a high albedo. * The yolk of the hardest-boiled egg is simulated simply using a constant-colored Lambertian material. * The yolks of the soft-boiled egg and the runny egg are simulated using the custom yolk material. * The egg shells are simulated with a Lambertian material with an image texture for the albedo. * The table material is a Fresnel blend that uses a marble image texture for the base.
(##) Challenges Our biggest challenge was setting the egg yolk color because it required tuning the scattering and absorption coefficients, which aren't completely intuitive. In addition, we tuned the image by rendering it with much fewer samples per pixel than our final image had, and so when we rendered the image with many samples per pixel, the resulting colors were much brighter than we expected. This made it particularly difficult to set the appropriate coefficients, and it also prevented us from rendering our image with even more samples per pixel. Other general challenges included refactoring the code to add new features, creating the detailed obj models, setting up the scene in Blender, and adjusting the camera angle.