Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
8
Question by damiant · Oct 23, 2013 at 06:17 PM · shadersurfacesurface shadersurfaceshader

Get local position in surface shader

Is there any way to get the local position (relative to the mesh) on the surface shader?

This is part of my code:

     fixed4 _Color;
     fixed4 _ReflectColor;
     half _Shininess;
     fixed _DrawLimit;

     struct Input {
         float2 uv_MainTex;
         float3 worldRefl;
         float3 worldPos;
     };

     void surf (Input IN, inout SurfaceOutput o) {
         clip(IN.worldPos.z - _DrawLimit);
     
         fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
         fixed4 c = tex * _Color;
         o.Albedo = c.rgb;
         o.Gloss = tex.a;
                     
         o.Specular = _Shininess;
         
         fixed4 reflcol = texCUBE (_Cube, IN.worldRefl);
         reflcol *= tex.a;
         o.Emission = reflcol.rgb * _ReflectColor.rgb;
         o.Alpha = reflcol.a * _ReflectColor.a;                                
     }

Instead of using worldPos I need the local position. I can't find a way to get it in the docs (at least here).

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
8
Best Answer

Answer by tanoshimi · Oct 23, 2013 at 07:12 PM

Untested, but here's an idea: First, add a member to your Input structure:

 struct Input {
   float2 uv_MainTex;
   float3 localPos;
 };

Then add a vertex modifier function that populates the localPos member with the vertex information from appdata:

 #pragma surface surf Lambert vertex:vert
 
 void vert (inout appdata_full v, out Input o) {
   UNITY_INITIALIZE_OUTPUT(Input,o);
   o.localPos = v.vertex.xyz;
 }

Now in your surf function you should be able to access IN.localPos as:

 void surf (Input IN, inout SurfaceOutput o) {
   // Do something with IN.localPos....
 }
Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image MaT227 · Jan 30, 2014 at 08:24 PM 0
Share

It works well ! BUT, what about objects with different axis. It's always the same problem with axis in different applications (3DS$$anonymous$$ax, Unity, $$anonymous$$aya, Blender, etc...) wen you import them. Is there a way to correct that in the shader ?

avatar image
4

Answer by Arwahanoth · Nov 23, 2016 at 06:25 PM

In fact I just discovered that we don't need the "vert" and we could do it only in "surf" with:

 float3 localPos = IN.worldPos -  mul(unity_ObjectToWorld, float4(0,0,0,1)).xyz;

Don't forget to declare worldPos in Input:

 struct Input {
    /// [....]
    float3 worldPos;
  };
Comment
Add comment · Show 10 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image chuckbergeron · Mar 01, 2017 at 09:12 PM 0
Share

Thanks for this addition! It kicked ass for me. Fixed the weird model import "what is y/up?" problem above. :)

avatar image mani3307 · Mar 26, 2018 at 08:23 AM 0
Share

Can you explain me what you are doing in the first line code

avatar image ahung89 mani3307 · Mar 29, 2018 at 06:21 AM 1
Share

He's converting the origin of the object, which is by definition (0, 0, 0) in its local space, into world space. Then he's subtracting that from IN.worldPos (which is the interpolated world position of the fragment) in order to get the difference between the fragment and the origin of the object. The difference between the fragment's position and the object's origin = its local position.

This is sometimes better than just getting the local position directly from the vertex shader input (via the POSITION semantic) because imported 3d models are often rotated, so the object's local axes won't be aligned with the world space axes.

avatar image mani3307 ahung89 · Mar 29, 2018 at 10:13 AM 0
Share

Can you clearly explain to me how mul(unity_ObjectToWorld, float4(0,0,0,1)).xyz works?

Show more comments
avatar image Nearo1 · Feb 07, 2020 at 07:27 AM 0
Share

This way is a good way, to consider the scale,

avatar image Bunny83 · Feb 07, 2020 at 09:43 AM 2
Share

This does only work in very special cases. Your object must not be scaled and must not be rotated in any way. Otherwise your result is completely wrong. Also using a matrix multiplication to get the last column of a matrix is just a waste of GPU power.

 float3 pos = unity_ObjectToWorld._m03_m13_m23;

This will get the x,y and z of the last column. The best solution is to just pass the local space position along in the vertex shader. Note that a surface shader will still compile a vertex and a fragment shader anyways. It's just a fancy highlevel way to write shaders. If you really need to convert the worldspace position back to local space, use the unity_WorldToObject matrix ins$$anonymous$$d

 float3 localPos = mul(unity_WorldToObject, IN.worldPos);

$$anonymous$$eep in $$anonymous$$d that worldPos need to be a float4, not a float3. We're dealing with homogeneous coordinates here. Alternatively you can use something like

 float3 localPos = mul(unity_WorldToObject, float4(IN.worldPos, 1));
avatar image Arwahanoth Bunny83 · Feb 08, 2020 at 06:26 PM 0
Share

Long time not used Unity but if I take you're advice the code should be:

 float3 localPos = mul(unity_WorldToObject, IN.worldPos);
 
  struct Input {
     /// [....]
     float4 worldPos;
   };

Right?

avatar image inakidiezgalarza Bunny83 · Dec 02, 2021 at 12:09 AM 0
Share

thank you very much! I was having problems because of the scale and this helped me fix them

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

23 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Surface shader ParallaxOffset issue 1 Answer

Z value shader 1 Answer

How to Modify Standard Surface Shader's SpecCube? 1 Answer

How to not require normals in a surface shader 1 Answer

uv-space to screenSpace in surface shader 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges