//pref
Ambient|float|0|0.25|1
Diffuse|float|0|0.75|1
Specular|float|0|0.4|1
DiffuseRough|float|0|1|5
SpecularRough|float|0.001|0.1|1
Sharpness|float|0|0.0|1
Edge|float|0|0|1.0
LightBackfaces|bool|false
Blinn-Phong shading. Adapted from Fluxus Library, Copyright 2007 Dave Griffiths, GPLv2.|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
uniform float Ambient, Diffuse, Specular, SpecularRough, DiffuseRough, Edge, Sharpness;
uniform bool LightBackfaces;
uniform vec4 ClipPlane;
in vec3 vN, vV, vL;
in vec4 vP, vClr;
out vec4 color;

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

const vec3 esheen = vec3( 0.1, 0.2, 0.5 );    // Environment sheen
const vec3 lsheen = vec3( 0.3, 0.4, 0.5 );    // Light sheen
const vec3 gsheen = vec3( 0.4, 0.35, 0.3 );   // Glow sheen
const float breathe = 0.8;                    // Sheen attenuation


void main() {
	if ((ClipPlane[0] < 1.5) && (dot( ClipPlane, vP) > 0.0)) 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);
	float backface = 1.0 - step(0.0, n.z); //1=backface
	n = mix(n, -n, backface * float(LightBackfaces)); //reverse normal if backface AND two-sided lighting
	d *= max(pow(max(dot( l, n), 0.0), DiffuseRough), 0.0);
	
	float cos = dot(n, v);
	float sin = sqrt(1.0-pow(cos, 2.0));
	vec3 specular = vec3(0.0, 0.0, 0.0);
	specular = specular + pow(sin, (1.0/breathe*5.0)) * dot(l, v) * vec3(Specular) * esheen;
	specular = specular + pow(sin, (1.0/breathe*5.0)) * dot(l, n) * vec3(Specular) * lsheen;
	specular = specular + pow(cos, (breathe*5.0)) * dot(l, n) * vec3(Specular) * gsheen;

	
	//float s = pow(max(0.0,dot(n,h)), 1.0/(SpecularRough * SpecularRough));
	//float w = 0.72*(1.0-Sharpness);
	//s = smoothstep(0.72-w,0.72+w,s) * Specular;
	vec3 frontcolor = a + d +  specular;
	frontcolor *= min((max(dot(n,normalize(v)), 0.0) - 0.5) * Edge, 0.0) + 1.0;
	backface = 1.0 - step(0.0, n.z); //1=backface
	//backcolor = vec3(1.0,0.0,0.0);
	color = vec4(mix(frontcolor,backcolor,   backface), 1.0);
}
// Copyright (C) 2007 Dave Griffiths
// Fluxus Shader Library
// ---------------------
// Glossy Specular Reflection Shader
// A more controllable version of blinn shading,
// Useful for ceramic or fluids - from Advanced
// Renderman, thanks to Larry Gritz
// http://www.pawfal.org/fluxus/
// https://github.com/danomatika/fluxus/blob/master/LICENCE