Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Get object center in a shader

Discussion in 'Shaders' started by Vade-Mecum, May 1, 2013.

  1. Vade-Mecum

    Vade-Mecum

    Joined:
    Dec 10, 2012
    Posts:
    17
    Hello! I have some issues about getting the object and the camera coordinates inside the shader.
    So, camera center command suppose to be _WorldSpaceCameraPos.xyz and that's ok. But i can't get the object center, i tried a lot but it won't work. Script input doesn't work either.
    _WorldPos, _Object2World - no effect, if it compiles at all. And it's strange because i get the vertex space positions correctly.
    So, can anyone help me to calculate the distance between the camera and the object/mesh center inside the shader?
     
    Last edited: May 1, 2013
    BAIZOR likes this.
  2. Farfarer

    Farfarer

    Joined:
    Aug 17, 2010
    Posts:
    2,249
    The object centre would be harder to find... but the object's origin is simply;

    float4 objectOrigin = mul(_Object2World, float4(0.0,0.0,0.0,1.0) );
     
  3. Vade-Mecum

    Vade-Mecum

    Joined:
    Dec 10, 2012
    Posts:
    17
    Thanks a lot, guys! It's finally working as it supposed to! Here's the code:
    Code (csharp):
    1. Shader "PinballShaders/BoundaryGlowShader2"
    2. {
    3.    Properties
    4.    {
    5.     _Color ("Main Color", Color) = (1,1,1,1)
    6.     _Shift ("Shift", Float) = 1.0
    7.     _MainTex ("Texture", 2D) = "white" {}
    8.    }
    9.    SubShader
    10.    {
    11.    Tags {"Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent"}
    12.    Lighting Off
    13.    Blend SrcAlpha OneMinusSrcAlpha
    14.    Cull Off
    15.       Pass
    16.       {
    17. CGPROGRAM
    18. #pragma vertex vert
    19. #pragma fragment frag
    20. #include "UnityCG.cginc"
    21. float4 _Color;
    22. sampler2D _MainTex;
    23. float4 _Fade;
    24. float _Shift;
    25.  
    26. struct v2f {
    27.     float4 pos : POSITION;
    28.     float4 color : COLOR0;
    29.     float2  uv : TEXCOORD0;
    30.     float alpha:TEXCOORD1;
    31.     float4 fragPos : TEXCOORD2;
    32.     float4 fade : TEXCOORD3;
    33. };
    34.  
    35. float4 _MainTex_ST;
    36.  
    37. v2f vert (appdata_base v)
    38. {
    39.     v2f o;
    40.     o.color = _Color;
    41.     o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
    42.     o.uv = TRANSFORM_TEX (v.texcoord, _MainTex);
    43.     o.fragPos = mul (UNITY_MATRIX_MV, v.vertex);
    44.     o.fade = mul (UNITY_MATRIX_MV, _Fade);
    45.     return o;
    46. }
    47.  
    48. half4 frag (v2f i) : COLOR
    49.  
    50. {
    51.     float4 outColor = i.color;
    52.     half4 texcol = tex2D (_MainTex, i.uv);
    53.     float dist = distance(i.fade, i.fragPos);
    54.     float4 objectOrigin = mul(_Object2World, float4(0.0,0.0,0.0,1.0) );
    55.     float dist2 = distance(objectOrigin, _WorldSpaceCameraPos) + _Shift;
    56.     if (dist < dist2)
    57.                 {
    58.                     discard;
    59.                 }
    60.         return texcol * outColor;
    61. }
    62. ENDCG
    63.       }
    64.    }
    65.    FallBack "VertexLit"
    66. }
    It's a shader, arranget from the pinball opacity shader and the alpha-self-illumin. shader, now it's doing cutoff! Thanks again!
     
    Last edited: May 2, 2013
    PrimalCoder likes this.
  4. Vade-Mecum

    Vade-Mecum

    Joined:
    Dec 10, 2012
    Posts:
    17
    Oh gosh.. once again searching for a lots of hours how to get an object position in fragment shader i get to my own question. Why is it like that? Why everyone says mul(_Object2World, vertex); and google just don't knows undefined "vertex" error in fragment shader? It's just awful.
     
  5. Marco-Sperling

    Marco-Sperling

    Joined:
    Mar 5, 2012
    Posts:
    620
    I wouldn't put this into the Fragment shader. That matrix multiplication gets called for each pixel of your rendered object which can be quite a lot.
    I recommend putting that transformation into the vertex shader.

    As for your second question: If I understand you correctly you were trying to do a transform on vertex data withing the fragment shader. Won't work.
    This line mul(_Object2World, vertex) hints at a vertex shader to be the correct place of usage.
    Of course you are free to name your variables whatever you want and you could easily name one vertex inside your fragment shader. But unless you have a very good reason to do so... just do yourself a favor and don't.

    That's why "Google" doesn't know about "vertex" error in fragment shader.
     
  6. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    11,631
    We've had this discussion before.

    Any sort of batching breaks that line (since meshes get combined and share "object space").

    And if you're not going to batch and share materials, you might as well calculate the center/origin in script and pass it with a unique variable in each material.

    Another method would be to encode it in Vertex Colors, but that might or might not be doable depending on what you want to do.
     
  7. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Yeah, although that's pretty bad practise. You really want less materials. The material change is more expensive than "just another draw call", not least with instancing on the way and console gpus being significantly better than cpu.

    But sure, if it's not many objects needing it, it's no problem. Just clarifying for any readers.
     
    AcidArrow likes this.
  8. Vade-Mecum

    Vade-Mecum

    Joined:
    Dec 10, 2012
    Posts:
    17
    What i was doing that time is a shader that would cut object in a half, view-dependent. AR app, factory tower. You look at it from a diffirent angles and see it schematically cut in a half and see it's insides.
    What i was doing this time is editing custom CGinc so when the terrain trees with shadow reciever shader gets farther than shadow distance it would not shine at the unlit areas. So what i did is calculated distance between object and camera and fade the attenuation down so the trees is smoothly lit where i need it to.
    That's more logical? And that's why i'm so mad at this question. Half of the problem is that developers has decided that YOU just don't need some really critical functional, the other half is that this free engine has a zoo of unpredictable and sometimes really expensive solutions that also may not work at all. And noone cares. That's drives me mad.
    Look at this!
    i just wanted a smooth LOD transition, but i end up making my own LOD system because no others works propertly.
     
  9. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    I wouldn't even put that in the vertex shader. I'd just use:
    Code (csharp):
    1.  
    2. float4 objectOrigin = _Object2World[3];
    3.  
     
  10. chingwa

    chingwa

    Joined:
    Dec 4, 2009
    Posts:
    3,789
    @jvo3dc Oh. My. God. Thank you so much!!! :D I just spent hours trying to get vertex object origins and tried at least 5 different methods and they all came up wrong. Turns out all I needed was this single line. Unity I hate you and love you at the same time.