If you have spent any time with 3D assets, you have seen both terms thrown around as if they are interchangeable. They are not. PBR and ORM operate at different levels of the pipeline, and understanding the distinction saves a lot of confusion when importing materials between engines.
PBR is the lighting model
PBR stands for Physically Based Rendering. It is a shading approach that simulates how light actually behaves, with energy conservation, microsurface scattering, and Fresnel effects baked into the maths. A PBR material is driven by a stack of greyscale and colour textures: base colour (sometimes called albedo), normal, roughness, metallic, and ambient occlusion, often with emissive or height on top.
The shader reads those inputs and produces results that look consistent under different lighting. A rusted iron surface looks rusted whether it is sitting in a sunlit field or a dim warehouse, because the maths accounts for the physics rather than faking it per-scene.
The textures that feed it
A PBR material is not one texture, it is a small bundle of them. Each one describes a different physical property of the surface. Here is what you will typically see in a material folder:
brick_wall/
├── brick_wall_basecolor.png (or _albedo, _diffuse, _col)
├── brick_wall_normal.png (or _nrm, _n)
├── brick_wall_roughness.png (or _rough, _r)
├── brick_wall_metallic.png (or _metal, _m)
├── brick_wall_ao.png (or _occlusion, _occ)
├── brick_wall_height.png (or _displacement, _disp, _h) [optional]
└── brick_wall_emissive.png (or _emission, _e) [optional]What each one does:
- Base colour is the raw surface colour with no lighting baked in. Think of it as what the surface would look like under flat, shadowless light. This is the only map stored in sRGB colour space. Everything else is linear data.
- Normal fakes surface detail by telling the shader which direction each pixel is facing. It is why a flat plane can look like a bumpy brick wall. Usually purple-blue in appearance.
- Roughness is greyscale. Black is a mirror, white is chalk. It controls how sharp or blurred reflections are.
- Metallic is also greyscale, and almost always close to pure black or pure white. Black means non-metal (plastic, wood, stone, skin). White means metal (iron, gold, aluminium). Values in between are rare outside of transition areas like rust.
- Ambient occlusion darkens crevices and contact points where light would naturally struggle to reach. Grayscale, white is fully lit, black is fully occluded.
- Height (sometimes called displacement) pushes the actual geometry in or out. More expensive than normal mapping but produces real silhouette detail.
- Emissive makes parts of the surface glow independently of scene lighting. Usually black everywhere except the glowing bits.
Naming conventions are not standardised. Some packs ship _diffuse instead of _basecolor. Some use _nrm instead of _normal. You will learn to recognise them by suffix.
ORM is a texture packing format
ORM stands for Occlusion, Roughness, Metallic. It is a way of packing three of those greyscale maps into the RGB channels of a single image:
- R channel holds Ambient Occlusion
- G channel holds Roughness
- B channel holds Metallic
This is purely an optimisation. Each of those three maps is single-channel data, so storing them as separate RGB textures wastes two-thirds of every file. Packing them together means one texture sample instead of three, less VRAM consumed, and fewer draw call overheads. It is standard practice in modern real-time pipelines.
How each engine handles it
Unreal Engine uses the standard ORM layout. Red is occlusion, green is roughness, blue is metallic. Most Unreal-ready materials on marketplaces ship with a base colour, normal, and ORM texture, sometimes with a separate emissive. The material editor expects this convention out of the box.
Unreal ORM:
├── R channel → Ambient Occlusion
├── G channel → Roughness
└── B channel → MetallicGodot matches Unreal's convention through ORMMaterial3D. Red is occlusion, green is roughness, blue is metallic. You assign the packed texture and the engine handles channel splitting automatically. This also matches the glTF 2.0 metallic-roughness spec, which is the closest thing to a cross-engine standard.
Godot ORM (and glTF 2.0):
├── R channel → Ambient Occlusion
├── G channel → Roughness
└── B channel → MetallicUnity does its own thing. Note that as of 2026, Unity has announced HDRP is going into maintenance mode and URP is becoming the primary rendering pipeline going forward, so URP is the convention to care about for new work.
URP's Lit and Complex Lit shaders support a channel-packed texture, but the layout is completely different from Unreal and Godot:
Unity URP (Lit/Complex Lit):
├── R channel → Metallic
├── G channel → Occlusion
├── B channel → (unused)
└── A channel → Smoothness (inverse of roughness)Two things to note. First, red is metallic in Unity but occlusion in Unreal, so a texture packed for one engine will render incorrectly in the other without channel swapping. Second, Unity uses smoothness instead of roughness. Smoothness is the numerical inverse: a roughness value of 0.2 becomes a smoothness value of 0.8. Importing an Unreal-style ORM into Unity without conversion gives you materials that look wrong in a way that is hard to diagnose.
HDRP's Mask Map is similar but uses the blue channel for a detail mask:
Unity HDRP Mask Map (maintenance mode):
├── R channel → Metallic
├── G channel → Occlusion
├── B channel → Detail mask
└── A channel → SmoothnessUnity's older Built-in Render Pipeline Standard shader packed smoothness into the alpha channel of the metallic map with no occlusion or detail slot, which is yet another convention you will still encounter in legacy projects and older asset packs.
Blender does not have an engine preference of its own. It reads individual texture inputs on the Principled BSDF node, so working with a packed texture means using a Separate Color node to split the channels before feeding each one to the correct shader input. Most Blender addons for PBR import handle this automatically, but it is worth knowing what is happening underneath. Because Blender is agnostic, it is also the most useful place to unpack and repack textures between conventions.
The quick comparison
| Engine | R | G | B | A |
|---|---|---|---|---|
| Unreal (ORM) | Occlusion | Roughness | Metallic | – |
| Godot (ORMMaterial) | Occlusion | Roughness | Metallic | – |
| glTF 2.0 | Occlusion | Roughness | Metallic | – |
| Unity URP Lit | Metallic | Occlusion | unused | Smoothness |
| Unity HDRP Mask Map | Metallic | Occlusion | Detail mask | Smoothness |
| Blender | user-defined | user-defined | user-defined | – |
If you are shipping assets for multiple engines, your safest bet is to distribute individual unpacked maps alongside a pre-packed ORM for Unreal and Godot, and leave Unity users to repack using their own convention.
Where to find free samples
These are the reliable CC0 sources:
- Poly Haven has 4K and 8K PBR textures with full map sets, CC0 with no attribution required
- ambientCG (formerly CC0Textures) has more than 2,000 PBR materials, also CC0
- CG Bookcase offers 500+ PBR textures with no account required
- TextureCan has 4K-minimum textures with SBSAR files for procedural tweaking
- ShareTextures covers wood, stone, metal, and ground textures up to 4K
Most of these deliver individual PBR maps rather than pre-packed ORM textures. If you need an ORM for Unreal or Godot, you can pack one yourself in any image editor by assigning AO to the red channel, roughness to green, and metallic to blue. ImageMagick does it in a single command, and most DCC tools have built-in or plugin-based packers.
The practical takeaway
PBR is the workflow. ORM is one way of organising the textures that feed it. When someone says a material is "PBR," they mean it works with a physically based shader. When they say it is "ORM packed," they mean the three greyscale maps are already combined into one file.
Knowing which is which makes it much easier to troubleshoot when a material looks wrong after import. Nine times out of ten, it is a channel convention mismatch rather than a broken texture.
If you work with a lot of PBR materials across different engines, keeping them organised gets painful fast. AssetHoard is a local-first desktop asset manager built for exactly this kind of library. It is free during open beta.
The Asset Hoard Team