//pref
Ambient|float|0.0|0.4|1
Diffuse|float|0.0|0.9|2
Specular|float|0.0|0.5|2
DiffuseRough|float|0.0|1.5|5
SpecularRough|float|0.0|0.1|0.5
Fresnel|float|0.1|0.6|1
OutlineWidth|float|0.0|0.0|0.25
Minnaert diffuse lighting with Ward anisotropic specular highlights, Copyright 2007, Sancho Pereira, GPL2 License|note
//frag
#version 120
varying vec3 vN, vV, vL;
varying vec4 vP, vClr;
uniform float Ambient = 0.35;
uniform float Diffuse = 1.0;
uniform float Specular = 1.0;
uniform float DiffuseRough = 1.5; // minnaert roughness  1.5
uniform float SpecularRough = 0.2; // Ward isotropic specular roughness 0.2
uniform float Fresnel = 1.5; // Schlick's fresnel approximation index of refraction 1.5
uniform vec4 ClipPlane = vec4(2.0, 0.0, 0.0, 0.0);
uniform vec3 LightPos = vec3(0.0, 20.0, 30.0); //LR, -DU+, -FN+
uniform float OutlineWidth = 0.1;

// Minnaert limb darkening diffuse term
float minnaert( vec3 L, vec3 Nf, float k) {
	float ndotl = max( 0.0, dot(L, Nf));
	return pow( ndotl, k);
}

// Ward isotropic specular term
float wardiso( vec3 Nf, vec3 Ln, vec3 Hn, float roughness, float ndotv ) {
	float ndoth = dot( Nf, Hn);
	float ndotl = dot( Nf, Ln);
	float tandelta = tan( acos(ndoth));
	return  exp( -( pow( tandelta, 2.0) / pow( roughness, 2.0)))
		* (1.0 / sqrt( ndotl * ndotv ))
		* (1.0 / (4.0 * pow( roughness, 2.0)));
	}

float schlick( vec3 Nf, vec3 Vf, float ior, float ndotv ) {
	float kr = (ior-1.0)/(ior+1.0);
	kr *= kr;
	return kr + (1.0-kr)*pow( 1.0 - ndotv, 5.0);
}

vec3 desaturate(vec3 color, float amount) {
    vec3 gray = vec3(dot(vec3(0.2126,0.7152,0.0722), color));
    return vec3(mix(color, gray, amount));
}

void main() {
 if ((ClipPlane[0] < 1.5) && (dot( ClipPlane, vP) > 0.0)) discard;
   vec3 eyePosition = vec3(0.0, 0.0, 0.0);
  //vec3 viewDirection = normalize(eyePosition - vP);
  vec3 viewDirection = normalize(vV);
  vec3 lightDirection = normalize(LightPos - vP.xyz);
  //Surface properties
  vec3 n = normalize(vN);
  vec3 a = vClr.rgb * Ambient;
  vec3 d = vClr.rgb * Diffuse;
  if (n.z < 0.0) { //i.e. if (!gl_FrontFacing)
    gl_FragColor = vec4(desaturate(0.75 * a + 0.75 * d * abs(dot(vL,n)), 0.5),1.0);
    return;
  }
  d = d * minnaert( vL, n, DiffuseRough);
  vec3 v = normalize(vV);
  float ndotv = dot(n, v);
  vec3 h = normalize(vL+v);
  float fresnel = schlick(n, v, Fresnel, ndotv);
  float specular = wardiso(n, vL, h, SpecularRough, ndotv) * fresnel * Specular;
  specular = max(specular, 0.0);
  float edge = 1.0;
  if ((OutlineWidth > 0.0) && (ndotv < OutlineWidth))
  	specular = -(1.0 - smoothstep(0.0, OutlineWidth, ndotv));
  //specular = specular * edge;
  //if ((OutlineWidth > 0.0) && (ndotv < OutlineWidth))
  //	specular *= 0.5 + 0.5 * smoothstep(0.0, OutlineWidth, ndotv);
  vec3 SpecularColor = vec3(1.0, 1.0, 1.0);
  gl_FragColor = vec4( a + d + SpecularColor * specular, 1.0);
}
//https://code.google.com/p/qshaderedit/source/browse/qshaderedit/shaders/sancho/minnaertward.glsl?spec=svn165&r=165
// Copyright 2007 Sancho Pereira
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.