3D Materials and Textures: How Surface Data Reaches the Screen
Understand materials, textures, UVs, samplers, color spaces, mipmaps, and the practical costs hidden inside a real-time 3D asset.
A mesh describes where a surface is. A material describes how that surface interacts with light, and textures supply spatially varying inputs to the material. Those jobs are related but not interchangeable. Adding a 4096 × 4096 image does not increase geometric detail, and adding triangles does not automatically make a surface look painted, metallic, rough, or transparent.
This separation is the foundation of useful optimization. If a model downloads slowly because of eight oversized images, decimating its mesh may barely change the result. If its silhouette is visibly faceted, resizing textures cannot repair it. Measure geometry and surface data as distinct systems before deciding what to change.
Five separate pieces of the texture system#
These terms are often collapsed into “the texture,” but each has a specific role.
A material is a collection of shading inputs and render state. In glTF's core metallic-roughness model, inputs can include base color, metallic factor, roughness factor, normal mapping, occlusion, and emissive output. Alpha mode and double-sided state affect how the primitive renders.
A texture connects an image to a sampler. It is a reusable binding, not necessarily a distinct image file.
An image contains encoded pixels, such as PNG, JPEG, or an extension format. In a GLB, image bytes may be stored in a buffer view instead of beside the model.
A sampler defines filtering and wrapping. It determines whether UVs outside 0–1 repeat, clamp, or mirror, and how pixels are filtered when the image covers a different number of screen pixels than its stored resolution.
UV coordinates are vertex attributes that map positions on the mesh to a 2D image domain. A material texture can select an available UV set, while supported extensions may transform those coordinates.
The glTF texture model keeps these objects separate so images and samplers can be reused. Following their references prevents accidental duplication during export.
What the common channels mean#
Base color#
Base color represents visible surface color before lighting. In the metallic-roughness workflow, its RGB meaning differs for metals and nonmetals: dielectric base color is diffuse reflectance, while metal base color represents specular color. Alpha may supply opacity or a mask, depending on the material alpha mode.
Base-color textures use the sRGB transfer function in glTF. The renderer converts stored values to linear space before lighting. Treating the same pixels as linear produces incorrect midtones even though the image opens normally in an editor.
Metallic and roughness#
Metallic and roughness are scalar properties. In glTF they share one image: roughness uses the green channel and metallic uses the blue channel. The red channel is unused by this core pair, allowing compatible workflows to pack another mask.
These are linear data channels, not color. Applying sRGB conversion changes their numbers. A stored 8-bit value of 128 is about 0.502 as linear data, but sRGB decoding produces roughly 0.216. That is a large material change.
Normal#
A tangent-space normal texture perturbs the direction used for lighting. Red and green commonly encode tangent-space X and Y; the third component can be stored or reconstructed. The map does not move the surface, alter its outline, or create real parallax.
Normal maps are linear data. Their result depends on vertex normals, tangents, UVs, triangulation, and tangent handedness agreeing with the baker. A green-channel convention mismatch can make dents appear as bumps. Test with a moving directional light that makes errors obvious.
Occlusion#
An occlusion texture approximates how much indirect light reaches a point. Core glTF reads it from the red channel. It is often packed with roughness and metallic into an ORM image: occlusion in R, roughness in G, metallic in B. Separate material references may point to that one image.
Occlusion should modulate appropriate indirect lighting, not paint permanent black shadows over all illumination. Excessive baked occlusion looks dirty and contradicts moving lights.
Emissive#
Emissive color makes a surface visibly self-lit in the material model. It does not automatically illuminate neighboring objects; that requires renderer-specific global illumination or actual lights. Emissive textures use sRGB encoding, while the factor multiplies the decoded color.
Resolution, download size, and GPU memory#
Image dimensions matter quadratically. Doubling width and height creates four times as many texels:
- 1024 × 1024 = 1,048,576 texels;
- 2048 × 2048 = 4,194,304 texels;
- 4096 × 4096 = 16,777,216 texels;
- 8192 × 8192 = 67,108,864 texels.
A 4096 × 4096 RGBA8 image occupies about 64 MiB at its top GPU level: 16,777,216 × 4 bytes. A complete mip chain adds approximately one third, bringing the uncompressed total to about 85.3 MiB. Four such maps can exceed 341 MiB even if their PNG or JPEG downloads total only 25 MB.
File compression and GPU representation are different budgets. PNG compresses repeated pixels losslessly for storage; JPEG compresses photographic color lossily. Neither normally remains PNG- or JPEG-compressed while sampled by a GPU. GPU-oriented formats such as KTX2 provide workflows designed for efficient transcoding or sampling, depending on device support.
Record at least three sizes:
- transferred bytes over the network;
- decoded CPU-side peak during loading;
- resident GPU texture memory after upload and mip allocation.
A small download can still produce a large allocation and a short-lived decode spike. Several full-size images decoding at once can be particularly costly on mobile browsers.
Choosing resolution from visible detail#
Do not choose 4096 because the source happened to be 4096. Estimate how much of the image the asset can display.
Suppose a unique UV layout uses 70% of a square texture and the object can occupy 1000 pixels vertically. A 2048 image offers roughly 1434 potentially useful texels along an equivalently packed dimension before island-specific variation. That may be ample. An 8192 image supplies far more samples than the display can reveal and contains 16 times as many texels as 2048.
For world assets, a team might define 256 or 512 texels per meter, then allocate islands by physical area and importance. For a product viewer, projected pixels are more direct: render the closest permitted view, inspect each region, and determine whether a smaller map changes the approved image.
Packing efficiency matters too. If islands use only 35% of the image, a 4096 texture can provide less useful surface resolution than a well-packed 2048 atlas for the relevant parts. Padding must still prevent lower mip levels from bleeding between islands.
Why mipmaps matter#
Mipmaps are progressively smaller versions of an image. A 1024 base level is followed by 512, 256, and so on down to 1 × 1. When the textured object becomes small, the renderer samples a suitable level instead of compressing thousands of unrelated texels into one screen pixel.
Mipmaps improve stability and cache behavior but require correct generation:
- normal-map mips should preserve meaningful vectors;
- alpha-mask mips may need coverage preservation;
- packed numeric channels must remain linear;
- color maps need appropriate color-space handling;
- UV islands need padding that survives coarse levels;
- atlases should avoid unrelated colors at island borders.
Without mips, distant detail can shimmer as the camera moves. With inadequate padding, seams may appear only at distance. Test beyond the close-up view.
Minification filtering controls how levels and texels combine. Trilinear filtering blends between two mip levels. Anisotropic filtering improves surfaces seen at grazing angles, such as floors, but increases sampling work. Apply it where it produces a visible benefit rather than selecting the maximum universally.
Wrapping and coordinate behavior#
Repeat wrapping tiles an image whenever UV coordinates pass an integer boundary. Clamp holds the edge texel outside the 0–1 range. Mirrored repeat alternates direction. The wrong sampler can create seams or unwanted tiling.
Texture transforms can offset, rotate, or scale a texture independently of base UVs when the runtime supports the relevant extension. This can help reuse a tiling material, but it does not eliminate the need to inspect UV ranges and sampler state.
Coordinate conventions also vary among tools. A vertically flipped image may result from origin handling, coordinate conversion, or a manual flip applied twice. Diagnose the whole path before changing source pixels.
Materials create rendering boundaries#
A mesh with six materials is normally partitioned into at least six primitives because one glTF mesh primitive references one material. Even if it is one named Blender object, the runtime may submit multiple draws. Fifty tiny material regions can therefore cost more CPU submission work than one geometrically complex surface.
Reducing material count can help, but atlasing has tradeoffs:
- unrelated parts may lose independent texture resolution;
- editing one part can require rebuilding a large atlas;
- repeated tiling regions may become uniquely baked;
- transparent and opaque surfaces need different render treatment;
- combining distant parts can interfere with culling;
- large atlases can increase peak memory and update cost.
Merge materials that share shader behavior and can use a coherent texture strategy. Do not combine them only to make a metric smaller.
Transparency is a render mode, not merely alpha#
Core glTF has three alpha modes. OPAQUE ignores alpha for coverage. MASK uses a cutoff, creating fully present or absent fragments. BLEND mixes the surface with what has already rendered.
Blending can introduce sorting artifacts, overdraw, and ordering constraints because transparent surfaces do not behave like ordinary depth-writing geometry. Use MASK for cutout leaves or fences when a hard threshold is acceptable. Reserve BLEND for genuinely partial coverage and test overlapping layers from several angles.
Double-sided materials also deserve scrutiny. Disabling back-face culling makes both orientations render. That is useful for thin sheets but can hide incorrectly wound geometry and increase fragment work. Give solid objects consistent outward-facing triangles instead.
A practical texture audit#
Export the actual GLB and inventory every image:
- semantic use and color-space expectation;
- width, height, channels, and encoded format;
- transferred bytes;
- estimated GPU format and mip memory;
- materials and UV sets that reference it;
- maximum projected size of the textured region;
- whether alpha contains meaningful variation;
- whether channels can be packed safely;
- whether a smaller candidate changes the target render.
Test reductions one variable at a time. Resize a 4096 base color to 2048 and compare. Convert an opaque RGBA image to RGB if the delivery format benefits. Pack compatible linear masks. Remove orphaned images. Change compression quality while inspecting gradients, text, and high-contrast edges.
Automated image metrics can flag large differences, but material evaluation remains perceptual. A small roughness error on a broad highlight may matter more than a larger pixel error inside a hidden region.
Frequent mistakes#
Treating every map as color. Numeric masks and normals must not receive the same transfer function as base color.
Counting only compressed bytes. Runtime memory can be many times larger than the image download.
Keeping unused alpha. A channel filled entirely with 255 may constrain formats or consume memory for no visual value.
Naively downscaling normal maps. Filtering without vector-aware processing can weaken or bias encoded directions.
Ignoring mip seams. A map can look perfect close up and fail when a lower level samples beyond an island.
Using one material per source part. Authoring organization should not automatically create dozens of runtime primitives.
Assuming emissive creates illumination. Visible glow and light cast into the scene are different features.
Delivery checklist#
- Every texture reference resolves and every image is used.
- Base-color and emissive maps are interpreted as sRGB.
- Normal, occlusion, roughness, and metallic data remain linear.
- ORM channel assignments match glTF material references.
- Dimensions follow measured projected-detail needs.
- GPU memory estimates include mip levels.
- UV islands have padding appropriate to the smallest used mip.
- Normal maps match triangulation and tangent basis.
- Opaque, masked, and blended materials use the least costly correct mode.
- Double-sided rendering is enabled only for intentionally thin geometry.
- Material count and primitive count are reviewed together.
- The final GLB is validated and rendered in the target engine.
Sources and further reading#
- Khronos glTF 2.0 specification: materials
- Khronos glTF Tutorial: textures, images, and samplers
- Khronos glTF Tutorial: metallic-roughness PBR
- Khronos KTX specification
- Blender Manual: UV unwrapping
Materials and textures form a data pipeline, not a decorative attachment. Once their references, numeric meanings, and memory costs are visible, teams can improve fidelity and delivery performance without guessing which part of the asset is responsible.