World_vertex_coords problem

Godot Version

4.3 beta

Question

Hello, i made a wind shader using vertex colors from model to simulate wind on a tree, my shader works as intended until i rotate my model and see that the wind effect is tied to the model rotation, i search the Docs and i found that i need to put “world_vertex_coords” in render mode but after adding this to my shader if i move my model from world origin (0,0,0) its get distorted and the models location is out of place. Can someone can give me any idea on what i can do. My shader without the world_vertex_coords works but its rotating with the model, if using world_vertex_coords is not possible there is a way to get the model rotation in radians and subtract from the wind_direction (is in radians too)?

Here is the code that is causing the problem:

void vertex() {


	float wind_factor = COLOR.b / 255.0;
	float wind_variation = COLOR.g;

	float height_factor = pow(VERTEX.y / 30000.0, 1.2);
	float wind_direction_radian_sway = float(wind_direction_angle + 135) * 3.14159 / 180.0;// convert to radians


	float sine_sign = (wind_direction_angle >= 180 && wind_direction_angle < 360) ? -1.0 : 1.0;

	float trunk_sway_angle = height_factor *
							sin(TIME * (trunk_frequency + model_scale) / 20.0 + wind_direction_radian_sway) *
							trunk_motion * 50.0 * 3.14159 / 180.0 * sine_sign;

	mat3 rotationWind = mat3(
		    vec3(cos(wind_direction_radian_sway), 0.0, sin(wind_direction_radian_sway)),
		    vec3(0.0, 1.0, 0.0),
		    vec3(-sin(wind_direction_radian_sway), 0.0, cos(wind_direction_radian_sway))
		);
	mat3 rotationX = mat3(
	    vec3(1.0, 0.0, 0.0),
	    vec3(0.0, cos(trunk_sway_angle), -sin(trunk_sway_angle)),
	    vec3(0.0, sin(trunk_sway_angle), cos(trunk_sway_angle))
	);


	mat3 rotationZ = mat3(
	    vec3(cos(trunk_sway_angle), -sin(trunk_sway_angle), 0.0),
	    vec3(sin(trunk_sway_angle), cos(trunk_sway_angle), 0.0),
	    vec3(0.0, 0.0, 1.0)
	);


	mat3 rotation_matrix = rotationWind * rotationX * rotationZ;
	vec3 trunk_vertex = rotation_matrix  * VERTEX;
	VERTEX = trunk_vertex;


	vec3 rotated_normal = rotation_matrix * NORMAL;
	NORMAL = normalize(rotated_normal);

}

The VERTEX is in view space.
And you are generating your rotation matrix as if its in world space.

So the easy solution is to just convert your rotation_matrix from world to view space and everything should world.

Space transformations can sound difficult but it is simpler than you might think. You can check the docs for the cheat-sheet.

So there we have
in mat4 VIEW_MATRIX | World space to view space transform.

What this means is that if you multiply your coordinaties by this variable, it’ll convert the coordinates.

So in your case, you could probably change the last line to:

VERTEX = (VIEW_MATRIX  * vec4(trunk_vertex, 1.0)).xyz;

To make the vertex coords work like you expect.

Its been a while since I used shaders so I might have got something confused along the way, but see if that works.

1 Like

Thank you but i already tried that. VERTEX = (VIEW_MATRIX * vec4(trunk_vertex, 1.0)).xyz;
Using VIEW_MATRIX my model moves with the camera. I also tried using MODEL_VIEW_MATRIX, INV_VIEW_MATRIX but the result are worst.

I am thinking if there is a way to get the model rotation angle in degrees or radians in the Y axis and subtract it from the uniform wind_direction_radian_sway? if i can do this in gdshader i can adjust the wind direction.

You can always take a look at some simple examples and check out how they did it to apply it to your shader.

See if this grass shader helps.
It uses a sway_dir variable to control the wind direction it seems.

Although this example is for Godot3. You can probably easily port it to godot4 by replacing the global variable names.
WORLD_MATRIXMODEL_MATRIX

1 Like

Update: The correct way to transform any directional movement (like wind) from local space to world space (you can rotate the model using transform) is:

float wind_x = cos(radians(wind_direction_angle));
float wind_z = sin(radians(wind_direction_angle));
	
vec2 wind_dir = (inverse(MODEL_MATRIX) * vec4(wind_x, 0.0,wind_z,0.0)).xz;
wind_dir = normalize(wind_dir);

wind_x = wind_dir.x;
wind_z = wind_dir.y;

This way we can use wind_x (x axis movement) and wind_z(z axis movement) for Vertex transformations in our shader.

1 Like

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