Search Unity

worldPos Is Zero, When Inside "#ifdef SHADER_API_D3D11" In Surface Shader..

Discussion in 'Shaders' started by brilliantgames, Sep 22, 2018.

  1. brilliantgames

    brilliantgames

    Joined:
    Jan 7, 2012
    Posts:
    1,937
    This is really frustrating me. I am working on some custom Area lights and worldPos goes to (0,0,0) when inside #ifdef SHADER_API_D3D11.

    worldPos works perfect anywhere else. Anyone have any idea why this happens? It's extremely annoying and I cannot calculate lighting without the world position..
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,348
    Surface shaders are overzealous with their “optimizations” and will skip passing necessary information through to the surface function if the shader generator thinks it is not being used. Encapsulating data inside preprocessor macros, like #if statements, or some more advanced use cases like derivatives, as well as some completely straight forward use cases, the shader generator completely mucks up and skips passing the data in. This is especially frustrating for stuff like world position, which Unity always passes from the vertex to the fragment anyway, there’s no reason to not pass it onto the surface function if it’s defined in the Input.

    It wasn’t always like this, sometime around mid Unity 5 they did a bunch of work to surface shaders and added this new “feature”. It has been reeking havoc ever since. The hack work around is doing something stupid like adding worldPos * 0.00001 to the Albedo.
     
  3. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    3,019
    That's not entirely correct... Surface shaders check what's using during an extra phase, which doesn't have the target API defined. Thus it thinks that you're not using worldPos.
    Try
    Code (CSharp):
    1. #if defined(SHADER_API_D3D11) || defined(SHADER_TARGET_SURFACE_ANALYSIS)
     
    bgolus likes this.
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,348
    I couldn't remember if there was a define for when it's doing the analysis or not, that's useful. It would be nice to have that define in the documentation.

    The analysis pass is still often "culling" properties that shouldn't be disabled, even with out using any #if statements. There's also fun stuff like IN.worldNormal when writing to o.Normal stopped working like two years ago now. If I remember correctly it gets set after the surf function is called.