0
\$\begingroup\$

I'm trying to apply UV mapping in parent space - ie. taking into account the object's own transformation matrix but no matrices further up the transformation hierarchy.

For example, I'd want to be able to transform a cube mesh (rotate/scale) and have UVs based on that, not the mesh vertices themselves. Then any transforms above that would not impact that object’s UVs.

What’s the best way to access the local transform matrix of an object in a shader in Unity?

I know that I can use objectToWorld to get access to the entire hierarchy’s flattened transform matrix, but I want to specifically access only the bottom most transform (the local one produced by the transform component on an object)

Do I have to pass this in as a custom variable each frame? Or is there a better method to use?

\$\endgroup\$
1
\$\begingroup\$

I think you're right that the only way to get this is to pass a custom variable each frame:

public class LocalMatrixToShader : MonoBehaviour
{
    Renderer _renderer;

    static MaterialPropertyBlock _block;
    static int _propertyIndex;

    void Start()
    {
        _renderer = GetComponent<Renderer>();

        if(_block == null) {
            _block = new MaterialPropertyBlock();
            _propertyIndex = Shader.PropertyToID("_LocalMatrix");
        }
    }

    void LateUpdate()
    {
        var worldToParent = transform.parent == null ?
                     Matrix4x4.identity
                     : transform.parent.worldToLocalMatrix;

        var localToParent = worldToParent * transform.localToWorldMatrix;

        _block.SetMatrix(_propertyIndex, localToParent);
        _renderer.SetPropertyBlock(_block);
    }
}
\$\endgroup\$
  • \$\begingroup\$ Is there a way to have this update in real-time in the editor then too? \$\endgroup\$ – Danny Yaroslavski Aug 12 '19 at 0:43
  • 1
    \$\begingroup\$ [ExecuteInEditMode] and change the business end from LateUpdate to Update. \$\endgroup\$ – DMGregory Aug 12 '19 at 0:45
  • \$\begingroup\$ Could just as easily construct the local matrix using the localPosition, localRotation and localScale values. \$\endgroup\$ – Danny Yaroslavski Aug 12 '19 at 5:00
  • \$\begingroup\$ Sure, localToParent = Matrix4x4.TRS(transform.localPosition, transform.localRotation, transform.localScale); I'm not sure whether this is faster than a matrix multiply — I haven't profiled the two cases against one another. \$\endgroup\$ – DMGregory Aug 12 '19 at 11:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.