Godot 4.4: Vertex colors import correctly but render as black in shaders and materials

Godot Version

Godot_v4.4.1-stable_win64

Question

I’m trying to build a 1:1 vertex terrain shader for both Godot and Blender (4.4.3).

In Blender, I have a Color Attribute named _MaterialID set to Vertex - Byte Color

I use this Color Attribute to vertex paint perfect RGB colors on a mesh where all vertexes are black.

In blender I have built a super simple shader to use these vertex colors, and use them as a mask for textures. All works correctly.

I exported this mesh as a GLTF:
Blender 4.4 → GLTFexport with “Use Vertex Color: Active” enabled
Custom attribute named “_MaterialID” (underscore prefix for GLTF export)
Domain: Vertex, Data Type: Byte Color
Attribute set as active before export
Colors visible correctly in Blender shader editor

Then I imported it in Godot:
Godot 4.4 import shows vertex colors correctly in Advanced Import Settings preview
Cleared import cache (deleted .godot folder)
Materials tab shows imported materials

But in the editor, no matter what I do the material stays black, and I don’t have access to the vertex colors in both the code shader editor and the visual shader editor, nor the standard material with “Vertex Color as Albedo” enabled.

As can be seen in the image below, in blender all is good, in the advanced import window all is good, but in the editor; no bueno!

Things I have tried and or verified:
:white_check_mark: Mesh Data Confirmed Present (with a custom script on the mesh, shown at bottom of text):

// Debug output proves vertex colors exist:
Has vertex colors: true
Color 87: (1.0, 0.0, 0.0, 1.0)  // Red
Color 108: (0.0, 0.0, 1.0, 1.0) // Blue  
Color 78: (0.0, 1.0, 0.0, 1.0)  // Green

:white_check_mark: All Standard Solutions Already Tested:

StandardMaterial3D with “Vertex Color → Use As Albedo” ✓
Material Override vs Surface Material Override
Extracted materials to external files
Both shader types: ALBEDO = COLOR.rgb; and visual shader COLOR input
Unshaded materials

:white_check_mark: Ruled Out Common Issues:

NOT a Face Corner domain issue (converted to Vertex)
NOT missing underscore prefix (tried both)
NOT import cache issue (cleared .godot folder)
NOT missing “Use As Albedo” setting
NOT alpha channel issue (alpha = 1.0)
NOT custom attribute mapping issue (data appears in standard COLOR array)

I’m STUMPED! How do I get access to my custom attribute in the shaders?

extends MeshInstance3D

func _ready():
	var mesh_data = mesh
	if mesh_data and mesh_data.get_surface_count() > 0:
		# Get the actual vertex color data
		var surface_data = mesh_data.surface_get_arrays(0)
		var colors = surface_data[Mesh.ARRAY_COLOR]
		
		if colors:
			print("Color count: ", colors.size())
			print("First 144 colors:")
			for i in min(144, colors.size()):
				print("Color ", i, ": ", colors[i])
		else:
			print("No color array found")

The script below was taken from Claude AI and actually WORKS!

I don’t know how rebuilding the mesh like that fixes it but it does.

@tool
extends MeshInstance3D

func _ready():
	# Get the mesh data
	var original_mesh = mesh
	var arrays = original_mesh.surface_get_arrays(0)
	var colors = arrays[Mesh.ARRAY_COLOR]
	
	# Force recreate the mesh with explicit color data
	var new_mesh = ArrayMesh.new()
	
	# Ensure colors are in the right format (Color array)
	if colors and colors.size() > 0:
		# Convert to PackedColorArray if it isn't already
		var color_array = PackedColorArray()
		for color in colors:
			if color is Color:
				color_array.push_back(color)
			else:
				# Try to convert if it's in a different format
				color_array.push_back(Color(color.x, color.y, color.z, color.w))
		
		arrays[Mesh.ARRAY_COLOR] = color_array
		print("After conversion - Color array size: ", color_array.size())
		
		# Create new mesh with the fixed color data
		new_mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, arrays)
		mesh = new_mesh

   
	print("Mesh recreated with vertex colors")

	# Force editor update
	if Engine.is_editor_hint():
		# Trigger editor refresh
		notify_property_list_changed()
		# Force material refresh
		var current_material = get_surface_override_material(0)
		if current_material:
			set_surface_override_material(0, null)
			await get_tree().process_frame
			set_surface_override_material(0, current_material)

I’m not marking this as solved yet as this is an obvious workaround.

This works as a HACK, but not as a pipeline workflow, after reexporting the mesh with changed vertex colors, it is extremely inconsistent to get the changes showing in the editor/runtime!

Seems to me others are having similar issues but no fixes.

I’ve got “it working” now, but it doesnt allow for fast iteration speed, as the process to import the updated vertex colors is so weird, I don’t know exactly how I did it, just that I did it (rebuilt the scene the mesh was in from scratch, readded the script, material, ran the scene, updated the scene, pray its updated in main scene editor).

Should I report this as an Issue to the github repo or wait for a wizard to hopefully appear here?

By lack of response, I’ve added this issue to the official Github repo, where I also linked this thread for further information. If you know what’s happening/going wrong, please post here.

1 Like

tom-jk (on github repo):
Have you tried turning off Generate LODs (in advanced import window, can be seen on right side of your image) and reimporting?

THIS WORKED!

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.