Search Unity

Set world-space normal in surface shader

Discussion in 'Shaders' started by Miguel-Ferreira, Jul 11, 2017.

  1. Miguel-Ferreira

    Miguel-Ferreira

    Joined:
    May 8, 2015
    Posts:
    90
    Hi,

    I have this simple surface shader

    Code (CSharp):
    1. #pragma surface surf SimpleLambert
    2. half4 LightingSimpleLambert (SurfaceOutput s, half3 lightDir, half atten) {
    3.     return fixed4(s.Normal,1.0);
    4. }
    5.              
    6. void surf (Input IN, inout SurfaceOutput o) {
    7.     o.Normal = fixed3(1,0,0);
    8. }
    just to debug the normal, but Unity requires the o.Nomal to be in tangent space.

    Is there any way to directly set the normal in world space inside the surf function instead of having to do a bunch of tricks to convert it to the tangent space...?
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    Nope.
     
  3. FlaxenFlash

    FlaxenFlash

    Joined:
    Oct 15, 2015
    Posts:
    28
    You can get the generated surface shader code and delete the bit where Unity converts the normal from your surface shader from tangent to world space. You have to change it in all the variants though and it becomes a bit of a pain to change the shader later because it needs to be changed for each variant. You could maybe refactor your surface function out into a separate cg file to make future changes easier though. I've been meaning to try that in the shaders where I do this myself
     
  4. brn

    brn

    Joined:
    Feb 8, 2011
    Posts:
    320
    Not a proper answer because its a hack but.......

    If you are only worried about the deferred path and you don't mind a little extra bloat in your shader you can set up your own surfaceOutput struct. Add your own wordspace normal to it then pass that directly to the deferred normalWorld input thats part of UnityStandardData data using a custom deferred lighting function.

    Don't write anything to o.Normal in your surface shader and most of the tangent space fandago should get culled by the compiler.

    Make sure you pass your world space normal to the GI light function and you will probably have to write dummy forward lighting functions as well.

    Nasty but functional :D

    PS. Don't forget to use the surface shader code generation options to remove unwanted variants and so on.
     
    Last edited: Aug 9, 2017