Is there a way to make transform in shader effecting Mesh's vertices position in World3d?

Godot Version

Godot 4.5.1 - mono Stable

Question

For example, creating a TextMesh, and set to MeshInstance3D.Mesh, then use a ShaderMaterial. Scale, translate or rotate VERTEX in shader, the Text will be transformed in display.

However, the Text sometime disappears suddenly, while camera excluding the original position of the TextMesh (saying the position before transformed by shader).

So, is there any way to make transform in shader effecting Mesh’s real position in World3d?

VERTEX in vertex shaders is in object space. You can transform it to world space by multiplying with MODEL_MATRIX, do you transforms in that space and then transform back to object space by multiplying with inverse(MODEL_MATRIX)

2 Likes

I tried to set MODEL_MATRIX by new transformed value, but it is a constant can’t be set. Is there any way using shader to transform object in world space?

In C# code, I could get mesh vertices by GetMeshArray(), and traversal every vertex multiplying a Transform to transform the whole mesh in world space. But I don’t know how to do same in shader.

VERTEX as you said just happens in object space, set it to new transformed value won’t change mesh’s “real” position in world space like done in C# code.

Since computing every transform of mesh vertex is better to do with GPU other than CPU, I wonder if there is a way in shader code to do the same thing as in C# code.

MODEL_MATRIX is not supposed to be changed. It’s a constant provided to you in the vertex() function. If you multiply MODEL_MATRIX with VERTEX the result will be vertex position in world space.

Once you have it in that space, you can do world space transformations with it, but since VERTEX will automatically be transformed from object to world to camera spaces between vertex() and fragment() functions, you need to transform VERTEX back into object space when you’re done tweaking it in world space.

void vertex(){
	// transform VERTEX from object to world space
	VERTEX = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz
	
	// VERTEX is now in world space
	// Do your world space tweaks here

	// transform tweaked VERTEX back to object space
	VERTEX = (inverse(MODEL_MATRIX) * vec4(VERTEX, 1.0)).xyz
}

Shaders also let you disable those transforms that happen automatically between vertex() and fragment() functions, by adding skip_vertex_transform to you render_mode directive. In that case your vertex() function becomes responsible for writing camera space position into VERTEX.

1 Like

Thanks for you reply. I tried the solution provided, and I understand your meaning.

May it is hard to express the question precisely in words, I will build a demo poject to display more details.

Define “real position”. Transformation matrix of an object is set on the cpu side. If you need that changed - simply change the position property. Why would you need a shader to do this?

I create a demo to test.

You can read more details in readme.

I want to create a lot text to display, but I can’t use many MeshInstance3D due to lagging. I need to transform evey TextMesh in single so that every text can set to proper position.

The reason I want to use shader is I’m curious if GUP can speed up vertex transform in such case.

You should have mentioned that you’re using RenderingServer.

Your instances probably get frustum culled away on the cpu side. Set their AABBs to enclose the actual geometry using RenderingServer::InstanceSetCustomAabb()

Btw why do you need to transform vertices? Just transform the whole instance.

1 Like

The default text direction of TextMesh is vertical. Yes, I can lay down text by transform instance only, but the Normal of vertices can’t be transformed correctly, only if traversal every vertex.

I will try this later. But I also tried not using ReaderingServer, that just add buch of Arrays of TextMesh into a single ArrayMesh in different surface layers. But the same thing happens to ArrayMesh too.

Oh, maybe set AABB will save the problem, I’ll try.

Well whatever you do, you need to ensure that geometry instance bounding boxes enclose all their vertices. Mesh instance nodes will calculate AABBs automatically for their normally transformed meshes but if you displace vertices in shaders they may go far out of those bounding boxes and the engine has no way of tracking how much the vertex shader displaced the vertices. When the bounding box goes out of the camera viewing volume, the object will be culled from the rendering pipeline, even if its displaced vertices are in the camera view. So check and maintain proper bounding boxes at all times, whether you’re using nodes and shaders, or the rendering server.

2 Likes

Yes, you are right. I reset AABB and it work. Thank you a lot !!

1 Like