SuperTuxKart 1.5 upstream source (from official release tarball)
This commit is contained in:
@@ -0,0 +1,189 @@
|
||||
vec3 PBRLight(
|
||||
vec3 normal,
|
||||
vec3 eyedir,
|
||||
vec3 lightdir,
|
||||
vec3 color,
|
||||
float perceptual_roughness,
|
||||
float metallic)
|
||||
{
|
||||
float NdotV = max(dot(normal, eyedir), 0.0001);
|
||||
float NdotL = clamp(dot(normal, lightdir), 0.0, 1.0);
|
||||
|
||||
vec2 F_ab = F_AB(perceptual_roughness, NdotV);
|
||||
|
||||
vec3 H = normalize(eyedir + lightdir);
|
||||
float NdotH = clamp(dot(normal, H), 0.0, 1.0);
|
||||
float LdotH = clamp(dot(lightdir, H), 0.0, 1.0);
|
||||
|
||||
vec3 diffuse_color = color * (1.0 - metallic);
|
||||
vec3 F0 = mix(vec3(0.04), color, metallic);
|
||||
// No real world material has specular values under 0.02, so we use this range as a
|
||||
// "pre-baked specular occlusion" that extinguishes the fresnel term, for artistic control.
|
||||
// See: https://google.github.io/filament/Filament.html#specularocclusion
|
||||
float F90 = clamp(dot(F0, vec3(50.0 * 0.33)), 0.0, 1.0);
|
||||
|
||||
float roughness = perceptualRoughnessToRoughness(perceptual_roughness);
|
||||
|
||||
vec3 diffuse = diffuse_color * Fd_Burley(roughness, NdotV, NdotL, NdotH);
|
||||
|
||||
float D = D_GGX(roughness, NdotH);
|
||||
float V = V_Smith_GGX_Correlated(roughness, NdotV, NdotL);
|
||||
vec3 F = fresnel(F0, F90, LdotH);
|
||||
vec3 specular = D * V * F * (1.0 + F0 * (1.0 / F_ab.x - 1.0));
|
||||
|
||||
return NdotL * (diffuse + specular);
|
||||
}
|
||||
|
||||
vec3 PBRSunAmbientEmitLight(
|
||||
vec3 normal,
|
||||
vec3 eyedir,
|
||||
vec3 sundir,
|
||||
vec3 color,
|
||||
vec3 irradiance,
|
||||
vec3 radiance,
|
||||
vec3 sun_color,
|
||||
vec3 ambient_color,
|
||||
float perceptual_roughness,
|
||||
float metallic,
|
||||
float emissive)
|
||||
{
|
||||
// Copied from PBRLight to use F_ab and F90 again
|
||||
float NdotV = max(dot(normal, eyedir), 0.0001);
|
||||
float NdotL = clamp(dot(normal, sundir), 0.0, 1.0);
|
||||
|
||||
vec2 F_ab = F_AB(perceptual_roughness, NdotV);
|
||||
|
||||
vec3 H = normalize(eyedir + sundir);
|
||||
float NdotH = clamp(dot(normal, H), 0.0, 1.0);
|
||||
float LdotH = clamp(dot(sundir, H), 0.0, 1.0);
|
||||
|
||||
vec3 diffuse_color = color * (1.0 - metallic);
|
||||
vec3 F0 = mix(vec3(0.04), color, metallic);
|
||||
// No real world material has specular values under 0.02, so we use this range as a
|
||||
// "pre-baked specular occlusion" that extinguishes the fresnel term, for artistic control.
|
||||
// See: https://google.github.io/filament/Filament.html#specularocclusion
|
||||
float F90 = clamp(dot(F0, vec3(50.0 * 0.33)), 0.0, 1.0);
|
||||
|
||||
float roughness = perceptualRoughnessToRoughness(perceptual_roughness);
|
||||
|
||||
vec3 diffuse = diffuse_color * Fd_Burley(roughness, NdotV, NdotL, NdotH);
|
||||
|
||||
float D = D_GGX(roughness, NdotH);
|
||||
float V = V_Smith_GGX_Correlated(roughness, NdotV, NdotL);
|
||||
vec3 F = fresnel(F0, F90, LdotH);
|
||||
vec3 specular = D * V * F * (1.0 + F0 * (1.0 / F_ab.x - 1.0));
|
||||
|
||||
vec3 sunlight = NdotL * (diffuse + specular);
|
||||
|
||||
vec3 diffuse_ambient = envBRDFApprox(diffuse_color, F_AB(1.0, NdotV));
|
||||
|
||||
vec3 specular_ambient = F90 * envBRDFApprox(F0, F_ab);
|
||||
|
||||
// Other 0.6 comes from skybox
|
||||
ambient_color *= 0.4;
|
||||
vec3 environment;
|
||||
if (u_ibl)
|
||||
{
|
||||
environment = environmentLight(irradiance, radiance, roughness,
|
||||
diffuse_color, F_ab, F0, F90, NdotV);
|
||||
}
|
||||
else
|
||||
{
|
||||
environment = u_global_light.m_skytop_color * ambient_color *
|
||||
diffuse_color;
|
||||
}
|
||||
|
||||
vec3 emit = emissive * color * 4.0;
|
||||
|
||||
return sun_color * sunlight
|
||||
+ environment + emit
|
||||
+ (diffuse_ambient + specular_ambient) * ambient_color;
|
||||
}
|
||||
|
||||
vec3 accumulateLights(int light_count, vec3 diffuse_color, vec3 normal,
|
||||
vec3 xpos, vec3 eyedir, float perceptual_roughness,
|
||||
float metallic)
|
||||
{
|
||||
vec3 accumulated_color = vec3(0.0);
|
||||
for (int i = 0; i < light_count; i++)
|
||||
{
|
||||
vec3 light_to_frag = (u_camera.m_view_matrix *
|
||||
vec4(u_global_light.m_lights[i].m_position_radius.xyz,
|
||||
1.0)).xyz - xpos;
|
||||
float invrange = u_global_light.m_lights[i].m_color_inverse_square_range.w;
|
||||
float distance_sq = dot(light_to_frag, light_to_frag);
|
||||
if (distance_sq * invrange > 1.)
|
||||
continue;
|
||||
// SpotLight
|
||||
float sattenuation = 1.;
|
||||
float sscale = u_global_light.m_lights[i].m_direction_scale_offset.z;
|
||||
float distance = sqrt(distance_sq);
|
||||
float distance_inverse = 1. / distance;
|
||||
vec3 L = light_to_frag * distance_inverse;
|
||||
if (sscale != 0.)
|
||||
{
|
||||
vec3 sdir =
|
||||
vec3(u_global_light.m_lights[i].m_direction_scale_offset.xy, 0.);
|
||||
sdir.z = sqrt(1. - dot(sdir, sdir)) * sign(sscale);
|
||||
sdir = (u_camera.m_view_matrix * vec4(sdir, 0.0)).xyz;
|
||||
sattenuation = clamp(dot(-sdir, L) *
|
||||
abs(sscale) +
|
||||
u_global_light.m_lights[i].m_direction_scale_offset.w, 0.0, 1.0);
|
||||
#ifndef TILED_GPU
|
||||
// Reduce branching in tiled GPU
|
||||
if (sattenuation == 0.)
|
||||
continue;
|
||||
#endif
|
||||
}
|
||||
vec3 diffuse_specular = PBRLight(normal, eyedir, L, diffuse_color,
|
||||
perceptual_roughness, metallic);
|
||||
float attenuation = 20. / (1. + distance_sq);
|
||||
float radius = u_global_light.m_lights[i].m_position_radius.w;
|
||||
attenuation *= (radius - distance) / radius;
|
||||
attenuation *= sattenuation * sattenuation;
|
||||
vec3 light_color =
|
||||
u_global_light.m_lights[i].m_color_inverse_square_range.xyz;
|
||||
accumulated_color += light_color * attenuation * diffuse_specular;
|
||||
}
|
||||
return accumulated_color;
|
||||
}
|
||||
|
||||
// Copied because reusing in a loop will be slower
|
||||
vec3 calculateLight(int i, vec3 diffuse_color, vec3 normal, vec3 xpos,
|
||||
vec3 eyedir, float perceptual_roughness, float metallic)
|
||||
{
|
||||
vec3 light_to_frag = (u_camera.m_view_matrix *
|
||||
vec4(u_global_light.m_lights[i].m_position_radius.xyz,
|
||||
1.0)).xyz - xpos;
|
||||
float invrange = u_global_light.m_lights[i].m_color_inverse_square_range.w;
|
||||
float distance_sq = dot(light_to_frag, light_to_frag);
|
||||
if (distance_sq * invrange > 1.)
|
||||
return vec3(0.0);
|
||||
// SpotLight
|
||||
float sattenuation = 1.;
|
||||
float sscale = u_global_light.m_lights[i].m_direction_scale_offset.z;
|
||||
float distance = sqrt(distance_sq);
|
||||
float distance_inverse = 1. / distance;
|
||||
vec3 L = light_to_frag * distance_inverse;
|
||||
if (sscale != 0.)
|
||||
{
|
||||
vec3 sdir =
|
||||
vec3(u_global_light.m_lights[i].m_direction_scale_offset.xy, 0.);
|
||||
sdir.z = sqrt(1. - dot(sdir, sdir)) * sign(sscale);
|
||||
sdir = (u_camera.m_view_matrix * vec4(sdir, 0.0)).xyz;
|
||||
sattenuation = clamp(dot(-sdir, L) *
|
||||
abs(sscale) +
|
||||
u_global_light.m_lights[i].m_direction_scale_offset.w, 0.0, 1.0);
|
||||
if (sattenuation == 0.)
|
||||
return vec3(0.0);
|
||||
}
|
||||
vec3 diffuse_specular = PBRLight(normal, eyedir, L, diffuse_color,
|
||||
perceptual_roughness, metallic);
|
||||
float attenuation = 20. / (1. + distance_sq);
|
||||
float radius = u_global_light.m_lights[i].m_position_radius.w;
|
||||
attenuation *= (radius - distance) / radius;
|
||||
attenuation *= sattenuation * sattenuation;
|
||||
vec3 light_color =
|
||||
u_global_light.m_lights[i].m_color_inverse_square_range.xyz;
|
||||
return light_color * attenuation * diffuse_specular;
|
||||
}
|
||||
Reference in New Issue
Block a user