- Spherical Harmonics com e sem Occ
Spherical Harmonics eh uma tecnica usada muito em games para criar falsa iluminacao ambiente nos objetos , ele dispensa o uso de HDRI para simular a irradiancia sobre o difuse de um shader , apesar da matematica envolvida ser cheio de letras e numeros malucos a aplicacao eh bem simples usando um pouco a ajuda e o programa do paper :
esse paper explica que voce pode pegar todos os valores de "luma"!!! :P atraves de 9 coeficientes processados de um mapa de HDR .. esses coeficientes sao depois multiplicados sobre o diffuse
a formula eh isso aqui :
vector DiffuseColor = vector ( C1 * L22 * (tnorm[0] * tnorm[0] - tnorm[1] * tnorm[1]) +C3 * L20 * tnorm[2] * tnorm[2] +C4 * L00 -C5 * L20 +2.0 * C1 * L2m2 * tnorm[0] * tnorm[1] +2.0 * C1 * L21 * tnorm[0] * tnorm[2]+2.0 * C1 * L2m1 * tnorm[1] * tnorm[2] +2.0 * C2 * L11 * tnorm[0] +2.0 * C2 * L1m1 * tnorm[1] + 2.0 * C2 * L10 * tnorm[2] );
um detalhe, como essa eh uma tecnica para produzir luz ambiente . ela nao gera sombra, alguns papers na net demonstram outras formas de usar esse calculo para retirar
o sample de cor pra producao de bleeding e sombras usando raytracing . mas basicamente
eh um looping de gather conferindo onde o raio obteve ou nao colisao , caso nao , ele utiliza o spherical harmonic para produzir o occlsuion , aqui . eu usei um simples occlusion do renderman para produzir isso. detalhe spherical harmonics pode ser usados tbm na composicao .. caso voce tenha um pass de normal ... no video "Nuke master Class de Roy Stelzer" encontrado no propio site da Foundry .. ele demonstra como aplicar isso ..
bem segue o codigo do shader :
surface spherical(float scalefactor = .2 , samples = 32 , occOnOff = 0.0)
{
// spherical harmonics coeficients
float C1 = 0.429043;
float C2 = 0.511664;
float C3 = 0.743125;
float C4 = 0.886227;
float C5 = 0.247708;
// Constants for Old Town Square lighting
vector L00 = vector( .79, .44, 0.54);
vector L1m1 = vector( 0.39, 0.35, 0.60);
vector L10 = vector( -0.34, -0.18, -0.27);
vector L11 = vector(-0.29, -0.06, .01);
vector L2m2 = vector(-0.11, -0.05, -0.12);
vector L2m1 = vector( -0.26, -0.22, -0.47);
vector L20 = vector(-0.16, -0.09, -0.15);
vector L21 = vector(0.56, 0.21, .14);
vector L22 = vector(.21, -0.05, -0.30);
vector tnorm = vector(faceforward(normalize(N),I));
vector DiffuseColor = vector ( C1 * L22 * (tnorm[0] * tnorm[0] - tnorm[1] * tnorm[1]) +
C3 * L20 * tnorm[2] * tnorm[2] +C4 * L00 -
C5 * L20 +
2.0 * C1 * L2m2 * tnorm[0] * tnorm[1] +
2.0 * C1 * L21 * tnorm[0] * tnorm[2]+
2.0 * C1 * L2m1 * tnorm[1] * tnorm[2] +
2.0 * C2 * L11 * tnorm[0] +
2.0 * C2 * L1m1 * tnorm[1] +
2.0 * C2 * L10 * tnorm[2] );
//occlusion
float average;
normal n = normalize(N),
nf = faceforward(n, I);
float hits = 0;
if(occOnOff != 0.0)
{
gather("illuminance", P, nf, PI/2, samples, "distribution","cosine")
{
hits += 1;
}
average = hits / samples;
}
else
{
average = 0;
}
Ci = (color(DiffuseColor * scalefactor)) - average;
Oi = 1;
}