Unity Shader World/Object Matrix

Hi all,

I’m trying to modify vertex position in the vertex shader, but this code does not work.

 float4 temp = mul(_Object2World, v.vertex);
 temp = mul(_World2Object,temp);
 o.pos = mul(UNITY_MATRIX_MVP, temp);

while
o.pos = mul(UNITY_MATRIX_MVP, temp);

does work. Why does multiplying by a matrix and it’s inverse break things?

float4 worldPos = mul(_Object2World, v.vertex);
//mess with worldPos.xyz
o.pos = mul(UNITY_MATRIX_VP, worldPos);

Note, that’s UNITY_MATRIX_ VP not MVP. So, convert the vertex point from model space to world space, then manipulate, then convert from world space through view/proj to screen space. Boom.

So the issue was that mul(_Object2World, _World2Object) was not the identity matrix. I was able to fix it by multiplying the _World2Object Matrix by unity_Scale.w. Doing this resulted in it half working, with some objects working and some not. I fixed this by changing the scale on the objects that weren’t working by ±0.0001 (WTF?). Seems to be mostly a random unity issue.

Here is a solution that works better than PEOWlfjpwoiqjf’s solution (did get me on the right track, thanks!).
You still must multiply _World2Object by unity_Scale.w but this should NOT be applied to the bottom right value of the matrix.

Here is an example.

float tmp = _World2Object[3][3];
float4x4 I_Object2World = _World2Object * unity_Scale.w;
I_Object2World[3][3] = tmp;
v.vertex = mul(I_Object2World, pos);

Well, they removed unity_Scale.w in Unity 5, so that leaves future people stumped. In theory now they should be proper inverses of each other.

[SOLVED] Had the same problem, the solution was to set the w value to 1.0:

float3 worldPosObject = mul (unity_ObjectToWorld, float4(v.vertex.xyz, 1.0)); // object space to world space

// do stuff in word space

v.vertex = mul (unity_WorldToObject, float4(worldPosObject,1.0)); // world to object space
}

The answer from @RazHollander13 above works perfectly. I add one extra thing on top of it.
UnityCG.cginc has UnityWorldToClipPos, a helper function to convert the world position to the clip position.

It is handy for me because what I eventually need after manipulating the world position is a clip position.

#pragma vertex vert
#include "UnityCG.cginc"
struct appdata {
    float4 vertex : POSITION;
};
struct v2f {
    float4 vertex : SV_POSITION;
}
v2f vert (appdata v) {
    v2f o;
    // o.vertex = UnityObjectToClipPos(v.vertex); // The following code results in the same clip position
    float3 wv = mul(unity_ObjectToWorld, v.vertex).xyz; // Object space to world space
    o.vertex = UnityWorldToClipPos(wv); // world space to clip space
    return o;
}

I’m on Unity 2021.3.1f1, by the way.