I am learning about Cubemap and I learned that A cubemap is basically a texture that contains 6 individual 2D textures but my question is Why does it contain 6 individual texture ? and also I've read that it uses 3D directional vector for sampling, so what are the advantages of using 3D directional vector ?
-
4$\begingroup$ Well, a cube has 6 faces to begin with, no? That's about the whole point of a cube map. However, I'm afraid your question is a little unclear. The "advantages of using 3D directional vector" as compared to what? That's just how cubemaps work. This largely comes down to how you learned about cubemaps and what you learned about them. Understandably just learning about their existence might leave you baffled what they are, but a proper source would tell you how they work and what they're for. $\endgroup$– Christian RauJun 27, 2019 at 11:22
2 Answers
A texture is just a fancy lookup table; that's all it is. It's a function that you input some coordinate T
into, which returns a value for that particular T
.
There are many ways that one might choose to build such a function. A 1D texture is a lookup table where the coordinate is a single value on the range [0, 1]. A 2D texture is a texture where the coordinate is a pair of values, each on the range [0, 1]. A 3D texture has its coordinates as a triple of values.
You can think of these textures as lookup tables that answer the question, "what is the value at the position T
within a normalized [0, 1] space?" 2D textures use a two-dimensional space. 3D textures use a three-dimensional space. But they're all asking about the value at a position.
A cubemap is a lookup table that answers the question "what is the value in the direction T
?" A 2D texture maps a position into a value; a cubemap maps a direction into a value.
The purpose of any texture, within a shader, is to fill in some parameter in the rendering equation. A texture might be used to define a surface's albedo, shininess, or some other surface property. But a texture might also be used to look up how much light reaches that particular point on the surface; that's what shadow mapping is all about. Textures are not just about changing material properties of a surface; they're useful for many kinds of math in shaders.
Directional textures (ie: cubemaps) are often used for point-light shadow maps. Given a position on a surface, they answer the question "can I see the light from here?" Well, "from here" means using a direction towards the light. Since point lights are within the scene and cast light in all directions, a direction from the light to the current point on the surface represents the path the light would follow to reach that surface.
So a cube shadow map stores the distance from the light to the nearest occluding surface in all directions around the point light. And when a surface checks to see if it is in shadow from that light, it computes the direction from the point light to the surface and checks the directional shadow map.
Cubemaps have 6 "textures" (no, they don't have 6 textures. They have 6 sets of potentially mipmapped 2D images. There's a difference between a texture and an image) because a cube has 6 faces. A cubemap implements its mapping from a direction to a value by taking that direction and figuring out which point(s) on these images correspond to that direction.
Imagine being in the center of a cube. Each surface around you is one of these 6 images. For any pixel in those images, there is a unique direction from the center of the cube to that pixel. That creates the mapping from direction to pixel values.
Why are directional textures cubes instead of something else? Because it's the easiest way to create a directional texture. GPU hardware already knows how to deal with 2D images, how to access pixels from them, how to filter such accesses, and how to do mipmapping on them. All you really need to make cubemaps work is to tie together sets of 6 mipmap image chains and change the mapping algorithm, the means of converting a particular T
into a pixel location. You don't have to invent some way of storing spherical information or somesuch.
Why starting from a 3D direction vector? Because that is most commonly the way you get the direction from the sight line where you want to sample the env map along.
Technically you can use any convex 3D shape as the surface of the map. For example a tetrahedron that gets unfolded into 2 rhomboids.
However the GPU is already optimized to render to a rectangle. This makes the cubemap easy to create at runtime. And the math to get which face to sample from and the coordinates from which to sample are extremely easy to calculate when dealing with an axis aligned cube. It boils down to finding the max value and dividing the other 2 coordinates with that max value.
The cubemap has some distortion around the corners of the cube but very much within reason.
You can also use another projection that lets you go from the direction to a coordinate on a single texture. These typically start from a latitude/longitude on a sphere direction and then map it to a texture using some map projection. Getting that lat/lon from a 3D direction vector requires using trig functions which are slower compared to the compares and divide the cubmap requires.
The simplest possible projection from lat/long to UV will create a lot of distortion at the poles. Which leads to massive oversampling of that area and can lead to artifacts.