Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
12 Jun 22 - 14 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
3
Question by weatxyz · Nov 06, 2016 at 09:17 AM · shadercgtransformstangentsviewdir

How can I transform a world view dir into tangent space in a Cg only shader

Hello, I've been trying to figure this one out for a while now and I can't seem to make it work. The only place it fails is when I rotate the object in any way.

My plan was to write a custom Cg shader that would transform the viewDir into tangent space so I could do my calculation there. This method is supposed to be much faster than transforming the tangent space normal into world space, and less complicated, so I thought :).

Here was my line of thinking. I create a TBN matrix with TANGENT_SPACE_ROTATION and multiply it with unity_ObjectToWorld so that the TBN will be in world space. Then I multiply the world space view dir UNITY_MATRIX_V[2].xyz by the transpose of that matrix to bring the view direction into tangent space.

Update: Updated to working code.

Here's the code:

 Shader "CgRimShader"
 {
     Properties
     {
         _Color("Color", COLOR) = (0,0,0,1)
         _RimColor("Rim Color", COLOR) = (1,1,1,1)
         _RimPower("Rim Power", Float) = 2
         _BumpMap ("Normalmap", 2D) = "bump" {}
     }
     SubShader
     {
         Tags {"RenderType"="Opaque" }
         LOD 100
 
         Pass
         {
             CGPROGRAM
             #pragma vertex vert
             #pragma fragment frag
             
             #include "UnityCG.cginc"
 
             struct appdata
             {
                 float4 vertex   : POSITION;
                 float2 uv       : TEXCOORD0;
                 float3 normal   : NORMAL;
                 float4 tangent  : TANGENT;
             };
 
             struct v2f
             {
                 float4 vertex   : SV_POSITION;
                 float2 uv       : TEXCOORD0;
                 float3 viewDir  : TEXCOORD1;
             };
 
             sampler2D   _BumpMap;
             float4      _BumpMap_ST;
             float4      _Color;
             float4      _RimColor;
             float       _RimPower;
             
             v2f vert (appdata v)
             {
                 v2f o;
 
                 o.vertex = UnityObjectToClipPos(v.vertex);
                 o.uv = TRANSFORM_TEX(v.uv, _BumpMap);
                             o.viewDir = COMPUTE_VIEW_NORMAL;
 
                 return o;
             }
             
             fixed4 frag (v2f i) : SV_Target
             {
                 float3 Normal = UnpackNormal(tex2D(_BumpMap, i.uv));
                 float3 ViewDir = normalize(i.viewDir);
                 float NdotV = max(0, dot(Normal, ViewDir));
 
                 fixed4 col = _Color + pow(1-NdotV, _RimPower) * _RimColor;
 
                 return col;
             }
             ENDCG
         }
     }
 }
Comment
Add comment · Show 2
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 weatxyz · Nov 06, 2016 at 03:08 AM 0
Share

Well the good news is that whatever I'm doing wrong, I'm doing it consistently. I transformed the object space normal into world space to see what that would look like and it's the same issue. I also brought the view space normal into object space and same thing. I can rotate the camera any way I want and the object looks right, but as soon as I rotate the object, it breaks.

The articles I've read, and what I already understand about matrices says this should be working, so this is driving me nuts. I'm just going in circles at this point.

avatar image weatxyz · Nov 06, 2016 at 06:05 PM 0
Share

One other thing about the version above. UNITY_$$anonymous$$ATRIX_V[2] is not the view direction in world space. It's supposed to be the transpose of the camera matrix. So I did a transpose on it to get the world view direction and that didn't work either. Then I found a post by someone saying that the world space view direction is in UNITY_$$anonymous$$ATRIX_T_$$anonymous$$V[2], but that didn't work either.

Then I was like fine, I'll see if I can translate a forward vector into tangent space using a trial and error method. Then finally it worked! I sort of get why it works for both the camera and model rotation, but not completely.

2 Replies

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

Answer by weatxyz · Nov 06, 2016 at 06:55 PM

OK, so I took a different approach with this and finally got it to work. Although I hate the fact that I stumbled onto this solution and still don't know why it works. Just replace the vert function above with this one and it works great.

Update: I kept optimizing this and optimizing this and discovered that the solution was staring me right in the face. there's one simple macro that does all that is needed called COMPUTE_VIEW_NORMAL! I updated the code below to reflect this change.

             v2f vert (appdata v)
             {
                 v2f o;
 
                 o.vertex = UnityObjectToClipPos(v.vertex);
                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                 o.viewDir = COMPUTE_VIEW_NORMAL;
 
                 return o;
             }

The definition of that macro is this: mul((float3x3)UNITY_MATRIX_IT_MV, v.normal)

This version also works and is the version I optimized my shader to before I found the macro: mul(v.normal, (float3x3)UNITY_MATRIX_T_MV)

Comment
Add comment · 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
0

Answer by ifurkend · Aug 22, 2020 at 03:05 PM

Kudos to Harry Alisavakis for providing the complete code to obtain the viewDir in tangent space:

https://halisavakis.com/my-take-on-shaders-parallax-effect-part-ii/

Comment
Add comment · 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

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

5 People are following this question.

avatar image avatar image avatar image avatar image avatar image

Related Questions

How to force the compilation of a shader in Unity? 5 Answers

Custom ambient lighting color in a Cg shader 2 Answers

What is struct Input (Shader)? 1 Answer

Object Space Normal Map - Object Clones break Normals 0 Answers

TEXCOORD 0 1 2 3 for cg shader scripting? 1 Answer


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