feat: add forward+ rendering
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
#ifndef LIGHTING_GLSL
|
||||
#define LIGHTING_GLSL
|
||||
|
||||
#include "lights.glsl"
|
||||
|
||||
#define PI 3.14159265359
|
||||
|
||||
// GGX / Trowbridge-Reitz normal distribution
|
||||
float distributionGGX(float NoH, float roughness)
|
||||
{
|
||||
float a = roughness * roughness;
|
||||
float a2 = a * a;
|
||||
float d = NoH * NoH * (a2 - 1.0) + 1.0;
|
||||
return a2 / (PI * d * d);
|
||||
}
|
||||
|
||||
// Smith-Schlick GGX, k remapped for direct lighting
|
||||
float geometrySmithGGX(float NoV, float NoL, float roughness)
|
||||
{
|
||||
float r = roughness + 1.0;
|
||||
float k = (r * r) / 8.0;
|
||||
float ggxV = NoV / (NoV * (1.0 - k) + k);
|
||||
float ggxL = NoL / (NoL * (1.0 - k) + k);
|
||||
return ggxV * ggxL;
|
||||
}
|
||||
|
||||
vec3 fresnelSchlick(float VoH, vec3 f0)
|
||||
{
|
||||
return f0 + (1.0 - f0) * pow(1.0 - VoH, 5.0);
|
||||
}
|
||||
|
||||
// Inverse square falloff, windowed so it reaches exactly 0 at the light range.
|
||||
// The range is also the sphere the light culling uses, so no light gets cut off at a tile edge.
|
||||
float calculateDistanceAttenuation(float distance, float range)
|
||||
{
|
||||
float window = clamp(1.0 - pow(distance / range, 4.0), 0.0, 1.0);
|
||||
return (window * window) / max(distance * distance, 0.0001);
|
||||
}
|
||||
|
||||
float calculateSpotAttenuation(Light light, vec3 l)
|
||||
{
|
||||
float cd = dot(normalize(light.direction), -l);
|
||||
return smoothstep(light.spotOuterCos, light.spotInnerCos, cd);
|
||||
}
|
||||
|
||||
vec3 calculateLight(Light light, vec3 fragPos, vec3 n, vec3 v,
|
||||
vec3 diffuseColor, float roughness, float metallic, vec3 f0)
|
||||
{
|
||||
vec3 l;
|
||||
float attenuation = 1.0;
|
||||
|
||||
if (light.type == TYPE_DIRECTIONAL_LIGHT) {
|
||||
l = normalize(-light.direction);
|
||||
} else {
|
||||
vec3 toLight = light.position - fragPos;
|
||||
float distance = length(toLight);
|
||||
l = toLight / max(distance, 0.0001);
|
||||
|
||||
attenuation = calculateDistanceAttenuation(distance, light.range);
|
||||
if (light.type == TYPE_SPOT_LIGHT) {
|
||||
attenuation *= calculateSpotAttenuation(light, l);
|
||||
}
|
||||
}
|
||||
|
||||
float NoL = clamp(dot(n, l), 0.0, 1.0);
|
||||
if (NoL <= 0.0 || attenuation <= 0.0) {
|
||||
return vec3(0.0);
|
||||
}
|
||||
|
||||
vec3 h = normalize(v + l);
|
||||
float NoV = clamp(dot(n, v), 0.0001, 1.0);
|
||||
float NoH = clamp(dot(n, h), 0.0, 1.0);
|
||||
float VoH = clamp(dot(v, h), 0.0, 1.0);
|
||||
|
||||
float D = distributionGGX(NoH, roughness);
|
||||
float G = geometrySmithGGX(NoV, NoL, roughness);
|
||||
vec3 F = fresnelSchlick(VoH, f0);
|
||||
|
||||
vec3 specular = (D * G * F) / (4.0 * NoV * NoL + 0.0001);
|
||||
vec3 kd = (vec3(1.0) - F) * (1.0 - metallic);
|
||||
vec3 diffuse = kd * diffuseColor / PI;
|
||||
|
||||
return (diffuse + specular) * light.color * light.intensity * attenuation * NoL;
|
||||
}
|
||||
|
||||
// blue -> green -> red, used to visualise how many lights a tile has
|
||||
vec3 lightHeatmapColor(uint lightCount)
|
||||
{
|
||||
float t = clamp(float(lightCount) / 16.0, 0.0, 1.0);
|
||||
if (t < 0.5) {
|
||||
return mix(vec3(0.0, 0.0, 1.0), vec3(0.0, 1.0, 0.0), t * 2.0);
|
||||
}
|
||||
return mix(vec3(0.0, 1.0, 0.0), vec3(1.0, 0.0, 0.0), (t - 0.5) * 2.0);
|
||||
}
|
||||
|
||||
#endif // LIGHTING_GLSL
|
||||
Reference in New Issue
Block a user