## Archive for November 6th, 2008

06
Nov
08

Simplified version of the Superformula shader made by gregsn, sanch and tonfilm for VVVV.

```/* ------------------------------------------

Original equation by Johan Gielis.
http://dataisnature.com/?p=318
http://en.wikipedia.org/wiki/superformula

gregsn, sanch and tonfilm.
Written as HLSL shader for VVVV.

HLSL-GLSL conversion and Quartz Composer setup
toneburst 2008
https://machinesdontcare.wordpress.com

This simplified version has no
normal-generation or lighting.

------------------------------------------ */

/////////////////////////////////
///          Functions          ///
/////////////////////////////////

// The basic Superformula equation

float superFormula(in float m, in float n1, in float n2, in float n3, in float phi)
{
vec2 ret;
float Out;
float a = 1.0, b = 1.0;
float t1___ = cos(m * phi / 4.0);
float t1__ = t1___ / a;
float t1_ = abs(t1__);
float t1 = pow(t1_, n2);
float t2___ = sin(m * phi / 4.0);
float t2__ = t2___ / b;
float t2_ = abs(t2__);
float t2 = pow(t2_, n3);
float T = t1 + t2;
Out = pow(T, 1.0 / n1);
if (abs(Out) == 0.0) {
Out = 0.0;
} else {
Out = 1.0 / Out;
}

return Out;
}

// Superformula equation applied to a sphere

vec3 sfs3DSphere(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 Out;
Out.x = rt * ct * rp * cp;
Out.y = rt * st * rp * cp;
Out.z = rp * sp;

return Out;
}

/////////////////////////////////
///        Tweakables 	    ///
/////////////////////////////////

// Superformula 3D parameters (with suggested ranges)
uniform float m;		//	 0 > 24	linear
uniform float n1;		//	20 > 1	exp.out
uniform float n2;		//	 1 > 2	linear
uniform float n3;		//	 1 > 4	linear

uniform float mb;		//	 0 > 24	linear (must be multiples of 4 for 'closed forms')
uniform float n1b;	//	20 > 1	linear
uniform float n2b;	//	 1 > 2	linear
uniform float n3b;	//	 1 > 4	linear

// Pre-Transform Grid
uniform vec2 PreScale;		// Pre-Scale
uniform vec2 PreTranslate;	// Values other than 0 may result in mesh edges not meeting

// 3D pixellate parameters
uniform float QSize;
uniform float QAmt;

uniform vec3 LightPosition;

// Variables for simple fake lighting
varying float SimpleLight;

/////////////////////////////////
///        MAIN LOOP          ///
/////////////////////////////////

void main()
{
// Vertex position
vec4 vertex = gl_Vertex;

// Pre-Transform vertices
vertex.xy *= PreScale;		// Pre-scale vertices
vertex.xy += PreTranslate;	// Pre-translate vertices

// Superformula vertex displacement
vertex.xyz = sfs3DSphere(m, n1, n2, n3,mb, n1b, n2b, n3b, vertex.x, vertex.y);

// 'Quantised' vertex position
vec3 vertexQ;
vertexQ = (floor(vertex.xyz * QSize) / QSize);
vertexQ =+ 0.8 * vertexQ;

// Mix quantised and unquantised vertex positions
vertex = vec4(mix(vertex.xyz,vertexQ,QAmt),1.0);

SimpleLight = 0.8 * length(LightPosition+vertex.xyz);

// Transform and set texture-coordinates
vec4 baseTexCoords = gl_TextureMatrix[0] * gl_MultiTexCoord0;
baseTexCoords.xy *= PreScale;
gl_TexCoord[0] = baseTexCoords;

// Output vertex position
gl_Position = gl_ModelViewProjectionMatrix * vertex;
}```

```/* ------------------------------------------

------------------------------------------ */

/////////////////////////////////
///         Tweakables        ///
/////////////////////////////////

// Varying variable from Vertex Shader
varying float SimpleLight;

uniform vec4 Color;			// Fragment Shader tweakables
uniform float LUT_Y;			// LUT Y-position
uniform sampler2D LUT;		// Texture input

uniform float LightRange;		// Light range
uniform float TileSize;			// Texture tile size
uniform sampler2D TileImg;		// Texture Tile

/////////////////////////////////
///          Functions 	    ///
/////////////////////////////////

float smoothstepVar(in float edge1, in float edge2, in float value)
{
float width = edge2 - edge1;
float phase = (value - edge1) / width;
phase = clamp(phase, 0.01, 0.99);
return phase;
}

/////////////////////////////////
///        MAIN LOOP 	    ///
/////////////////////////////////

void main()
{
vec2 xy = gl_TexCoord[0].xy;
vec2 phase = fract(xy / TileSize);
vec4 texTile = texture2D(TileImg, phase);

float lookupX = smoothstepVar(0.0, LightRange, SimpleLight);

// Multiply input Color by Lookup Table color
vec4 outPix = Color * texture2D(LUT, vec2(lookupX, LUT_Y)) * texTile;
outPix.a = SimpleLight;

// Output Fragment color
gl_FragColor = outPix;
}```

I’ve removed all the code for normal-calculation and lighting in this one, which makes the whole thing a lot simpler. I’ll put all that stuff back in again later, but I want to work on a different parameterisation (is that the right word?) first, so stay tuned.