Textures & Samplers
Texture coordinate convention: OpenGL's (0,0) is the bottom-left of the image; most image files start at the top-left — flip on load (stbi_set_flip_vertically_on_load(true)) or flip uv.y.
16.1 Sampling a 2-D texture
uniform sampler2D uAlbedo;
in vec2 vUV;
out vec4 outColor;
void main() {
vec4 c = texture(uAlbedo, vUV); // filtered sample, mip level chosen automatically
vec4 l = textureLod(uAlbedo, vUV, 2.0); // explicit mip level
vec4 o = textureOffset(uAlbedo, vUV, ivec2(1, 0)); // neighbor texel (constant offset)
vec4 t = texelFetch(uAlbedo, ivec2(gl_FragCoord.xy), 0); // exact texel, no filtering, integer coords
ivec2 size = textureSize(uAlbedo, 0); // dimensions of mip level 0
vec4 g = textureGrad(uAlbedo, vUV, dFdx(vUV), dFdy(vUV)); // explicit derivatives
vec4 four = textureGather(uAlbedo, vUV, 0); // red channel of the 4 texels used by bilinear filtering
outColor = c;
}16.2 Texture setup on the host
Texture coordinate convention: OpenGL's (0,0) is the bottom-left of the image; most image files start at the top-left — flip on load (stbi_set_flip_vertically_on_load(true)) or flip uv.y.
GLuint tex; glGenTextures(1, &tex);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB8_ALPHA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // trilinear
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // REPEAT, CLAMP_TO_EDGE, MIRRORED_REPEAT, CLAMP_TO_BORDER
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY, 16.0f); // anisotropic filtering (4.6 / extension)
// Separate sampler objects: glGenSamplers / glSamplerParameteri / glBindSampler(unit, sampler)16.3 Filtering & mipmapping concepts
Nearest (pixelated) vs linear (bilinear) filtering.
Mipmaps: prefiltered smaller versions; avoid aliasing/shimmering for distant/minified textures; selected via screen-space derivatives.
Trilinear (blend between mips) and anisotropic filtering (oblique surfaces).
Derivatives are undefined in non-uniform control flow → sample before branching, or use textureLod/textureGrad.
16.4 Texture types
uniform samplerCube uSkybox; vec4 sky = texture(uSkybox, direction); // cube maps
uniform sampler3D uVolume; vec4 v = texture(uVolume, vec3(uv, slice)); // 3-D textures (LUTs, volumes)
uniform sampler2DArray uLayers; vec4 a = texture(uLayers, vec3(uv, layerIndex)); // texture arrays
uniform sampler2DShadow uShadowMap; float lit = texture(uShadowMap, vec3(uv, depthRef)); // hardware depth compare
uniform sampler2DMS uMSAA; vec4 s = texelFetch(uMSAA, ivec2(gl_FragCoord.xy), sampleIndex);
uniform usampler2D uIDs; uint id = texelFetch(uIDs, px, 0).r; // integer textures
uniform samplerBuffer uData; vec4 d = texelFetch(uData, index); // buffer textures16.5 Texture tricks
// Tiling & scrolling
vec2 uv = vUV * 4.0 + vec2(uTime * 0.1, 0.0);
// Texture atlas: select a sub-rectangle
vec2 atlasUV = tileOffset + fract(uv) * tileSize;
// Triplanar mapping (no UVs needed)
vec3 w = abs(normalize(vNormal)); w /= (w.x + w.y + w.z);
vec4 tri = texture(uTex, vWorldPos.yz) * w.x + texture(uTex, vWorldPos.xz) * w.y + texture(uTex, vWorldPos.xy) * w.z;
// Distortion / heat haze
vec2 offset = (texture(uNoise, vUV + uTime * 0.05).rg - 0.5) * 0.02;
vec4 scene = texture(uScene, vUV + offset);
// Color grading with a 3-D LUT
vec3 graded = texture(uLUT, clamp(color, 0.0, 1.0)).rgb;