# Change Texture dinamically

**URL:** https://forum.castle-engine.io/t/change-texture-dinamically/2119
**Category:** Uncategorized
**Created:** [February 16, 2026, 6:47pm UTC](https://forum.castle-engine.io/t/change-texture-dinamically/2119 "2026-02-16T18:47:15Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![krivoj](https://forum.castle-engine.io/letter_avatar_proxy/v4/letter/k/f05b48/32.png) [@krivoj](https://forum.castle-engine.io/u/krivoj)
#### Post date: [February 16, 2026, 6:47pm UTC](https://forum.castle-engine.io/t/change-texture-dinamically/2119/1 "2026-02-16T18:47:15Z")

</div>

What is the easiest way to change the texture of a TCastleScene? For example, I have two files: red.jpg and yellow.jpg. I want to change an athlete’s jersey.

---

<div class="post-metadata">

### Author: ![michalis](https://forum.castle-engine.io/user_avatar/forum.castle-engine.io/michalis/32/3_2.png) [@michalis](https://forum.castle-engine.io/u/michalis)
#### Post date: [February 16, 2026, 9:34pm UTC](https://forum.castle-engine.io/t/change-texture-dinamically/2119/2 "2026-02-16T21:34:57Z")

</div>

Note that `TCastleScene` represents a 3D model with potentially multiple shapes, each one can have material that can use multiple textures (for various purposes – base texture, metallic/roughness, normal map etc.).

The general way to replace all occurrences of `red.jpg` → `yellow.jpg` is to find all `TImageTextureNode` instances inside your `Scene.RootNode`, and change their `FdUrl` value. The `FdUrl` is a list of URLs from which the texture is loaded (usually just 1 URL, but in general case it can list fallbacks).

Do something like this:

```delphi
procedure TMyView.ReplaceTexture;
begin
  MyScene.RootNode.EnumerateNodes(TImageTextureNode,
    {$ifdef FPC}@{$endif} HandleImageTextureNode, false);
end;

procedure TMyView.HandleImageTextureNode(Node: TX3DNode);
var
  ImageTexture: TImageTextureNode;
begin
  ImageTexture := Node as TImageTextureNode;

  // log texture found
  WritelnLog('Found TImageTextureNode with %d URLs:', [ImageTexture.FdUrl.Count]);
  for I := 0 to ImageTexture.FdUrl.Count - 1 do
    WritelnLog('URL %d is %s', [I, ImageTexture.FdUrl[I]]);

  if ImageTexture.FdUrl.Items.IndexOf('red.jpg') <> -1 then
    ImageTexture.SetUrl(['yellow.jpg']);
end;

```

Hope this helps 🙂 As you see, I added above logging of the texture URLs actually found – you should check the log, what URLs are actually used by your model, and potentially adjust the replacement code to detect/set it correctly.

Please note that I didn’t test whether the above code compiles now, it’s possible I made some small mistakes 🙂 If anything is unclear or doesn’t work, let me know.

---

<div class="post-metadata">

### Author: ![krivoj](https://forum.castle-engine.io/letter_avatar_proxy/v4/letter/k/f05b48/32.png) [@krivoj](https://forum.castle-engine.io/u/krivoj)
#### Post date: [February 17, 2026, 2:44pm UTC](https://forum.castle-engine.io/t/change-texture-dinamically/2119/3 "2026-02-17T14:44:02Z")

</div>

I’ll try to explain myself better: imagine a Formula 1 game. The cars are 3D models to which you need to apply a texture (MyCar.LoadTexture(FilePath + MyTexture.bmp)). Or imagine a soccer game (MyPlayer.LoadTexture(FilePath + jersey.bmp)). I searched through all the documentation and there doesn’t seem to be a way in Castle Game Engine to load textures on the fly.

---

<div class="post-metadata">

### Author: ![DiggiDoggi](https://forum.castle-engine.io/letter_avatar_proxy/v4/letter/d/6a8cbe/32.png) [@DiggiDoggi](https://forum.castle-engine.io/u/DiggiDoggi)
#### Post date: [February 17, 2026, 5:26pm UTC](https://forum.castle-engine.io/t/change-texture-dinamically/2119/4 "2026-02-17T17:26:55Z")

</div>

The key part is exactly here:

> [@michalis](#):
>
> ```auto
> if ImageTexture.FdUrl.Items.IndexOf('red.jpg') <> -1 then
> ImageTexture.SetUrl(['yellow.jpg']);
> 
> ```

This works when your model already contains a texture like `red.jpg`. CGE loads it automatically, so you can later find it by name and replace it.

As @michalis mentioned a `TCastleScene` can contain many shapes and many textures. Which means, simple `MyPlayer.LoadTexture(FilePath + jersey.bmp)` can not be implemented. Searching by filename guarantees you replace the correct one.

In case when your model has exactly one texture, you could skip the loop and use index 0. However, as soon as you add more textures (e.g., roughness, metallic, normal maps), this breaks. More troubles than benefit in my opinion.

I myself use models with multiple change-able textures - for example birch or oak wooden cupboard can also have silver or black hinges. To replace the textures, I use algorithm very similar to the one above. It’s very simple.

* * *

> [@krivoj](#):
>
> The cars are 3D models to which you need to apply a texture

I may be wrong but it sounds like the model can be texture-less (ie. exported with no any textures) and you need to apply ‘red.jpg’, ‘yellow.jpg’, etc. only at runtime. In that scenario things are considerably less straight forward.

In such case the model is loaded as is, with empty texture list, so you’ll have an extra job setting things up manually.

The easiest workflow is to include a **dummy texture** in the model (even a 1x1 pixel file), or use the ‘red.jpg’. Once the model has _any_ texture, CGE loads it, and then you can replace it at runtime using the same code as above.

This avoids manually creating texture nodes in code.

---

<div class="post-metadata">

### Author: ![michalis](https://forum.castle-engine.io/user_avatar/forum.castle-engine.io/michalis/32/3_2.png) [@michalis](https://forum.castle-engine.io/u/michalis)
#### Post date: [February 17, 2026, 10:52pm UTC](https://forum.castle-engine.io/t/change-texture-dinamically/2119/5 "2026-02-17T22:52:39Z")

</div>

> [@DiggiDoggi](#):
>
> I may be wrong but it sounds like the model can be texture-less (ie. exported with no any textures) and you need to apply ‘red.jpg’, ‘yellow.jpg’, etc. only at runtime. In that scenario things are considerably less straight forward.

If you want to _create_ a texture node, rather than replace an existing one, it’s still relatively easy:) You would search for TPhysicalMaterialNode (I’m assuming here you use glTF with standard material) and assign it’s `BaseTexture` field, if not set (`nil`) now. Like

```delphi
procedure TMyView.AddTextureIfMissing;
begin
  MyScene.RootNode.EnumerateNodes(TPhysicalMaterialNode,
    {$ifdef FPC}@{$endif} HandleMaterialNode, false);
end;

procedure TMyView.HandleMaterialNode(Node: TX3DNode);
var
  Material: TPhysicalMaterialNode;
  ImageTexture: TImageTextureNode;
begin
  Material := Node as TPhysicalMaterialNode;

  if Material.BaseTexture = nil then
  begin
    ImageTexture := TImageTextureNode.Create;
    ImageTexture.SetUrl(['red.jpg']);
    Material.BaseTexture := ImageTexture;
  end;
end;

```

Of course you could combine these 2 answers. I.e. you could create a texture if missing, but replace the texture in `Material.BaseTexture` if it already existed (you could replace the URL, or just replace the whole node, the old node wil be garbage collected; both approaches make sense – depends on whether you want to preserve something from the old texture parameters, like “repeat/clamp” options).

> [@krivoj](#):
>
> I’ll try to explain myself better: imagine a Formula 1 game. The cars are 3D models to which you need to apply a texture (MyCar.LoadTexture(FilePath + MyTexture.bmp)). Or imagine a soccer game (MyPlayer.LoadTexture(FilePath + jersey.bmp)).

I hope our answers explain how you can effectively implement something like `LoadTexture` for your use-case 🙂

As you see above, there are many “details” when doing such thing, so it’s not a method we’d like to introduce in the engine. For starters, a scene is many shapes, which may have different material types, and materials potentially use many textures for different parameters. So everyone would imagine “assigning a texture to a model” does something a bit different.

So we give you tools to effectively implement something like this yourself, suitable for your situation.

---

<div class="post-metadata">

### Author: ![krivoj](https://forum.castle-engine.io/letter_avatar_proxy/v4/letter/k/f05b48/32.png) [@krivoj](https://forum.castle-engine.io/u/krivoj)
#### Post date: [February 17, 2026, 11:53pm UTC](https://forum.castle-engine.io/t/change-texture-dinamically/2119/6 "2026-02-17T23:53:37Z")

</div>

```auto
Thank you! This is the perfect solution I was looking for!

```
