diff options
Diffstat (limited to 'res/effectlib/funcdiffuseReflectionBSDF.glsllib')
-rw-r--r-- | res/effectlib/funcdiffuseReflectionBSDF.glsllib | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/res/effectlib/funcdiffuseReflectionBSDF.glsllib b/res/effectlib/funcdiffuseReflectionBSDF.glsllib new file mode 100644 index 0000000..bda0ea6 --- /dev/null +++ b/res/effectlib/funcdiffuseReflectionBSDF.glsllib @@ -0,0 +1,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 ) ); +} |