# Cubemaps

You may need to read the articles about lighting and textures before this one.

A *cubemap* is a type of texture that consists of six faces, each referenced by their direction from the center of a cube. Cubemaps are sampled using normals representing the direction from the origin to the fragment instead of texture coordinates. A cubemap can be sampled using a `samplerCube`

variable. For example:

```
#version 300 es
precision highp float;
in vec3 v_normal;
uniform samplerCube u_texture;
out vec4 outColor;
void main() {
vec3 normal = normalize(v_normal);
outColor = texture(u_texture, normal);
}
```

## Environment Maps

The most common thing that cubemaps are used for are *environment maps*, which represent the environment of the scene. Environment maps are a way to approximate reflections. If a fragment shader knows the position and normal of its fragment relative to the origin, it can use the `reflect`

function to calculate a reflection. For example:

```
#version 300 es
precision highp float;
in vec3 v_surfacePosition;
in vec3 v_normal;
uniform samplerCube u_texture;
uniform vec3 u_cameraPosition;
out vec4 outColor;
void main() {
vec3 normal = normalize(v_normal);
vec3 cameraToSurfaceDirection =
normalize(v_surfacePosition - u_cameraPosition);
vec3 reflectionDirection =
reflect(cameraToSurfaceDirection, normal);
outColor = texture(u_texture, reflectionDirection);
}
```

Check out the source of the example texture here.

## Skyboxes

A *skybox* is a cubemap that represents the background of a scene (often a sky). Skyboxes can be implemented by using the inverse of the view projection matrix to rasterize the skybox to a plane that covers the entire rendering context.

The vertex shader should ensure that the skybox is always at the back of the depth buffer. For example:

```
#version 300 es
in vec4 a_position;
out vec4 v_position;
void main() {
gl_Position = a_position;
gl_Position.z = 1.0;
v_position = a_position;
}
```

The skybox is treated as being infinitely far away from the camera, so calculations involving it should use a *view direction matrix*, which is a view matrix with the translation component removed.

A fragment shader can multiply a fragment's position by the inverse of a *view direction projection matrix* (a product of a projection matrix a view direction matrix) to undo it. Then, it needs to manually divide the `xyz`

vector by `w`

to apply perspective. The result can be sampled from the environment map to make a skybox. For example:

```
#version 300 es
precision highp float;
in vec4 v_position;
uniform samplerCube u_texture;
uniform mat4 u_inverseViewDirectionProjection;
out vec4 outColor;
void main() {
vec4 t = u_inverseViewDirectionProjection * v_position;
vec3 skyboxNormal = normalize(t.xyz / t.w);
outColor = texture(u_texture, skyboxNormal);
}
```

The next article is about shadows.