<?xml version='1.0' encoding='UTF-8'?>

<?xml-stylesheet href="./_c74_tut.xsl" type="text/xsl"?>

<chapter name="Video and Graphics 9: Building live video effects">

<previous name="jitterchapter00j_Audio into a matrix">Audio into a matrix</previous>
<next name="jitterchapter00l_Composing the screen">Composing the Screen</next>
<parent name="jitindex">Jitter Tutorials</parent>

<openfile name="Building live video effects" patch="jitter_core_-_9_-_live_video_effects_1.maxpat"/>

<h1>Video and Graphics Tutorial 9: Building live video effects</h1>



<h2>Intro</h2>



<p>Jitter really shines when it comes to creating custom visual effects. With a little ingenuity, you can quickly move beyond the toolbox of distortion, compositing, and color effects found in video software. In this section, we’ll learn some of the basic skills needed to build your own effect.</p>

<p>In many cases, standard Matrix effects objects will do the trick, but when you get into HD (high definition) video processing and complex effect chains, they won’t always deliver the performance you are looking for. In this tutorial, we will also learn how to lean on the <o>jit.gl.pix</o> and <o>jit.gl.slab</o> objects for some extra image processing power.</p>

<h2>Setup</h2>

<p><openfilelink filename="jitter_core_-_9_-_live_video_effects_1.maxpat">Open the starter patch</openfilelink>. </p>

<p>Here we see a <o>jit.world</o> object and a <o>jit.movie</o> and <o>jit.grab</o> object patched into a new object, <o>jit.gl.pix</o>.</p>

<illustration><img src="images/jitter_core - 9a.png"/></illustration>

<p>Notice that the <o>jit.world</o> and <o>jit.grab</o> objects are both set with the <i>@output_texture 1</i> attribute, which causes them to output <b><i>texture data</i></b>. Texture data is similar to the standard jitter matrix, but it is handled <i>directly</i> by the GPU and can only be processed by objects that handle textures - the <o>jit.gl.pix</o> object is one of them. The <o>jit.gl.pix</o> object part of the Gen library of objects, and it is designed to process <b><i>pixels</i></b> - 4-plane color texture data representing RGBA (red, green, blue, alpha). Note the difference the order of the data - RGBA rather than the ARGB order that standard Jitter objects use. The <o>jit.gl.pix</o> object is similar to <o>jit.gen</o>, but it lets us patch together processes that are automatically compiled to efficient code that runs on the GPU (using a GLSL shader).</p>

<div>
	<techdetail>
		<ul>

			<li><link type="vignette" module="core" name="jitter_gl_texture_output">About output_texture</link> — OpenGL Texture Output</li>

		</ul>

	</techdetail>
</div>



<p>Turn on the <o>jit.world</o> and click on the <m>open</m> <o>mesage</o> box to enable the <o>jit.grab</o> object. Our <o>jit.gl.pix</o> object in this example acts as a crossfader between the two incoming textures. Adjust the <i>xfade</i> parameter in the main patcher to see it in action. A floating point value of 0. will fade all the way to the left input’s texture and a value of 1.0 will fade all the way to the right, with a linear crossfade at values between. (For a list and discussion of gen objects, see <link type="vignette" module="Gen" name="gen_jitter_operators">here</link>.) To see how the <o>jit.gl.pix</o> object does its job, double-click on the object to open its patcher window. </p>

<illustration><img src="images/jitter_core - 9b.png"/></illustration>

<p>The internal patcher can be used to create a wide variety of effects, allowing it to replace many of the standard Jitter objects. In this case, we are simply using the Gen <b>mix</b> object to crossfade between the two inputs based on a value between 0. and 1. The <b>param xfade</b> object creates a parameter called <i>xfade</i>. Whenever our object receives the message <m>xfade</m> followed by a value (e.g. <m>xfade .5</m>), it will output the value from our <b>param</b> object. Go ahead and close the <o>jit.gl.pix</o> window. A <o>jit.gl.pix</o> object will save its internal patch state with the parent patch. We could also save this patch as a .genjit file and call it up later using the patcher name (<i>@gen &lt;thepatchname&gt;</i>, but this one is already in the system as “xfade.genjit”. Try changing the object name to <b>jit.gl.pix @gen xfade</b> (no file extension is needed).</p>

<illustration><img src="images/jitter_core - 9c.png"/></illustration>

<p>Let’s add another <o>jit.gl.pix</o> using the name of a gen patcher in our file system to call up its internal state. Create a <b>jit.gl.pix @gen brcosa</b> object. </p>

<illustration><img src="images/jitter_core - 9d.png"/></illustration>

<p> If you double-click this object, you will see that it uses a variety of Gen objects to create an equivalent of the <o>jit.brcosa</o> object. Add the object between your <o>jit.movie</o> and the first <o>jit.gl.pix</o> object so you adjust the brightness, contrast and saturation of the movie texture before mixing it with the live video. Create an <o>attrui</o> object and connect it to the <o>jit.gl.pix</o>, then open the <o>attrui</o> menu. The parameters declared inside of a <o>jit.gl.pix</o> object (with the <b>param</b> object) will show up on the bottom of the list on the left, after “Warp”. </p>

<illustration><img src="images/jitter_core - 9e.png"/></illustration>

<p>Add three <o>attrui</o> objects - one each for <i>brightness</i>, <i>contrast</i> and <i>saturation</i> - and play with them to see how they affect the image. </p>


<h2>Bypassing an effect</h2>

<p>A key element in any effect chain is the ability to bypass effects as needed - this allows you to quickly introduce or remove an effect without the need to unlock and repatch. Create a <o>toggle</o>, connect it to the left inlet of a <b>+ 1</b> object, and connect that to the left inlet of a <b>gate 2 1</b> object. Nove the connection going from <o>jit.movie</o> into <o>jit.gl.pix</o> into the right inlet of the gate, connect the left outlet of <o>gate</o> object to the <o>jit.gl.pix</o> used for the crossfade, and connect the right outlet of the <o>gate</o> to the <b>jit.gl.pix @brcosa</b> object. </p>

<illustration><img src="images/jitter_core - 9f.png"/></illustration>

<p>When you turn the <o>toggle</o> on, the brcosa effect is enabled. When you turn it off, it is bypassed.</p>

<div>
	<techdetail>

		<p>Another way to bypass an effect is to use a crossfade - allowing you to mix the amount of the effect you want, or to ease it in/out. Add a <o>bline</o> object with an argument-set transition time to autofade in/out of an effect. Lock your patcher and double-click on the <b>bline_crossfade</b> subpatch to see this in action.</p>


	</techdetail>
</div>


<p>Before we move on, duplicate the brcosa effect and bypass and implement them for your <o>jit.grab</o>.</p>

<p>Let’s add a couple more effects to our chain. Make a <b>jit.gl.pix @gen lumadisplace</b> for the <o>jit.movie</o> and a  <b>jit.gl.pix @gen kaleido</b> for the camera. Insert them below the brcosa effects, each with a bypass. Double-click the <o>jit.gl.pix</o> objects to open them up or use <o>attrui</o> objects to find the parameters (again, look at the bottom left of the dropdown menu after the “Warp” entry).</p>

<illustration><img src="images/jitter_core - 9g.png"/></illustration>

<p>The last object we will explore is the <o>jit.gl.slab</o> object. Like <o>jit.gl.pix</o>, slab (shader lab) objects are made to process data on the GPU. Where <o>jit.gl.pix</o> allows shaders to be patched together with Gen objects, <o>jit.gl.slab directly</o> hosts GLSL fragment shaders.</p>

<p>Make a <b>jit.gl.slab @file td.mirror.jxs</b> to load a simple mirror effect. Double-click the object to reveal the shader code. You can find the relevant parameters by looking for “bind param” entries, or you can find them by using a <m>get</m> command to the object. Close the text window and make a <m>getparamslist</m> message, then connect it to the <o>jit.gl.slab</o> object. </p>

<illustration><img src="images/jitter_core - 9h.png"/></illustration>

<p>When you send the <m>get</m> message, it will return the list of parameters out of the dumpout (right outlet). Connect a <o>print</o> object to the dumpout to see them. In this case, it’s just ‘offset’ and ‘origin’. </p>

<illustration><img src="images/jitter_core - 9i.png"/></illustration>

<p>Unlike the <o>jit.gl.pix</o> object, <o>attrui</o> does not give us access to custom slab parameters, so you need to access it with the message <m>param &lt;attribute name&gt; &lt;value(s)&gt;</m>. In this case, creating a <b>pak param offset 0. 0.</b> object with a couple of <o>flonum</o> inputs will do the work.</p>

<illustration><img src="images/jitter_core - 9j.png"/></illustration>








<div>
	<techdetail>

		<h2>Explore Further</h2>

		<p>For a more in-depth treatment of building a live video effects system, see the  <a href="https://cycling74.com/2008/12/22/the-video-processing-system-part-1"> Video Processing System article series on Cycling74.com </a> For more detailed info on writing shaders for <o>jit.gl.slab</o>, take a look at <a href="https://cycling74.com/2007/05/23/your-first-shader">Your First Shader</a> as well. Max ships with a number of Shaders designed to work with <o>jit.gl.slab</o> and several <o>jit.gl.pix</o> examples as well.  Look for these in Max’s File Browser to explore further.</p>


	</techdetail>
</div>

</chapter>
