# 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 that represent the direction from the origin to the desired texel (rather than texture coordinates). A cubemap can be sampled using a `samplerCube`

variable.

```
#version 300 es
precision mediump 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 a 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.

```
#version 300 es
precision mediump float;
in vec3 v_worldPos;
in vec3 v_normal;
uniform samplerCube u_texture;
uniform vec3 u_camPos;
out vec4 outColor;
void main() {
vec3 normal = normalize(v_normal);
vec3 camToSurfaceDir = normalize(v_worldPos - u_camPos);
vec3 reflectDir = reflect(camToSurfaceDir, normal);
outColor = texture(u_texture, reflectDir);
}
```

You can find 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 sample the skybox onto 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.

```
#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.

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

The next article is about shadows.