Cubemap Texture: Difference between revisions

From OpenGL Wiki
Jump to navigation Jump to search
Linking
m Mention that zoffset is used when uploading cube map data via glTexSubImage3D
 
(18 intermediate revisions by one other user not shown)
Line 4: Line 4:
}}
}}


A '''Cubemap Texture''' is a texture composed of 6 2D images. The images are arranged in a cube-shape, hence the name. Each separate face of the cube can have its own mipmaps.
A '''Cubemap Texture''' is a [[Texture|texture]], where each mipmap level consists of six 2D images which must be square. The 6 images represent the faces of a cube. The texture coordinate used to access a cubemap is a 3D direction vector which represents a direction from the center of the cube to the value to be accessed.


== Overview ==
Cubemaps can have multiple mipmap levels.


Cubemaps are a texture type, using the type GL_TEXTURE_CUBE_MAP. Cubemaps conceptually contain 6 2D textures, each one representing a particular face of a cube.
== Creation ==


=== Creation ===
Cubemaps are a texture type, using the type {{enum|GL_TEXTURE_CUBE_MAP}}. They are similar to 2D textures in that they have two dimensions. However, each mipmap level has 6 faces, with each face having the same size as the other faces. The width and height of a cubemap must be the same (ie: cubemaps are squares), but these sizes need not be powers of two.


To allocate storage for the 6 faces of the cubemap, bind the texture to GL_TEXTURE_CUBE_MAP. Then call glTexImage2D 6 times, using the same size, mipmap ''level'', and ''image format''. The ''target'' parameter specifies which of the 6 faces of the cubemap to specify. These faces are:
If {{require|4.3|texture_storage}} is available, then immutable storage for a cubemap texture can be allocated with {{apifunc|glTexStorage2D}}.


* GL_TEXTURE_CUBE_MAP_POSITIVE_X
To allocate mutable storage for the 6 faces of a cubemap's mipmap chain, bind the texture to {{enum|GL_TEXTURE_CUBE_MAP}}. [[Texture Storage#Cube map storage|Then call {{code|glTexImage2D}} 6 times, using the same size, mipmap {{param|level}}, and {{param|internalformat}}.]] The {{param|target}} parameter is not {{enum|GL_TEXTURE_CUBE_MAP}}; instead, it specifies which of the 6 faces of the cubemap is being allocated. These faces are:
* GL_TEXTURE_CUBE_MAP_NEGATIVE_X
 
* GL_TEXTURE_CUBE_MAP_POSITIVE_Y
* {{enum|GL_TEXTURE_CUBE_MAP_POSITIVE_X}}
* GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
* {{enum|GL_TEXTURE_CUBE_MAP_NEGATIVE_X}}
* GL_TEXTURE_CUBE_MAP_POSITIVE_Z
* {{enum|GL_TEXTURE_CUBE_MAP_POSITIVE_Y}}
* GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
* {{enum|GL_TEXTURE_CUBE_MAP_NEGATIVE_Y}}
* {{enum|GL_TEXTURE_CUBE_MAP_POSITIVE_Z}}
* {{enum|GL_TEXTURE_CUBE_MAP_NEGATIVE_Z}}


Cubemaps may have mipmaps, but each face must have the same number of mipmaps. Cubemaps can use any of the filtering modes and other texture parameters.
Cubemaps may have mipmaps, but each face must have the same number of mipmaps. Cubemaps can use any of the filtering modes and other texture parameters.


=== Texture Access ===
=== Upload and orientation ===


The [[GLSL Sampler|sampler]] type for cubemaps is <code>''g''samplerCube</code>. <code>''g''samplerCubeShadow</code> can also be used for shadow lookups. The fourth component of the texture coordinate for shadow lookups is the comparison value.
Uploading pixel data for cubemaps is somewhat complicated. If {{require|4.5|direct_state_access}} is available, then {{apifunc|glTexSubImage3D}} can be used to upload face data for a particular mipmap level. The third dimension values (''zoffset'') for {{apifunc|glTexSubImage3D}} represents which face(s) to upload data to. The faces are indexed in the following order:


The texture coordinates for cubemaps are 3D vector directions. These are conceptually directions from within the cube defined by the cubemap, pointing in a particular direction. The vectors do not have to be normalized.
<div style="font-size: 60%;">{{cubemap layer face ordering}}</div>


Filtering does not take place across cubemap face boundaries. So a visible seam can appear between cubemap face boundaries regardless of the texture filtering modes.
The older mechanism of uploading to faces of a cubemap uses {{apifunc|glTexSubImage2D}}. This function selects which face to upload to via the same mechanism as {{apifunc|glTexImage2D}} does: the {{enum|GL_TEXTURE_CUBE_MAP_*}} face targets mentioned above. So if you want to upload to the positive Y axis, you would set the {{param|textarget}} parameter of the call to {{enum|GL_TEXTURE_CUBE_MAP_POSITIVE_Y}}.
 
Understanding the orientation of a cubemap is very important, and it can be somewhat unusual due to differences with traditional OpenGL orderings. The following diagram shows how each face in the cubemap is oriented relative to the cube being defined.
 
[[File:CubeMapAxes.png|alt=Anatomy of a Texture|Diagram of the contents of a texture object]]
 
Note that the coordinate system for cubemaps is left-handed. If X is forward, and Y is up, then Z is to the left. The axis labels on the 6 face diagrams shows the direction that the given face will be oriented in cubemap space. So the positive Y axis face (the top of the cube, in our example) as the local V coordinate of the texture map going towards positive Z.
 
Let's say that +Z is forward, and +Y is up, so +X to the right. Given that orientation, the texture coordinates of the 6 faces of the cube look like this:
 
* +Z face (directly in front): The U coordinate goes to the right, with the V coordinate going down.
* +X face (to our right): The U coordinate is going behind the viewer, with the V coordinate going down.
* -Z face (directly behind): The U coordinate goes to the left (relative to us facing forwards), with the V coordinate going down.
* -X face (to our left): The U coordinate is going forward, with the V coordinate going down.
* +Y face (above): The U coordinate goes to the right, with the V coordinate going forward.
* -Y face (bottom): The U coordinate goes to the right, with the V coordinate going backward.
 
Intuitively, you can think of it as standing in the center of the cube and turning in place. The four faces in the X/Z plane are oriented as if you're rotating clockwise around the Y axis. The meaning of the Y axis never changes, but right/left is rotating around with you. For the top and bottom faces, it's like facing along the +Z axis and craning your head up and down. The meaning of the X axis doesn't change; it's always to the right. But if you're looking up, the direction that meant "up" now means "backwards"; if you're looking down, the direction that used to mean "down" now points forwards.
 
And of course V is flipped in all cases, because OpenGL uses a bottom-left coordinate system for its textures. So the diagram makes more sense if you mentally flip the V coordinate in the diagrams.
 
== Texture Access ==
 
The [[GLSL Sampler|sampler]] type for cubemaps is {{code|''g''samplerCube}}. {{code|''g''samplerCubeShadow}} can also be used for shadow lookups. The fourth component of the texture coordinate for shadow lookups is the comparison value.
 
The texture coordinates for cubemaps are 3D vector directions. These are conceptually directions from the center of the cube to the texel you want to appear. The vectors do not have to be normalized.
 
Filtering does not usually take place across cubemap face boundaries. So a visible seam can appear between cubemap face boundaries regardless of the texture filtering modes. Though a [[#Seamless cubemap|setting]] can permit filtering between faces.


== Layered Rendering ==
== Layered Rendering ==
{{main|Framebuffer Object#Layered Images}}
{{main|Framebuffer Object#Layered Images}}


Cubemaps can be bound to [[Framebuffer Object|framebuffer objects]] for layered rendering. The 6 faces are given a specific order, as defined in the linked article.
Cubemaps can be bound to [[Framebuffer Object|framebuffer objects]] for layered rendering. The 6 faces are given a specific order:
 
<div style="font-size: 60%;">{{cubemap layer face ordering}}</div>
 


== Seamless cubemap ==
== Seamless cubemap ==
Line 45: Line 77:
Under the standard filtering rules for cubemaps, filtering does not work across faces of the cubemap. This results in a seam across the faces of a cubemap. This was a hardware limitation in the past, but modern hardware is capable of interpolating across a cube face boundary.
Under the standard filtering rules for cubemaps, filtering does not work across faces of the cubemap. This results in a seam across the faces of a cubemap. This was a hardware limitation in the past, but modern hardware is capable of interpolating across a cube face boundary.


To globally enable this, use <code>glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS)</code>. In general, it is not a good idea to enable and disable this within a program. It should be set as part of initialization and never changed.
To globally enable seamless cubemap texture accesses, use {{apifunc|glEnable|(GL_TEXTURE_CUBE_MAP_SEAMLESS)}}.
{{clear float}}


== Cubemap array textures ==
== Cubemap array textures ==
Line 54: Line 87:
}}
}}


[[Array Texture|Array textures]] can also come in cubemap flavors, in addition to 1D and 2D. They use the texture type GL_TEXTURE_CUBE_MAP_ARRAY.
[[Array Texture|Array textures]] can also come in cubemap flavors, in addition to 1D and 2D. They use the texture type {{enum|GL_TEXTURE_CUBE_MAP_ARRAY}}.
 
Layers also have to be dealt with in an unusual way. Cubemap array textures have, for each mipmap, some number of cubemaps. That number of cubemaps is the number of layers. But since each cubemap is composed of 6 2D faces, array cubemaps also have a number of ''layer-faces'', which is 6 times the number of layers. Some interfaces count by layers, and others count by layer-faces.
 
The order of the faces within a layer is the standard order:


Uploading to cube map arrays works differently from uploading to regular cubemaps. They are uploaded like array textures, using glTex(Sub)Image3D.
<div style="font-size: 60%;">{{cubemap layer face ordering}}</div>


The layers work differently from 1D and 2D array textures. The ''depth'' parameter in the glTexImage3D call does not specify how many array layers there are. If you have N array layers in the cubemap array, then ''depth'' must be 6*N. Therefore, every group of 6 2D images in the 3D block of data is a single cubemap layer.
Every OpenGL API call that operates on cubemap array textures takes ''layer-faces'', not array layers. For example, when you allocate storage for the texture, you would use {{apifunc|glTexStorage3D}} or {{apifunc|glTexImage3D}} or similar. However, the {{param|depth}} parameter will be the number of layer-faces, not layers. So it must be divisible by 6.


The order of the faces within a 6 2D image group is the same as that used for layered rendering of cubemaps.
Similarly, when uploading texel data to the cubemap array, the parameters that represent the Z component are layer-faces. So if you want to upload to just the positive Z face of the second layer in the array, you would use call {{apifunc|glTexSubImage3D}}, with the {{param|zoffset​}} parameter set to 10 (layer 1 * 6 faces per layer + face index 4), and the {{param|depth}} set to 1 (because you're only uploading one layer-face).


Cubemap arrays can have mipmaps. They are uploaded in the same way as for other kinds of array textures.
Cubemap arrays can have mipmaps. They are uploaded in the same way as for other kinds of array textures. Remember that the number of layer-faces does not change for mipmaps.


=== Samplers ===
=== Samplers ===
The [[GLSL Sampler|sampler]] type for cubemap arrays is <code>''g''samplerCubeArray</code>. <code>''g''samplerCubeArrayShadow</code> can be used for comparison lookups. The texture coordinates are 4D values; the first three values are the vector direction, and the fourth value is the array layer to use. Note that here, the array layer is a value from 0 to N-1, where there are N layers. Remember that ''depth'', the number of uploaded 2D slices, is 6 times the number of array layers.
The [[GLSL Sampler|sampler]] type for cubemap arrays is {{code|''g''samplerCubeArray}}. {{code|''g''samplerCubeArrayShadow}} can be used for comparison lookups. The texture coordinates are 4D values; the first three values are the vector direction, and the fourth value is the layer to use. Note that this is the ''actual layer'' to use, not the layer-face.
 
For comparison modes, the texture functions take an additional parameter for the comparison value. The parameter always comes immediately after the texture coordinate.


For comparison modes, the texture functions take an additional parameter for the comparison value. The comparison parameter always comes immediately after the texture coordinate.


[[Category:Textures]]
[[Category:Textures]]

Latest revision as of 16:27, 16 June 2021

Cubemap Texture
Core in version 4.6
Core since version 1.3
ARB extension ARB_texture_cube_map

A Cubemap Texture is a texture, where each mipmap level consists of six 2D images which must be square. The 6 images represent the faces of a cube. The texture coordinate used to access a cubemap is a 3D direction vector which represents a direction from the center of the cube to the value to be accessed.

Cubemaps can have multiple mipmap levels.

Creation

Cubemaps are a texture type, using the type GL_TEXTURE_CUBE_MAP. They are similar to 2D textures in that they have two dimensions. However, each mipmap level has 6 faces, with each face having the same size as the other faces. The width and height of a cubemap must be the same (ie: cubemaps are squares), but these sizes need not be powers of two.

If OpenGL 4.3 or ARB_texture_storage is available, then immutable storage for a cubemap texture can be allocated with glTexStorage2D.

To allocate mutable storage for the 6 faces of a cubemap's mipmap chain, bind the texture to GL_TEXTURE_CUBE_MAP. Then call glTexImage2D 6 times, using the same size, mipmap level​, and internalformat​. The target​ parameter is not GL_TEXTURE_CUBE_MAP; instead, it specifies which of the 6 faces of the cubemap is being allocated. These faces are:

  • GL_TEXTURE_CUBE_MAP_POSITIVE_X
  • GL_TEXTURE_CUBE_MAP_NEGATIVE_X
  • GL_TEXTURE_CUBE_MAP_POSITIVE_Y
  • GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
  • GL_TEXTURE_CUBE_MAP_POSITIVE_Z
  • GL_TEXTURE_CUBE_MAP_NEGATIVE_Z

Cubemaps may have mipmaps, but each face must have the same number of mipmaps. Cubemaps can use any of the filtering modes and other texture parameters.

Upload and orientation

Uploading pixel data for cubemaps is somewhat complicated. If OpenGL 4.5 or ARB_direct_state_access is available, then glTexSubImage3D can be used to upload face data for a particular mipmap level. The third dimension values (zoffset) for glTexSubImage3D represents which face(s) to upload data to. The faces are indexed in the following order:

Layer number Cubemap face
0 GL_TEXTURE_CUBE_MAP_POSITIVE_X
1 GL_TEXTURE_CUBE_MAP_NEGATIVE_X
2 GL_TEXTURE_CUBE_MAP_POSITIVE_Y
3 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
4 GL_TEXTURE_CUBE_MAP_POSITIVE_Z
5 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z

The older mechanism of uploading to faces of a cubemap uses glTexSubImage2D. This function selects which face to upload to via the same mechanism as glTexImage2D does: the GL_TEXTURE_CUBE_MAP_* face targets mentioned above. So if you want to upload to the positive Y axis, you would set the textarget​ parameter of the call to GL_TEXTURE_CUBE_MAP_POSITIVE_Y.

Understanding the orientation of a cubemap is very important, and it can be somewhat unusual due to differences with traditional OpenGL orderings. The following diagram shows how each face in the cubemap is oriented relative to the cube being defined.

Anatomy of a Texture

Note that the coordinate system for cubemaps is left-handed. If X is forward, and Y is up, then Z is to the left. The axis labels on the 6 face diagrams shows the direction that the given face will be oriented in cubemap space. So the positive Y axis face (the top of the cube, in our example) as the local V coordinate of the texture map going towards positive Z.

Let's say that +Z is forward, and +Y is up, so +X to the right. Given that orientation, the texture coordinates of the 6 faces of the cube look like this:

  • +Z face (directly in front): The U coordinate goes to the right, with the V coordinate going down.
  • +X face (to our right): The U coordinate is going behind the viewer, with the V coordinate going down.
  • -Z face (directly behind): The U coordinate goes to the left (relative to us facing forwards), with the V coordinate going down.
  • -X face (to our left): The U coordinate is going forward, with the V coordinate going down.
  • +Y face (above): The U coordinate goes to the right, with the V coordinate going forward.
  • -Y face (bottom): The U coordinate goes to the right, with the V coordinate going backward.

Intuitively, you can think of it as standing in the center of the cube and turning in place. The four faces in the X/Z plane are oriented as if you're rotating clockwise around the Y axis. The meaning of the Y axis never changes, but right/left is rotating around with you. For the top and bottom faces, it's like facing along the +Z axis and craning your head up and down. The meaning of the X axis doesn't change; it's always to the right. But if you're looking up, the direction that meant "up" now means "backwards"; if you're looking down, the direction that used to mean "down" now points forwards.

And of course V is flipped in all cases, because OpenGL uses a bottom-left coordinate system for its textures. So the diagram makes more sense if you mentally flip the V coordinate in the diagrams.

Texture Access

The sampler type for cubemaps is gsamplerCube. gsamplerCubeShadow can also be used for shadow lookups. The fourth component of the texture coordinate for shadow lookups is the comparison value.

The texture coordinates for cubemaps are 3D vector directions. These are conceptually directions from the center of the cube to the texel you want to appear. The vectors do not have to be normalized.

Filtering does not usually take place across cubemap face boundaries. So a visible seam can appear between cubemap face boundaries regardless of the texture filtering modes. Though a setting can permit filtering between faces.

Layered Rendering

Cubemaps can be bound to framebuffer objects for layered rendering. The 6 faces are given a specific order:

Layer number Cubemap face
0 GL_TEXTURE_CUBE_MAP_POSITIVE_X
1 GL_TEXTURE_CUBE_MAP_NEGATIVE_X
2 GL_TEXTURE_CUBE_MAP_POSITIVE_Y
3 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
4 GL_TEXTURE_CUBE_MAP_POSITIVE_Z
5 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z


Seamless cubemap

Seamless Cubemap Filtering
Core in version 4.6
Core since version 3.2
Core ARB extension ARB_seamless_cube_map

Under the standard filtering rules for cubemaps, filtering does not work across faces of the cubemap. This results in a seam across the faces of a cubemap. This was a hardware limitation in the past, but modern hardware is capable of interpolating across a cube face boundary.

To globally enable seamless cubemap texture accesses, use glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS).

Cubemap array textures

Cubemap Array Textures
Core in version 4.6
Core since version 4.0
ARB extension ARB_texture_cube_map_array

Array textures can also come in cubemap flavors, in addition to 1D and 2D. They use the texture type GL_TEXTURE_CUBE_MAP_ARRAY.

Layers also have to be dealt with in an unusual way. Cubemap array textures have, for each mipmap, some number of cubemaps. That number of cubemaps is the number of layers. But since each cubemap is composed of 6 2D faces, array cubemaps also have a number of layer-faces, which is 6 times the number of layers. Some interfaces count by layers, and others count by layer-faces.

The order of the faces within a layer is the standard order:

Layer number Cubemap face
0 GL_TEXTURE_CUBE_MAP_POSITIVE_X
1 GL_TEXTURE_CUBE_MAP_NEGATIVE_X
2 GL_TEXTURE_CUBE_MAP_POSITIVE_Y
3 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
4 GL_TEXTURE_CUBE_MAP_POSITIVE_Z
5 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z

Every OpenGL API call that operates on cubemap array textures takes layer-faces, not array layers. For example, when you allocate storage for the texture, you would use glTexStorage3D or glTexImage3D or similar. However, the depth​ parameter will be the number of layer-faces, not layers. So it must be divisible by 6.

Similarly, when uploading texel data to the cubemap array, the parameters that represent the Z component are layer-faces. So if you want to upload to just the positive Z face of the second layer in the array, you would use call glTexSubImage3D, with the zoffset​​ parameter set to 10 (layer 1 * 6 faces per layer + face index 4), and the depth​ set to 1 (because you're only uploading one layer-face).

Cubemap arrays can have mipmaps. They are uploaded in the same way as for other kinds of array textures. Remember that the number of layer-faces does not change for mipmaps.

Samplers

The sampler type for cubemap arrays is gsamplerCubeArray. gsamplerCubeArrayShadow can be used for comparison lookups. The texture coordinates are 4D values; the first three values are the vector direction, and the fourth value is the layer to use. Note that this is the actual layer to use, not the layer-face.

For comparison modes, the texture functions take an additional parameter for the comparison value. The comparison parameter always comes immediately after the texture coordinate.