18
Mar
08

### Spherical Harmonics GLSL (No Lighting, Lookup Table)

```/*
Spherical Harmonics code Paul Bourke, adapted from
http://local.wasp.uwa.edu.au/%7Epbourke/surfaces_curves/sphericalh/

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   ////
/////////////////////

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);

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;
}
```

```/////////////////////
//// TWEAKABLES  ////
/////////////////////

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

/////////////////////
////  VARYINGS   ////
/////////////////////

varying float colpos;

/////////////////////
////  TEXTURES   ////
/////////////////////

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

// 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. 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.

So:

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.

alx

3. 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

Ok:

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.

alx

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.

alx

6. 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.

alx

8. March 19, 2008 at 8:00 pm

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

9. 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!

alx

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.

thanks

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.

a|x