Unity shader code injection
Monday, July 20, 2015 at 8:30PM
n00body in Shaders, Unity3D

Background

I’m sure many of you have had this thought, “Boy, Alloy is great but I really wish I could use its area lights and nice attenuation with other Unity shaders!” As luck would have it, I am implementing that very ability using a little known feature of Unity’s shader system.

“What might that feature be?”, I hear you ask. Well…

 

Shader code injection

That’s right, it is possible to force a shader to use custom code without having to modify the shader. It works because of how Unity’s shader system resolves “#include” directives for handling headers. If you use it like “#include “myHeader.cginc” with just the filename and no path then Unity will first look in the same directory as the shader file, and then search the editor’s hidden include directory.

So basically, if the shader uses an editor header (eg. “UnityCG.cginc”) you can trick that shader into using a customized local version by copying the header into the same directory as the shader. Then you can simply modify that local copy and the shader will use that instead. This will work for any shader code, even the Standard shader and the generated output of a Unity surface shader.

 

Conclusion

After mucking around in surface shader output, and mangling some of Unity’s macros, I now have it working with Alloy. So any surface shaders that use the Standard and StandardSpecular lighting models can now be lit using Alloy’s lighting model and material options. This way, forward-only shaders can now match deferred-compatible shaders when used alongside Alloy.

Keep an eye out, as we will be releasing this new feature in beta form in our next bugfix release.

 

Article originally appeared on Crunchy Bytes (http://n00body.squarespace.com/).
See website for complete article licensing information.