Search Unity

Overriding UnityGC.cginc

Discussion in 'Shaders' started by lverhoef, Apr 10, 2015.

  1. lverhoef

    lverhoef

    Joined:
    Jan 15, 2015
    Posts:
    13
    Hello all! I'm trying to override UnityCG.cginc in Unity 5 to make it do some custom fog things. I tried dropping the file into Assets/Resources and restarting, but it didn't seem to have any effect... Am I forgetting something important/obvious? Is this even possible?
     
  2. scabnog

    scabnog

    Joined:
    Jan 30, 2014
    Posts:
    3
    I'd like to know this too. Including the builtin .cginc files doesn't seem to be sufficient. I can only get this working by renaming all of the files, which is a pain, since I would want explicitly included versions to be used before falling back to default CG includes, basically to minimize any changes.
     
  3. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,880
    You can write your own custom fog things in an other custom cginc file or the shader file itself, why bother?
    You will need the unitycg.cginc file for other important stuff anyways.
     
  4. lverhoef

    lverhoef

    Joined:
    Jan 15, 2015
    Posts:
    13
    The reason I'm trying to get this working is that I'm working with a project that's been in development for a few years now, and having to manually patch it in to all the shaders that the game uses isn't the most attractive of options. It is, however, the workaround I'm looking at having to do. If I could get Unity using my OWN version of UnityCG.cginc, I could add code to the fog defines in there to have my custom code automagically patched into every shader.
     
  5. UnityGuillaume

    UnityGuillaume

    Unity Technologies

    Joined:
    Mar 16, 2015
    Posts:
    123
    Well, include path are relative to shader, and that relative path is I think the first one looked at.

    So if you drop your modified UnityCG.inc next to your shader, it should pick this one instead of the built in one.

    But that require you to put all shader using that modified cginc inside the same folder as it.


    NOTE : Unity don't pick up include change properly sometime, so to be sure, select all shader that should use the new cginc and right click->reimport to force a recompile
     
  6. lverhoef

    lverhoef

    Joined:
    Jan 15, 2015
    Posts:
    13
    Ah, so there's no way to override UnityCG project-wide? Bummer. Looks like I've got to manually patch my code into overrides for all the shaders the game uses. :/
     
  7. UnityGuillaume

    UnityGuillaume

    Unity Technologies

    Joined:
    Mar 16, 2015
    Posts:
    123
    Well project wide I don't think sadly =/

    There is another solution but it's not practical (and terrible for multiple teams) :

    Modify the cginc directly into Unity folder... (program files/Unity/Editor/Data/CGInclude)

    Risky, make a backup before, but then all your projects will use that cginc...

    As the include directive is simply "copy pasting file content at that place in the files", once your game built, the shader will still be valid, it don't have to be built INTO the game data.

    But that mean everyone on the project must do it, and you need to be sure you don't override it...
     
  8. lverhoef

    lverhoef

    Joined:
    Jan 15, 2015
    Posts:
    13
    Yeah I had considered that as an option as well, but I'm not the only developer on the project, and also have other projects that would be affected by that. Thinking about it now I could probably write a build script that swaps out the files before the build and then swaps them back, but that's just asking for trouble.

    In this thread by Aras he mentioned the change to doing fog in shaders as making it easier to do custom fog modes. I sort of thought that it would allow us to inject our own custom fog code into the pipeline somewhere. Do you happen to know what the plan was for this sort of thing?
     
  9. StaffanEk

    StaffanEk

    Joined:
    Jul 13, 2012
    Posts:
    380
    This isn't working for me. I even removed UnityCG.cginc and restarted Unity without it having any effect.
     
  10. UnityGuillaume

    UnityGuillaume

    Unity Technologies

    Joined:
    Mar 16, 2015
    Posts:
    123
    That's because once your shader is compiled it is kept as a binary in your Library folder. Restarting Unity don't trigger a recompile of your shader.

    Right click it -> Reimport will trigger a recompile, and should display :

    Code (CSharp):
    1. Shader error in 'YourShader': Can't find include file UnityCG.cginc
     
    StaffanEk likes this.
  11. StaffanEk

    StaffanEk

    Joined:
    Jul 13, 2012
    Posts:
    380
    So what do I do if I want to change the way Unity uses Cookie textures for lights? How do I recompile lights?
     
  12. StaffanEk

    StaffanEk

    Joined:
    Jul 13, 2012
    Posts:
    380
    If I understand correctly the actual cookie texture uses autolights.cginc. I would love to test how this works.
     
  13. UnityGuillaume

    UnityGuillaume

    Unity Technologies

    Joined:
    Mar 16, 2015
    Posts:
    123
    Hum if I understand your problem correctly, you use Standard Shader (so can't re-import it to recompile it).

    You can try :

    - modify AutoLight.cginc
    - Right click on the header of a Inspector of a Material (where there is a small thumbnail of the material, its name & shader drop down) and click "Select shader"
    - There click : compile & show code.

    (NOTE : you can click the small arrow to select only the dev platform for faster iteration (left click to tick one, right click to untick), otherwise it will have to generate a lot of combination & take lots of time)

    And hopefully that should work.
     
    StaffanEk likes this.
  14. StaffanEk

    StaffanEk

    Joined:
    Jul 13, 2012
    Posts:
    380
    That works. Thank you very much.

    I still need some help though. I hope you won't mind.

    I'm trying to get the cookie texture to work with colored textures. So I changed the following in AutoLight.cginc


    inline fixed UnitySpotCookie(unityShadowCoord4 LightCoord)

    to

    inline fixed4 UnitySpotCookie(unityShadowCoord4 LightCoord)


    and


    fixed destName = (lightCoord.z > 0) * UnitySpotCookie(lightCoord) * UnitySpotAttenuate(lightCoord.xyz) * SHADOW_ATTENUATION(input);

    to

    fixed destName = (lightCoord.z > 0) * UnitySpotCookie.r(lightCoord) * UnitySpotAttenuate(lightCoord.xyz) * SHADOW_ATTENUATION(input);

    That doesn't help.

    I'm a bit of a noob when it comes to shaders.

    Am I even close to doing that correctly?
     
  15. UnityGuillaume

    UnityGuillaume

    Unity Technologies

    Joined:
    Mar 16, 2015
    Posts:
    123
    Modifying builtin include with limited knowledge of shading technique & shader language may be a bit risky! So be sure to backup things.

    UnitySpotCookie is a function, you can't use .r on it,
    UnitySpotCookie(lightCoord).r would work, but UnitySpotCookie return only .w (so alpha) of the given texture. So remove that .w in the UnitySpotCookie function, and your fonction will return full texture information (rgba).
     
    StaffanEk likes this.
  16. StaffanEk

    StaffanEk

    Joined:
    Jul 13, 2012
    Posts:
    380
    IGNORE THIS POST

    I understand. I even have a separate Unity installation that I use to play around with things, just in case.

    I appreciate your help and interest but I haven't been able to fully test things out.

    I have tried different changes to the shader but haven't noticed any changes.

    The problem is that after compiling a shader and failing. I can't recompile that particular shader ever again.

    For instance:

    I tested removing AutoLight.cginc and recompiling the standard shader. It threw out an exemption.

    After that, it will always recompile regardless if AutoLight.cginc or the whole CGIncludes folder is present. It took a long time to figure it out and I have now run out of "Uncursed" shaders to try.

    Is there a way to revert the shaders so that they will behave as though I haven't touched them in the first place?

    Currently it is hard to change the .cginc files since there is no way for me to know whether the shader actually took the changes I made into account. Since they don't even need the AutoLight.cginc file to recompile at all.


    EDIT: I think I need to untick "Skip unused shader_features". If I do that, it throws an exception if the .cginc file is missing. This is going to be much slower than I though.
     
    Last edited: Oct 14, 2015
  17. StaffanEk

    StaffanEk

    Joined:
    Jul 13, 2012
    Posts:
    380
    Ok.

    I got the shader to take the .cginc into account if I copied and renamed the standard shader and cut it out of the asset folder and reimported it for every change in the .cginc file.

    I can't see any effect from the changes I made.

    I changed the bolded parts:

    #ifdef SPOT
    uniform sampler2D _LightTexture0;
    uniform unityShadowCoord4x4 _LightMatrix0;
    uniform sampler2D _LightTextureB0;
    // Changed fixed to fixed4
    inline fixed4 UnitySpotCookie(unityShadowCoord4 LightCoord)

    {
    // Removed .w at the end of the function
    return tex2D(_LightTexture0, LightCoord.xy / LightCoord.w + 0.5);
    }
    inline fixed UnitySpotAttenuate(unityShadowCoord3 LightCoord)
    {
    return tex2D(_LightTextureB0, dot(LightCoord, LightCoord).xx).UNITY_ATTEN_CHANNEL;
    }
    #define UNITY_LIGHT_ATTENUATION(destName, input, worldPos) \
    unityShadowCoord4 lightCoord = mul(_LightMatrix0, unityShadowCoord4(worldPos, 1)); \
    // Added .r at after UnitySpotCookie
    fixed destName = (lightCoord.z > 0) * UnitySpotCookie(lightCoord).r * UnitySpotAttenuate(lightCoord.xyz) * SHADOW_ATTENUATION(input);
    #endif

    Is there any way to take a look at the actual code that controls the spotlight?
     
    Last edited: Oct 14, 2015
  18. olli_vrcoaster

    olli_vrcoaster

    Joined:
    Sep 1, 2017
    Posts:
    24
    is it possible to somehow import the whole CGIncludes folder to the project, to make all the standard shaders use the copied cginc's ? It would make it much easier to customize the whole shader workflow. Since the Project uses them anyway, why not add them to the projects assetsfolder? I would as well change something about the fog and would like the standard-shaders to use it without making new shaders for everything
     
  19. Philip_Zhang

    Philip_Zhang

    Joined:
    Feb 15, 2017
    Posts:
    25
    If anyone just needs to modify some of the built-in .cginc files, one way to relatively neatly do this is:

    1) If your own .shader is a surface shader, click "Show generated code" to view the generated vertex fragment shader and copy all the code out to make it a vertex fragment shader. (Yes I didn't find a neat way to do this for surface shaders.)

    2) Place your modified .cginc file anywhere you like inside your Assets folder.

    3) #include your modified .cginc file before any of the built-in include files in all the passes that need it using relative path, so that include guard will guard out the built-in .cginc file because your modified version is included first.
     
    olli_vrcoaster likes this.
  20. Zergling103

    Zergling103

    Joined:
    Aug 16, 2011
    Posts:
    392
    OMG - I figured out how to do this, finally. I'm excited because this was always a pain to deal with.

    If you want to override a cginc file with your own version project-wide, simply:
    1. Find the file in your editor directory (e.g. C:\Program Files\Unity\Hub\Editor\2022.1.0a13\Editor\Data\CGIncludes)
    2. Copy and then paste it beside (BEside, NOT INside) the "Assets" folder of your project.
    3. Reimport the all of the shaders in your project.
    4. Bonus points for anyone who knows how to force builtin shaders (e.g. Standard) to reimport.
    The order unity checks for .cginc files is:
    1. Path relative to your .shader file.
    2. Absolute path, starting from your project directory (the directiory containing the "Assets" folder).
    3. Your editor's install path.
    This solution should work with .git and such as your project directory is usually the folder contained in a git repo.
     
    shelim likes this.
  21. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,880
    If this order is really working, that is brilliant. Ill try now.
    Thanks for sharing.
     
  22. Zergling103

    Zergling103

    Joined:
    Aug 16, 2011
    Posts:
    392
    One caviat about this is when you make modifications to the .cginc files, it is fairly difficult to get shaders to recompile. From what I found, you have to delete Library/ShaderCache and then restart Unity. I'm not sure if restarting Unity is sufficient, but it is definitely required.

    I suppose a work-around to avoid this annoyance might be to have UnityCG.cginc simply contain #include "Assets/TheRealUnityCGThatYouCanActuallyModifyWithoutRestartingButContainsTheStuffUnityCGNormallyHas.cginc" and nothing else.
     
    shelim likes this.
  23. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,880
    Unfortunately this doesnt work.
     
  24. shelim

    shelim

    Joined:
    Aug 26, 2017
    Posts:
    29
    It actually works, but you really need to pursue to path @Zergling103 mention: close Unity, delete Library/ShaderCache, re-open Unity.
     
    Zergling103 likes this.
  25. chris-nolet

    chris-nolet

    Joined:
    Feb 18, 2014
    Posts:
    13
    It works for me, as well. I needed to include a couple of other files, for the
    UnityCG.cginc
    changes to be picked up:
    • UnityCG.cginc
    • UnityStandardCore.cginc
    • UnityStandardCoreForward.cginc
    • UnityStandardCoreForwardSimple.cginc
    I imported those additional files unchanged. I'm using forward rendering with the standard pipeline. If you have a different setup, you might need to include a different subset.

    I've used this technique before. It's a bit of a pain to set up, but it works.

    Also, I can confirm that deleting
    Library/ShaderCache
    and restarting Unity is all you need to do for the changes to propagate.
     
    Last edited: Nov 6, 2022
    Zergling103 likes this.
  26. Zergling103

    Zergling103

    Joined:
    Aug 16, 2011
    Posts:
    392
    Hmm, after some digging, it looks like you might be able to disable the "Caching shader preprocessor".

    It seems like Unity holds onto something in memory which prevents a "refresh" of shaders that were already compiled, which is why you need to close Unity and not just delete the cache.

    Maybe if you disable it, delete the folder, then re-enable it in a sneaky way, it'll force Unity to clear its cache and recompile shaders that are currently being used to render something, and you won't need to close unity or delete a folder, or wait for the legacy S*** to recompile the universe.
     
  27. eyecoder

    eyecoder

    Joined:
    Feb 8, 2019
    Posts:
    2
    Hi I have tried to do the same. It is not working. When I restart Unity, the screen is pink. What do you mean precisely with deleting LIBRARY/SHADERCACHE? Should I delete the whole folder "Shaderdercache" or just empty it? Or maybe I have to delete -or- empty the sub-folders inside?
     
  28. eyecoder

    eyecoder

    Joined:
    Feb 8, 2019
    Posts:
    2

    Hi. I tried your solution. Its not working. And my issue is quite tricky. I want to override many cginc files with our own versions project-wide. The thing is that we make changes mostly in the vertex shaders. In addition, we need to use the built-in shaders (meaning FORCE REIMPORT THEM). When I restart after deleting the folder "Shadercache", the screen is pink. Read also my post above. Any idea? Thanks