Archive for the 'Uncategorized' Category


Garish Psychedelic Colours

Garish psychedelic colours from 1D lookup table. Part of an update to a commercial project I worked on a while back.

This is actually a different method for applying colour curves to the image than the one I used originally. Waiting for reports on which method is faster.


Perlin Vertex Clip

Nice work offonoll.
The extra light makes such a difference!


NVIDIA Post Star Filter

CoreImage Filter conversion of NVIDIA ‘Post Star Filter’ shader, from the NVIDIA Shader Library.

Works nicely on stars (or I guess anything with bright points on a dark background), not so impressive on other material (where it tends to look like a cheap bloom filter).

Here’s an example:
NVIDIA Post Star Filter Example
Original image on left, filter applied on right.

And the Code:

	Post-process Star Filter.
	Code from NVIDIA Shader Library

	Quartz Composer conversion
	toneburst 2009

// Tap weighs
const float wt0 = 1.0;
const float wt1 = 0.8;
const float wt2 = 0.6;
const float wt3 = 0.4;
const float wt4 = 0.2;
const float wtNorm = (wt0 + 2.0 * (wt1 + wt2 + wt3 + wt4));

// X-Pass (Horizontal blur)
kernel vec4 blurX(sampler Image, float Offset)
	// Tap offsets for horizontal (x-axis) blur
	const vec2 tx0 = vec2(Offset, 0.0);
	const vec2 tx1 = vec2(Offset * 2.0, 0.0);
	const vec2 tx2 = vec2(Offset * 3.0, 0.0);
	const vec2 tx3 = vec2(Offset * 4.0, 0.0);
	//const vec2 tx4 = vec2(0.0, 0.0);
	const vec2 tx5 = vec2(-Offset, 0.0);
	const vec2 tx6 = vec2(-Offset * 2.0, 0.0);
	const vec2 tx7 = vec2(-Offset * 3.0, 0.0);
	const vec2 tx8 = vec2(-Offset * 4.0, 0.0);
	// Init output color
	vec4 outPix = sample(Image, samplerCoord(Image) + tx0) * (wt1 / wtNorm);
	// Sample other taps and accumulate color
	outPix += sample(Image, samplerCoord(Image) + tx1) * (wt2 / wtNorm);
	outPix += sample(Image, samplerCoord(Image) + tx2) * (wt3 / wtNorm);
	outPix += sample(Image, samplerCoord(Image) + tx3) * (wt4 / wtNorm);
	outPix += sample(Image, samplerCoord(Image)) * (wt0 / wtNorm);
	outPix += sample(Image, samplerCoord(Image) + tx5) * (wt1 / wtNorm);
	outPix += sample(Image, samplerCoord(Image) + tx6) * (wt2 / wtNorm);
	outPix += sample(Image, samplerCoord(Image) + tx7) * (wt3 / wtNorm);
	outPix += sample(Image, samplerCoord(Image) + tx8) * (wt3 / wtNorm);
	// Return blurred pixel
	return outPix;

// Y-Pass (Vertical blur)
kernel vec4 blurY(sampler Image, float Offset)
	// Tap offsets for vertical (y-axis) blur
	const vec2 ty0 = vec2(0.0, Offset);
	const vec2 ty1 = vec2(0.0, Offset * 2.0);
	const vec2 ty2 = vec2(0.0, Offset * 3.0);
	const vec2 ty3 = vec2(0.0, Offset * 4.0);
	//const vec2 ty4 = vec2(0.0, 0.0);
	const vec2 ty5 = vec2(0.0, -Offset);
	const vec2 ty6 = vec2(0.0, -Offset * 2.0);
	const vec2 ty7 = vec2(0.0, -Offset * 3.0);
	const vec2 ty8 = vec2(0.0, -Offset * 4.0);

	// Init output color
	vec4 outPix = sample(Image, samplerCoord(Image) + ty0) * (wt1 / wtNorm);
	// Sample other taps and accumulate color
	outPix += sample(Image, samplerCoord(Image) + ty1) * (wt2 / wtNorm);
	outPix += sample(Image, samplerCoord(Image) + ty2) * (wt3 / wtNorm);
	outPix += sample(Image, samplerCoord(Image) + ty3) * (wt4 / wtNorm);
	outPix += sample(Image, samplerCoord(Image)) * (wt0 / wtNorm);
	outPix += sample(Image, samplerCoord(Image) + ty5) * (wt1 / wtNorm);
	outPix += sample(Image, samplerCoord(Image) + ty6) * (wt2 / wtNorm);
	outPix += sample(Image, samplerCoord(Image) + ty7) * (wt3 / wtNorm);
	outPix += sample(Image, samplerCoord(Image) + ty8) * (wt3 / wtNorm);
	// Return blurred pixel
	return outPix;

// Composite pass
kernel vec4 compBlur(sampler Image, sampler HPass, sampler VPass, float StarBright)
	vec4 img		= sample(Image, samplerCoord(Image));
	vec4 hBlur	= sample(HPass, samplerCoord(HPass));
	vec4 vBlur	= sample(VPass, samplerCoord(VPass));
	// Return composited images
	return img + StarBright * (hBlur + vBlur);

..and the JavaScript from the CIFilter patch bottom panel (with ‘Edit Filter Function’ option enabled):

	NVIDIA Post Star Filter blur and composite passes.

function __image main(__image Image, __number BlurAmt, __number BlurSize) {
	// Scale blur size
	BlurSize *= 10;
	// X-Pass
	var xBlurred = blurX.apply(Image.definition, null, Image, BlurSize);
	// Y-Pass
	var yBlurred = blurY.apply(Image.definition, null, Image, BlurSize);
	// Composite
	compBlurred = compBlur.apply(Image.definition, null, Image, xBlurred, yBlurred, BlurAmt);
	// Output
	return compBlurred;

VDMX version of filter in widget, name


Voronoi Volumes

It occurred to me yesterday that, it would be possible to render ‘slices’ of the Voronoi texture on a series of sprites arranged in 3D space, to give a kind of volume rendering effect.

I’ve thought about this before, but it’s always meant running some kind of shader inside an Iterator, and the whole thing would crawl to a halt.

My brainwave yesterday was that I could use the Queue to eliminate the need for the texture to be generated inside the Iterator. All you have to do is change the texture, and every change made adds another item to the Queue, and you end up with a 3D map of the changes to the texture over time, as each new image pushes the Queue along and each sprite is updated with a new texture.

Here are some examples of my cheap volume-rendering in action:

The macro/DOF type effect is simply the result of applying a circular vignette to the alpha, so it fades out a little around the edges. I’ve also added a small square vignette around the edges of the texture to help smooth things out when the volume is rotated. Of course, since it’s just a stack of 2D sprites (50, in this case), when viewed near edge-on, the illusion of a 3-dimensional volume disappears, and you get all kinds of nasty glitching. If I ever decide to finalise this experiment, and setup proper controls, I’ll limit rotation so you’ll never see this though.


Watery Audio-Reactive VDMX Courtesy of L1nk-dna

l1nk-dna has kindly donated a VDMX file using a new QTZ I converted from an original VVVV shader by Digital Slaves. I’m not quite sure if the conversion worked properly, since I’ve never managed to get VVVV fully-working, but it looks quite nice, anyway.

l1nk-dna has done a nice setup using the Audio Analysis plugin in VDMX, and several layers with feedback taps. He’s also asked me to mention that it’s ‘a bit rough around the edges’, but it looks cool to me!

‘l1nk-dna + toneburst Fake Wave’ in the widget

Note: you might have to relink the QTZ. If so, it’s in the same folder as the VDMX file itself.

Here’s an example clip, from the man himself:


Superformula Toroidal Mapping

Some screenshots of an alternative version of the superformula vertex shader. Where the previous version was based on a applying the superformula equation to a parametric sphere, this version applies the formula to a base torus (doughnut shape).

Again, no normal calculation.

Here’s a code-snippet, from the vertex shader:

// Superformula equation applied to a sphere or torus

vec3 sf3D(in float m, in float n1, in float n2, in float n3,
	in float mb, in float n1b, in float n2b, in float n3b,
	in float theta, in float phi)
	float rt = superFormula(m, n1, n2, n3, theta);
	float rp = superFormula(mb, n1b, n2b, n3b, phi);
	float st = sin(theta);
	float ct = cos(theta);
	float sp = sin(phi);
	float cp = cos(phi);
	vec3 sSphere;
	sSphere.x = rt * ct * rp * cp;
	sSphere.y = rt * st * rp * cp;
	sSphere.z = rp * sp;
	vec3 sTorus;
	sTorus.x = cp * (rp + rt * ct);
	sTorus.y = sp * (rp + rt * ct);
	sTorus.z = rt * st;
	sTorus *= 0.55;
	return (SphereTorus == 0.0) ? sSphere : sTorus;

Now There’s an Idea….

This is very cool. I’ve been a big fan of Flight404‘s work for a while now, and just spotted this on his Vimeo page. I won’t feel at all bad about blatantly copying it, because I got half way to doing it anyway, with my CubeIterator qcFX, which is included with the current VDMX beta.

I did several versions of the Iterator qcFX, using different primitives, including this one using nested cylinders. Most of the qcFX I did for VDMX are pretty old now. I really should revisit them, I think. I’m sure they need updating, and I’ve learnt a lot since then!

June 2020


Blog Stats

  • 492,858 hits