Getting Texture Data Into Your Pipeline
I used to spend days fighting subsurface scattering issues on character models before I stopped treating textures as just images slapped onto geometry. The workflow starts with understanding what you are actually mapping and where the bottlenecks live. I learned this the hard way when a client sent me three terabytes of unorganized scan data from a concrete facade and demanded photorealistic PBR output by the end of the week. I ended up writing a Python script that batch-renamed and sorted the albedo, roughness, and normal maps by surface region before they even hit Substance. That took about forty minutes and saved what would have been three days of manual cataloging. The first decision you need to make is whether you are working with scanned photographic data or procedural setups. Scanned data gives you real-world accuracy but introduces problems like inconsistent lighting across the capture passes and resolution mismatches between passes. Procedural textures avoid those issues entirely but require more upfront mathematical thinking about how the pattern should behave at different scales. Most production pipelines use a hybrid approach where base patterns come from nodes and imperfections are baked from scans.
Different Types Of Textures
Albedo or diffuse maps store the base color information and that is about as straightforward as it gets, but people still mess this up constantly by packing color data into formats that do not support enough bit depth. A ten-bit PNG for albedo on a large architectural exterior will show banding in the sky reflections unless you are careful about tone mapping. Normal maps encode surface directionality into RGB channels and the tricky part is knowing which convention your engine expects. Unity uses tangent-space conventions that flip the green channel compared to Unreal, and if you export from Blender without checking the forward and up axis settings you will get normals that point the wrong way. You can catch this immediately by looking at a white sphere with normal mapping applied. If the highlight sits on the wrong side of the sphere, your handedness is flipped. Roughness and metallic maps are single-channel grayscale textures where white means maximum roughness or maximum metallic reflectance depending on which map you are looking at. This is where a lot of beginners go wrong because they assume roughness works like a reflection intensity slider. It does not. Roughness controls the microfacet distribution, meaning a value of zero gives you a perfect mirror and a value of one gives you a completely matte surface with zero specular contribution. The counter-intuitive part is that most real-world materials sit somewhere between 0.3 and 0.7 roughness. A polished car hood might be 0.05. Wet pavement might be 0.2. Dry concrete is usually around 0.9. If your material looks plastic, check the roughness value before you change the color or the normal map. Height and displacement maps use luminance values to physically displace geometry rather than just simulating the illusion of depth. Bump mapping fakes it with normals. Displacement actually moves vertices. I ran into a specific edge case last year where a displacement map I exported from ZBrush was reading as inverted on the GPU because the software stored height data as unsigned 16-bit integers but the rendering engine expected signed 32-bit floats. The walls of a procedural cave architecture were collapsing inward instead of bulging outward. The fix was converting the texture to OpenEXR format with the proper bit depth and applying a invert node in the material editor to flip the luminance values back. That whole debugging session took about six hours because the asset looked correct in the viewport but wrong in render, and viewport shading often previews displacement differently than the final pass.
AO or ambient occlusion maps simulate indirect shadowing in crevices and contact points. You can bake these directly from geometry or paint them by hand, but baked AO tends to look muddy when you combine it with a strong directional light. The workaround I use is to sample the AO map at a lower resolution and blend it back in at maybe forty percent strength rather than letting it sit at full opacity. This preserves the contact shadow information without crushing the midtones of the underlying albedo. Emissive maps define which parts of a surface emit light. This is not the same as making a material bright. Emission adds actual radiance to the scene that other surfaces can reflect and that can expose the camera sensor in a render. I once had a client complain that their product visualization looked flat until I realized the emissive map on the LCD screen of a monitor prop was set to pure white at full intensity while the rest of the scene had reasonable HDRI lighting. The renderer was trying to represent infinite brightness on a small area and it was throwing off the entire exposure. Dialing the emissive strength down to about 2000 nits and enabling tone mapping in the render engine fixed it without changing anything else in the scene. Thickness maps control how light scatters through thin materials like leaves, skin, fabric, and wax. This is probably the most underused texture type in indie and small studio pipelines because it requires additional shader support and not every render engine exposes it cleanly. When it is available though, it makes a dramatic difference in translucency. Without a thickness map, subsurface scattering in a marble column looks like it is lit from behind. With it, the light correctly travels through the material and exits at the opposite side with the right color shift.
Get the Full Details

Curvature maps are a specialized type that store information about concave and convex surface areas. They are useful for edge wear, dirt accumulation, and paint chipping effects that follow the geometry naturally. You can generate these procedurally inside most 3D packages, which means you do not need a separate texture file. I recommend generating them at render resolution rather than baking them at a lower resolution because the angle calculation depends on the actual polygon normals and lowering the resolution loses that precision. The result is that curvature-driven wear looks sloppy on high-poly assets when the curvature map was baked too small. When you are assembling a full PBR texture set, the order in which you generate and validate each map matters. Start with albedo because every other map references it. Then do the roughness and metallic passes since they define how light interacts with the surface independently of color.Normals come next because they depend on the geometry that the albedo color suggests. Displacement and height maps are generated after the normal maps because you need to know how much detail the normals are already conveying. AO is baked last since it is a global Illumination approximation that works best when all the surface data is already in place. The biggest mistake I see people make is assuming that texture resolution should scale linearly with polygon count. A ten-megapixel texture on a fifty-polygon sphere is useless. A fifty-kilobyte normal map on a multi-million-polygon architectural scan will choke your GPU memory. The practical rule is to keep your texture atlas sized to the viewing distance and the screen space that the surface actually occupies. If a wall occupies three hundred pixels horizontally in your final frame, you do not need more than about two thousand texels dedicated to that wall's texture data. Everything above that is wasted VRAM that could be used elsewhere.
File format choice affects quality and workflow speed. EXR supports 16-bit and 32-bit floating point data and is the standard for displacement and high-dynamic-range maps. PNG is acceptable for albedo and roughness if you stay at sixteen bits per channel. JPEG should never be used for any texture map because the compression artifacts introduce visible noise into the surface that is extremely difficult to clean up later. TGA is a legacy format that still works for simple alpha channels but offers no advantage over PNG in modern pipelines. If you are working in real-time engines and need to ship texture sets efficiently, KTX2 with BasisU compression gives you hardware-decoded texture streaming that reduces memory footprint significantly compared to uncompressed ASTC or BC formats. The tradeoff is that you lose the ability to edit the individual maps quickly because the compression is done at the pack level. I typically keep the source EXRs and PNGs in a master archive and only compile KTX2 versions for the final build. That way I can go back to the uncompressed data if something looks wrong in a later pass. The bottom line is that texture data is only as good as the validation you put into it before it reaches the renderer. Check your color spaces. Verify your normal map handedness on a test sphere. Convert your height data to the right bit depth. Bake your AO at full resolution. Use the correct file formats for each map type. The extra twenty minutes of validation work will save you hours of rework later.