Archive for the 'GLSL' Category



It turns out the internal coordinate-systems of some of the Quartz Composer geometric primitive patches are orientated in different directions. These two primitives have the X and Y coordinates of their vertices scales along the Z axis in model-space using a very simple GLSL Vertex Shader, but one appears to be rotated at 90deg. to the other along the X-axis. Odd.


VasaRiley Belated Release

I’ve been tied up with other things lately, but finally got around to releasing the VasaRiley qcFX for VDMX I made for Weirdcore last year. I’d hoped to find time to do a quick demo video, and put together some documentation of the controls (since it’s quite complex), but haven’t had time, with other projects etc., unfortunately.

‘tb_VasaRiley_1.0.qtz’ in the widget, anyway.


Interference Patterns

2D 2 and 3-point light-interference patterns, converted from WebGL code at:


GLSL Crosshatch

Straight port of

Fragment Shader:

	Straight port of code from

uniform sampler2D Texture;

void main()
	float lum = length(texture2D(Texture, gl_TexCoord[0].xy).rgb);
	gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
	if (lum < 1.00) {
		if (mod(gl_FragCoord.x + gl_FragCoord.y, 10.0) == 0.0) {
			gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
	if (lum < 0.75) {
		if (mod(gl_FragCoord.x - gl_FragCoord.y, 10.0) == 0.0) {
			gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
	if (lum < 0.50) {
		if (mod(gl_FragCoord.x + gl_FragCoord.y - 5.0, 10.0) == 0.0) {
			gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
	if (lum < 0.3) {
		if (mod(gl_FragCoord.x - gl_FragCoord.y - 5.0, 10.0) == 0.0) {
			gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);


Non-Marching Squares

I has looking into Marching cube algorithms for extracting meshes from volume data yesterday, and thought, as a little test, I’d try making a very simple 2D edge-detection type setup, using some of the same principles. There’s lots of stuff on the web about marching cubes, and the 2D version, marching squares, so I’m not going to go into a detailed explanation here, but to summarise my setup:

• divide the image into tiles
• for each tile, test to see if the colour/luminosity value pixel at each corner is above or below a given threshold value.
• use the results of these tests to lookup into a table.
In my case, this table is an image strip something like this (I’ve added the numbers for debugging purposes)

In the original Marching Cubes code, the logic for choosing the correct cell from the table is quite elegant. You basically create a binary number, where each digit is either a 0 or a 1, according to whether the corresponding grid-point value is above or below the threshold. Decoding the binary into an integer gives you the index into the table. Unfortunately, because GLSL doesn’t have support for binary numbers, I’ve had to kludge that a bit, but it works fine.
• draw the selected table cell into the working tile of the input image

Here’s some results.

It’s a bit glitchy around the edges of the tiles, but I’m quite pleased with it. I’ve added some controls to recolour the tiles in various ways, and to deliberately scan the corners in the wrong order, for a more abstract look.

I call this ‘non-marching cubes’ because I’m not really doing the marching bit. Variations on this technique are often used iteratively to detect, and then follow edges in an image. Tools like the Magic Wand in Photoshop use similar techniques to create selections based on colour values, for example.

Vertex Shader code for the simple black-and-white version:

uniform float CellCount;
varying vec2 cellCoords;

void main()
	//Transform vertex by modelview and projection matrices
	gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
	//Forward current color and texture coordinates after applying texture matrix
	gl_FrontColor = gl_Color;
	gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
	cellCoords = gl_TexCoord[0].xy * CellCount;

..and the Fragment Shader:

uniform sampler2D Texture, EdgeTable;
uniform vec2 CellSize;
uniform float Threshold;
uniform int Scramble;
uniform vec2 ClampAmt;  // Values for clamping edges
varying vec2 cellCoords;
const float eTableCellWidth = 1.0 / 16.0;

void main()
	// Cell corners (putting in vec4 allows swizzling for different tile patterns)
	vec4 corners;
	corners[0] = max(floor(cellCoords.x) * CellSize.x, ClampAmt[0]);       // Left
	corners[1] = min(ceil(cellCoords.x) *CellSize.x, 1.0 - ClampAmt[0]);   // Right
	corners[2] = max(floor(cellCoords.y) * CellSize.y, ClampAmt[0]);       // Top
	corners[3] = min(ceil(cellCoords.y) * CellSize.y, 1.0 - ClampAmt[0]);  // Bottom
	// Swizzle corners for different effects
	corners = (Scramble == 1) ? corners.xywz : (Scramble == 2) ? corners.yxzw : (Scramble == 3) ? corners.zwyx : corners;

	// Sample corners	
	float c0	= texture2D(Texture, vec2(corners[0], corners[2])).r;
	float c1 	= texture2D(Texture, vec2(corners[1], corners[2])).r;
	float c2 	= texture2D(Texture, vec2(corners[0], corners[3])).r;
	float c3 	= texture2D(Texture, vec2(corners[1], corners[3])).r;
	// Clamp coords for edge-table
	vec2 cellCoordsClamp = fract(cellCoords);
	cellCoordsClamp.x = clamp(cellCoordsClamp.x, ClampAmt[1], 1.0 - ClampAmt[1]); 
	cellCoordsClamp.y = clamp(cellCoordsClamp.y,ClampAmt[1], 1.0 - ClampAmt[1]);
	// Calculate index for edge-table
	// Returns 0.0 > 15.0 to index into edge-table strip
	float index = 0.0;
	index += step(Threshold, c0);
	index += step(Threshold, c1) * 2.0;
	index += step(Threshold, c2) * 4.0;
	index += step(Threshold, c3) * 8.0;
	// Sample edge-table and return
	vec2 ttcoords	= vec2(cellCoordsClamp.x * eTableCellWidth + (eTableCellWidth * index), cellCoordsClamp.y);
	gl_FragColor = texture2D(EdgeTable, ttcoords);

tb Pleasure Division

Coming soon.


VasaRiley GLSL

Well, after all that messing around with OpenCL kernels, it turns out it’s much easier, and more importantly, much faster, to do it in GLSL.

June 2020


Blog Stats

  • 492,858 hits