Adding your own shaders

ProPixelizer v1.9 adds a ProPixelizer Subtarget for ShaderGraph that allows all required passes to be completed authored within shadergraph. If you would like to help me beta test, please drop me an email at elliot.bentine@gmail.com!

In order to pixelate and outline objects, ProPixelizer uses custom render passes to draw the required information. Although Unity has developed ShaderGraph for many years now, it still lacks an ability to define custom render passes (which were easy to add in ShaderLab, its code-based predecessor), which leaves us unable to add all required passes to our materials using ShaderGraph alone.

To overcome this shortcoming of ShaderGraph, we must define two shaders:

How it works

PixelizedWithOutline is a standard ShaderLab shader. The subshader program is defined near the top of the file:

SubShader

{

Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" }


UsePass "ProPixelizer/Hidden/ProPixelizerBase/UNIVERSAL FORWARD"

UsePass "ProPixelizer/Hidden/ProPixelizerBase/SHADOWCASTER"

UsePass "ProPixelizer/Hidden/ProPixelizerBase/DEPTHONLY"

...

The UsePass statements instruct Unity to use the forward, shadowcaster and depth passes generated by the ShaderGraph shader. After this, we add the ProPixelizerPass required for pixelation and outline:

Pass

{

Name "ProPixelizerPass"

Tags {

"RenderPipeline" = "UniversalRenderPipeline"

"LightMode" = "ProPixelizer"

"DisableBatching" = "True"

}

...

The body of the pass is defined within the file ProPixelizer/SRP/OutlinePass.hlsl. At the very end of file, we add a FallBack statement to use any other passes we may require from our ShaderGraph shader:

...

FallBack "ProPixelizer/Hidden/ProPixelizerBase"

}

Adding your own shaders

If you want to add your own shader, start by copying both ProPixelizerBase.shadergraph and PixelizedWithOutline.shader. Don't forget to change the UsePass statements in your new *.shader  to include the passes from your new *.shadergraph! After you modify your ShaderGraph, you may not immediately see the changes reflected in your combined shader, because Unity does not know it has to rebuild the*.shader that uses these passes. You can force Unity to rebuild it by using Right click > Reimport on your *.shader file, or add your shader to the function ReimportShaders() in ProPixelizer/Tools/Package/ProPixelizerVerification.cs to have ProPixelizer do this for you when the domain is reloaded (e.g. on clicking play).

Finally, to make your shader work with the SRPBatcher you must make sure that the material properties and CBuffer blocks match between your *.shadergraph and *.shader. This step is only required when adding new properties to your shader. The easiest way to do this is to copy from the ShaderLab your shadergraph can create:

2. Copy the generated material properties into your *.shader.

3. Most of the shader code generated is unreadable, but you don't need it anyway! Use search to find a CBUFFER block and copy it and the samplers and texture definitions into the ProPixelizerPass of your *.shader (you can check PixelizedWithOutline to see where to place it if you are unsure).

Conclusion

This workaround is a bit tedious, but is generally the only way to add custom passes to a ShaderGraph for now. I hope Unity changes this in the future! 

I hope this was useful. As always, please feel free to email me or Discord if you have any issues. Good luck and have fun!