**DirectX Raytracing, Tutorial 10**
**Using a miss shader to index into a high dynamic range light probe**
In [Tutorial 9](../Tutor9/tutorial09.md.html), we added a Lambertian shading model with ray traced shadows.
Before moving on to global illumination, we want to load and render with [environment map](https://en.wikipedia.org/wiki/Reflection_mapping)
light probes, which easily allow much more complex lighting.
For this tutorial, we assume our environment maps are parameterized using a [lat-long projection](https://en.wikipedia.org/wiki/Equirectangular_projection),
for instance the free environment maps [available here](http://www.hdrlabs.com/sibl/archive.html). I encourage you to use
[high dynamic range](https://en.wikipedia.org/wiki/High-dynamic-range_imaging) environments (e.g., with a .hdr filename),
since they provide more realistic lighting with larger variations in light intensity.
Environment Maps in our Tutorials
=================================================================================
Unlike most of the functionality we have added in our tutorials, using an environment map does not necessarily
add a new *`RenderPass`*. Instead, it simply modifies existing ones, changing the behavior of our miss shaders
as rays hit a more complex environment. In more complex pipelines, *_every_* *`RenderPass`* may need to use the
environment map.
To simplify this tutorial to focus on exactly how environment maps are used, we add an environment to
our *`ThinLensGBufferPass`* from [Tutorial 8](../Tutor8/tutorial08.md.html). Instead of storing a
constant background color to our G-buffer when we hit the background, we will now store a color from our
environment map.
To do this, in *`Tutor10-LightProbeEnvironmentMap.cpp`*, we swap out the
*`ThinLensGBufferPass`* for our new *`LightProbeGBufferPass`*, which handles jittered antialiasing, a thin lens
camera model, and rendering an environment mapped background all in a single, more complex *`RenderPass`*.
Setting up a Render Pass For Environment Mapping
=================================================================================
Look in *`LightProbeGBufferPass.h`*. This header looks almost identical to the *`ThinLensGBufferPass.h`* except for the
following addition:
~~~~~~~~~~~~~~~~~~~~C
bool usesEnvironmentMap() override { return true; }
~~~~~~~~~~~~~~~~~~~~
The method *`usesEnvironmentMap()`* overrides an inherited method from *`RenderPass`* and tells the pipeline that
our passes plan to use an environment light probe. Our tutorial framework does a couple things with this information. First,
it adds a control to the GUI allowing you to dynamically load new environment maps. Second,
it tells our *`ResourceManager`* to allocate a default environment map texture.
Loading an Environment Map
=================================================================================
Falcor and our tutorial framework have various built-in texture loading utilites. After adding the *`usesEnvironmentMap()`*
override above, you can dynamically load new light probes using the GUI. However, to specify
the environment map loaded on initialization, we add the following line in *`LightProbeGBufferPass::initialize()`*:
~~~~~~~~~~~~~~~~~~~~C
mpResManager->updateEnvironmentMap( "MonValley_G_DirtRoad_3k.hdr" );
~~~~~~~~~~~~~~~~~~~~
This tells the resource manager to creates an environment map and initialize it with the texture in
*`"MonValley_G_DirtRoad_3k.hdr"`*. Note that if *`updateEnvironmentMap()`* is called multiple times (e.g., in different
*`RenderPass::initialize()`* methods), the last one called wins.
Falcor uses [FreeImage](http://freeimage.sourceforge.net), so you can load any [image formats it supports](http://freeimage.sourceforge.net/features.html),
including .hdr, .exr, .dds, .png, and .jpg (among many others).
Sending an Evironment Map to a Miss Shader
=================================================================================
Look down in *`LightProbeGBufferPass::execute()`* and you will see the following new lines related to environment mapping:
~~~~~~~~~~~~~~~~~~~~C
// Pass our environment map down to our miss shader
auto missVars = mpRays->getMissVars(0);
missVars["gEnvMap"] = mpResManager->getTexture(ResourceManager::kEnvironmentMap);
missVars["gMatDif"] = mpResManager->getTexture("MaterialDiffuse");
~~~~~~~~~~~~~~~~~~~~
This sends down two variables (*`gEnvMap`* and *`gMatDif`*) for access in miss shader #0. Note: these
variables will *_only_* be accessible in miss shader #0. (However, since the code *_also_* sets *`"gMatDif"`*
as a hit shader variable later on, if is also accessible to hit group #0).
Using an Evironment Map in our Miss Shader
=================================================================================
Now that we loaded an environment map and sent it to our miss shader, we can index into it as follows
(see *`lightProbeGBuffer.rt.hlsl`*):
~~~~~~~~~~~~~~~~~~~~C
// The texture containing our environment map
Texture2D