cosineDirection I get. Just a random direction in the hemisphere with the pole "nor".

coneDirection should return a random direction within a cone. I faked this by using either a flat disk or hemisphere pushed in the direction of the normal but there must be a better way. If I get the polar coordinates and "jitter" them randomly will that be uniform??

For a cone direction on a hemisphere, I use the following in Fragmentarium in sample e.g. a sun-like light source:

vec3 getSample(vec3 dir, float extent) {

// Create orthogonal vector (fails for z,y = 0)

vec3 o1 = normalize(vec3(0., -dir.z, dir.y));

vec3 o2 = normalize(cross(dir, o1));

// Convert to spherical coords aligned to dir

vec2 r = getUniformRandomVec2();

r.x=r.x*2.*PI;

r.y=1.0-r.y*extent;

float oneminus = sqrt(1.0-r.y*r.y);

return cos(r.x)*oneminus*o1+sin(r.x)*oneminus*o2+r.y*dir;

}

Here ‘extent’ is the size of the light source we sample. It is given as ’1-cos(angle)’, so 0 means a point-like light source (sharp shadows) and 1 means a full hemisphere light source (no shadows).

It is formular 34 in

http://people.cs.kuleuven.be/~philip.dutre/GI/TotalCompendium.pdf, just adapted to a coordinate system aligned with the 'dir' direction.

But you shouldn't use the above formula for glossy specular reflectance. I can see that IQ suggests it, but it is really a hack - you are effectively sampling using a box distribution function, whereas the phong reflection uses a cosine-power distribution. You need to sample the full hemisphere and weight the samples according to dot(reflectedVector, sampleDirection)^Power. Since this is slow, you will want to use importance sampling, and sample according to the cosinus-distribution. Notice, that you should not multiply by the samples by the dot-product-power term if you do this.

Here is a cosine-power distribution sampling function:

vec3 getSampleBiased(vec3 dir, float power) {

// create orthogonal vector (fails for z,y = 0)

vec3 o1 = normalize( vec3(0., -dir.z, dir.y));

vec3 o2 = normalize(cross(dir, o1));

// Convert to spherical coords aligned to dir;

vec2 r = rand(viewCoord*(float(backbufferCounter)+1.0));

if (Stratify) {r*=0.1; r+= cx;}

r.x=r.x*2.*PI;

r.y = 1.0-r.y;

// This should be cosine^n weighted.

// See, e.g. http://people.cs.kuleuven.be/~philip.dutre/GI/TotalCompendium.pdf

// Item 36

r.y=pow(r.y,1.0/(power+1.0));

float oneminus = sqrt(1.0-r.y*r.y);

vec3 sdir = cos(r.x)*oneminus*o1+

sin(r.x)*oneminus*o2+

r.y*dir;

return sdir;

}

Btw, I think that IQ's cosineDirection means a direction chosen according to the power-1 cosinus distribution (because the diffuse light has a cos(normal, sampleDirection) weight), and not a random direction.

The code above is part of the 'Theory/Convolution.frag' example in Fragmentarium. This fragment can be used to derive precalculated specular and diffuse light maps for IBL lightning. I plan to write a blog entry with more details of this soon.