GLSL transform direction into world space

Hello everyone :wave:

Inside my shader I am passing a uniform vec3 direction to periodically offset the vertices positions, like so:

// Pars
uniform vec3 direction; // passed in normalized
uniform float timeElapsed;
...
// After #include <begin_vertex>
transformed += direction * sin( timeElapsed );

This works well, until I realized everything is in local space, while the direction is meant to be always the same, i.e. world space
After rotating the object on Y axis

object.rotation.y = Math.PI / 4; // 45 deg

the direction of the offset has changed, while I need it to be independent of the object’s transform.
I tried transforming the direction inside the shader with modelMatrix like so:

vec3 worldSpaceDirection = normalize( ( modelMatrix * vec4 ( direction, 0.0 ) ).xyz );
transformed += worldSpaceDirection * sin( timeElapsed );

and even extracting the rotation component of the matrix like this:

mat3 extractRotationMatrix( mat4 mat ) {
    return mat3( mat[0].xyz, mat[1].xyz, mat[2].xyz );
}
...
mat3 rotationMatrix = extractRotationMatrix( modelMatrix );
vec3 worldSpaceDirection = normalize( rotationMatrix * direction );
transformed += worldSpaceDirection * sin( timeElapsed );

Both have not provided the desired result. Model’s Y rotation still affects the direction of the animation.
I don’t understand why this doesn’t work. Does anyone have any idea?

I made sure that:

  1. direction uniform passed to the shader is normalized and is constant throughout the life of the application.
  2. The same happens when I apply the shader code to a different material, like MeshPhongMaterial
  3. This animation line of code ( transformed += ... ) is the only thing affecting the vertices movement, i.e. if I comment that line, the vertices are static and there is no animation.

Thank you for any help and have a nice day :hugs:

Turns out the correct way to do this is to multiply not by the matrix but the inverse of the matrix :sweat_smile:

2 Likes