Skip to content

Latest commit

 

History

History
304 lines (238 loc) · 8.04 KB

lighting.org

File metadata and controls

304 lines (238 loc) · 8.04 KB

Contents

Lighting calculations

Lambert

float lambert(vec3 surfaceNormal, vec3 lightDirection) {
  return clamp(dot(surfaceNormal, lightDirection), 0.0, 1.0);
}

Two-sided lambert (using absolute dot product)

float lambertAbs(vec3 surfaceNormal, vec3 lightDirection) {
  return clamp(abs(dot(surfaceNormal, lightDirection)), 0.0, 1.0);
}

Phong

float phong(vec3 lightDir, vec3 eyeDir, vec3 surfaceNormal) {
  return dot(reflect(-lightDir, surfaceNormal), eyeDir);
}

Blinn-Phong

float blinnPhong(vec3 lightDir, vec3 eyeDir, vec3 surfaceNormal) {
  return dot(normalize(lightDir + eyeDir), surfaceNormal);
}

Beckmann distribution

float beckmannDistribution(float x, float roughness) {
  float NdotH = max(x, 1e-4);
  float cos2Alpha = NdotH * NdotH;
  float tan2Alpha = (cos2Alpha - 1.0) / cos2Alpha;
  float roughness2 = roughness * roughness;
  float denom = PI * roughness2 * cos2Alpha * cos2Alpha;
  return exp(tan2Alpha / roughness2) / denom;
}

Beckmann specular

float beckmannSpecular(vec3 lightDirection,
                       vec3 viewDirection,
                       vec3 surfaceNormal,
                       float roughness) {
  return beckmannDistribution(dot(surfaceNormal, normalize(lightDirection + viewDirection)), roughness);
}

Schlick approximation

float schlick(float r0, float smooth, vec3 normal, vec3 view) {
  float d = clamp(1.0 - dot(normal, -view), 0.0, 1.0);
  float d2 = d * d;
  return mix(r0, 1.0, smooth * d2 * d2 * d);
}

Calculate R0 from refractive indices

float schlickR0(float ior1, float ior2) {
  float r = (ior1 - ior2) / (ior1 + ior2);
  return r * r;
}

Gaussian specular

float gaussianSpecular(vec3 lightDirection,
                       vec3 viewDirection,
                       vec3 surfaceNormal,
                       float shininess) {
  vec3 H = normalize(lightDirection + viewDirection);
  float theta = acos(dot(H, surfaceNormal));
  float w = theta / shininess;
  return exp(-w * w);
}

Cook-Torrance

float cookTorrance(vec3 lightDirection,
                   vec3 viewDirection,
                   vec3 surfaceNormal,
                   float roughness,
                   float fresnel) {

  float VdotN = max(dot(viewDirection, surfaceNormal), 0.0);
  float LdotN = max(dot(lightDirection, surfaceNormal), 0.0);

  //Half angle vector
  vec3 H = normalize(lightDirection + viewDirection);

  //Geometric term
  float NdotH = max(dot(surfaceNormal, H), 0.0);
  float VdotH = max(dot(viewDirection, H), 1e-6);
  float LdotH = max(dot(lightDirection, H), 1e-6);
  float G1 = (2.0 * NdotH * VdotN) / VdotH;
  float G2 = (2.0 * NdotH * LdotN) / LdotH;
  float G = min(1.0, min(G1, G2));

  //Distribution term
  float D = beckmannDistribution(NdotH, roughness);

  //Fresnel term
  float F = pow(1.0 - VdotN, fresnel);

  //Multiply terms and done
  return G * F * D / max(PI * VdotN, 1e-6);
}

Oren-Nayar

float orenNayar(vec3 lightDirection,
                vec3 viewDirection,
                vec3 surfaceNormal,
                float roughness,
                float albedo) {

  float LdotV = dot(lightDirection, viewDirection);
  float NdotL = dot(lightDirection, surfaceNormal);
  float NdotV = dot(surfaceNormal, viewDirection);

  float s = LdotV - NdotL * NdotV;
  float t = mix(1.0, max(NdotL, NdotV), step(0.0, s));

  float sigma2 = roughness * roughness;
  float A = 1.0 + sigma2 * (albedo / (sigma2 + 0.13) + 0.5 / (sigma2 + 0.33));
  float B = 0.45 * sigma2 / (sigma2 + 0.09);

  return albedo * max(0.0, NdotL) * (A + B * s / t) / PI;
}

Ward

float ward(vec3 lightDirection,
           vec3 viewDirection,
           vec3 surfaceNormal,
           vec3 fiberParallel,
           vec3 fiberPerpendicular,
           float shinyParallel,
           float shinyPerpendicular) {

  float NdotL = dot(surfaceNormal, lightDirection);
  float NdotR = dot(surfaceNormal, viewDirection);

  if(NdotL < 0.0 || NdotR < 0.0) {
    return 0.0;
  }

  vec3 H = normalize(lightDirection + viewDirection);

  float NdotH = dot(surfaceNormal, H);
  float XdotH = dot(fiberParallel, H);
  float YdotH = dot(fiberPerpendicular, H);

  float coeff = sqrt(NdotL/NdotR) / (2.0 * TWO_PI * shinyParallel * shinyPerpendicular);
  float theta = (pow(XdotH/shinyParallel, 2.0) + pow(YdotH/shinyPerpendicular, 2.0)) / (1.0 + NdotH);

  return coeff * exp(-2.0 * theta);
}

Skylight

float skylight(float height){
  return smoothstep(0.0, PI, PI - acos(height));
}
vec3 skylightColor(vec3 col1, vec3 col2, float height) {
  return mix(col1, col2, skylight(height));
}

Spotlight

float spotlightAttenuation(vec3 dir, float amp){
  float dist = length(dir);
  float radiance = 1.0 / (1.0 + pow(dist / amp, 2.0));
  return clamp(radiance * amp, 0.0, 1.0);
}
float spotlightInfluence(vec3 normal, float coneAngle, float fallOffAngle){
  float minConeAngle = (360.0 - coneAngle - fallOffAngle) * RAD;
  float maxConeAngle = (360.0 - coneAngle) * RAD;
  return smoothstep(minConeAngle, maxConeAngle, acos(normal.z));
}

Complete namespace definition

(ns thi.ng.glsl.lighting
  (:require
   [thi.ng.glsl.core :as glsl :include-macros true]))

(glsl/defglsl lambert
  nil "
<<lambert>>")

(glsl/defglsl lambert-abs
  nil "
<<lambert-abs>>")

(glsl/defglsl phong
  nil "
<<phong>>")

(glsl/defglsl blinn-phong
  nil "
<<blinn-phong>>")

(glsl/defglsl schlick
  nil "
<<schlick>>")

(glsl/defglsl schlick-r0
  nil "
<<schlick-r0>>")

(glsl/defglsl beckmann-distribution
  nil "
<<beckmann-dist>>")

(glsl/defglsl beckmann-specular
  [beckmann-distribution] "
<<beckmann-specular>>")

(glsl/defglsl gaussian-specular
  nil "
<<gaussian>>")

(glsl/defglsl cook-torrance
  [beckmann-distribution] "
<<cook-torrance>>")

(glsl/defglsl oren-nayar
  nil "
<<oren-nayar>>")

(glsl/defglsl ward
  nil "
<<ward>>")

(glsl/defglsl skylight
  nil "
<<skylight>>")

(glsl/defglsl skylight-color
  [skylight] "
<<skylight-color>>")

(glsl/defglsl spotlight-attenuation
  nil "
<<spotlight-att>>")

(glsl/defglsl spotlight-influence
  nil "
<<spotlight-influence>>")