Search Unity

trying to deform based on world coordinates with unity_ObjectToWorld not working

Discussion in 'Shaders' started by memoid, Jun 13, 2019.

  1. memoid

    memoid

    Joined:
    Aug 30, 2014
    Posts:
    10
    I'm trying to write a vertex shader which deforms vertices based on world coordinates, i.e. like a 'deformation' field embedded in the world, and deforming vertices based purely on where they are in space, irrespective of the owner objects' scale, rotation, translation etc.

    So I'm using ```mul(v.vertex.xyz, unity_ObjectToWorld)``` to base my noise on world coordinates, but it's not working, and I'm going crazy for hours trying to figure out why.

    My full code is below. I can toggle _NoiseWorldCoordinates in runtime. With it off (i.e. working in object space), everything looks correct. I.e. I have 2 spheres side by side, one is scaled twice as large. And its noise deformations are also scaled twice as large. if I rotate one sphere, it rotates as a solid object (deformations don't change). All good.

    When I enable _NoiseWorldCoordinates, I would expect the size of the deformations to be independent of scale, and that is correct. But when I rotate or translate the sphere, it just moves as a solid object. The sphere, the deformations don't change even though the vertices are moving in space!. What is going on?

    Unity 2019.3.a04
    Code (CSharp):
    1.        void vert(inout appdata_full v) {
    2.            float4 pos = _NoiseWorldCoordinates ? mul(v.vertex, unity_ObjectToWorld) : v.vertex; // work in world coordinates
    3.            float3 norm = normalize(_NoiseWorldCoordinates ? mul(v.normal, unity_ObjectToWorld) : v.normal); // work in world coordinates
    4.            pos.xyz += norm.xyz * _NoiseAmp * snoise_grad(pos * _NoiseFreq + (_Time * _NoiseSpeed)).xyz;
    5.            v.vertex.xyz = _NoiseWorldCoordinates ? mul(pos.xyz, unity_WorldToObject) : pos.xyz; // convert world coordinates back to object
    6.        }
     
    Last edited: Jun 13, 2019
  2. memoid

    memoid

    Joined:
    Aug 30, 2014
    Posts:
    10
    Turns out I had the multiplication order wrong :/ the code below works.
    Code (CSharp):
    1.        void vert(inout appdata_full v) {
    2.            float4 pos = _NoiseWorldCoordinates ? mul(unity_ObjectToWorld, v.vertex) : v.vertex; // work in world coordinates
    3.            float3 norm = normalize(_NoiseWorldCoordinates ? mul(v.normal, unity_WorldToObject) : v.normal); // work in world coordinates
    4.            pos.xyz += norm.xyz * _NoiseAmp * snoise_grad(pos * _NoiseFreq + (_Time * _NoiseSpeed)).xyz;
    5.            v.vertex.xyz = _NoiseWorldCoordinates ? mul(unity_WorldToObject, pos).xyz : pos.xyz; // convert world coordinates back to object
    6.        }
     
    bgolus likes this.