summaryrefslogtreecommitdiffstats
path: root/res/effectlib/funcdiffuseReflectionBSDF.glsllib
diff options
context:
space:
mode:
Diffstat (limited to 'res/effectlib/funcdiffuseReflectionBSDF.glsllib')
-rw-r--r--res/effectlib/funcdiffuseReflectionBSDF.glsllib43
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 ) );
+}