Supershape 2D GLSL Rewrite

I’ve just re-written the Superformula 2D effect in GLSL, rather than CIKernel code, because I couldn’t work out how to fix an annoying CoreImage Filter bug. You can see it clearly as a horizontal line of displaced pixels from the centre to the right edge of the image below.

The rewrite only took me a few minutes, and it works just as well as it did before now (but without the glitch, obviously). I’m not sure what performance differences there are between the GLSL and CIFilter versions, though they should in theory both run on the GPU, rather than the CPU.

I’m going to upload this qcClip to Memo’s site too, in the next couple of days.

CIFilter Bug


7 Responses to “Supershape 2D GLSL Rewrite”

  1. 1 hob
    March 12, 2008 at 4:03 pm

    how much have you had to modify the original code?

    I wonder because I’m writing a report about Quartz Composer and would like to know what exactly you can use GLSL for!

  2. 2 toneburst
    March 12, 2008 at 4:11 pm

    Hi hob.

    not much, actually. CoreImage Filters use a language which is basically a subset of standard GLSL.
    The CIFilter code I used for the earlier version of the effect can be found here:


    The GLSL Shader code is below. This provides identical functionality:

    Based on supershape formula
    GLSL conversion by alx at toneburst, 2008
    ////        INPUTS        ////
    // Superformula controls
    uniform float M, N1, N2, N3;
    // View controls
    uniform float Scale, Twist, Width, Zoom;
    uniform vec2 Center;
    uniform float PolarMix, CartesianMix, PolarCartesianMix;
    // Color controls
    uniform float ColorTable;
    uniform vec4 Color;
    uniform sampler2D LUT;
    ////    SUPERSHAPE 2D     ////
    vec2 super2D(float m, float n1, float n2, float n3, float val)
    	float r;
    	float t1, t2;
    	float a = 1.0, b = 1.0;
    	t1 = cos(m * val / 4.0) / a;
    	t1 = abs(t1);
    	t1 = pow(t1, n2);
    	t2 = sin(m * val / 4.0) / b;
    	t2 = abs(t2);
    	t2 = pow(t2, n3);
    	r = pow(t1 + t2, 1.0 / n1);
    	r = 1.0 / r;
    	vec2 xy = (abs(r) == 0.0) ?	vec2(0.0,0.0) : 
    							vec2(r * cos(val),r * sin(val));
     	// Output
     	return xy;  
    ////      MAIN LOOP       ////
    void main()
    	// Normalised sampler coords 
    	vec2 xy = gl_TexCoord[0].xy;
    	// Centered coords (-1.0 > 1.0) + center-offset
    	vec2 xyCenter = ((2.0 * xy - 1.0) + Center) * Zoom;
    	// Polar coords (angle)
    	float phi = (atan(xyCenter.y,xyCenter.x));
    	// Distance from center (including offset)
    	float r = distance(xyCenter,vec2(0.0,0.0) + Center);
    	/* Create value to send to superShape function */
    	// Mix polar-coordinate values phi and r
    	float polar = mix(phi,r,PolarMix);
    	// Mix cartesian coordinate X and Y values
    	float cartesian = mix(xyCenter.x,xyCenter.y,CartesianMix);
    	// Mix the mixed values
    	float polarCartesian = mix(polar,cartesian,PolarCartesianMix)  * Scale + Twist;
    	// Send value to superShape function
    	vec2 point = super2D(M,N1,N2,N3,polarCartesian);
    	// Distance between current pixel and superShape result for this pixel
    	float dist = distance(xyCenter,point);
    	// Scale distance
    	float distSmooth = smoothstep(Width,0.0,dist);
    	// Output
    	gl_FragColor = texture2D(LUT, vec2(distSmooth,ColorTable)) * Color;

    Hope this helps.


  3. 3 toneburst
    March 12, 2008 at 5:36 pm

    It’s worth mentioning that since this is a purely 2D effect, I’d generally do this with a CIFilter patch. I’m only using a GLSL Patch here because of the annoying bug that appears when I use a CIFilter.

    GLSL can be used to do much more interesting 3D stuff, that can’t be done any other way in QC.


  4. 4 hob
    March 13, 2008 at 10:44 pm

    That’s great, I’m just about to give it a go! I should probably have posted this afterwards, but I thought I’d say thanks, and also that I’m slightly befuddled by the lack of meat to QC. I assumed once I’d gotten well into it that there’d be more stuff there – but no!

    Cheers for all your stuff here, you’ve given me a lot to think on 🙂

  5. 5 toneburst
    March 13, 2008 at 11:01 pm

    hi hob,

    I kinda know what you mean there- QC has nowhere near the complexity or flexibility of something like VVVV or Max/Jitter. Having said that, there’s still a lot you can do with it. I must say, though, I’ve mainly been working in the programmable patches lately.

    There’s some interesting work being done in terms of extending QCs capabilities with 3rd-party plugins. I’m thinking particularly of the work coming out of Kineme.net, which is really exciting. It’s always been my aim eventually to move towards coding QC plugins in OpenGL and Cocoa- long way to go before I get to that though, and if some of the Kineme projects come to fruition, I’ll have plenty of fun toys to distract me in the meantime.


  6. 6 Neb
    March 17, 2008 at 6:55 am

    Yeah, I’m starting to see the same kinds of limitations myself. I’ve been hard at Quartz3 for the past three weeks building a performance tool. Even as it lets someone (such as myself) with very rudimentary code skills create something fairly robust, it’s lack of interface is a bit frustrating. As mainly a designer and performer, branching out into xcode isn’t in my itinerary.
    Keep up the great work, and good luck on your progress in Cocoa.

  7. 7 toneburst
    March 17, 2008 at 10:37 am

    I find the things that annoy me the most about QC3 are it’s UI niggles. Some things just really get on your nerves if you’ve been using it for a while.

    While it’s nice to be able to visually patch things together, there are definitely times when the graphical approach actually hinders progress. This is especially true once a project exceeds a certain level of complexity. That’s partly why I’ve been using the programmable modules more and more- I actually like the idea of keeping the layout of thw project as simple as possible.

    I don’t come from a programming background at all myself. Though I’ve been tinkering with various scripting languages for years, I have no formal background in that area at all, so I struggle with the basics, to be honest. This kind of work is particularly challenging for me because of the maths involved (never a strong point for me). Having said that, it’s made the whole process more rewarding in some ways. Actually being able to put together a QTZ that visualizes a mathematical equation, in 3D, seems like powerful voodoo to this maths dunce, so it’s exciting stuff. It’s amazing what you can do with the lightest of sprinklings of code and the simplerst application of mathematical concepts…

    I’d be interested to see how you’re getting on with that performance tool. I’m not actually a VJ myself (yet), so I have no real idea how (or if) the stuff I do will ever find a practical application.

    Cocoa coding is still a long way off for me, sadly. I’m sure it’s the right way to go in the end though.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s


March 2008
« Feb   Apr »


Blog Stats

  • 481,663 hits

%d bloggers like this: