Professional Documents
Culture Documents
Amplify Template
Amplify Template
Amplify Template
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 and, if the given shader has multiple passes, each one is represented by its own Output node.
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.
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.
Options available at the Output node are determined on what was made available to modify over the template.
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.
Template Nodes
New nodes were added in order to get access to specific template data from inside the graph.
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.
Templates Vertex and Fragment Data
Similar to Template Parameters, Amplify Shader Editor also allows direct access to Vertex and Interpolated data.
The Vertex Data node allows users to get direct access to vertex data declared over the structure set over the vertex shader body on the template.
Likewise the Fragment Data node allows user to get direct access to fragment data declared over the interpolator structure on the template which will be sent into the
fragment function.
SubShader
{
Tags { "RenderType"="Opaque" }
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*/
};
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_main_pass
This tag is specific to multi-pass effects and let ASE to now which pass is the main one. Please check the Multi-Pass section for additional information.
ase_hide_pass
This tag is specific to multi-pass effects and allows passes to be hidden, or completely excluded from being modified. Please check the Excludind/Hidding Passes
section for additional information.
ase_tags
This tag specifies where ASE can inject new shader tags/parameters.
LEGACY: The /*ase_tag*/ tag is no longer used on ASE version v1.4.5 or newer since the template can automatically figure out where they are.
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.
LEGACY: The /*ase_pass*/ tag is optional on ASE version v1.4.5 or newer since the template can automatically figure out where to place the Grab Pass declaration.
ase_pass_end
This tag should be used only on multi-pass templates after the end of the subshader's last pass. This tags helps ASE parser to know where the last pass end so all
passes can be correctly excluded (if requested) on the generated 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.
Besides internal usage by the referred nodes, the /*ase_pragma*/ is also used to add new #defines, #includes and #pragmas explicitly declared on the Additional
Defines, Additional Includes and Additional Pragmas subsection on Pass section of the Output node.
We heavily encourage this tag to be declared BEFORE the /*ase_globals*/ tag.
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:
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;
ase_funcs
By default ASE places all functions used on the shader after global variable declaration over the /*ase_globals*/. By setting this optional tag it lets ASE know that its
default behavior should be ignored and functions should be placed over the /*ase_funcs*/ 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.
ase_dependencies_list
Allow adding shader dependencies when using this template. The dependencies list will replace the tag when creating the final shader.
Since Stencil Buffer operation cannot be defined on a disabled state, the tag /*ase_stencil*/ was created to let users be able to add the stencil option into their
templates. Stencil operations are disabled by default when first setting this template to a shader.
An /*ase_all_modules*/ tag was also created to, instead of manually adding all properties, automatically enables all the following options into the Subshader/Pass
properties.
• Blend
• Cull Mode
• Color Mask
• Stencil
• Depth
• Shader Model
Please note that if any of these properties is already defined over the SubShader/Pass then their original definition will be used.
Multi-Pass
Some extra considerations must be taken when creating multi-pass templates.
Excluding/Hidding Passes
Passes can be completely excluded from being modified on ASE or simply be on hidden state. For a pass to be excluded, the /*ase_hide_pass*/ tag must be set over
its body and no vertex or fragment data entry points can be declared. This way the Pass body will be copied from the template to the final resulting shader.
An hidden pass is one which is not visible over the canvas but new code can be injected on it. This is done by not only applying the /*ase_hide_pass*/ tag but also
declaring data entry points as linked ports. This way the graph connected to the main link port will also be analyzed to each one of the ports on the invisible pass.
Template Multi-Pass Switch
Template Multi-Pass Switch is a node specific to multi-pass shaders as it relays, in compile time, the input port data corresponding to the current pass being analyzed
over its output.
SubShader
{
Tags{ "RenderType" = "Opaque" }
Pass
{
Cull Front
Blend Off
Name "Outline"
CGPROGRAM
#pragma target 3.0
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
/*ase_pragma*/
struct appdata
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
/*ase_vdata:p=p;n=n;uv0=tc0.xy*/
};
struct v2f
{
float4 vertex : SV_POSITION;
float4 texcoord : TEXCOORD0;
UNITY_VERTEX_OUTPUT_STEREO
/*ase_interp(0.zw,7):sp=sp.xyzw;uv0=tc0.xy*/
};
Pass
{
/*ase_main_pass*/
Cull Back
Blend Off
Name "MainBody"
CGPROGRAM
#pragma target 3.0
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
/*ase_pragma*/
struct appdata
{
float4 vertex : POSITION;
float4 texcoord : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
/*ase_vdata:p=p;uv0=tc0.xy*/
};
struct v2f
{
float4 vertex : SV_POSITION;
float4 texcoord : TEXCOORD0;
UNITY_VERTEX_OUTPUT_STEREO
/*ase_interp(0.zw,7):sp=sp.xyzw;uv0=tc0.xy*/
};
uniform float4 _MainBodyColor;
/*ase_globals*/
Like stated before, each pass will be represented by its own output node. There are two passes declared over this template so, two output nodes will be created.
Each output node name is set by the respective pass name. For the first pass we can see its name declared via the Name "Outline":
Pass
{
Cull Front
Blend Off
Name "Outline"
(...)
}
As for the second pass its name is declared via the Name "MainBody" line.
Pass
{
/*ase_main_pass*/
Cull Back
Blend Off
Name "MainBody"
(...)
}
If no name is set then an internal name is generated, p.e. SubShader 0 Pass 0, SubShader 0 Pass 1 and so on.
Main Output
Although multiple output nodes are created, one must be assigned to be the main one ( and rule them all ). This is visually represented by the icon.
Going back to the Main Body template source shown right above, we can see the /*ase_main_pass*/ tag. This lets ASE know Main Body output was selected to be
the main one.
Linking Ports
For demonstration purposes, lets link both Color ports. In order to achieve this, on the first pass we'll replace the fragment Color declaration:
myColorVar = /*ase_frag_out:Color;Float4*/_OutlineColor/*end*/;
by:
myColorVar = /*ase_frag_out:Color;Float4;_Color*/_OutlineColor/*end*/;
by:
myColorVar = /*ase_frag_out:Color;Float4;_Color*/fixed4 ( 1,1,1,1 )/*end*/;
Each Color input port now shares the _Color Id and lets ASE know they are linked. Notice that it will disappear from the Outline output node.
Now the graph connected to the Main Body's Color port will also be shared to an invisible Color port on the Outline node.
Template Options
Beginning on ASE v1.6.2 rev 01, users will be able to add options to output node properties directly via the templates. These can be declared either on the beginning
of a pass or subshader bodies, depending on where the user wants the options to appear over pass or subshader sections. Subshader options should be ones that will
affect the behavior of multiple passes as Pass options should affect the current one where they were declared.
Options Block
All the options and what they do are declared over this block.
Example
Here is a simple example used over the Unlit template.
/*ase_subshader_options:Name=Additional Options
Option:Vertex Position,InvertActionOnDeselection:Absolute,Relative:Relative
Absolute:SetDefine:ASE_ABSOLUTE_VERTEX_POS 1
Absolute:SetPortName:1,Vertex Position
Relative:SetPortName:1,Vertex Offset
*/
This snippet is declared right at the beginning of the subshader template and creates an options block called Additional Options. Inside this block, a Vertex Position
option is created which will have two possible values, Absolute and Relative, with the latter being the default one. After that actions are added to each one its
possible values. For Absolute, a #define ASE_ABSOLUTE_VERTEX_POS 1 is added to only pass available and the input port with the Unique Id 1 has its Name
set to Vertex Position. For Relative, the input port with the Unique Id 1 has its Name set to Vertex Position.
Now there's a small detail. Since the flag InvertActionOnDeselection is used, the opposite action for each will be taken when its value is deselected. For the
SetPortName there's no opposite action, but for the SetDefine action there's the opposite RemoveDefine. So, when the Relative value is selected ( Absolute is
deselected ) the RemoveDefine:ASE_ABSOLUTE_VERTEX_POS 1 action will be taken.
For a more complete example on template options please check the HD Lit template packed inside the AmplifyShaderEditor > Plugins > EditorResources >
Templates > SRP > HDSRPTemplates.unitypackage package