Simplified version of the Superformula shader made by gregsn, sanch and tonfilm for VVVV.
Vertex Shader:
/* ------------------------------------------
3D Superformula shader.
Original equation by Johan Gielis.
More info at
http://dataisnature.com/?p=318
http://en.wikipedia.org/wiki/superformula
Original Shader implementation by
gregsn, sanch and tonfilm.
Written as HLSL shader for VVVV.
http://www.vvv.org/tiki-index.php?page=User+Shaders
HLSL-GLSL conversion and Quartz Composer setup
toneburst 2008
http://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;
// Shading parameters (more options in Fragment Shader)
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);
// Fake lighting shade value
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;
}
Fragment Shader:
/* ------------------------------------------
3D Superformula shader.
More info in Vertex Shader comments.
------------------------------------------ */
/////////////////////////////////
/// 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
// Shading + surface controls
uniform float LightRange; // Light range
uniform float TileSize; // Texture tile size
uniform sampler2D TileImg; // Texture Tile
/////////////////////////////////
/// Functions ///
/////////////////////////////////
// Shading range/dropoff function
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);
// Shading from varying var
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.


Hi Alex. Would you please post a working supershape composition? Thanks
.xX
I will post share the QTZ from the next post sometime soon. There are still a couple of things that need fixing and/or tidying up first though.
Cheers,
a|x