Search Unity

Surface shader overhead frustrations

Discussion in 'Shaders' started by jistyles, Nov 15, 2014.

  1. jistyles

    jistyles

    Joined:
    Nov 6, 2013
    Posts:
    34
    Hi all,
    I've been struggling to implement a fairly basic shopping list of features in surface shaders, and keep hitting a frankly ridiculous limit of 3 spare interpolators when attempting to get a world space normal. Eg, my attempted struct is currently:

    struct Input
    {
    float3 UVPackedBlend;
    float4 effectuv;
    float4 fogParam;

    float3 worldNormal;
    INTERNAL_DATA
    };

    worldNormal and INTERNAL_DATA being required to get a per pixel world space normal, and only 3 elective extras.
    My question is two fold:
    1) what are effective ways to reduce IMPLICIT surface shader interpolator pressure. I do not use lightmaps, spherical harmonics, unity ambient, etc, I only use the basic light types and roll my own custom fog, radiosity, and stateless PBR lighting model.
    2) If this is a hard wall, are there any basic hlsl implementations of point/spot/directional unity lights, or should I just start implementing my own lighting architecture and trash all this black-box nonsense?

    If it's not obvious, I find this quite a frustrating facet of Unity development - to preface this a little I come from a AAA dev background as a graphics engineer, so I'm used to full source code and the ability to rip everything apart and micro optimise, but with unity I feel I can't get away from hidden or inherent overheads.​
     
  2. jRocket

    jRocket

    Joined:
    Jul 12, 2012
    Posts:
    700
    If you need to micro optimize everything, and aren't using the built in unity features, it you may get better results with with writing vertex/pixel shaders instead of using surface shaders.

    Keep in mind that surface shaders themselves generate cg vertex/pixel shaders, so if you ever need to see how something is done, you can make a basic surface shader with #pragma debug and open up the resulting code that gets spit out. i.e The basic point/spot/directional light implementation.

    http://docs.unity3d.com/Manual/SL-ShaderPrograms.html
     
  3. Farfarer

    Farfarer

    Joined:
    Aug 17, 2010
    Posts:
    2,249
    Yeah, you're better off writing it is straight up CG vert/frag shaders. You can interact with Unity's lighting system fairly easily using the macros provided by UnityCG.cginc and AutoLight.cginc, too.
     
    brn likes this.
  4. jistyles

    jistyles

    Joined:
    Nov 6, 2013
    Posts:
    34
    tl;dr version:
    use #pragma debug to get you started in converting surface shaders to manually curated hlsl
    --------------------------

    Thanks guys, I'm a little late in reporting back, but I wanted to let you know I've taken your suggestions and ended up with the following:
    - used the #pragma debug to rip the existing surface shader permutations and kick me off that path.
    - simplified the tangent frame to world transform to be 1 interpolator (instead of 3).
    - used up those 2 interpolators with my radiosity indexing + a spare contextual effects channel.

    This allowed me to push a lot further with my deferred path, as it was blocking a number of other things I'd either prototyped, or couldn't get to co-exist with the previous surface shader overhead. Specifically:
    - got another packed gbuffer channel in deferred by abusing the unit length nature of the normals (least significant bit drops, so slightly inferior normal mapping when using upper bits in the packed form). I'm using this as a translucency term for deferred (sss).
    - Bundled the main 2 scene lights to save on ROP
    - created batched 'cheap lights' as an alternative light type -- only has a diffuse result and a shared fake specular, but it's a good alternative for lots of performant on-screen lights if you get bound by the stencil and pixel ROP of real deferred lights.

    So at least I've managed to get around a number of blockers here, so I thank you again!