# Reflections and Refractions

> Learn all about reflection and refraction in Babylon.js.

Source: https://doc.babylonjs.com/features/featuresDeepDive/materials/using/reflectionTexture

## About environment mapping

Babylon.js uses _environment mapping_ ([wikipedia](https://en.wikipedia.org/wiki/Reflection_mapping)) to simulate reflection (mirror-like materials) and refraction (glass-like materials).

Environment maps are pictures of the world (as seen from some vantage point) which are transformed and applied to meshes to simulate reflection or refraction. These pictures may be single images or composite panoramas, and may be static snapshots or dynamically updated to track scene changes.

Once created (as described below), environment maps may be used in [StandardMaterial](https://doc.babylonjs.com/typedoc/classes/babylon.standardmaterial)'s [.reflectionTexture](https://doc.babylonjs.com/typedoc/classes/babylon.standardmaterial#reflectiontexture) or [.refractionTexture](https://doc.babylonjs.com/typedoc/classes/babylon.standardmaterial#reflectiontexture); environment maps are also used in [Physically Based Rendering](https://doc.babylonjs.com/features/featuresDeepDive/materials/using/introToPBR) for sophisticated material surfaces.

## Static environment maps (CubeTexture and friends)

[CubeTexture](https://doc.babylonjs.com/typedoc/classes/babylon.cubetexture) instances use six images to make a static wraparound environment map (or "cubemap"). [The CubeMap constructor](https://doc.babylonjs.com/typedoc/classes/babylon.cubetexture#constructor) takes a base URL and appends "\_px.jpg", "\_nx.jpg", "\_py.jpg", "\_ny.jpg", "\_pz.jpg" and "\_nz.jpg" to load images for the +x, -x, +y, -y, +z, and -z facing sides of a cube.

![Diagram of X/Y/Z axes and CubeTexture sides](https://doc.babylonjs.com/img/how_to/Materials/cubetexture1.webp)

([Use the _extensions_ argument](https://doc.babylonjs.com/typedoc/classes/babylon.cubetexture#constructor) to customize these suffixes, e.g. to load .png instead of .jpg images.)

Despite the "Texture" name, CubeTexture can _only_ be used with the [.reflectionTexture](https://doc.babylonjs.com/typedoc/classes/babylon.standardmaterial#reflectiontexture) or [.refractionTexture](https://doc.babylonjs.com/typedoc/classes/babylon.standardmaterial#reflectiontexture) properties of [StandardMaterial](https://doc.babylonjs.com/typedoc/classes/babylon.standardmaterial), _not_ other properties like [.diffuseTexture](https://doc.babylonjs.com/typedoc/classes/babylon.standardmaterial#diffusetexture).

### Skybox cubemaps

[Skybox images](https://doc.babylonjs.com/features/featuresDeepDive/environment/skybox) may be used directly as environment maps. (Conveniently, skyboxes also typically use CubeTexture.) In this case only the skybox will show up in the reflection/refraction; other scene members will not be reflected, but that may be acceptable for simple scenes or small surfaces.

This classic cloudy skybox helps demonstrate skybox reflection:

|                                      +x (right)                                       |                                       -x (left)                                       |                                          +y (up)                                           |                                      -y (down)                                       |                                       +z (back)                                       |                                      -z (front)                                       |
| :-----------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------: |
| ![Some clouds](https://doc.babylonjs.com/img/getstarted/skybox_px.webp) | ![More clouds](https://doc.babylonjs.com/img/getstarted/skybox_nx.webp) | ![The sun overhead](https://doc.babylonjs.com/img/getstarted/skybox_py.webp) | ![Solid gray](https://doc.babylonjs.com/img/getstarted/skybox_ny.webp) | ![More clouds](https://doc.babylonjs.com/img/getstarted/skybox_pz.webp) | ![More clouds](https://doc.babylonjs.com/img/getstarted/skybox_nz.webp) |

<br/>

<p>[Playground: Cube Reflecting Skybox](https://playground.babylonjs.com/#UU7RQ#3) - A cube reflecting skybox images.
[Playground: Ground Reflecting Skybox](https://playground.babylonjs.com/#UU7RQ#5) - A ground plane reflecting skybox images.
[Playground: Sphere Reflecting Skybox](https://playground.babylonjs.com/#UU7RQ#4) - A sphere reflecting skybox images.</p>

With two shapes in the scene, it becomes clear that only the skybox is reflected:

<p>[Playground: Vampire Cube Isn't Reflected](https://playground.babylonjs.com/#UU7RQ#1590) - A cube reflecting skybox images but not reflecting a nearby red cube.</p>

This "vampire effect" can be fixed by carefully adding scene contents to cubemap images, or by using [dynamic maps](#dynamic-environment-maps-rendertargettexture-and-friends).

### Local cubemaps

Environment maps (static or dynamic) are flat images with no depth. By default, they are treated as infinitely far away. This works for distant environments (like skyboxes) or small surfaces, but can cause parallax errors in other cases.

As an alternative, cubemaps can be treated as axis-aligned boxes of a specific size and location by setting the cubemap texture's [.boundingBoxSize](https://doc.babylonjs.com/typedoc/classes/babylon.cubetexture#boundingboxsize) and [.boundingBoxPosition](https://doc.babylonjs.com/typedoc/classes/babylon.cubetexture#boundingboxposition) to the desired box size and position (as [Vector3](https://doc.babylonjs.com/typedoc/classes/babylon.vector3)).

<p>[Playground: Local cubemap demo](https://playground.babylonjs.com/#RNASML#37) - Demonstration of the effect of local cubemap projection.</p>

(Local cubemaps must use the default CUBIC_MODE [coordinate mode](#coordinate-modes).)

An axis-aligned box is still an approximation of true reflected/refracted scene geometry, but it may be a useful approximation. See "[Reflections Based on Local Cubemaps](https://developer.arm.com/documentation/102179/0100/Implement-reflections-with-a-local-cubemap)" (from the ARM Developer's Graphics and Gaming Blog) for a good write-up of the concept as used in Unity (Babylon.js's implementation is similar).

### EquiRectangularCubeTexture

Equirectangular panoramic images ([panotools wiki](https://wiki.panotools.org/Equirectangular_Projection)) squish a spherical panorama into one image (unlike the six sides needed for ordinary CubeTexture) using equirectangular projection ([wikipedia](https://en.wikipedia.org/wiki/Equirectangular_projection)).

<p>![A warped view of a dock with boats](https://playground.babylonjs.com/textures/equirectangular.jpg)</p>

[EquiRectangularCubeTexture](https://doc.babylonjs.com/typedoc/classes/babylon.equirectangularcubetexture) instances load an equirectangular panorama image into a CubeTexture-compatible environment map.

- [Playground: Spheres Reflecting Equirectangular Skybox](https://playground.babylonjs.com/#RY8LDL#32) - Reflections and refractions of an equirectangular skybox panorama.

### HDRCubeTexture

High Dynamic Range ([wikipedia](https://en.wikipedia.org/wiki/High-dynamic-range_imaging)) images capture brighter and dimmer colors than a typical monitor can display. This can be useful for environment mapping even if the final output uses standard dynamic range.

<p>![A warped view of a room with lamps](https://doc.babylonjs.com/img/how_to/Materials/room.webp)</p>

[HDRCubeTexture](https://doc.babylonjs.com/typedoc/classes/babylon.hdrcubetexture) instances (Babylon.js v3.2+) load a Radiance RGBE format ([wikipedia](https://en.wikipedia.org/wiki/RGBE_image_format)) HDR equirectangular panorama image into a CubeTexture-compatible environment map.

- [Playground: HDR Skybox](https://playground.babylonjs.com/#114YPX#5) - An HDR equirectangular skybox panorama.

### EXRCubeTexture

EXR images ([wikipedia](https://en.wikipedia.org/wiki/OpenEXR)), like HDR textures, can be useful for environment mapping even if the final output uses standard dynamic range.

[EXRCubeTexture](https://doc.babylonjs.com/typedoc/classes/babylon.exrcubetexture) instances (Babylon.js v8.27+) load an EXR equirectangular panorama image into a CubeTexture-compatible environment map.

This follows exactly the same code as the HDRCubeTexture section.

### Flat textures as environment maps

Wraparound cubemaps work well for environment mapping, but ordinary flat Texture instances can be used for [.reflectionTexture](https://doc.babylonjs.com/typedoc/classes/babylon.standardmaterial#reflectiontexture) and [.refractionTexture](https://doc.babylonjs.com/typedoc/classes/babylon.standardmaterial#reflectiontexture) as well. The texture's .coordinatesMode must be set to define how the flat image should be "wrapped around" as an environment ([see "Coordinate Modes"](#coordinate-modes)).

<p>![Mona Lisa's head](https://doc.babylonjs.com/img/how_to/Materials/mona_lisa_head.webp)</p>

<p>[Playground: Mona Lisa in SPAAAACE, reflected using PLANAR_MODE](https://playground.babylonjs.com/#UU7RQ#1629) - A sphere reflecting a flat Mona Lisa texture.</p>

(Note, cubemaps are normally preferred for environment mapping instead of flat textures.)

## Dynamic environment maps (RenderTargetTexture and friends)

[RenderTargetTexture](https://doc.babylonjs.com/typedoc/classes/babylon.rendertargettexture) instances hold environment maps updated during scene rendering, allowing reflections and refractions to track the scene in real time (unlike the [static maps](#static-environment-maps-cubetexture-and-friends) described above).

RenderTargetTexture instances are usually created through classes like ReflectionProbe or MirrorTexture, which manage the dynamic update process.

### ReflectionProbe

Each [ReflectionProbe](https://doc.babylonjs.com/typedoc/classes/babylon.reflectionprobe) instance provides a cubemap (in [.cubeTexture](https://doc.babylonjs.com/typedoc/classes/babylon.reflectionprobe#cubetexture)) that is dynamically rendered from a specified point in the scene, typically at or near an object that will use the cubemap.

<p>[Playground: Reflection Probes](https://playground.babylonjs.com/#KA93U#243) - Moving shapes reflecting each other and the ground using reflection probes.</p>

You must set each ReflectionProbe's [.renderList](https://doc.babylonjs.com/typedoc/classes/babylon.reflectionprobe#renderlist) to an explicit list of meshes to render. Be mindful of efficiency as each probe renders six times (once for each cube face) for every update. See the [Reflection Probes main page](https://doc.babylonjs.com/features/featuresDeepDive/environment/reflectionProbes) for more details.

### MirrorTexture

[MirrorTexture](https://doc.babylonjs.com/typedoc/classes/babylon.mirrortexture) (a RenderTargetTexture subclass) acts as a dynamically rendered environment map for flat mirrors.

<p>[Playground: Mirrors](https://playground.babylonjs.com/#1YAIO7#747) - Several mirrors surrounding a sphere.</p>

As with reflection probes, you must set each MirrorTexture's [.renderList](https://doc.babylonjs.com/typedoc/classes/babylon.mirrortexture#renderlist) to an explicit list of meshes to show in the mirror, keeping efficiency in mind. You must also set each MirrorTexture's [.mirrorPlane](https://doc.babylonjs.com/typedoc/classes/babylon.mirrortexture#mirrorplane) to the [Plane](https://doc.babylonjs.com/typedoc/classes/babylon.plane) of reflection, with the plane's normal pointing _into_ the mirror (away from the viewer).

You may set Plane coordinates directly, but it can be convenient to build the Plane from mesh geometry:

```javascript
// Create, position, and rotate a flat mesh surface.
const mesh = BABYLON.MeshBuilder.CreatePlane("mirrorMesh", {width: 5, height: 5}, scene);
mesh.position = new BABYLON.Vector3(0, 0, 4);
mesh.rotation = new BABYLON.Vector3(Math.PI/4, Math.PI/6, Math.PI/8);

// Create the reflective material for the mesh.
mesh.material = new BABYLON.StandardMaterial("mirrorMaterial", scene);
mesh.material.reflectionTexture = new BABYLON.MirrorTexture("mirrorTexture", 512, scene, true);

// Get a normal vector from the mesh and invert it to create the mirror plane.
mesh.material.reflectionTexture.mirrorPlane = BABYLON.Plane.FromPositionAndNormal(
    mesh.position, mesh.getFacetNormal(0).scale(-1));
mesh.material.reflectionTexture.renderList = [... list of meshes ...];
```

To create a blurred reflection, set MirrorTexture's [.blurKernel](https://doc.babylonjs.com/typedoc/classes/babylon.mirrortexture#blurkernel) to the blur kernel size (higher is blurrier) relative to the render texture size (set when MirrorTexture is created). Use [.adaptiveBlurKernel](https://doc.babylonjs.com/typedoc/classes/babylon.mirrortexture#blurkernel) instead to scale the blur value by the ratio of the render texture size and viewport size.

<p>[Playground: Reflection Blur](https://playground.babylonjs.com/#LVTTQX#1) - A shape reflected in a surface with blurring.</p>

### RefractionTexture

[RefractionTexture](https://doc.babylonjs.com/typedoc/classes/babylon.refractiontexture) (also a RenderTargetTexture subclass) is similar to MirrorTexture, but designed for refraction instead of reflection.

RefractionTexture acts as a dynamically rendered single-image environment map for flat _refractors_ (materials like glass or water that bend light). You can use RefractionTexture instances directly in [.refractionTexture](https://doc.babylonjs.com/typedoc/classes/babylon.standardmaterial#reflectiontexture). (Note, RefractionTexture simulates fixed-thickness plates of refractive material, and does not support lenses or shapes "bent" by immersion.)

<p>[Playground: Refraction](https://playground.babylonjs.com/#22KZUW#15) - A refractive disc in a simple scene.</p>

As with MirrorTexture, you must set each RefractionTexture's [.renderList](https://doc.babylonjs.com/typedoc/classes/babylon.refractiontexture#renderlist) to an explicit list of meshes to show in the refraction, keeping efficiency in mind.

You must also set each RefractionTexture's [.refractionPlane](https://doc.babylonjs.com/typedoc/classes/babylon.refractiontexture#refractionplane) to the [Plane](https://doc.babylonjs.com/typedoc/classes/babylon.plane) of refraction, with the plane's normal pointing _out of_ the refractor (_toward_ the viewer). You may set Plane coordinates directly, but it can be convenient to build the Plane from mesh geometry as described above for MirrorTexture (but without the `.scale(-1)` call).

Finally, you must set each RefractionTexture's [.indexOfRefraction](https://doc.babylonjs.com/typedoc/classes/babylon.refractiontexture#indexofrefraction) and [.depth](https://doc.babylonjs.com/typedoc/classes/babylon.refractiontexture#depth) to the index of refraction ([wikipedia](https://en.wikipedia.org/wiki/Refractive_index)) and thickness of the refractive plate to simulate.

<p>
[Playground: Changing Index Of Refraction](https://playground.babylonjs.com/#1YAIO7#19) - A plate with varying index of refraction.
[Playground: Changing Refraction Depth](https://playground.babylonjs.com/#1YAIO7#20) - A plate with varying refraction depth.
</p>

## Coordinate modes

By default, cubemap textures (static and dynamic) simulate the physical Laws of Reflection ([wikipedia](<https://en.wikipedia.org/wiki/Reflection_(physics)#Laws_of_reflection>)), to create realistic shiny surfaces. However, you may set a texture's [.coordinatesMode](https://doc.babylonjs.com/typedoc/classes/babylon.texture#coordinatesmode) to select different reflection behavior, and [flat (non-cubemap) textures](#flat-textures-as-environment-maps) always require you to set .coordinatesMode. (Refraction does not use coordinate modes.)

See the source ([reflectionFunction.fx](https://github.com/BabylonJS/Babylon.js/tree/master/packages/dev/core/src/Shaders/ShadersInclude/reflectionFunction.fx), called by [default.fragment.fx](https://github.com/BabylonJS/Babylon.js/tree/master/packages/dev/core/src/Shaders/default.fragment.fx)) for the mathematical definition of each mode.

| coordinatesMode                                          | Description                                                                                                                                                                                                                                            |
| -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| CUBIC_MODE                                               | The default mode for cubemaps. Works best with cubemaps, but will project flat textures onto the X/Y axes of an environment sphere as 4 upside-down copies.                                                                                            |
| INVCUBIC_MODE                                            | Like CUBIC_MODE, but inverts texture Y, so flat texture images are right side up.                                                                                                                                                                      |
| PLANAR_MODE                                              | Like CUBIC_MODE, but handles flat texture scaling and ][translation](https://doc.babylonjs.com/typedoc/classes/babylon.transformnode#translate) slightly better. (Despite the name, PLANAR_MODE is not otherwise plane-oriented.)                                                                                                    |
| SKYBOX_MODE                                              | Rather than reflecting, applies texture images directly to the object surface. Mostly used to make [skyboxes](https://doc.babylonjs.com/features/featuresDeepDive/environment/skybox). Works best for cubemaps, but will project flat textures onto the X/Y axes of the object. |
| EQUI&shy;RECTANGULAR\_<wbr/>MODE                         | Wraps flat textures into an environment map with equirectangular projection ([wikipedia](https://en.wikipedia.org/wiki/Equirectangular_projection)). Not recommended for cubemaps.                                                                     |
| FIXED\_<wbr/>EQUIRECTANGULAR\_<wbr/>MODE                 | Like SKYBOX_MODE, but wraps flat textures around the object with equirectangular projection. Does not support [reflection matrix](#the-reflection-matrix) transforms. Not recommended for cubemaps.                                                    |
| FIXED\_<wbr/>EQUIRECTANGULAR\_<wbr/>MIRRORED\_<wbr/>MODE | Like FIXED_EQUIRECTANGULAR_MODE, but inverts texture X so images look "correct" on the outside of an object.                                                                                                                                           |
| PROJECTION_MODE                                          | Scales flat textures to the _screen size_ and shows them wherever the material is visible, as if projecting from the camera onto the scene. Mostly used for special effects. Not recommended for cubemaps.                                             |
| SPHERICAL_MODE                                           | Performs reflection in _screen coordinates_ rather than world coordinates. Not useful in most cases.                                                                                                                                                   |
| EXPLICIT_MODE                                            | Uses only one point of the texture. Not useful in most cases.                                                                                                                                                                                          |

### Examples with a test pattern cubemap

|                                             +x (right)                                             |                                             -x (left)                                              |                                              +y (up)                                               |                                             -y (down)                                              |                                             +z (back)                                              |                                             -z (front)                                             |
| :------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------: |
| ![RGT test pattern](https://doc.babylonjs.com/img/how_to/Materials/testcube_px.webp) | ![LFT test pattern](https://doc.babylonjs.com/img/how_to/Materials/testcube_nx.webp) | ![TOP test pattern](https://doc.babylonjs.com/img/how_to/Materials/testcube_py.webp) | ![BOT test pattern](https://doc.babylonjs.com/img/how_to/Materials/testcube_ny.webp) | ![BCK test pattern](https://doc.babylonjs.com/img/how_to/Materials/testcube_pz.webp) | ![FRT test pattern](https://doc.babylonjs.com/img/how_to/Materials/testcube_nz.webp) |

<br/>

<p>[Playground: PLANAR, (INV)CUBIC, SKYBOX, and PROJECTION Modes with Test Cubemap](https://playground.babylonjs.com/#20OAV9#4308) - Demonstration of cubemap reflection coordinate modes</p>

### Examples with a test pattern flat texture

![Letters A-Y in a grid](https://doc.babylonjs.com/img/how_to/Materials/letter_grid.webp)<br/>

<p>[Playground: PLANAR, EQUIRECTANGULAR, PROJECTION, and SPHERICAL Modes with Flat Test Pattern](https://playground.babylonjs.com/#20OAV9#4307) - Demonstration of flat texture reflection coordinate modes</p>

### The reflection matrix

In addition to selecting the overall coordinate mode, a texture's reflection matrix ([.getReflectionTextureMatrix()](https://doc.babylonjs.com/typedoc/classes/babylon.texture#getreflectiontexturematrix)) may be adjusted to transform the environment map to match scene changes (e.g. a moving background) or for special effects.

<p>[Playground: Sphere Reflecting Rotating Skybox](https://playground.babylonjs.com/#UU7RQ#1631) - A sphere reflecting spinning skybox images</p>

## Further reading

- [Skyboxes](https://doc.babylonjs.com/features/featuresDeepDive/environment/skybox)
- [Reflection Probes](https://doc.babylonjs.com/features/featuresDeepDive/environment/reflectionProbes)
- [Introduction to Physically Based Rendering](https://doc.babylonjs.com/features/featuresDeepDive/materials/using/introToPBR)
