Skip to content
AssetLoom

Game assets

PBR textures in Blender, Unity, Unreal and Godot: OpenGL vs DirectX normals, colour space, tiling

Set up metal/roughness PBR materials correctly in four tools: which maps are sRGB, how to spot an inverted normal map, channel packing and texel density.

By AssetLoom Team, published , 5 min read

A PBR (physically based rendering) material is a set of texture maps that together describe a surface: its colour, how rough it is, whether it is metal, and its small-scale shape. The same set of maps works in every modern renderer, but each tool wires them up slightly differently, and two settings cause most problems: colour space and normal map convention.

This guide explains both, then walks through setup in Blender, Unity, Unreal Engine and Godot, and finishes with tiling and texel density. The examples use the metal/roughness workflow, which is what our seamless PBR texture pack and most current packs use.

The maps and their colour space

Colour space is the single most common mistake. Only the albedo (base colour) map holds colour meant for display, so only it should be read as sRGB. Every other map holds data, and must be read as linear, also called Non-Color or “sRGB off”.

PBR maps in the metal/roughness workflow
MapWhat it storesColour space
Albedo / Base ColorSurface colour with no lighting or shadows baked insRGB
NormalSmall surface detail as direction vectorsLinear (Non-Color)
RoughnessMicrosurface: black is glossy, white is matteLinear
MetallicBlack for non-metals, white for bare metalLinear
Ambient OcclusionCavity shadowing in crevicesLinear
HeightSurface height for displacement or parallaxLinear (16-bit if available)

If a material looks washed out or too shiny, a data map is probably being read as sRGB. If the colour looks too dark and saturated, the albedo is probably being read as linear.

OpenGL vs DirectX normal maps

Tangent-space normal maps store a direction in the red, green and blue channels. There are two conventions for the green channel: OpenGL style, where green points up (often written Y+), and DirectX style, where green points down (Y−). The maps look almost identical, but using the wrong one inverts the lighting on bumps.

Which normal map convention each tool expects
ToolExpectsWith an OpenGL map
BlenderOpenGL (Y+)Use as-is
UnityOpenGL (Y+)Use as-is
Godot 4OpenGL (Y+)Use as-is
Unreal EngineDirectX (Y−)Tick Flip Green Channel in the texture settings

How to spot the wrong convention

Look at a material with clear bumps, such as brick mortar or cobblestone joints, under a single light. If the grooves look raised and the bricks look sunken, or the highlights appear on the side facing away from the light, the green channel is inverted. Flip it in the engine’s import settings or invert the green channel in an image editor.

Blender

  1. Add an Image Texture node for each map and connect them to a Principled BSDF.
  2. Set the albedo node’s colour space to sRGB and every other map to Non-Color.
  3. Route the normal map through a Normal Map node (tangent space) before the BSDF’s Normal input.
  4. Connect roughness and metallic directly. Leave metallic at 0 for materials without a metallic map.
  5. Optional: connect the height map to a Displacement node and the Material Output’s Displacement input. In Cycles, set the material’s displacement method to include true displacement, and subdivide the mesh enough to show it.

Ambient occlusion is usually left out in Cycles and Eevee, which calculate their own. For tiling, add a Texture Coordinate node and a Mapping node, and drive every map from the same Mapping node so they stay aligned.

Unity

  • Select the normal map and set Texture Type to Normal map.
  • For roughness, metallic, AO and height, untick sRGB (Color Texture) in the import settings.
  • Unity’s Lit shaders use smoothness, the inverse of roughness. In URP and the Built-in pipeline, smoothness is read from the alpha channel of the metallic map (or the albedo), so pack a texture with metallic in red and inverted roughness in alpha.
  • HDRP uses a Mask Map: metallic in red, ambient occlusion in green, a detail mask in blue and smoothness in alpha.
  • Set tiling in the material’s Tiling fields; keep all maps on the same tiling.

Packing tip

Any image editor or a short script can pack channels. Keep the unpacked originals as your source and regenerate packed maps whenever you edit them.

Unreal Engine

  • On the normal map texture, tick Flip Green Channel if the map is OpenGL style, and keep the compression setting at Normalmap.
  • For data maps, untick sRGB. For packed maps, use the Masks compression setting.
  • A common pattern is an ORM texture: occlusion in red, roughness in green and metallic in blue. One texture sample then feeds three material inputs, which saves samplers.
  • For tiling, multiply a TexCoord node by a scalar or vector parameter and feed it to every Texture Sample in the material.

Godot 4

  • Create a StandardMaterial3D and assign the albedo texture.
  • Enable Normal Map and assign the normal texture. Godot expects OpenGL-style normals.
  • Assign roughness and metallic textures and check which channel each reads from (the texture channel setting next to each slot).
  • For packed occlusion/roughness/metallic textures, use ORMMaterial3D instead.
  • Set tiling with UV1 Scale in the material, or turn on triplanar mapping for terrain-like surfaces without good UVs.

Tiling, scale and texel density

Seamless textures repeat without visible edges, but the repetition itself can still show. Getting the scale right is the first step. Texel density is the number of texture pixels per metre of surface. A 2048 px texture covering 2 m gives 1024 px/m; covering 4 m gives 512 px/m.

Rough texel density targets
UseTypical density2048 px texture covers
First-person, close surfaces1024 px/mAbout 2 m
Third-person or architectural512 px/mAbout 4 m
Top-down, distant or mobile256 px/mAbout 8 m

Keep density consistent across neighbouring surfaces so one wall doesn’t look sharper than the floor next to it. To hide repetition:

  • break up large areas with trims, decals and props;
  • blend two materials with a mask, or add a large-scale variation texture multiplied over the albedo;
  • rotate or offset UVs on adjacent surfaces.

Using the height map

A height map can drive true displacement (moving vertices, which needs dense geometry or tessellation) or parallax occlusion mapping (a shader trick that fakes depth on flat geometry). Use 16-bit height maps where you can: 8-bit height has only 256 levels and produces visible stepping when displaced. Start with a small displacement strength and increase it until edges look right; real-world surfaces like brick need only a centimetre or two.

Our texture pack ships 16-bit height maps and OpenGL normals for every material, with metallic maps only for the two metals. For a starter set of matching game assets, browse Game Assets; the textures pair well with the low-poly dungeon kit. Remember that file names like brick_normal.png don’t tell you the convention; check the pack’s README.

Spotted a mistake or have a question? Email support@assetloom.io.