Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TSL - add documentation for rotate node #30728

Open
zaesur opened this issue Mar 12, 2025 · 0 comments
Open

TSL - add documentation for rotate node #30728

zaesur opened this issue Mar 12, 2025 · 0 comments

Comments

@zaesur
Copy link
Contributor

zaesur commented Mar 12, 2025

Description

To try out TSL and compute shaders, I am working on a small application with boids.

To point the instanced meshes in the direction they are travelling, I needed to rotate the vertices.

I looked at TSL.rotate, but I found that it is undocumented. It would be nice to add documentation and/or examples of this function to https://github.com/mrdoob/three.js/wiki/Three.js-Shading-Language, as well as describing in which Euler order the rotation is applied.

Additionally, Euler angles were not particularly practical in this case. I imagine Euler angles are useful when you want to perform a rotation and have some geometric intuition about the rotation you're performing, but in my use case this varied from instance to instance. Instead, I would have appreciated a TSL equivalent of lookAt.

Solution

I have the following suggestions:

  1. Add documentation for rotate
  2. Implement lookAt
  3. Update webgpu-compute-birds example to use lookAt

Alternatives

With some help of AI, I ended up implementing this successfully as follows:

import * as TSL from "three/tsl";

const calculateRotationMatrix = TSL.Fn(
  ({ direction, forward }) => {
    const axis = direction.cross(forward).normalize();
    const angle = TSL.acos(direction.dot(forward));

    const s = TSL.sin(angle);
    const c = TSL.cos(angle);
    const t = c.oneMinus();

    const rotationMatrix = TSL.mat3(
      t.mul(axis.x).mul(axis.x).add(c),
      t.mul(axis.x).mul(axis.y).sub(axis.z.mul(s)),
      t.mul(axis.x).mul(axis.z).add(axis.y.mul(s)),

      t.mul(axis.y).mul(axis.x).add(axis.z.mul(s)),
      t.mul(axis.y).mul(axis.y).add(c),
      t.mul(axis.y).mul(axis.z).sub(axis.x.mul(s)),

      t.mul(axis.z).mul(axis.x).sub(axis.y.mul(s)),
      t.mul(axis.z).mul(axis.y).add(axis.x.mul(s)),
      t.mul(axis.z).mul(axis.z).add(c)
    );

    return rotationMatrix;
  }
);

// ....

material.vertexNode = TSL.Fn(() => {
    const position = positions.element(TSL.instanceIndex);
    const velocity = velocities.element(TSL.instanceIndex);

    const rotationMatrix = calculateRotationMatrix({
      direction: velocity.normalize(),
      forward: TSL.vec3(0, 1, 0),
    });
    const localPosition = rotationMatrix.mul(TSL.positionLocal);
    const worldPosition = TSL.modelWorldMatrix.mul(localPosition).add(position);

    const transformedNormal = rotationMatrix.mul(TSL.normalLocal);
    normal.assign(transformedNormal);

    return TSL.cameraProjectionMatrix
      .mul(TSL.cameraViewMatrix)
      .mul(worldPosition);
  })();

Additional context

No response

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant