Unity Products:Amplify Shader Editor/Templates

From Amplify Creations Wiki
Jump to: navigation, search

Product Page - Included Shaders - Manual - Shader Functions - Tutorials - API - Shader Templates - Nodes - Community Nodes

Templates Description

Introduction

This feature allows users to create an ASE shader from an already existing one which will be used as base, or Template.
Templates are regular Unity shaders with special ASE tags placed on key points. These tags are written as comments so they don't affect the shader compilation and its default behavior. Any shader can be converted to a template, but for now ASE can only inject code on single passes. The template can contain multiple passes but only one of its passes can be configured to be used inside the ASE canvas. Support for multi-pass templates will be added on a future update.

How to use

Create a Shader

Creating an ASE shader using templates is as easy as creating a regular surface one. Hit the right mouse button on the project view, select Create > Amplify Shader and from that menu a list with the default ASE Surface Shader is shown followed with all the available templates.



As for now, the available templates are:

  • Post-Process
  • Default Unlit
  • Default UI
  • Default Sprites
  • Particles Alpha-Blended


A user can, at any time, swap which template is being currently used and also go back to the default Surface Shader. This is done by hitting the Shader Type drop down on the current Output Node property window.

Templates Parameters

A new Template Parameter node is also available now. It gives you access to Properties and Global Variables available on the current template.
Simply hit the Parameter drop down on its Node Properties window, or on the upper left corner of the nodes body to choose which Property/Global Variable to use. When selecting a parameter it will let you know if a Property or a Global Variable is selected.

Multiple Templates Parameter nodes can be placed across the shader graph, each one with the same or different selected parameters.

Please note that previews for this node are only available when on Material mode and for Property type parameters.

Check Template Source Code

A user can, at any time, hit the Edit Template button on the Output Node properties window to check the source code of the current template.
Please note that, as for now, ASE only loads a template's info on its startup, so any changes on the template require the user to restart the plugin to take effect on your shader's next compilation.
This limitation will be addressed in a future update.

Create your own template

The process of converting a shader into a Template is quite straightforward. Here's a simple example of an unlit vertex/frag shader converted to an ASE Template.

Shader /*ase_name*/ "ASETemplateShaders/DefaultUnlit" /*end*/
{
	Properties
	{
		_MainTex ("Sprite Texture", 2D) = "white" {}
		_Color ("Tint", Color) = (1,1,1,1)
		/*ase_props*/
	}
	
	SubShader
	{
		Tags { "RenderType"="Opaque" "LightMode" = "ForwardBase" /*ase_tags*/}
		LOD 100
		Cull Off
		/*ase_pass*/

		Pass
		{
			CGPROGRAM
			#pragma target 3.0 
			#pragma vertex vert
			#pragma fragment frag
			#include "UnityCG.cginc"
			/*ase_pragma*/

			struct appdata
			{
				float4 vertex : POSITION;
				float4 texcoord : TEXCOORD0;
				float4 texcoord1 : TEXCOORD1;
				/*ase_vdata:p=p;uv0=tc0.xy;uv1=tc1.xy*/
			};
			
			struct v2f
			{
				float4 vertex : SV_POSITION;
				float4 texcoord : TEXCOORD0;
				/*ase_interp(1,7):sp=sp.xyzw;uv0=tc0.xy;uv1=tc0.zw*/
			};

			uniform sampler2D _MainTex;
			uniform fixed4 _Color;
			/*ase_globals*/
			
			v2f vert ( appdata v /*ase_vert_input*/)
			{
				v2f o;
				o.texcoord.xy = v.texcoord.xy;
				o.texcoord.zw = v.texcoord1.xy;
				
				// ase common template code
				/*ase_vert_code:v=appdata;o=v2f*/
				
				o.vertex.xyz += /*ase_vert_out:Local Vertex;Float3*/ float3(0,0,0) /*end*/;
				o.vertex = UnityObjectToClipPos(v.vertex);
				return o;
			}
			
			fixed4 frag (v2f i /*ase_frag_input*/) : SV_Target
			{
				fixed4 myColorVar;
				// ase common template code
				/*ase_frag_code:i=v2f*/
				
				myColorVar = /*ase_frag_out:Frag Color;Float4*/fixed4(1,0,0,1)/*end*/;
				return myColorVar;
			}
			ENDCG
		}
	}
}

As can be noted, there are a couple of ASE tags scattered across the shader code. Here's a brief explanation for each one of them:

ase_name

This tag is extremely important since it's the one which lets ASE know this shader needs to be analysed as a Template. It also shows where ASE can inject a new custom shader name.
Shader /*ase_name*/ "ASETemplateShaders/DefaultUnlit" /*end*/
The string between ase_name and end is used as the default name when a new shader is created using this template.

ase_props

This tag specifies both where the current shader properties are and where ASE can inject new ones. Only properties declared before the tag are read and made available to the user.
On this template, two properties will be detected and registered, Sprite Texture and Tint.

ase_tags

This tag specifies where ASE can inject new shader tags/parameters.

ase_pass

This tag specifies where ASE can inject new passes and/or states setup. This is necessary for nodes like Grab Screen Color, where a Grab Pass needs to be declared on the shader.

ase_pragma

This tag specifies where ASE can inject new pragma directives and include files. Multiple important nodes like Texture Sampler require this tag to work since they internally use Unity functions from its library.

ase_vdata

This tag specifies where vertex data is declared and where to add new one. It must be set at the final of the vertex data struct. It's also responsible for letting ASE know which type of data each element contains."
On this example,
/*ase_vdata:p=p;uv0=tc0.xy;uv1=tc1.xy*/
Three elements are declared on the struct.

float4 vertex : POSITION;
float4 texcoord : TEXCOORD0;
float4 texcoord1 : TEXCOORD1;

For the POSITION, semantic data sent is usually a vertex position but semantics like COLOR or TEXCOORD# can be used for a lot of different purposes.
Each data type is declared via Data Type = Semantic shortcut using a ; as a separator between declarations.
Here are all the data types:

Data Type Description
p Local Vertex Position
sp Clip Space Position
c Color
n Normal
t Tangent
uv# UV Coordinates #
Shortcut Semantic
p POSITION
sp SV_POSITION
c COLOR
n NORMAL
t TANGENT
tc# TEXCOORD0#

Looking at how this tag was declared, we can see the following info:

  • p=p: POSITION semantic variable contains local vertex position
  • uv0=tc0.xy: TEXCOORD0 semantic variable, most specifically its x and y component, contains UV set 0
  • uv1=tc1.xy: TEXCOORD0 semantic variable, most specifically its x and y component, contains UV set 1

ase_interp

This tag is quite similar to ase_vdata on how it's declared but it now lets ASE know where the interpolators struct is being declared.
It also must be set at the final of the interpolators data struct and is responsible for letting ASE know which type of data each element contains.

An additional step is required, where interpolators that can be used by ASE must be explicitly declared on the tag.
This is done via the current syntax ase_interp(Min,Max). All interpolators between Min and Max , [ TEXCOORD#MIN - TEXCOORD#MAX ] are considered available to be used. Please note that Min may be not be a full interpolator but only part of it.
E.g. if x and y of TEXCOORD1 is being used, you can declare the tag like this ase_interp(1.zw,7). This way TEXCOORD1 can be used by ASE, but only the z and w channels.

So, on this example,
/*ase_interp(1,7):sp=sp.xyzw;uv0=tc0.xy;uv1=tc0.zw*/
two elements are declared on the struct.

float4 vertex : SV_POSITION;
float4 texcoord : TEXCOORD0;

We can see the following info set on the tag.

  • ase_interp(1,7): Interpolators between TEXCOORD1 and TEXCOORD7 are available
  • sp=sp.xyzw: SV_POSITION semantic variable contains Clip Space Position
  • uv0=tc0.xy: TEXCOORD0 semantic variable contains UV Set 0 on its xy components
  • uv1=tc0.zw: TEXCOORD0 semantic variable contains UV Set 1 on its xy components

ase_globals

This tag is similar to ase_props and specify both where current global variables are and where ASE can inject new ones. Only declared global variables before the tag are read and made available to the user.
On this template, two global variables will be detected _MainTex and _Color. Since these global variables are associated to properties they will not be registered since this already was done by the ase_props tag.

ase_vert_input

This tag defines where the vertex function input parameters are located so ASE can add additional parameters if needed. E.g. Switch By Face node requires a VFACE type variable to be declared as input.

ase_vert_code

This tag defines where ASE can insert additional vertex code created by vertex input ports on the graph. Two additional parameters need to be defined, the first specifies the type and name of the function input parameter while the second defines the type and name of the output/return parameter.
/*ase_vert_code:v=appdata;o=v2f*/

  • v=appdata: Vertex data received from variable v of type appdata
  • o=v2f: Return output variable o of type v2f

ase_vert_out

This tag defines major code injection points inside the vertex body. These points are transformed into Vertex Input ports on the Output Node.
Port Name and Port Type are defined inside the tag as the first and second of its parameters. On this current example a port of name Local vertex and type Float3/Vector3 is going to be created.
The tag must be placed inside a variable operation and encompasses the operation itself. This variable must then used by the original template code.

On this example,
o.vertex.xyz += /*ase_vert_out:Local Vertex;Float3*/ float3(0,0,0) /*end*/
The tag can modify o.vertex and this way add an offset to it. If no node is connected to that input port then the original operation is maintained.

ase_frag_input

This tag is similar to ase_vert_input but it defines where the fragment function input parameters are located so ASE can add additional parameters if needed.

ase_frag_code

This tag is similar to ase_vert_code and defines where ASE can insert additional fragment code created by fragment input ports on the graph.
However, only one parameter is defined on this tag, since a fragment always returns a color. This parameter specifies the type and name of the interpolator parameter.<br/
/*ase_frag_code:i=v2f*/

  • i=v2f: Interpolator variable i of type v2f

ase_frag_out

This tag is similar to ase_vert_out but it defines major code injection points inside the fragment body. These points are transformed into Fragment Input ports on the Output Node.
Port Name and Port Type are defined inside the tag as the first and second of its parameters. On this current example a port of name Frag Color and type Float4/Vector4 is going to be created.
The tag must be placed inside a variable operation and must encompass a default operation. This variable must then be used in some manner by the original template code.

On this example:
myColorVar = /*ase_frag_out:Frag Color;Float4*/fixed4(1,0,0,1)/*end*/
The tag can modify the myColorVar in order to modify the final fragment color. If no node is connected to the input port then the original operation is maintained.

Under the Hood

Let's take a closer look at a compiled shader using templates and compare it with its selected template. A simple example was created for demonstration purposes using the Unlit Template explained above.

On this simple shader, a color is being fetched from the already existing 2D Sampler template property and a luminance value is being calculated from it. A lerp is then applied between the luminance value and the original color using a newly created Float property called Amount as the interpolator.

Here's the final result after compiling the shader. Template original source code is presented on the left and compiled shader is on the right.

  • The usual Made with Amplify Shader Editor header is placed and ase_name is replaced by the new user name My Shader.
  • The ase_props tag is replaced by the newly created Amount property.
  • Since no new tags were added, ase_tags was only removed.
  • Since no new passes were added, ase_pass was only removed.
  • Since no new pragmas were added, ase_pragma was only removed.
  • Since no new vertex data were added, ase_vdata was only removed.
  • Since no new interpolators were added, ase_interp was only removed
  • The ase_globals tag was replaced by the _Amount variable declaration. Also a _MainTex_ST variable was declared which will be used to calculate texture coordinates.
  • Since no new vertex function parameters were added, ase_vert_input was only removed.
  • Since no new vertex instructions were added, ase_vert_code was only removed.
  • Since the Local Vertex input port is not connected ase_vert_out is removed but it keeps the default float3(0,0,0) value assigned to the o.vertex.xyz += operation.
  • Since no new fragment function parameters were added, ase_frag_input was only removed.
  • The ase_frag_code tag was replaced with all the necessary code for textures fetching, applying the Luminance function and creating the Lerp result.
  • Since Frag Color input color is connected,ase_frag_out is removed and the default value is replaced with the new lerp result.

Examples

Please check the folder AmplifyShaderEditor > Examples > Official > TemplateExamples on your Amplify Shader Editor package for samples using each one of the available templates.