Decals Not Rendering on Custom Mesh in Godot 4

Godot Version

4.3

Question

I’m developing a 3D painting tool in Godot 4 using the PaintableContainer and PaintHead scripts. I have set up a simple cube mesh in PaintableContainer and a decal system in PaintHead, but the decals are not appearing as expected when I attempt to paint on the mesh.

Here’s a brief overview of my setup:

PaintableContainer.gd:

@tool
extends Node3D
class_name PaintableContainer

@export var texture_size: Vector2 = Vector2(1024, 1024)
var target_mesh: MeshInstance3D

func _ready():
    setup_test_mesh()

func setup_test_mesh():
    target_mesh = MeshInstance3D.new()
    var cube_mesh = BoxMesh.new()
    target_mesh.mesh = cube_mesh
    add_child(target_mesh)
    setup_material(target_mesh)
    setup_collision(target_mesh)

func setup_material(mesh_instance: MeshInstance3D):
    var material = StandardMaterial3D.new()
    material.albedo_color = Color(1, 1, 1, 1)
    material.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA
    mesh_instance.material_override = material

func setup_collision(mesh_instance: MeshInstance3D):
    var static_body = StaticBody3D.new()
    var collision_shape = CollisionShape3D.new()
    var shape = mesh_instance.mesh.create_trimesh_shape()
    collision_shape.shape = shape
    static_body.add_child(collision_shape)
    mesh_instance.add_child(static_body)

PaintHead.gd:

@tool
extends Node3D
class_name PaintHead

@export var decal_size: float = 1
@export var paint_color: Color = Color.RED
var decal: Decal
var mesh_instance: MeshInstance3D

func _ready():
    setup_paint_head()

func setup_paint_head():
    var color_texture = ImageTexture.new()
    var image = Image.create(1, 1, false, Image.FORMAT_RGBA8)
    image.set_pixel(0, 0, paint_color)
    color_texture.create_from_image(image)

    mesh_instance = MeshInstance3D.new()
    var mesh = CylinderMesh.new()
    mesh_instance.mesh = mesh
    add_child(mesh_instance)

    decal = Decal.new()
    decal.texture_albedo = preload("res://icon.svg")
    decal.modulate = paint_color
    add_child(decal)

func _process(_delta):
    if Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT):
        update_paint_position()

func update_paint_position():
    var mouse_pos = get_viewport().get_mouse_position()
    var camera = get_viewport().get_camera_3d()
    if camera:
        var from = camera.project_ray_origin(mouse_pos)
        var to = from + camera.project_ray_normal(mouse_pos) * 1000
        var space_state = get_world_3d().direct_space_state
        var result = space_state.intersect_ray(from, to)
        if result:
            decal.global_transform.origin = result.position
            decal.look_at(result.position + result.normal, Vector3.UP)

Key Issues:

The decals do not appear on the cube mesh when I click to paint.
I have implemented raycasting to detect the mesh surface, and I see debug output confirming hit positions, but the decals remain invisible.
What I’ve checked:

Verified that the collision shape matches the mesh.
Ensured that the decal’s layer matches the mesh’s layer.
Printed various debug information, including decal orientation and layer settings.
Questions:

Are there specific settings or configurations I might be missing that could affect decal visibility?
Is there a common issue with decals not rendering on custom meshes that I should be aware of?
I would appreciate any guidance or suggestions to help resolve this issue. Thank you!