#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 ) ); }