1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
#ifndef PI
#define PI 3.14159265358979
#define PI_SQUARE ( PI * PI )
#endif
vec4 diffuseReflectionBSDF(in vec3 N, in vec3 L, in vec3 viewDir,
in vec3 lightDiffuse, in float roughness)
{
float cosThetaI = max( 0.0, dot( N, L ) );
float factor = cosThetaI;
if ( ( 0.0 < factor ) && ( 0.0 < roughness ) )
{
// see http://en.wikipedia.org/wiki/Oren%E2%80%93Nayar_reflectance_model
float sigmaSquare = 0.25 * PI_SQUARE * roughness * roughness;
float A = 1.0 - 0.5 * sigmaSquare / ( sigmaSquare + 0.33 );
float B = 0.45 * sigmaSquare / ( sigmaSquare + 0.09 );
// project L and viewDir on surface to get the azimuthal angle between them
// as we don't really need the projections, but the angle between them,
// it's enough to just use the cross instead
vec3 pl = normalize( cross( L, N ) );
vec3 pv = normalize( cross( viewDir, N ) );
float cosPhi = max( 0.0, dot( pl, pv ) );
float sinAlpha, tanBeta;
float cosThetaO = max( 0.0, dot( N, viewDir ) );
float sinThetaI = sqrt( max( 0.0, 1.0 - cosThetaI * cosThetaI ) );
float sinThetaO = sqrt( max( 0.0, 1.0 - cosThetaO * cosThetaO ) );
if ( cosThetaI < cosThetaO )
{ // -> thetaO < thetaI
sinAlpha = sinThetaI;
tanBeta = sinThetaO / cosThetaO;
}
else
{
sinAlpha = sinThetaO;
tanBeta = sinThetaI / cosThetaI;
}
factor *= A + B * cosPhi * sinAlpha * tanBeta;
}
return( vec4( factor * lightDiffuse, 1.0 ) );
}
|