A great benefit of working with the Matchbox tool is being able to create your own effects, depending on your particular needs. Creating a Matchbox shader can be as simple as copying and pasting GLSL code snippets, or can be complex multipass effects with multiple inputs and dozens of UI elements. For example, here is the contents of a simple Add effect:
uniform sampler2D input1, input2;
uniform float adsk_result_w, adsk_result_h;
void main()
{
vec2 coords = gl_FragCoord.xy / vec2( adsk_result_w, adsk_result_h );
vec3 sourceColor1 = texture2D(input1, coords).rgb;
vec3 sourceColor2 = texture2D(input2, coords).rgb;
gl_FragColor = vec4( sourceColor1+sourceColor2, 1.0 );
}Here's a quick high-level workflow to follow when creating Matchbox shaders:
Writing and Testing GLSL Fragment Shader Code
You can repurpose existing fragment shader code, or create an effect specific to your needs. In either case, you can use the test_shader utility to validate and debug your code, and optionally help you design user interface elements in a sidecar XML file. The test_shader utility also has an extensive Help file that lists the available uniforms (including a number of adsk_ custom uniforms) and XML structure.
The test_shader utility can be found in /usr/discreet/<product home>/bin. To access the Help file, from the bin directory, type test_shader --help.
To create and test a fragment shader:
1 uniform float size;
2 uniform sampler2D myInputTex;
3
4 void main (void) {
5 vec4 tex0 = texture2D(myInputTex, gl_TexCoord[0] * size);
6 gl_FragColor = vec4 (tex0.rgb, 1.0);
7 }0(5) : warning C7011: implicit cast from "vec4" to "vec2"
XML :
<ShaderNodeDescription Description="" Name="Preset Name">
<Shader Index="1">
<Uniform RepeatMode="Off" InterpolationMode="Linear" Type="sampler2D" Tooltip="" Name="myInputTex">
</Uniform>
<Uniform DisplayName="size" Type="float" Name="size">
<SubUniform Inc="0.01" Max="1000000.0" Min="-1000000.0" Default="0.0" Row="0" Col="0" Page="0" Tooltip="" Name="size">
</SubUniform>
</Uniform>
</Shader>
<Page Name="Page 1" Page="0">
<Col Name="Column 1" Col="0" Page="0">
</Col>
</Page>
</ShaderNodeDescription>In this case, the first line displays a compilation warning that you might want to fix. In some cases, you'll receive errors that need to be fixed for the shader to work properly in Smoke.
Simply copy the XML shader node description section of the test output into a new file and save it using the same name, but with an .xml extension. In our example, you can edit scale.xml to add default values, better names for inputs and other UI elements, and even tooltips to help the user (see the bold sections below):
<ShaderNodePreset SupportsAdaptiveDegradation="0" Description="" Name="Next Generation Scaling">
<Shader OutputBitDepth="Output" Index="1">
<Uniform Index="0" NoInput="Error" Tooltip="" DisplayName="Front" Mipmaps="False" GL_TEXTURE_WRAP_T="GL_REPEAT" GL_TEXTURE_WRAP_S="GL_REPEAT" GL_TEXTURE_MAG_FILTER="GL_LINEAR" GL_TEXTURE_MIN_FILTER="GL_LINEAR" Type="sampler2D" Name="myInputTex">
</Uniform>
<Uniform ResDependent="None" Max="100.00" Min="-100.00" Default="0.0" Inc="0.01" Tooltip="Displays the percentage of scaling applied to the image." Row="0" Col="0" Page="0" DisplayName="size" Type="float" Name="Scale">
</Uniform>
</Shader>
<Page Name="Page 1" Page="0">
<Col Name="Effect Settings" Col="0" Page="0">
</Col>
</Page>
</ShaderNodePreset>In order to build more efficient, complex, or sophisticated effects, you can split your effects into multiple passes. In order to do this, you can separate your effect into multiple .glsl files using advanced adsk_ uniforms. For example, the existing Median Filter preset consists of MedianFilter.1.glsl and MedianFilter.2.glsl. In this case, when selecting this effect from the Load Shaders browser in Smoke, you need to select the root group MedianFilter.glsl file to incorporate all of the passes as one effect.
Optional: Creating Browser Proxy Files
Along with the .glsl and optional .xml files that comprise a fragment shader, you can also create a file that can display a proxy of your effect in the Load Shaders browser. You can use Smoke to create a proxy of your effect, but if you don't have access to Smoke, or want to create proxies programmatically, you can use the following header (byteswap). The standard width and height of the proxy is 126x92, and the file is RGB 8-bit. Save your proxy files as .p, and place them in the same folder as your .glsl and .xml files of the same name.
typedef struct {
unsigned short Magic;
float Version;
short Width;
short Height;
short Depth;
float Unused [ 6 ];
} LibraryProxyHeaderStruct;
#define PROXY_MAGIC 0xfaf0
#define PROXY_VERSION 1.1f
#define PROXY_DEPTH 130