Spherical Harmonics GLSL (No Lighting, Lookup Table)

Vertex Shader:

Spherical Harmonics code Paul Bourke, adapted from

GLSL assistance and general encouragement Memo

GLSL implementation alx @ toneburst, 2008

////  CONSTANTS  ////

#define TWOPI 6.28318531
#define PI    3.14159265

//// TWEAKABLES  ////

// Pre-Transform controls
uniform vec4 TT_0;		// TT_0(X) = Pre-Scale X (range 0.0 > 1.0)
uniform vec4 TT_1;		// TT_1(Y) = Pre-Scale Y (range 0.0 > 1.0)
uniform vec4 TT_2;
uniform vec4 TT_3;		// TT_3(X),(Y) = Pre-Translate X,Y (range 0.0 > 1.0)

// Spherical Harmonics controls (range 0.0 to 10.0)
uniform float M0,M1,M2,M3,M4,M5,M6,M7;

// Light position
uniform vec3 LightPosition;

////  VARYINGS   ////

// Passes result of shading calculation to Fragment Shader
varying float colpos;

////  FUNCTIONS  ////

// The actual Spherical Harmonics formula (operates on Spherical coordinates)
vec3 sphericalHarmonics(float theta, float phi, float m0,float m1,float m2,float m3,float m4,float m5,float m6,float m7)
	vec3 point;
	float r = 0.0;
	r += pow(sin(m0*phi),m1);
	r += pow(cos(m2*phi),m3);
	r += pow(sin(m4*theta),m5);
	r += pow(cos(m6*theta),m7);
	point.x = r * sin(phi) * cos(theta);
	point.y = r * cos(phi);
	point.z = r * sin(phi) * sin(theta);

	return point;

////  MAIN LOOP  ////

void main()
	// Create pre-transform matrix from uniform vec4s
	mat4 TT = mat4(TT_0,TT_1,TT_2,TT_3);
	// Get vertex coordinates (cartesian)
	vec4 vertex = gl_Vertex;
	// Initial vertex position pre-transformed
	vertex = TT * vertex;
	// Spherical coordinates to send to Spherical Harmonics function
	float theta = (vertex.x + 0.5) * TWOPI;	// set range to 0 > TWOPI
	float phi = (vertex.y + 0.5) * PI;		// set range 0 > PI
	// Spherical Harmonics function
	vertex.xyz = sphericalHarmonics(theta, phi, M0, M1, M2, M3, M4, M5, M6, M7);
	// Shading calculation
	colpos = length(vertex.xyz + LightPosition);

	// Transform vertex by modelview and projection matrices
	gl_Position = gl_ModelViewProjectionMatrix * vertex;
	// Forward current color and texture coordinates after applying texture matrix
	gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;

And Fragment Shader:

//// TWEAKABLES  ////

// Base color
uniform vec4 Color;
// Lighting range. Range 0.1 > 1.0 (use exponential control)
uniform float LightRange;

////  VARYINGS   ////

// Shading calculation from Vertex Shader
varying float colpos;

////  TEXTURES   ////

// Shading lookup table input
uniform sampler2D LUT;
// Lookup y-position. Range 0.0 > 1.0
uniform float LUT_Y;

// Surface texture input
uniform sampler2D TileImg;
// Surface texture scale. Range 0.001 > 0.5
uniform vec2 Tile;

////  MAIN LOOP  ////

void main()
	// Fake lighting shading with Lookup Table
	float lookupX = clamp((1.0-LightRange) * colpos,0.1,0.9);
	// Lookup shade across x-axis of LUT at y-position set by LUT_Y input
	vec4 shade = texture2D(LUT, vec2(lookupX,LUT_Y));

	// Surface tiling texture
	vec2 xy = gl_TexCoord[0].xy;
	vec2 phase = fract(xy / Tile);
	vec4 texTile = texture2D(TileImg,phase);

	// Output color compute
	gl_FragColor = Color * shade * texTile;

15 Responses to “Spherical Harmonics GLSL (No Lighting, Lookup Table)”

  1. 1 hob
    March 18, 2008 at 3:31 pm

    So presumably you need to have some sort of primitive to do this to? such as a cube…? I chucked a cube in and played with some of the values but the best I could get was a dark half-section of my viewer… Any clues?

  2. 2 toneburst
    March 18, 2008 at 3:45 pm

    Ah, no, it needs to me a GLSL Grid primitive.


    you need a GLSL Shader with the Vertex and Fragment Shader code as above

    then inside that, a Trackball or 3D Transformation Macro (if you want to be able to turn the mesh around)

    then inside that, a GLSL Grid. Set the Vertical and Horizontal resolution to 150 or 200 otherwise you’ll get a very low-res surface.

    You need to hook up some controls. I’ve added comments with suggested ranges. The Pre-Scale X and Y ones should be set to 1.0 initially or you won’t see anything.

    Also, download the Lookup Table from the next post and hook it up to the LUT input on the shader.

    Hope all this helps.


  3. 3 hob
    March 18, 2008 at 4:15 pm

    I’m obviously doing something wrong here. I’ve got the whole caboodle set up like you described, I think, and I’m still just ending up with random dark objects. Although this GLSL one is better than the cube!

    Here are the settings I’ve got:

    in the GLSL Shader patch (hastily stitched together from two screen grabs, I might add!)

    inside that is a 3D Transformation, and inside that is a GLSL Grid:

    which gives this output:

    …which all seems a little far away from where you’re at. Do I just need to sit here tweaking it for hours? I’m just a little surprised that it’s coming out dark, I think…

  4. 4 toneburst
    March 18, 2008 at 5:02 pm


    TT_0(X) and TT_1(Y) both need to be set to 1
    TT_3(Z) and TT_3(W) also have to be set to 1

    These determine the scale of the initial mesh.

    You need to set LightRange so something other than 0 (try 0.5).

    Parameters M0 > M7 are inputs to the Spherical Harmonics formula, and change the form of the mesh. There are suggested ranges in the comments in the shader code (look for greyed-out text after ‘//’).

    Tile(X) and (Y) need to be set to something. Try 0.1 for both initially. Don’t forget to hook up a square picture to the TileImg input.

    That should get you started.


  5. 5 toneburst
    March 18, 2008 at 5:04 pm

    Also, you may find it necessary to make the mesh smaller by tweaking the Z-Position value of the 3D Tramsform patch.


  6. 6 hob
    March 18, 2008 at 5:59 pm

    Ahh that’s the stuff! 🙂

    Now, my BSc dissertation is on making live visuals for music, so I’ve just been having a play around making the M values change in time to music, and it’s very easy!

    So I was wondering whether you’d mind me using this for that? Of course I’ll make sure you and all of your code is properly referenced…

    Please drop me a line if you like! (email address included with this post)

  7. 7 toneburst
    March 18, 2008 at 6:35 pm

    Ah.. you’ve got it to work, hob- good news!

    I’ll drop you a mail in a moment.


  8. 8 Neb
    March 19, 2008 at 8:00 pm

    Probably missing something very obviose, linking in from memo.tv. Where is the lookup table?

  9. 9 Neb
    March 19, 2008 at 8:01 pm

    Probably missing something very obvious, linking in from memo.tv. Where is the lookup table?

  10. March 19, 2008 at 8:09 pm

    Nevermind, just grabbed the .QTZ. Awesome work, is it cool to use this in a live performance?

  11. 11 toneburst
    March 22, 2008 at 6:11 pm

    Hi Neb!

    Absolutely, use it for anything you like. Hopefully, without the lighting calculation, you’ll be able to get a decent framerate. Lot me know how it goes with the gig!


  12. 12 Pablo
    December 8, 2009 at 10:35 pm

    Hi Alex,

    i’ve tried to follow the steps of this example but nothing appears on the viewer yet. i have a GLSL SHADER with your code lines pasted on both types of shaders,inside it could be a TRACKBALL with a GLSL GRID or just the grid. i was wondering if there is a plugin or something needed for this goal.


  13. 15 toneburst
    December 11, 2009 at 9:13 am

    I’m a non-programmer, too, really. I guess I gravitated towards QCs programming patches because I enjoy tinkering with code, and there’s a lot you can do with a few lines, or a few tweaks to other’s code.

    There’s always too much to learn, no matter how much you already know 😉

    Good luck with the performances. Let me know how you get on.


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: