precision mediump float; uniform vec3 uLightPos; // Light position in camera space uniform float uLightPower; // Light power uniform vec3 uDiffuseColor; // Diffuse color uniform float uBeta; // Roughness uniform float uIOR; // Index of refraction uniform float uAmbient; // Ambient uniform vec3 uSpecularColor; // Specular varying vec3 vPosition; // Fragment position (camera space) varying vec3 vNormal; // Fragment normal (camera space) void main(void) { // Dummy variable to ensure the use of all vertex attributes. vec4 zero = vec4(vPosition + vNormal - vPosition - vNormal, 0.0); vec3 i = uLightPos - vPosition; vec3 i_hat = normalize(i); float I = uLightPower / ((pow(length(i), 2.0) / 5.0) + 5.0); vec3 n_norm = normalize(vNormal); vec3 o_hat = -normalize(vPosition); float dni = dot(n_norm, i_hat); vec3 h_hat = normalize(i_hat + o_hat); if (dni > 0.0) { float c = dot(i_hat, h_hat); float g = sqrt(pow(uIOR, 2.0) - 1.0 + pow(c, 2.0)); float F = 0.5 * (pow(g - c, 2.0) / pow(g + c, 2.0)); F = F * (1.0 + pow((c * (g + c) - 1.0) / (c * (g - c) + 1.0), 2.0)); float B_square = pow(uBeta, 2.0); float theta_h = acos(dot(n_norm, h_hat)); float theta_i = acos(dot(n_norm, i_hat)); float theta_o = acos(dot(n_norm, o_hat)); float D = B_square / (3.14159 * pow(cos(theta_h), 4.0) * pow(B_square + pow(tan(theta_h), 2.0), 2.0)); float Gi = 2.0 / (1.0 + sqrt(1.0 + B_square * pow(tan(theta_i), 2.0))); float Go = 2.0 / (1.0 + sqrt(1.0 + B_square * pow(tan(theta_o), 2.0))); float G = Gi * Go; gl_FragColor = zero + vec4(I * dni * (uDiffuseColor + uSpecularColor * ((F * D * G) / (4.0 * dni * dot(n_norm, o_hat)))) + (uDiffuseColor * uAmbient), 1.0); } else { gl_FragColor = zero + vec4(uDiffuseColor * uAmbient, 1.0); } }