Skip to content

Import custom attributes with GLTFDocumentExtension#97756

Open
huwpascoe wants to merge 1 commit into
godotengine:masterfrom
huwpascoe:custom_attrib
Open

Import custom attributes with GLTFDocumentExtension#97756
huwpascoe wants to merge 1 commit into
godotengine:masterfrom
huwpascoe:custom_attrib

Conversation

@huwpascoe

@huwpascoe huwpascoe commented Oct 3, 2024

Copy link
Copy Markdown
Contributor

Proposal

Import ARRAY_CUSTOM# attributes with GLTFDocumentExtension using a function to specify layer name. Also added "Export Attributes" checkbox to the blender importer.
godotengine/godot-proposals#10892

Test Project

image
custom_attrib_test.zip

changes

  • Ability to combine 2 attributes per CUSTOM
  • Created new GLTFAttributeMap resource to deal with the sheer number of possibilities
extends GLTFDocumentExtension

func _import_get_attribute_map(state: GLTFState, mesh_index: int) -> GLTFAttributeMap:
	var attrmap := GLTFAttributeMap.new()

	var mesh_name: String = state.json["meshes"][mesh_index]["name"]
	match mesh_name:
		"mesh_1": attrmap.color = "COLOR_1"
		"mesh_2": attrmap.color = "_MY_DATA"
		"custom":
			attrmap.custom0 = "_ROCK"
			attrmap.custom1 = "_MUD"
			attrmap.custom2 = ""
			attrmap.custom3 = "_GRASS"
			attrmap.custom3_mux = "_SNOW"

	return attrmap

Supported attributes

  • Mesh.ARRAY_TEX_UV (vec2)
  • Mesh.ARRAY_TEX_UV2 (vec2)
  • Mesh.ARRAY_COLOR (vec3, vec4)
  • Mesh.ARRAY_CUSTOM# (scalar, vec2, vec3, vec4)

@fire

fire commented Oct 3, 2024

Copy link
Copy Markdown
Member

I'm having a hard time understanding the extension. Can you link or write a proposal in https://github.com/godotengine/godot-proposals?

Something like: I have a game workflow that uses blender I want the vertex attributes to import from blender, but it needs this pr. I can use the attributes for a shader effect.

Comment thread modules/gltf/gltf_document.cpp Outdated
Comment thread modules/gltf/extensions/gltf_document_extension.cpp Outdated
@huwpascoe

Copy link
Copy Markdown
Contributor Author

godotengine/godot-proposals#10892

@huwpascoe

Copy link
Copy Markdown
Contributor Author

Refactored and removed like a hundred duplicate lines of code.

_decode_accessor_as_floats();
_decode_accessor_as_ints();
_decode_accessor_as_vec2();
_decode_accessor_as_vec3();
_decode_accessor_as_color();
_decode_accessor_as_quaternion();
_decode_accessor_as_xform2d();
_decode_accessor_as_basis();
_decode_accessor_as_xform();

// VVV

_decode_accessor<T>();

Multi-element scalars are now decoded with _decode_accessor<T, N>()

array[Mesh::ARRAY_TANGENT] = _decode_accessor<float, 4>(p_state, a["TANGENT"], true, indices_mapping);

@aaronfranke

Copy link
Copy Markdown
Member

Since this PR alters the accessor code, it will have to wait until after #94165 which also touches this code.

@Flynsarmy

Copy link
Copy Markdown
Contributor

Since this PR alters the accessor code, it will have to wait until after #94165 which also touches this code.

PR in question was just merged so we should be good to continue here.

@fire

fire commented Nov 6, 2024

Copy link
Copy Markdown
Member

@huwpascoe Many people think this is a good enhancement. Would you happen to have time to rebase it? <3

@huwpascoe

huwpascoe commented Nov 7, 2024

Copy link
Copy Markdown
Contributor Author

@fire

Would it be better to keep as an extension or promote it to import options?
https://github.com/user-attachments/assets/52dc1357-7b32-49c2-a2ce-216343f69d60

There are trade-offs for each.

@fire

fire commented Nov 7, 2024

Copy link
Copy Markdown
Member

I am trending towards promoting it to import options

@Flynsarmy

Copy link
Copy Markdown
Contributor

Remember to take this PR out of draft if it's ready :)

@huwpascoe

Copy link
Copy Markdown
Contributor Author

Remember to take this PR out of draft if it's ready :)

Don't worry! I haven't forgotten.

I am trending towards promoting it to import options

Right, I've determined that the UI approach is just too much of a mess for what is a technical feature. So I'll be moving forward with the original plan to add the method to DocumentExtension.

@huwpascoe huwpascoe force-pushed the custom_attrib branch 2 times, most recently from fd4dff7 to 4db4bdb Compare December 15, 2024 05:59
@huwpascoe huwpascoe marked this pull request as ready for review December 15, 2024 06:46
@huwpascoe huwpascoe requested review from a team as code owners December 15, 2024 06:46
Comment thread modules/gltf/gltf_document.h Outdated
@huwpascoe huwpascoe force-pushed the custom_attrib branch 3 times, most recently from 8921298 to e429182 Compare November 29, 2025 00:13
Comment thread modules/gltf/extensions/gltf_document_extension.h Outdated
Comment thread modules/gltf/gltf_document.cpp Outdated
Comment thread modules/gltf/gltf_document.cpp Outdated
Comment thread modules/gltf/gltf_document.cpp Outdated
Comment thread modules/gltf/gltf_document.cpp Outdated
@huwpascoe huwpascoe force-pushed the custom_attrib branch 2 times, most recently from f0f9cd4 to 6848be9 Compare November 29, 2025 15:59
@huwpascoe

Copy link
Copy Markdown
Contributor Author

I've updated the test scene for the name change (_import_get_attribute_for_mesh_array)

@aaronfranke aaronfranke self-requested a review November 30, 2025 22:54

@lyuma lyuma left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have some comments about the design that I'd like a chance to discuss.

Firstly, I have concerns about the usability of depending on a customized GLTFDocumentExtension to perform the remapping... it certainly could work, but document extensions are registered globally (project-wide), so any attempt to use this feature would have to condition the remapping on some condition or add a setting to the import dock. If I were to copy the sample code as written, it would break all other glTF models in my project, even if they do not have that custom attribute. But explaining all this is probably too much for a method description, so I'm not sure how to clarify this.

Second, as I noticed, if I use this to override any custom attributes, then I can no longer combine two UV channels into one custom channel which limits the number of custom 2-channel UVs I can import. I feel like maybe something simple like "TEXCOORD_1,TEXCOORD_2" could work to handle that case. I think it only needs to support 2 x vec2 or 1 x anything cases , so no need to handle every combination.

Basically the usecase is for compacting multiple 2-channel UVs into a CUSTOM, and this is Godot's current behavior so it would be nice to support it for that reason without needing a whole special case. At a minimum, it should be possible to return "" for an individual custom channel to get the current behavior without losing all the other custom channels.

Comment thread modules/gltf/gltf_document.cpp Outdated
@huwpascoe

Copy link
Copy Markdown
Contributor Author

If I were to copy the sample code as written, it would break all other glTF models in my project, even if they do not have that custom attribute. But explaining all this is probably too much for a method description, so I'm not sure how to clarify this.

That's why GLTFState is provided to determine if changes apply. If this method needs explaining, then every other method of GLTFDocumentExtension would require the same explanation. So that's out of scope, I think.

At a minimum, it should be possible to return "" for an individual custom channel to get the current behavior without losing all the other custom channels.

That sounds reasonable, I'll see if I can get it working efficiently.

@huwpascoe huwpascoe requested a review from a team as a code owner December 2, 2025 03:54
@huwpascoe huwpascoe force-pushed the custom_attrib branch 2 times, most recently from f564792 to 0db8539 Compare December 2, 2025 04:05
@huwpascoe

Copy link
Copy Markdown
Contributor Author

Individual attribute querying is gone, now extensions only need to return a GLTFAttributeMap resource. With defaults set to how texture UVs were originally handled.

Any 2 attributes can combine into a CUSTOM provided they fit within a vec4. For example, vec3+scalar is valid.

image

Comment thread modules/gltf/doc_classes/GLTFAttributeMap.xml Outdated
Comment thread modules/gltf/doc_classes/GLTFAttributeMap.xml Outdated
Comment thread modules/gltf/doc_classes/GLTFAttributeMap.xml Outdated
Comment thread modules/gltf/doc_classes/GLTFAttributeMap.xml Outdated
Comment thread modules/gltf/doc_classes/GLTFDocumentExtension.xml Outdated
@PurpBatBoi

Copy link
Copy Markdown

updates?

@fire fire requested a review from a team February 17, 2026 21:58
@lyuma

lyuma commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

Some thoughts from the asset meeting.

I can see that this feature could be useful for advanced users. We need to balance this with the additional complexity, and the lack of discoverability of this feature.

Since #96748 was approved, this change will have to be rebased on top of it. In particular, it may impact the order of the UV attributes based on _gltf_primary_texture_coord and _gltf_secondary_texture_coord meta in each of the Material3D attached to the various mesh primitives, often leading TEXCOORD_0 and TEXCOORD_1 to be swapped.

So we can automatically do this fix on the default GLTFAttributeMap. We need to consider how this change may impact extensions that set a custom one.

Finally, my other concern is this feature is difficult to discover and therefore has a very limited set of users who will know about or use this. Ideally, it would be visible in the advanced importer for example something you can set on each mesh/material to override the GLTFAttributeMap resource slot, and then of course can be again overridden by extensions.

@Christakou

Copy link
Copy Markdown

Just wondering if there's been progress on this as I just encountered a usecase in my engine usage where this would be super useful

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Development

Successfully merging this pull request may close these issues.

10 participants