← Back to Blog 3d-modeling

Unity URP Shader Graph: Build a Custom PBR Material for Any Imported GLB Model

By BitSoul Team7/29/2026Updated 8/2/20266 min read36 views
Unity URP Shader Graph: Build a Custom PBR Material for Any Imported GLB Model

If you've imported a GLB model into a Unity URP project and slapped the default Lit material on it, you've already hit the wall: blown-out highlights, missing roughness data, no vertex color support, and zero control over how your textures connect. The default Lit material assumes a specific texture slot layout that GLB assets often don't match. Shader Graph fixes this — you wire exactly what you have to exactly what you need, and the result is a fully PBR-correct material that works across every imported model in your project.

This guide walks through building that Shader Graph from scratch: setting up the asset, wiring albedo/normal/metallic/roughness, adding vertex color tint support, and making the whole thing SRP Batcher compatible so you don't blow your draw call budget.

Why Unity's Default Lit Material Fails on Imported GLB Assets

The standard Lit shader in URP expects textures in Unity's internal format: a packed mask texture (metallic in R, AO in G, detail mask in B, smoothness in A). GLB files from Blender, Sketchfab, or BitSoul's marketplace pack their data differently — metallic-roughness is a two-channel texture where roughness lives in G and metallic in B, following the glTF 2.0 spec.

Plugging a glTF metallic-roughness texture directly into Unity's Lit material metallic slot gives you garbage output. You either manually re-pack the texture in Photoshop (slow, breaks your pipeline) or you build a Shader Graph that reads the channels correctly.

Why Unity's Default Lit Material Fails on Imported GLB Assets — illustrated

There's a second problem: vertex colors. GLB models exported from Blender frequently carry vertex color data for tinting, AO baking, or foliage wind data. The default Lit shader ignores vertex colors entirely. A Shader Graph reads them in two lines.

Setting Up Shader Graph in URP

Before you start, confirm your project is on URP. In `Edit > Project Settings > Graphics`, the Scriptable Render Pipeline Settings field should point to a URP asset. If it's empty, you're on Built-in — stop here and migrate first.

Install Shader Graph via `Window > Package Manager > Unity Registry > Shader Graph`. Create your first graph:

  1. Right-click in the Project window → `Create > Shader Graph > URP > Lit Shader Graph`
  2. Name it `GLBLitCustom`
  3. Double-click to open the Shader Graph editor

In the Graph Inspector (top-right), set:

Check `Enable GPU Instancing` in the Graph Inspector — this is critical for performance when you have hundreds of the same model in a scene.

Wiring GLB Textures: Albedo, Normal, Metallic, and Roughness

Add these nodes to your graph (`Space` to open the search panel):

Albedo (Base Color)
```
Texture2D [_BaseMap] → Sample Texture 2D → Base Color (fragment)
```

Normal Map
```
Texture2D [_NormalMap] → Sample Texture 2D (Normal mode) → Normal (Tangent Space) (fragment)
```
Set the Sample Texture 2D node type to Normal so Unity applies the correct decoding.

Metallic-Roughness from glTF

glTF packs roughness in the Green channel and metallic in the Blue channel of a single ORM texture:

```
Texture2D [_MetallicRoughness] → Sample Texture 2D
├─ G channel → [1 - x] (Subtract from 1) → Smoothness (fragment)
└─ B channel → Metallic (fragment)
```

The `1 - roughness` conversion is the key step. Unity's Lit shading model uses smoothness (the inverse of roughness), so skipping this step makes every imported asset look like wet clay.

Ambient Occlusion

If your GLB includes a separate AO texture (common in Blender exports):
```
Texture2D [_AOMap] → Sample Texture 2D → R channel → Ambient Occlusion (fragment)
```

Emission (optional)
```
Texture2D [_EmissionMap] → Sample Texture 2D → Multiply [_EmissionColor] → Emission (fragment)
```

Wiring GLB Textures: Albedo, Normal, Metallic, and Roughness — illustrated

Adding Vertex Color Support for Tinting and AO

Vertex colors are free data — they're already in the mesh, you just have to read them:

```
Vertex Color → Multiply (with Base Color output) → Base Color (fragment)
```

This multiplies the albedo by whatever vertex color is painted on the mesh. A white vertex color leaves the texture unchanged; a tinted vertex color shifts the hue. This is the standard approach for foliage variation, where the same tree mesh uses vertex colors to randomize hue across instances.

For foliage models specifically (grab a free GLB tree from BitSoul's marketplace to test this), you can also route the vertex color Alpha channel to a wind displacement node on the vertex stage:

```
Vertex Color (Alpha) → Multiply [_WindStrength] → Position offset (vertex)
```

| Vertex Channel | Common Use in GLB Assets |
|---|---|
| RGB | Mesh tinting, ambient occlusion bake |
| Alpha | Wind strength mask, blend weight |
| All white | No vertex color data — safe to ignore |

GPU Instancing and SRP Batcher Compatibility

Two things kill draw calls in scenes with many instances of the same model:

SRP Batcher requires all material properties to live in a single `CBUFFER` block. Shader Graph handles this automatically when you expose properties via the Blackboard — each exposed property gets added to the constant buffer. Do not use `GetComponent<Renderer>().material.SetTexture()` at runtime on batched materials; use `MaterialPropertyBlock` instead.

GPU Instancing (enabled in Graph Inspector earlier) lets the GPU render thousands of identical meshes in a single draw call with per-instance data. To verify it's working:

```
// In your C# spawn script
Graphics.DrawMeshInstanced(mesh, 0, material, matrices, count);
```

Run the Frame Debugger (`Window > Analysis > Frame Debugger`) and look for `Draw Mesh (instanced)` entries. If you see individual `Draw Mesh` calls instead, check that:

Applying This to Free GLB Assets

The entire workflow above is designed around assets in GLB/glTF format because that's what you'll encounter most often in free asset libraries. Every model in BitSoul's marketplace ships as a game-ready GLB, so you can grab a free character, vehicle, or prop, import it into your URP project, assign this `GLBLitCustom` Shader Graph material, and have correct PBR shading in under 20 minutes — no texture repacking, no channel guessing.

The metallic-roughness channel swap (G = roughness, B = metallic) described above applies to all of them, so once you've built this graph once, it works across the entire library.

Key Steps at a Glance

| Step | What to Do |
|---|---|
| Setup | Create URP Lit Shader Graph, enable GPU Instancing |
| Albedo | Sample `_BaseMap`, wire to Base Color |
| Normal | Sample `_NormalMap` in Normal mode |
| Metallic | Sample ORM texture B channel → Metallic |
| Roughness | Sample ORM texture G channel, invert → Smoothness |
| AO | Sample AO texture R channel → Ambient Occlusion |
| Vertex Color | Read Vertex Color node, multiply into Base Color |
| Performance | SRP Batcher + sharedMaterial references |

Build it once, save it as a `.shadergraph` asset, and reuse it across every GLB import in the project. Head to BitSoul's marketplace and grab a free GLB model to test the shader on — filter by character, vehicle, or environment prop and you'll have a working test case in two clicks.

Tags: unity 3d-assets pbr shader-graph urp glb

Skip the modelling — download it instead

A free BitSoul account gets you 2 game-ready models every month plus 25 AI Engine credits to generate one of your own, no card required. Clean topology, PBR textures, and GLB downloads that drop straight into Unreal, Unity, Godot or Blender — plus OBJ and 3D-printable STL export.

Create a free account → Browse 846 models