How to see position relative to another gameobject in fragment shader?

My goal is a custom shader applied to any object which clips pixels based on the position of a shared bounding volume. That shared bounding volume is simply a cube, and I upload the min/max corners to the shader whenever it changes.

I thought it would be sufficient to get the world position within the shader, and then multiply that by the shared bounding volume’s worldToLocalMatrix (I upload this as a float4x4 matrix). However, this is incorrect – it works if all rotations are 0, but the clipping area moves around depending on the rotation, so I know that the coordinate space conversion is wrong.

This is what I do:

float4 posWorld = mul(unity_ObjectToWorld, v.vertex);
o.objectPosInBoundingSpace = mul(_FadeWorldToLocal, posWorld);

Then in the fragment, I discard pixels based on the z axis of the Min/Max (right now I only care about the z axis)

if(_FadeMaxWorld.z < i.objectPosInBoundingSpace.z || _FadeMinWorld.z > i.objectPosInBoundingSpace.z)
{
discard;
}

What am I missing? Is the “worldspace” unique per gameobject at least where the shader is concerned? I thought that I could rely on worldspace for all conversion.

Do you have batching enabled?

Yes. I just disabled batching and am having the same problem.

For what it’s worth – the clipping area seems to have the correct orientation and scale, but not position. It moves along the z axis as I rotate an object which contains both the shared transform and the individual gameobjects.

World space should be consistent regardless of batching or not. In fact batched geometry’s vertex locations are already in world space.

I’m going to suggest you try something a little odd. Do this:

mul(worldPos, _CustomWorldToLocal);

Instead of mul(_CustomWorldToLocal, worldPos); ?

I just tried that – now I have the same type of position alignment issue, but also an orientation issue.