How can I find the nearest texture coordinate from a mouse click?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By speckledsea
:warning: Old Version Published before Godot 3 was released.

If I have a mesh that the user “clicks on”, is there a way I could correlate that event with the coordinates of the mesh’s textures at that point using GDScript? The reason for this is I want to be able to reference a non-visible mask texture for the mesh.

If it is possible what would be the idiomatic way of doing so in Godot?

I’ve never done such things in Godot but usually the typical way is to render your scene with the same camera on an off-screen render texture, and make sure it renders only objects that you care about, with a replacement shader that handles your transparency, and nothing else (no lighting, no texturing, no color, just the info you care about).
Then, when you click anywhere on the screen, you can render and download that RenderTexture to GDScript, get the same screen coordinate in the image and test if it’s 0 or 1 for example. Then, you will know if you clicked your object or an invisible part or not.
This can be further-extended to do color picking and pick up objects in a pixel-perfect way that handles transparency, without relying on physics.
If what you care about is the UVs rather than the image’s content, then you could render the UVs as pixels, but you will loose some precision as RGB is in 0.255.

Unfortunately I have no experience at all in doing this in Godot yet, and I don’t know if it supports replacement shaders…

Alternatively, you could iterate the whole mesh to see which triangle your click ray intersects, interpolate the UVs and get your pixels from there, but it will be a lot slower.

Maybe a Mesh collider could do that, but it currently only give you intersection normal, so to give you the information you need, the physics engine would have to provide the index of the triangle’s vertices so that you can get the UVs back. Maybe that info is in hit[“metadata”]? (where hit is what intersect_ray gives you in 3D).

Zylann | 2017-08-04 18:11

Thank you for the detailed reply. Yes, a replacement shader seems to be the best option. I thought about asking about a “light guns” method in the original post, but decided to omit it for the sake of brevity. I’m new with Godot, so I’m not sure what the preferred way of achieving this in Godot is either, but it seems like it should be doable from what I’ve seen so far. I’ll have to poke around when I get time.

speckledsea | 2017-08-05 15:11