18
Mar
08

Spherical Harmonics GLSL (No Lighting, Lookup Table)

Vertex Shader:


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

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

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

    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. 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!)
    http://farm3.static.flickr.com/2267/2342760731_6ca2e21c2f_o.jpg

    inside that is a 3D Transformation, and inside that is a GLSL Grid:
    http://farm4.static.flickr.com/3021/2342760735_f857ac1400_o.png

    which gives this output:
    http://farm4.static.flickr.com/3196/2342760739_11d288714e_o.png

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

    alx

  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. 10 Neb 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

Leave a Reply




 

March 2008
M T W T F S S
« Feb   Apr »
 12
3456789
10111213141516
17181920212223
24252627282930
31  

Categories

Links

Blog Stats

  • 28,387 hits