Skip to content

Instantly share code, notes, and snippets.

@galek
Created January 26, 2017 21:48
Show Gist options
  • Save galek/430fc985e2fb85f97e5a15085e6a0d54 to your computer and use it in GitHub Desktop.
Save galek/430fc985e2fb85f97e5a15085e6a0d54 to your computer and use it in GitHub Desktop.
#ifndef PHONG_LIGHTING_INC
#define PHONG_LIGHTING_INC 1
#define USE_OPTIMIZATION 1
#include "BRDF.h"
float GetAngleAttenuation(vec3 _l, vec3 _lightDir, float _angleScale, float _angleOffset)
{
float cosa = -dot(_l, _lightDir);
float atten = clamp(cosa * _angleScale + _angleOffset, 0.0, 1.0);
return atten * atten;
}
/* Calculates the color when using a point light. */
vec3 _LightingPoint(int _index, vec2 texCoord, vec3 normal, vec3 fragPos, vec4 _color, inout vec3 F0, in float _roughness)
{
vec3 unormalizedLightVector = lights[_index].u_light_pos - fragPos;
float distance = length(unormalizedLightVector);
#if USE_OPTIMIZATION
if (distance > (1 / lights[_index].attIRadius))
return auto_globalAmbient;
#endif
vec3 vdir = auto_globalViewPosition - fragPos;
vec3 n = normalize(normal);
vec3 v = normalize(vdir);
vec3 l = normalize(unormalizedLightVector);
vec3 h = normalize(v + l);
float ndotl = clamp(dot(n, l), 0.0, 1.0);
float ndoth = clamp(dot(n, h), 0.0, 1.0);
float ndotv = clamp(dot(n, v), 0.0, 1.0);
float ldoth = clamp(dot(l, h), 0.0, 1.0);
// Specular
F0 = BRDF_CookTorrance(F0, ldoth, ndoth, ndotv, ndotl, _roughness);
float dist2 = max(dot(unormalizedLightVector, unormalizedLightVector), dot(0.1, 0.1));
// See "Moving Frostbite to PBR" page 30, formula 22
float falloff = (lights[_index].lumIntensity / dist2) * max(0.0, 1.0 - distance * lights[_index].attIRadius);
float fade = max(0.0, (_color.w - 0.75) * 4.0);
float shadow = mix(1.0, falloff, fade);
return (_color.xyz * _color.w + F0) * shadow * ndotl * lights[_index].color;
}
//TODO:NOT READY
/* Calculates the color when using a directional light. No attenuation for directional lights*/
vec3 BlinnPhongDir(int _index, vec2 texCoord, vec3 normal, vec3 fragPos, vec4 _color, inout vec3 F0, in float _roughness)
{
return auto_globalAmbient * _color.xyz * _color.w;
}
/* Calculates the color when using a directional light. No attenuation for directional lights*/
vec3 _LightingSpot(int _index, vec2 texCoord, vec3 normal, vec3 fragPos, vec4 _color, inout vec3 F0, in float _roughness)
{
vec3 unormalizedLightVector = lights[_index].u_light_pos - fragPos;
float distance = length(unormalizedLightVector);
#if USE_OPTIMIZATION
if (distance > (1 / lights[_index].attIRadius))
return auto_globalAmbient;
#endif
vec3 vdir = auto_globalViewPosition - fragPos;
vec3 n = normalize(normal);
vec3 v = normalize(vdir);
vec3 l = normalize(unormalizedLightVector);
vec3 h = normalize(v + l);
float ndotl = clamp(dot(n, l), 0.0, 1.0);
float ndoth = clamp(dot(n, h), 0.0, 1.0);
float ndotv = clamp(dot(n, v), 0.0, 1.0);
float ldoth = clamp(dot(l, h), 0.0, 1.0);
// Specular
F0 = BRDF_CookTorrance(F0, ldoth, ndoth, ndotv, ndotl, _roughness);
float dist2 = max(dot(unormalizedLightVector, unormalizedLightVector), dot(0.1, 0.1));
float falloff = (lights[_index].lumIntensity / dist2) * max(0.0, 1.0 - distance * lights[_index].attIRadius);
#if 0 // TODO: when SM will be ready
falloff *= GetAngleAttenuation(l, lights[_index].u_light_dir, lights[_index].angleScale, lights[_index].angleOffset);
float shadow = falloff * VarianceShadow2D(sampler2, ltov, clipPlanes);
#else
float shadow = 1.0;
#endif
float fade = max(0.0, (_color.w - 0.75) * 4.0);
shadow = mix(1.0, shadow, fade);
return (_color.xyz * _color.w + F0) * shadow * ndotl * lights[_index].color;
}
vec3 _LightingEnv(int _index, vec2 texCoord, vec3 normal, vec3 fragPos, vec4 _color, inout vec3 F0, in float _roughness)
{
#define NUM_MIPS 8
vec3 vdir = auto_globalViewPosition - fragPos;
vec3 n = normalize(normal);
vec3 v = normalize(vdir);
vec3 r = 2 * dot(v, n) * n - v;
float ndotv = clamp(dot(n, v), 0.0, 1.0);
float miplevel = _roughness * (NUM_MIPS - 1);
vec3 diffuse_rad = texture(envprobe_diffuse_rad, n).rgb * _color.rgb;
vec3 specular_rad = textureLod(envprobe_specular_rad, r, miplevel).rgb;
vec2 f0_scale_bias = texture(envprobe_f0_scale_bias, vec2(ndotv, _roughness)).rg;
vec3 F = F0 * f0_scale_bias.x + vec3(f0_scale_bias.y);
return diffuse_rad * _color.a + specular_rad * F;
}
vec4 ComputeLighting(int _index, vec2 _uv, vec3 _normal, vec3 _pos, vec4 _color, inout vec3 _F0, in float _roughness)
{
vec4 lighting = vec4(0);
switch (lights[_index].type)
{
case POINT:
lighting.xyz += _LightingPoint(_index, _uv, _normal, _pos, _color, _F0, _roughness);
lighting.w = _color.w;
break;
case DIR:
lighting.xyz += auto_globalAmbient;
lighting.w = _color.w;
break;
case SPOT:
lighting.xyz += _LightingSpot(_index, _uv, _normal, _pos, _color, _F0, _roughness);
lighting.w = _color.w;
break;
case ENVPROBE:
lighting.xyz += _LightingEnv(_index, _uv, _normal, _pos, _color, _F0, _roughness);
break;
}
return lighting;
}
#endif //PHONG_LIGHTING_INC
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment