Search Unity

Setting Shader Maximum LOD different for secondary cameras

Discussion in 'Shaders' started by Meceka, Jun 16, 2017.

  1. Meceka

    Meceka

    Joined:
    Dec 23, 2013
    Posts:
    423
    I want to have different shader Lod levels for each camera in my scene.

    What I want to achieve;
    Main camera: should render with higher Shader LOD of around 800.
    Secondary cameras that are rendering to render texture (mirror, rendertocubemap, etc): Lower Shader LOD around 400 or 100.

    For this setting, I added a script that has OnPreRender and OnPostRender functions to the secondary camera.
    In prerender function It reduces Shader LOD to 400, and in postrender function It increases it back to 800 with using Shader.globalMaximumLOD. But that function turned out to be quite heavy (It calls Shader.Find internally) and therefore it decreased framerate by half.
    To increase performance I decided to make a list of shaders that I wish to change, and call
    Shader.maximumLOD for each of them. And it still consumes performance more than it would gain by shader LOD.

    Is there a better way to have different Shader LOD levels for each camera?

    Profiler Image: The time in ms will probably be higher in mobile platforms that we are targeting. (Turquoise line in the profiler is OnPostRender and OnPreRender)
    upload_2017-6-17_0-36-10.png
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,342
    You could try using a global keyword and using #pragma multi_compile and #ifdef to change the shader complexity in a single pass instead of using shader LODs.
     
  3. Meceka

    Meceka

    Joined:
    Dec 23, 2013
    Posts:
    423
    Thanks, I understand what you recommend, but it's not exactly what I need.

    I have custom shaders or built-in shaders that are heavy on GPU, but would be hardly noticeable in the mirrors (in vehicle mirror) or other rendertocubemap cameras.
    I want shaders to follow fallback chain and reduce to simpler shaders for those cameras.
    For example, road or sidewalks are set to bump specular, when I set global shader lod to a low value, they follow fallback chain and revert to legacy diffuse or legacy vertexlit shaders, and the difference is not really noticeable in the mirror because screen size and resolution is small.

    For my custom wet surface shaders, they fallback to the wet surface shader without reflection or specular, and for mirror cameras or rendertocubemap, it's not really noticeable and I think it would reduce GPU usage considerably.

    And for lower graphics settings, I can just set shader lod for mirrors and rendertocubemap to 100, they usually revert to vertexlit or diffuse shaders even if surface should normally use my complex wet shader. This is ok for cubemap reflection or mirrors for low/mid performance mobile devices even if mirrors show all shaders as vertexlit/diffuse/spec.

    In my onprerender and onpostrender functions I also set qualitysettings.shadowdistance to disable shadows for those cameras. It has no performance impact. I wish there was such an option in quality settings for maximum shader LOD, maybe it could be faster.