Created
November 26, 2011 00:14
-
-
Save rorydriscoll/1394734 to your computer and use it in GitHub Desktop.
Shader experiment
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// bind gloss {label:"Gloss", default:0.5, max:1, step:0.01} | |
// bind cdiff {label:"Diffuse Colour", r:0.6, g:0.0, b:0.0} | |
// bind cspec {label:"Specular Colour", r:0.3, g:0.3, b:0.3} | |
// bind lightstrength {label:"Light Strength", default:3, max:100, step:0.1} | |
// bind envtop {label:"Environment Top", r:0.0, g:0.2, b:0.4} | |
// bind envmiddle {label:"Environment Middle", r:0.2, g:0.2, b:0.2} | |
// bind envbottom {label:"Environment Bottom", r:0.01, g:0.1, b:0.01} | |
// bind refractiveindex {label:"Refracive Index", default:1.5, max:3, step:0.1} | |
// bind normalmap {label:"Normal Map", default:false} | |
// bind diffuse {label:"Diffuse", default:true} | |
// bind specular {label:"Specular", default:true} | |
// bind exposure {label:"Exposure", default:0, min:-8, max:8, step:0.1} | |
varying vec2 texcoord; | |
varying vec3 wview; | |
varying vec3 wnormal; | |
varying vec3 wtangent; | |
uniform sampler2D normal_map; | |
uniform sampler2D gloss_map; | |
uniform float gloss; | |
uniform vec3 cdiff; | |
uniform vec3 cspec; | |
uniform vec3 envtop; | |
uniform vec3 envmiddle; | |
uniform vec3 envbottom; | |
uniform float lightstrength; | |
uniform float exposure; | |
uniform bool normalmap; | |
uniform bool diffuse; | |
uniform bool specular; | |
vec3 light = normalize(vec3(1, 1, 1)); | |
const float gamma = 2.2; | |
const float pi = 3.1415927; | |
float saturate(float v) | |
{ | |
return clamp(v, 0.0, 1.0); | |
} | |
vec3 pow(vec3 v, float p) | |
{ | |
return vec3(pow(v.x, p), pow(v.y, p), pow(v.z, p)); | |
} | |
vec3 lerp(vec3 a, vec3 b, float f) | |
{ | |
float r = 1.0 - f; | |
return vec3(r * a.x + f * b.x, r * a.y + f * b.y, r * a.z + f * b.z); | |
} | |
vec3 ToLinear(vec3 v) | |
{ | |
return pow(v, gamma); | |
} | |
vec3 ToSRGB(vec3 v) | |
{ | |
return pow(v, 1.0/gamma); | |
} | |
vec3 Fresnel(vec3 reflectance, float x) | |
{ | |
return reflectance + (1.0 - reflectance - 2.0 * reflectance * x) * pow(1.0 - x, 5.0); | |
} | |
vec3 SampleEnvironment(vec3 direction) | |
{ | |
vec3 top = ToLinear(envtop); | |
vec3 middle = ToLinear(envmiddle); | |
vec3 bottom = ToLinear(envbottom); | |
if (direction.y > 0.0) | |
return lerp(middle, top, direction.y); | |
return lerp(middle, bottom, -direction.y); | |
} | |
float DiffuseConservation() | |
{ | |
return 1.0 / pi; | |
} | |
float SpecularConservation(float power) | |
{ | |
return 0.0397436 * power + 0.0856832; | |
} | |
void main() | |
{ | |
// Unpack normal map | |
vec3 bump = texture2D(normal_map, texcoord.xy).xyz; | |
bump = bump*2.0 - 1.0; | |
// Transform normal to world-space | |
vec3 wbitangent = cross(wnormal, wtangent); | |
mat3 t2w = mat3(wtangent, wbitangent, wnormal); | |
vec3 n = normalize(t2w*bump); | |
if (!normalmap) | |
n = normalize(wnormal); | |
// Other vectors for lighting | |
vec3 l = normalize(light); | |
vec3 v = normalize(wview); | |
vec3 h = normalize(v + l); | |
vec3 r = reflect(-v, n); | |
// Cosines | |
float ndoth = saturate(dot(n, h)); | |
float ndotv = saturate(dot(n, v)); | |
float ndotl = saturate(dot(n, l)); | |
float power = exp2(13.0 * gloss); | |
// Linearise material properties | |
vec3 cs = max(ToLinear(cspec), vec3(0.01)); | |
vec3 cd = ToLinear(cdiff) * (1.0 - cs); | |
// Energy conserving diffuse and specular | |
vec3 diff = DiffuseConservation() * cd; | |
vec3 spec = SpecularConservation(power) * Fresnel(cs, ndoth) * pow(ndoth, power) / max(ndotv, ndotl); | |
// Combine diffuse and specular lighting | |
vec3 lightcontribution = vec3(0.0); | |
if (diffuse) | |
lightcontribution += cd*diff*ndotl*lightstrength; | |
if (specular) | |
lightcontribution += cs*spec*ndotl*lightstrength; | |
// Add simple environment lighting | |
vec3 envcontribution = vec3(0.0); | |
if (diffuse) | |
envcontribution += cd * SampleEnvironment(n); | |
if (specular) | |
envcontribution += Fresnel(cs, ndotv) * SampleEnvironment(r); | |
// Combine! | |
vec3 color = lightcontribution + envcontribution; | |
// Basic tone mapping | |
color *= pow(2.0, exposure); | |
color = color / (1.0 + color); | |
// Convert to sRGB for display | |
color = ToSRGB(color); | |
gl_FragColor = vec4(color, 1.0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment