I’m trying to get a scaling value to animate an object swaying, so that the top vertices move more than the bottom.

I’ve managed to achieve this with by using the z component of the vertex position, but this only seems to work correctly for a simple quad model - when I’ve tried on a more complicated model, the z value scaling seems to be somehow proportional to the world position of the model ( & vertex ), and scales disproportionately.

So I’m wondering if there is a way to get a ‘normalized’ relative height for a vertex to its model.

I’ve tried transforming the vertex position using the projection matrices, eg:

float4 oPos = mul( UNITY_MATRIX_P, v.vertex );

However, the scaling still seems to be affected by the world position of the object.
Maybe I’m doing it wrong, or there is another way - or this is not possible?

There are a number of ways that you could get a normalized height value. With each one, you have to decide though do you increase your memory by “baking” more of it, or do you do more at runtime.

The fastest to setup. Make sure your characters pivot point is at its feet. Store a float for the characters height. Then (vertexPos - objectPos).z / objHeight. That would give you a normalized value, but presetting a height is almost a hack.

My personal favorite. If you can spare an extra uv channel. Create a straight forward projection of your model. No seems or anything just project your model directly into uv space from the front. Then scale it so its feet are at the bottom and its head is at the top. Then in your shader, access the v (y) component of the vertex’s uv and you’ll get a normalized range. the bottom will be at ( n , 0) and the top will be at ( n , 1).

scaleFactor = vertex.uv.y;

You could get a very similar effect with vertex colors with a gradient all the way up the model. I like the latter two because the only thing you are doing in real time is reading the value.

Using matrices is probably possible, but it makes the calculations more expensive and shaders are run so many times a frame you never want to do more in them more than you have to.

v.vertex is the “raw” position. For every cow in the scene, v.vertex of the nose is the exact same number. That’s probably what you want. Multiplying by the world matrix turns this into the position in the game world (“proportional to world position” in your terms.) It applies the transform, so this is where scale is used.

Multiplying by the projection matrix turns it into the actual pixel on the screen (sort of,) by taking the camera into account. Not good for much except lens blurs w/o using render-to-texture.

For a quick test, try (in the shader) if(v.vertex.z > val) color=float3(1,0,0,1); then you can easily check whether z is really up, the range of values, whether moving the camera, model … is affecting things.

Also, a “top-sway” sideways makes the model appear the stretch. For a cheap fix, can also lower the vert by 1/2 or 1/3 of the sideways amount.

I am not experienced in shaders, but you actually -might- have a scale problem, as in “your model’s scale is irregular”.
What I suggest is that you reset your model’s scale.

In blender for example, you select all the meshes in the model and press CTRL A, and then apply position, rotation and scale.

This way, the majority of operations on the mesh won’t have scale problems, and your shader might work as expected.

Please post the shader code if you get it working by this suggestion.

Usually the incoming vertex position in the vertex shader contains the local position. Inside the vertex shader you have to transform it into worldspace -->cameraspace–>viewspace by multiply it with your MVP(Model-View-Projection) matrix to prepare it for the fragment shader.

Usually you have something like this:

o.pos = mul (UNITY_MATRIX_MVP, v.vertex);

which transforms the local position directly into viewspace.

You want to skew your mesh so just multiply your local position with a skew matrix (or do the skewing yourself but a skewmatrix is simpler) before you transfrom it into viewspace.

Keep in mind that the skewing will happen around your pivot-point (0,0,0 in local space). If you want to know how to setup a skew matrix, see this post: