Look At Vertex Shader for Instancing (GLSL)


Here’s a vertex shader that warps instances to look at an object :eyes:


The lookAt mat is created like so:

mat3 lookAtPoint(vec3 eye, vec3 at) {

	vec3 localUp = vec3(0, 1, 0); // temp sop space up vector
	vec3 fwd = normalize(at - eye); // direction to look at position
	vec3 right = normalize(cross(localUp, fwd)); // right vector of direction
	vec3 up = normalize(cross(fwd, right)); // up vector of direction

	return mat3(right, up, fwd);

And here it is at the call site:

mat3 lookAtMat = lookAtPoint(TDInstanceTranslate(), uLookAtPos.xyz);
vec3 newPos = lookAtMat * P;
vec3 newNorm = lookAtMat * N;

I’m also interpolating between the original verticies and the modified ones based on the height of the vertex. This sticks the monkey head to floor and creates the nice warping effect. Remove this to just have the head rotate without sticking.

float mixer = smoothstep(-0.5, 1, P.y);
newPos = mix(P, newPos, mixer);
newNorm = mix(N, newNorm, mixer);

Hope this helps someone!

LookAtShader.toe (29.7 KB)


Hi jayyson,

Nice work! And great technique of interpolating the vertices to make the monkey more organic :slight_smile: Really gives an expression to the guy :smiley:
Also thank you for sharing the look-at matrix calculation, those can be quite tricky without the knowledge of linear algebra.

I wanted to point out there is 1 small issue with the calculation when the look-at position is directly above the camera. This will set ‘fwd’ vector equal to localUp, the cross product in this case will return all zeros. Then normalizing a vec3(0) will result in NaN’s and will eventually make the monkey disappear. You would need to check manually if the two vectors are equal and if so take another axis to do the cross products.

Though did you know about TDRotateToVector() (described here Write a GLSL Material - Derivative under ‘matrix functions’)? It can be used to calculate the same matrix, but already does this equal check for you. You could use it something like:

mat3 lookAtMat = TDRotateToVector(normalize(uLookAtPos.xyz - TDInstanceTranslate()), vec3(0,1,0));



Hiya Tim! Thanks so much for this! Yea I did actually know about the up vector problem but honestly didn’t think to guard for it, really good point!

I’m aware of the TD functions but I’ve been trying to stick to pure GLSL where I can for learning purposes :slight_smile:

I’m still wrapping my head around matrices so thanks very much for the feedback :grin: I’m working my way through the “3D Math Primer for Game Dev” book :books:

1 Like

Hi Jayyson,

Ah great! That’s indeed the best approach to learn I think as well.
What really helped me understanding linear algebra was the MIT lectures by Gilbert Strang (https://www.youtube.com/playlist?list=PL49CF3715CB9EF31D). He’s an amazing teacher!
Though I don’t know the book you’re working through, but it sounds like it’s quite complete as well :slight_smile:



Ooo nice one, just had a little look, seems perfect!

1 Like

This is quite hypnotic and in my mind, I can hear all the little monkeys saying “Oooooooooh …”

which math book are you working through? My kid is really enjoying math and I thought maybe it’s time to suck him into touchdesigner. :slight_smile:

1 Like

It’s this one but I got the 2002 version for very cheap on eBay. It’s quite a tome.

3D Math Primer for Graphics and Game Development

It’s funny because it’s talks about Phong shading like it’s cutting edge stuff.

I wouldn’t say it’s the most fun read but it shows the theory and the practicalities, which is what I was after.

Also I wish I’d made the ball a banana now.

@rodberry I’ve just learned the 2nd (and better) edition of this book is totally free online provided by the authors: Introduction - 3D Math Primer for Graphics and Game Development