The JXS File Format

Jitter objects that work with shaders use a special shader description file format called JXS, or Jitter XML Shader. This file tells Max how to load a list of shaders and connect them up to Max. It includes a description, a list of textures and parameters, and a list of shaders. There must always be one vertex and fragment shader, and there can be an optional geometry shader. A typical JXS file looks like this:

<jittershader name="myshader">
  <!-- optional description -->
  <description>This is my shader</description>

  <!-- optional list of texture objects to bind -->
  <texture file="chilis.jpg" rectangle="0"/>  

  <!-- optional list of shader parameters -->
  <param name="myparam" type="vec3" default="1 2 3" >
    <description>This is my parameter</description>
  </param>

  <!-- optional list of shader state parameters -->
  <param name="modelViewProjectionMatrix" type="mat4" state="MODELVIEW_PROJECTION_MATRIX" />
  <param name="jit_position" type="vec3" state="POSITION" />
  <param name="jit_texcoord" type="vec2" state="TEXCOORD" />

  <!-- optionally include other glsl sources -->
  <include source="diffuse.glsl" program="vp" />

  <!-- list of language implementations -->
  <language name="glsl" version="1.5">

    <!-- list of binding targets for shader parameters -->
    <bind param="modelViewProjectionMatrix" program="vp" />
    <bind param="jit_position" program="vp" />
    <bind param="jit_texcoord" program="vp" />
    <bind param="myparam" program="fp" />

    <program name="vp" type="vertex">
      <![CDATA[
      #version 330 core
      
      in vec3 jit_position;
      in vec2 jit_texcoord;
      out jit_PerVertex {
        vec2 texcoord0;
      } jit_out;
      uniform mat4 modelViewProjectionMatrix;
      
      void main() {
        gl_Position = modelViewProjectionMatrix*vec4(jit_position, 1);
        jit_out.texcoord0 = jit_texcoord;
      }
      ]]>
    </program>
    <program name="fp" type="fragment">
      <![CDATA[
      #version 330 core
      
      in jit_PerVertex {
        vec2 texcoord0;
      } jit_in;
      layout (location = 0) out vec4 outColor;
      uniform sampler2D tex0;
      uniform vec3 myparam;
      void main() {
        outColor = vec4(myparam, 1) * texture(tex0, jit_in.texcoord0);
      }
      ]]>
    </program>
  </language>
</jittershader>

The jittershader Tag

A JXS file opens with a jittershader tag. This tag has a single, optional attribute, the name attribute. This attribute is currently unused by Max, but by convention a JXS author should provide a descriptive name.

The description tag

A jittershader may include a description. This description is also optional, but by convention this is a good place to document the intended behavior of a JXS file. Max may use this information when listing available shaders.

The texture tag

A jittershader may have one or more textures, defined using a texture tag. The file attribute loads the texture from an image file, which may be any file in Max's Search Path.

<texture file="mytexture.jpg"/>

A texture may be modified, using any attribute of the jit.gl.texture object.

<texture file="gn.gradperm.png" rectangle="0" filter="none none" wrap="repeat repeat" mipmap="none" anisotropy="0" />

Bind a texture to a parameter using the unit attribute. This defaults to zero, and so may be omitted if there is only one texture parameter.

<!-- The texture has unit="1", so binds to texture tex_rand with default="1" -->
<param name="tex_normals" type="int" default="0" />
<param name="tex_rand" type="int" default="1" />
<texture file="random-tex.png" type="float16" unit="1" rectangle="0" filter="none none" wrap="repeat repeat"/>	

See texture parameters for more details about binding Max textures to shader programs.

Parameters and the param tag

Use the param tag to create parameters, which define bindings between values available in Max and shader variables. These can bind to numerical Max values, to Jitter textures, or to specific state variables calculated by the graphics engine. A parameter may contain a description.

<jittershader>
    <param name="myparam" type="float" default="1.0">
        <description> A parameter description </description>
    </param>
</jittershader>

A parameter must also have a type. Parameter types can be most of the primitive types defined by the glsl standard.

TypeDescription
boolboolean type
intinteger type, also used for texture input
floatfloat-width number type
doubledouble-width number type
bvec2, bvec3, bvec4boolean vector of length 2, 3, or 4
ivec2, ivec3, ivec4integer vector of length 2, 3, or 4
vec2, vec3, vec4float vector of length 2, 3, or 4
dvec2, dvec3, dvec4double vector of length 2, 3, or 4
mat2two-by-two matrix
mat3three-by-three matrix
mat4four-by-four matrix

Numeric parameters

Create a binding to a numerical value in Max by creating a param tag without a state attribute.

<jittershader>
    <param name="myparam" type="float" default="1.0" />
</jittershader>

Set this value in Max using the param message.

Set a numeric parameter with a Max message.

Texture parameters

To define a texture parameter, a param should have the type "int" and a default value that matches the parameter index. Max will recognize that this "int" param represents a texture if the param is later bound to a sampler type, for example a sampler2DRect or a sampler2D.

<jittershader>
  <!-- Two input textures -->
  <param name="image1" type="int" default="0" />
  <param name="image2" type="int" default="1" />
  
  <param name="modelViewProjectionMatrix" type="mat4" state="MODELVIEW_PROJECTION_MATRIX" />
  <param name="textureMatrix0" type="mat4" state="TEXTURE0_MATRIX" />
  <param name="textureMatrix1" type="mat4" state="TEXTURE1_MATRIX" />
  <param name="jit_position" type="vec3" state="POSITION" />
  <param name="jit_texcoord" type="vec2" state="TEXCOORD" />
  <language name="glsl" version="1.5">
    <bind param="image1" program="fp" />
    <bind param="image2" program="fp" />
    <bind param="modelViewProjectionMatrix" program="vp" />
    <bind param="textureMatrix0" program="vp" />
    <bind param="textureMatrix1" program="vp" />
    <bind param="jit_position" program="vp" />
    <bind param="jit_texcoord" program="vp" />
    <program name="vp" type="vertex">
      <![CDATA[
      #version 330 core
      
      in vec3 jit_position;
      in vec2 jit_texcoord;
      out jit_PerVertex {
        vec2 texcoord0;
        vec2 texcoord1;
      } jit_out;
      uniform mat4 modelViewProjectionMatrix;
      uniform mat4 textureMatrix0;
      uniform mat4 textureMatrix1;
      
      void main() {
        gl_Position = modelViewProjectionMatrix*vec4(jit_position, 1.);
        jit_out.texcoord0 = vec2(textureMatrix0 * vec4(jit_texcoord, 0., 1.));
        jit_out.texcoord1 = vec2(textureMatrix1 * vec4(jit_texcoord, 0., 1.));
      }
    ]]>
    </program>
    <program name="fp" type="fragment">
      <![CDATA[
      #version 330 core
      
      // texcoords
      in jit_PerVertex {
        vec2 texcoord0;
        vec2 texcoord1;
      } jit_in;
      
      layout (location = 0) out vec4 outColor;
      
      // samplers
      uniform sampler2DRect image1;
      uniform sampler2DRect image2;
      void main() {
        vec4 im1 = texture(image1, jit_in.texcoord0);
        vec4 im2 = texture(image2, jit_in.texcoord1);
        outColor = im1 + im2;
      }
    ]]>
    </program>
  </language>
</jittershader>

In Max, you can set these textures using a texture list, or using the inlets of a jit.gl.slab object.

Setting the texture inputs of a shader

State parameters

Parameters can also bind to shader state variables, built-in uniform variables that expose the graphics engine state to JXS shader programs. To create a param bound to a state variable in this way, use the state attribute.

<param name="itvmat" type="mat3" state="NORMAL_MATRIX" />

Available shader parameter state bindings are listed below.

Model View and Projection Matrices

WORLD_MATRIXmat4transforms into world coordinates, also known as model matrix
VIEW_MATRIXmat4transforms into current camera view, also known as eye
MODELVIEW_MATRIXmat4combined view and model (world) transform
PROJECTION_MATRIXmat4current camera projection transform
VIEW_PROJECTION_MATRIXmat4combined projection and view transform
MODELVIEW_PROJECTION_MATRIXmat4combined projection view and model transform
PREV_MODELVIEW_PROJECTION_MATRIXmat4The previous frame's model-view projection matrix, used for velocity based effects
NORMAL_MATRIXmat3orients the normals in eye space
CAM_PROJECTION_MATRIXmat4provides the current rendering camera's projection matrix; in most cases is equivalent to PROJECTION_MATRIX except in cases where a full-screen quad is rendering, e.g. in a jit.gl.slab/pix (or jit.gl.pass).

Camera

CAMERA_POSITIONvec3camera position in world space
CAMERA_DIRECTIONvec3camera direction in world space
VIEWPORTvec2the pixel size of rendering window
INVERSE_VIEWPORTvec2the inverse of the viewport dims
NEAR_CLIPfloatcamera near clipping distance
FAR_CLIPfloatcamera far clipping distance
FAR_CORNERvec3far corner of the view frustrum

Light

Shaders used in Jitter can reference up to eight simultaneous lights. To create a param bound to the state of a particular light, use a state attribute with a value like LIGHT0_POSITION to bind to the position of the first light, LIGHT1_POSITION to bind to the position of the second light, and so on.

LIGHT_VIEWPROJ_MATRIX0-7mat4scene seen from the light position
LIGHT_RANGE0-7floatdistance reached by the light
LIGHT0-7_POSITIONvec3position of the light
LIGHT0-7_DIRECTIONvec3direction of the light
LIGHT0-7_AMBIENTvec4ambient light color
LIGHT0-7_DIFFUSEvec4diffuse light color
LIGHT0-7_SPECULARvec4specular light color
LIGHT0-7_CUTOFFfloatthe spotlight cutoff in degrees
LIGHT0-7_EXPONENTfloatthe spotlight exponent defining dropoff from cone center

Material

AMBIENTvec4material ambient color
DIFFUSEvec4material diffuse color
SPECULARvec4material specular color
EMISSIONvec4material emission color
COLOR0vec4object color

Texture

Similar to lights, Jitter shaders can reference up to eight texture inputs. For each one, create a param bound to the state of a particular texture with an indexed key for state. So TEXTURE0_MATRIX will bind to the texture transform matrix of the first texture, TEXTURE1_MATRIX to bind the texture transform matrix of the second texture, and so on.

TEXTURE0-7_MATRIXmat4Texture tranform matrix for textures 0-7
TEXDIM0-7vec2Texture dimentions for textures 0-7

Time

Jitter provides time, frame and date based state parameters, useful for tasks like animating values and seeding random number generators in your shader program. TIME and FRAME will be specific to a particular shader program, whereas GLOBAL_TIME, DELTA_TIME, CONTEXT_FRAME, and DATE will be uniform for all shader programs running in a particular context.

TIMEfloattime in seconds since program compilation
GLOBAL_TIMEfloattime in seconds since context initialization
DELTA_TIMEfloattime in seconds since previous frame
FRAMEintframe count since program compilation
CONTEXT_FRAMEintframe count since context initialization
DATEvec4year, month, day, time in seconds

Matrix transformations

You can apply a matrix transformation to any param with a mat4 type, using the transform attribute.

<param name="itvmat" type="mat4" state="VIEW_MATRIX" transform="INVERSE_TRANSPOSE" />

Recognized matrix transformations include IDENTITY, TRANSPOSE, INVERSE and INVERSE_TRANSPOSE.

Vertex attributes

Several built-in vertex attributes are available via the following state tags:

POSITIONvec3
TEXCOORDvec2
NORMALvec3
TANGENTvec3
BITANGENTvec3
COLORvec4
VERTEX_ATTRuser-defined
VERTEX_ATTR0user-defined
VERTEX_ATTR1user-defined
VERTEX_ATTR2user-defined
VERTEX_ATTR3user-defined

The state tags VERTEX_ATTR and VERTEX_ATTR0 through VERTEX_ATTR4 are for custom vertex attributes. Define the param tag like so:

<param name="pvel" type="vec4" state="VERTEX_ATTR" />

and in the vertex program:

in vec4 pvel;

To set the values of custom vertex attributes from the patcher, send jit.gl.mesh the vertex_attr_matrix message followed by the name of a jit.matrix containing the attribute values. The example patcher custom.vertex.attribute demonstrates this.

Shaders and the language tag

After the description, textures, and parameters are declared, the language tag includes the shader definitions themselves.

  <!-- list of language implementations -->
  <language type="glsl" version="1.0">

    <!-- list of binding targets for shader parameters -->
    <bind param="myparam" program="vp"/>

    <!-- vertex and fragment programs -->
    <program name="vp" type="vertex" source="sh.passthru.xform.vp.glsl"/>
    <program name="fp" type="fragment">
        <![CDATA[
            // entry point
            void main()
            {
                gl_FragColor=vec4(0.5, 0.5, 0.5, 1.0);
            }
        ]]>
    </program>
</language>

The language tag includes the type, which will always be "glsl", as well as the version. Shader versions 1.5 or higher are treated as "modern" shaders, whereas anything lower will be treated as legacy and transformed automatically before getting passed to the graphics engine.

The bind tag

The bind tag binds declared parameters to variables in any one of the shader programs.

<jittershader>
    <param name="myparam1" type="vec3" default="3.0 4.0 5.0" />
    <param name="myparam2" type="float" default="0" />

    <language type="glsl" version="1.5">

    <bind param="myparam1" program="vp" />
    <bind param="myparam2" program="fp" />

    <program name="vp" type="vertex">
    <![CDATA[
        uniform vec3 myparam1;

        void main() {
            // ... the vertex program
        }
    ]]>
    </program>

    <program name="fp" type="fragment">
    <![CDATA[
        uniform float myparam2;

        void main() {
            // ... the fragment program
        }
    ]]>
    </program>

    </langauge>
</jittershader>

The param attribute of a bind tag identifies a parameter with that name. The program attribute directs that parameter to a particular program. Within the program, the parameter is bound to the variable with the same name.

The type of the param tag should match the type of the variable in the vertex, fragment, or geometry shader program. One exception is for texture parameters. The type of the param for a texture parameter should be int, and it should be bound to a variable with a "Sampler" type, like Sampler2D or Sampler2DRect.

The include tag

After binding parameters but before declaring shaders, you can use the include tag to include external glsl sources. These can be any files in the Max search path.

<bind param="FrontMaterialParameters" program="vp" />
<bind param="LightingParameters" program="vp" />

<include source="diffuse.glsl" program="vp" />
<include source="specular.glsl" program="vp" />

<program name="vp" type="vertex">

The program tag

A program tag contains the actual shader program. The name of a program tag can be anything, and is used by the bind tag to bind external parameters to program variables. The type attribute of a program tag can be vertex, fragment, or geometry. To define the shader program itself, a program can use the source attribute to specify a .glsl file, or the contents of the program tag can be character data containing the glsl shader program itself.

<language type="glsl" version="1.0">
    <program name="vp" type="vertex" source="sh.passthru.xform.vp.glsl"/>
    <program name="fp" type="fragment">
        <![CDATA[
        void main()
        {
            gl_FragColor=vec4(0.5, 0.5, 0.5, 1.0);
        }
        ]]>
    </program>
</language>