//pref
Ambient|float|0.0|0|1
Diffuse|float|0.0|1|2
Specular|float|0.0|0.25|1
SpecularRough|float|0.01|0.05|1
Edge|float|0|0.05|1.0
CurvThreshLo|float|0.0|0.0|1.0
CurvThreshHi|float|0.0|0.51|1.0
Use ComputeCurvature (in Advanced menu) and then adjust the CurvThresh.|note
//vert
#version 330
layout(location = 0) in vec3 Vert;
layout(location = 3) in vec3 Norm;
layout(location = 6) in vec4 Clr;
out vec3 vN, vL, vV;
out vec4 vClr, vP;
uniform mat4 ModelViewProjectionMatrix;
uniform mat4 ModelViewMatrix;
uniform mat3 NormalMatrix;
uniform vec3 LightPos = vec3(0.0, 20.0, 30.0); //LR, -DU+, -FN+
void main() {
    vN = normalize((NormalMatrix * Norm));
    vP = vec4(Vert, 1.0);
    gl_Position = ModelViewProjectionMatrix * vec4(Vert, 1.0);
    vL = normalize(LightPos);
    vV = -vec3(ModelViewMatrix*vec4(Vert,1.0));
    vClr = Clr;
}
//frag
#version 330
in vec4 vClr, vP;
in vec3 vN, vL, vV;
out vec4 color;
uniform float Ambient = 0.5;
uniform float Diffuse = 0.7;
uniform float Specular = 0.2;
uniform float SpecularRough = 0.05;
uniform float Edge = 0.05;
uniform float CurvThreshLo = 0.0;
uniform float CurvThreshHi  = 0.51;
uniform vec4 ClipPlane = vec4(2.0, 0.0, 0.0, 0.0);

//Spherical harmonics constants
const float C1 = 0.429043;
const float C2 = 0.511664;
const float C3 = 0.743125;
const float C4 = 0.886227;
const float C5 = 0.247708;

//Spherical harmonics coefficients
// Ramamoorthi, R., and P. Hanrahan. 2001b. "An Efficient Representation for Irradiance Environment Maps." In Proceedings of SIGGRAPH 2001, pp. 497–500.
// https://github.com/eskimoblood/processingSketches/blob/master/data/shader/shinyvert.glsl
// https://github.com/eskimoblood/processingSketches/blob/master/data/shader/shinyvert.glsl
// See table on page 397 of OpenGL programming Guide, 8th Edition Shreiner et al.

// Constants for Old Town Square lighting
const vec3 L00 = vec3( 0.871297, 0.875222, 0.864470);
const vec3 L1m1 = vec3( 0.175058, 0.245335, 0.312891);
const vec3 L10 = vec3( 0.034675, 0.036107, 0.037362);
const vec3 L11 = vec3(-0.004629, -0.029448, -0.048028);
const vec3 L2m2 = vec3(-0.120535, -0.121160, -0.117507);
const vec3 L2m1 = vec3( 0.003242, 0.003624, 0.007511);
const vec3 L20 = vec3(-0.028667, -0.024926, -0.020998);
const vec3 L21 = vec3(-0.077539, -0.086325, -0.091591);
const vec3 L22 = vec3(-0.161784, -0.191783, -0.219152);

// Constants for Eucalyptus Grove lighting
/*const vec3 L00  = vec3( 0.3783264,  0.4260425,  0.4504587);
const vec3 L1m1 = vec3( 0.2887813,  0.3586803,  0.4147053);
const vec3 L10  = vec3( 0.0379030,  0.0295216,  0.0098567);
const vec3 L11  = vec3(-0.1033028, -0.1031690, -0.0884924);
const vec3 L2m2 = vec3(-0.0621750, -0.0554432, -0.0396779);
const vec3 L2m1 = vec3( 0.0077820, -0.0148312, -0.0471301);
const vec3 L20  = vec3(-0.0935561, -0.1254260, -0.1525629);
const vec3 L21  = vec3(-0.0572703, -0.0502192, -0.0363410);
const vec3 L22  = vec3( 0.0203348, -0.0044201, -0.0452180);*/

vec3 SH(vec3 vNormal)
{
	vNormal = vec3(vNormal.x,vNormal.z,-vNormal.y);
	vec3 diffuseColor =  C1 * L22 * (vNormal.x * vNormal.x - vNormal.y * vNormal.y) +
                    C3 * L20 * vNormal.z * vNormal.z +
                    C4 * L00 -
                    C5 * L20 +
                    2.0 * C1 * L2m2 * vNormal.x * vNormal.y +
                    2.0 * C1 * L21  * vNormal.x * vNormal.z +
                    2.0 * C1 * L2m1 * vNormal.y * vNormal.z +
                    2.0 * C2 * L11  * vNormal.x +
                    2.0 * C2 * L1m1 * vNormal.y +
                    2.0 * C2 * L10  * vNormal.z;
    return diffuseColor;
}

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;
	if ((vClr.a < CurvThreshLo) || (vClr.a > CurvThreshHi)) discard;
	vec3 l = normalize(vL);
	vec3 n = normalize(vN);
	vec3 v = normalize(vV);
	vec3 h = normalize(l+v);
	vec3 a = vClr.rgb;
	vec3 d = a * Diffuse;
	a *= Ambient;
	vec3 backcolor = desaturate(0.75 * a + 0.75 * d *  abs(dot(n,l)), 0.5);
	d *= SH(-reflect(n, l) );
	float specular = max(0.0,dot(n,h));
	specular = pow(specular, 1.0/(SpecularRough * SpecularRough));
	color = vec4(a + d + specular* Specular, 1.0);
	float edge =((max(dot(n,normalize(vV)), 0.0) - 0.5) * Edge) + 1.0;
	edge = min(1.0, edge);
	color.rgb *= edge;
	float backface = step(0.0, n.z);
	color = vec4(mix(backcolor.rgb, color.rgb,  backface), 1.0);
}