Search Unity

'Pull to Camera' shader?

Discussion in 'Shaders' started by eco_bach, Mar 7, 2017.

  1. eco_bach

    eco_bach

    Joined:
    Jul 8, 2013
    Posts:
    1,601
    Watched an excellent GDC seminar on mobile optimization strategies. One trick mentioned was to use a 'pull to camera ' shader so that a Billboard render is pulled towards camera on z axis, effectively putting it in 'front' of the game object instead of slicing thru it. Haven't heard of this before. Is anyone aware of such a shader or how I might enable this on an existing fx shader?
     
  2. sweetclimusic

    sweetclimusic

    Joined:
    Nov 11, 2016
    Posts:
    12
    do you have a link to this seminar? is it up on their youtube archives yet?
     
  3. eco_bach

    eco_bach

    Joined:
    Jul 8, 2013
    Posts:
    1,601
    yep here
     
  4. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    I've done this many times and it's actually pretty simple to do. The easiest way to do this is in world space. So in the vertex shader:
    - Convert the input object space position to world space
    - Lerp the world space position between the original and the camera position
    - Convert the world space position to clip space

    So a lerp value of 0.5 would place the object halfway between the original position and the camera. You'll want to use a value that's as low as possible.
     
  5. Phantom_X

    Phantom_X

    Joined:
    Jul 11, 2013
    Posts:
    314
    I have this that seems to be working:

    Code (CSharp):
    1.        
    2. float4 pos = mul(_Object2World,v.vertex);
    3. pos.xyz   = lerp(pos.xyz,_WorldSpaceCameraPos,_Pull);
    4.  o.pos     = mul(UNITY_MATRIX_MVP,mul(_World2Object,pos));
    5.  
    However I'm having some trouble making it work with my billboard code:

    Code (CSharp):
    1.  
    2. float4 pos = mul(UNITY_MATRIX_P,
    3. mul(UNITY_MATRIX_MV,
    4. float4(0.0, 0.0, 0.0, 1.0)) - float4(v.vertex.x, v.vertex.y, 0.0, 0.0));
    5.  
     
    Alekxss likes this.
  6. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    Change this:
    Code (csharp):
    1.  
    2. o.pos     = mul(UNITY_MATRIX_MVP,mul(_World2Object,pos));
    3.  
    To this for some simple optimization:
    Code (csharp):
    1.  
    2. o.pos     = mul(UNITY_MATRIX_VP,pos);
    3.  
    And for the other one I'm also not that sure. You're taking a fixed base in camera/view space, then subtract the actual vertex positions there.
     
  7. Phantom_X

    Phantom_X

    Joined:
    Jul 11, 2013
    Posts:
    314
    ok simple solution,

    using my billboard code, you can actually pull the z from the quad by changing it's z value like this. I use a variable _Pull to control it.

    Code (CSharp):
    1.  
    2. float4 pos = mul(UNITY_MATRIX_P,
    3. mul(UNITY_MATRIX_MV,
    4. float4(0.0, 0.0, 0.0, 1.0)) - float4(v.vertex.x, v.vertex.y, _Pull, 0.0));
    5.  
     
  8. SimonOliver

    SimonOliver

    Joined:
    Jul 16, 2007
    Posts:
    30
    Depending on your needs, you might want to move a specific amount in world space towards the camera (we needed to for current project) - this should do the trick!

    Code (CSharp):
    1. // Convert to world space
    2.                 float3 pullPos = mul(unity_ObjectToWorld,v.vertex);
    3.                 // Determine cam direction (needs Normalize)
    4.                 float3 camDirection=normalize(_WorldSpaceCameraPos-pullPos);                              
    5.                 // Pull in the direction of the camera by a fixed amount
    6.                 pullPos+=camDirection*_PullDistance;
    7.                 // Convert to clip space              
    8.                 o.pos=mul(UNITY_MATRIX_VP,float4(pullPos,1));
     
    LazloBonin likes this.
  9. Johannski

    Johannski

    Joined:
    Jan 25, 2014
    Posts:
    826
    Hm, I think you're all putting a bit too much effort into it. I would just use the Offset feature of unity.
    From the documentation:
    Here is an example shader you can play around with: https://github.com/supyrb/ConfigurableShaders/wiki/Rendering

    By using an offset of -20 (well depends on the distance the camera is away from the object) you might just achieve what you want to achieve.
     
  10. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,348
    The problem with the Offset feature is it's potentially going to be different for every device it runs on as the implementation isn't defined in the spec. So a value of -20 not only changes with distance, but also per device. On some devices it might do nothing!

    The other problem with Offset is it is often (always?) implemented as a fragment shader depth write which has potential performance implications. Specifically that disables any early z rejection. Doing a manual offset in the vertex shader can potentially be much faster.
     
    Johannski likes this.
  11. Netuddmeg

    Netuddmeg

    Joined:
    Mar 2, 2018
    Posts:
    14
    And what is the solution?
    I'm also interested in "pull to camera" / and uv distortion smoke shaders/technique.