I decided to get started on an alpha erosion shader today, as I’d recently made one in nodes and wanted to convert it to HLSL.
I started off by adding inputs for material and normal. I added these as properties at the top of the shader, then added a sampler2D in the subshader so that I could use the texture, as well as UV1 in the Input struct so I could access its texture coordinates.
In order to actually sample the texture, I used the built in HLSL function tex2D(), which takes a sampler2D and a UV coordinate. Once I had this, I could use my surf function to fill in the metallic and smoothness outputs in my instance of Unity’s SurfaceOutputStandard. This struct gives information about surface properties to Unity in order to build the actual pixel shader, as well as generating any required render passes.
This gave me some lovely boxes with a shiny intended squiggle!
Getting transparency working was a little more challenging, as I had to think about render pass order and blending modes. Not being familiar with Unity’s render pipe, this was very interesting!
The first things we need to do are set the correct render queue, and remove the object from the depth buffer write. As this is blended transparency, I want my object to be forward rendered and don’t want it pushed into an earlier pass for the zbuffer.
To do this, I set the render queue and type tags to “transparent”, and added “ZWrite Off”.
After this, I had to specify the blend mode and set the correct lighting model. As I wanted this to use traditional transparency, I set the source to source alpha and the destination to one minus source alpha. By default, this is an additive blend, but I believe you can change this. To set the lighting model, I added “alpha: fade” after the lighting model pragma. The pragma sends additional information to the shader compiler – if no alpha is specified, you’ll get an opaque object!
Once that was all set, I had to actually specify my alpha values in the surface function! Initially, I just set the surface output alpha parameter to equal my erosion texture r multiplied by my alpha multiplier input, but this only produced transparency between particles in the same system and not between other objects (probably to do with the way unity batches particle draw calls?). I needed to set the alpha of the colour value (c.a) I created from my texture sampler to this, and then set the alpha output to c.a.
Doing this gave me some nice transparency! Next I want to add photoshop levels style controls to the alpha mask in order to create the erosion effect. I’ve previously done this using a mixture of smoothstepping and remapping values. It looks like remap value is not a built in function, so I’ll have to write my own which should be interesting.