CS 4621: Lecture 3
Recap
- The GLSL Programming Language
- Vector data types:
vec2
, vec3
, vec4
, and so on.
- Matrix data types:
mat2
, mat3
, and mat4
.
- Arrays
- Swizzling
- Three ways to pass data to GLSL:
- Vertex attributes (per-vertex data)
- Uniform variables (data that is constant for all vertices)
- Textures (Other constant data, usually in the form of pixels or images)
- We'll introduce these today, and go into more depth in a later lecture.
- Varying variables transfer data between vertices and fragments.
- The full screen quad allows each fragment to know its position on the canvas. This enables powerful shading techniques.
Textures
- Another way to transfer data to the GPU is through textures.
- Think of a texture as a 2D array of data that has special accessors.
- Most commonly, textures are used to transfer pixel data to the GPU, but they are not limited to that.
- Textures are more flexible than uniform arrays:
- There is generally a much higher memory limit for texture data than uniform arrays.
- Uniform arrays can only be traversed by combinations of constants and loop indices; random access is not allowed. Textures do not have this restriction.
- Note that this means shaders cannot access indexed mesh structures through uniform arrays.
- Extents can be set dynamically at runtime.
- However, textures have a number of limitations as well.
- Very few data types are supported; most are different representations of color data.
- In WebGL 1, floating point data are not supported by default. There is an extension to enable floating point textures. In WebGL 2, floating point textures are allowed by default.
- Data values are assumed to be grouped in sets of 1 (greyscale), 3 (rgb), or 4 (rgba).
- In WebGL 1, texture dimensions are typically restricted to powers of 2. WebGL 2 allows arbitrarily sized textures.
- There are ways around this in WebGL 1, which we will discuss later.
- Values in textures are indexed by continuous UV coordinate, not integers.
- This means that if you want to find the value in row
i
, column j
, you need to know the size of the texture.
- Add
0.5
to each index before dividing by size to target the center of the pixel.
- UV coordinate for value at
(i,j)
with r
rows and c
columns: ((i + 0.5) / c, (j + 0.5) / r)
- In WebGL 1, all textures are assumed to be 2D. WebGL 2 allows 3D textures as well.
- Texture Management:
- On the JavaScript side, textures are referenced through texture objects generated by
gl.createTexture()
.
- To make all texture-related functions refer to a particular texture, call
gl.bindTexture(gl.TEXTURE_2D, texture)
.
- All subsequent WebGL commands that include
gl.TEXTURE_2D
as an argument will apply to texture
.
- To upload texture data to the GPU, use
gl.texImage2D(...)
.
- This function has many arguments; see this page for an explanation.
- On the GLSL side, you can access values in a texture through a sampler.
- Samplers are declared as uniform variables, e.g.,
uniform sampler2D sampler;
- Values are retrieved using
texture2D(sampler, uv)
. This returns a vec4
.
- Textures are linked to samplers on the JavaScript side through texture units.
- A texture unit is activated through
gl.activeTexture(gl.TEXTUREi)
where i
is replaced with the integer index of the texture unit.
- Use
gl.uniform1i
to set the sampler to the index of the appropriate texture unit.
- Make sure the texture is bound while you do this!
- If you no longer need a texture, you can free up resources by calling
gl.deleteTexture(texture)
.
Exhibits