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;
}
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?
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
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…
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
Also, you may find it necessary to make the mesh smaller by tweaking the Z-Position value of the 3D Tramsform patch.
alx
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)
Ah.. you’ve got it to work, hob- good news!
I’ll drop you a mail in a moment.
alx
Probably missing something very obviose, linking in from memo.tv. Where is the lookup table?
Probably missing something very obvious, linking in from memo.tv. Where is the lookup table?
Nevermind, just grabbed the .QTZ. Awesome work, is it cool to use this in a live performance?
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