Godot Version
4.3
Question
Hello everyone,
I’m currently generating a mesh procedurally, and everything is working correctly. I’ve reached a stage where I need to communicate additional data to the shader per vertex in the form of a Vector3, which I will use as splat-map data to blend textures from a Texture2DArray.
I thought about using ARRAY_TEX_UV2 to pass this data to the shader since it offers the possibility of being a PackedVector3Array. However, once in the shader, UV2 can’t be considered as anything other than a vec2.
I find this surprising in itself since it’s not uncommon to use up to 4 values per UV (u/v min/max), but let’s assume that’s the case… However, I don’t understand why GDScript allows me to type ARRAY_TEX_UV2 as PackedVector3Array (and I was able to verify that it indeed contained the z value) if the shader doesn’t allow access to this value.
Being quite new to Godot, I’m perfectly willing to hear that I’m doing it wrong, and if someone here has a better solution to propose for transmitting these Vector3 values, I would be delighted to hear your suggestions!
Thank you in advance and have a great day, everyone!
Let’s address this issue in an otherway. What method should I use to pass extra vertices data (in vector3 format) to my shader ?
For anyone who might face a similar situation in the future, here’s how I solved the problem.
I created a PackedFloat32Array for each of the Vector3 values that I wanted to pass to the shader. I then assigned these arrays respectively to CUSTOM0 for x, CUSTOM1 for y, and CUSTOM2 for z. However, if the custom arrays are not explicitly formatted, these arrays will expect data in the form of PackedBytesArray, thus normalizing the vectors. Here is the imperative formatting for these arrays to accept PackedFloat32Array:
var x_indices:PackedFloat32Array
var y_indices:PackedFloat32Array
var z_indices:PackedFloat32Array
(…)
generated_mesh = ArrayMesh.new()
var format = Mesh.ARRAY_FORMAT_VERTEX |
Mesh.ARRAY_FORMAT_INDEX
format |= Mesh.ARRAY_FORMAT_COLOR
mesh_array[Mesh.ARRAY_CUSTOM0] = PackedFloat32Array(x_indices)
mesh_array[Mesh.ARRAY_CUSTOM1] = PackedFloat32Array(y_indices)
mesh_array[Mesh.ARRAY_CUSTOM2] = PackedFloat32Array(z_indices)
format |= Mesh.ARRAY_FORMAT_CUSTOM0 | Mesh.ARRAY_FORMAT_CUSTOM1 | Mesh.ARRAY_FORMAT_CUSTOM2
format |= (Mesh.ARRAY_CUSTOM_R_FLOAT << Mesh.ARRAY_FORMAT_CUSTOM0_SHIFT)
format |= (Mesh.ARRAY_CUSTOM_R_FLOAT << Mesh.ARRAY_FORMAT_CUSTOM1_SHIFT)
format |= (Mesh.ARRAY_CUSTOM_R_FLOAT << Mesh.ARRAY_FORMAT_CUSTOM2_SHIFT)
generated_mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, mesh_array, , {}, format)
mesh = generated_mesh
mesh.surface_set_material(0, material)
The documentation for custom arrays and their formatting exists, but I personally find it unintuitive, and the lack of implementation examples is really confusing.
I hope that one day this post will help someone save the time I spent on this problem.