Jamie Greunbaum 8eaef49f2e - Added game room, including pool and skee-ball.
- Moved video screen into its own separate movie tent.
- Adjusted stable post-processing volume.
- Chickens are now at full volume.
- Added button to toggle chickens off and on.
2026-02-09 03:49:54 -05:00

120 lines
4.4 KiB
HLSL

#ifndef FILAMENT_COMMON_OCCLUSION
#define FILAMENT_COMMON_OCCLUSION
//------------------------------------------------------------------------------
// Ambient occlusion configuration
//------------------------------------------------------------------------------
// Diffuse BRDFs
#define SPECULAR_AO_OFF 0
#define SPECULAR_AO_SIMPLE 1
#define SPECULAR_AO_BENT_NORMALS 2
//------------------------------------------------------------------------------
// Ambient occlusion helpers
//------------------------------------------------------------------------------
float SpecularAO_Lagarde(float NoV, float visibility, float roughness) {
// Lagarde and de Rousiers 2014, "Moving Frostbite to PBR"
return saturate(pow(NoV + visibility, exp2(-16.0 * roughness - 1.0)) - 1.0 + visibility);
}
#if defined(MATERIAL_HAS_BENT_NORMAL)
float sphericalCapsIntersection(float cosCap1, float cosCap2, float cosDistance) {
// Oat and Sander 2007, "Ambient Aperture Lighting"
// Approximation mentioned by Jimenez et al. 2016
float r1 = acosFastPositive(cosCap1);
float r2 = acosFastPositive(cosCap2);
float d = acosFast(cosDistance);
// We work with cosine angles, replace the original paper's use of
// cos(min(r1, r2)) with max(cosCap1, cosCap2)
// We also remove a multiplication by 2 * PI to simplify the computation
// since we divide by 2 * PI in computeBentSpecularAO()
if (min(r1, r2) <= max(r1, r2) - d) {
return 1.0 - max(cosCap1, cosCap2);
} else if (r1 + r2 <= d) {
return 0.0;
}
float delta = abs(r1 - r2);
float x = 1.0 - saturate((d - delta) / max(r1 + r2 - delta, 1e-4));
// simplified smoothstep()
float area = sq(x) * (-2.0 * x + 3.0);
return area * (1.0 - max(cosCap1, cosCap2));
}
#endif
// This function could (should?) be implemented as a 3D LUT instead, but we need to save samplers
float SpecularAO_Cones(float NoV, float visibility, float roughness) {
#if defined(MATERIAL_HAS_BENT_NORMAL)
// Jimenez et al. 2016, "Practical Realtime Strategies for Accurate Indirect Occlusion"
// aperture from ambient occlusion
float cosAv = sqrt(1.0 - visibility);
// aperture from roughness, log(10) / log(2) = 3.321928
float cosAs = exp2(-3.321928 * sq(roughness));
// angle betwen bent normal and reflection direction
float cosB = dot(shading_bentNormal, shading_reflected);
// Remove the 2 * PI term from the denominator, it cancels out the same term from
// sphericalCapsIntersection()
float ao = sphericalCapsIntersection(cosAv, cosAs, cosB) / (1.0 - cosAs);
// Smoothly kill specular AO when entering the perceptual roughness range [0.1..0.3]
// Without this, specular AO can remove all reflections, which looks bad on metals
return lerp(1.0, ao, smoothstep(0.01, 0.09, roughness));
#else
return SpecularAO_Lagarde(NoV, visibility, roughness);
#endif
}
/**
* Computes a specular occlusion term from the ambient occlusion term.
*/
float computeSpecularAO(float NoV, float visibility, float roughness) {
#if SPECULAR_AMBIENT_OCCLUSION == SPECULAR_AO_SIMPLE
return SpecularAO_Lagarde(NoV, visibility, roughness);
#elif SPECULAR_AMBIENT_OCCLUSION == SPECULAR_AO_BENT_NORMALS
return SpecularAO_Cones(NoV, visibility, roughness);
#else
return 1.0;
#endif
}
#if MULTI_BOUNCE_AMBIENT_OCCLUSION == 1
/**
* Returns a color ambient occlusion based on a pre-computed visibility term.
* The albedo term is meant to be the diffuse color or f0 for the diffuse and
* specular terms respectively.
*/
float3 gtaoMultiBounce(float visibility, const float3 albedo) {
// Jimenez et al. 2016, "Practical Realtime Strategies for Accurate Indirect Occlusion"
float3 a = 2.0404 * albedo - 0.3324;
float3 b = -4.7951 * albedo + 0.6417;
float3 c = 2.7552 * albedo + 0.6903;
return max((visibility), ((visibility * a + b) * visibility + c) * visibility);
}
#endif
void multiBounceAO(float visibility, const float3 albedo, inout float3 color) {
#if MULTI_BOUNCE_AMBIENT_OCCLUSION == 1
color *= gtaoMultiBounce(visibility, albedo);
#endif
}
void multiBounceSpecularAO(float visibility, const float3 albedo, inout float3 color) {
#if MULTI_BOUNCE_AMBIENT_OCCLUSION == 1 && SPECULAR_AMBIENT_OCCLUSION != SPECULAR_AO_OFF
color *= gtaoMultiBounce(visibility, albedo);
#endif
}
float singleBounceAO(float visibility) {
#if MULTI_BOUNCE_AMBIENT_OCCLUSION == 1
return 1.0;
#else
return visibility;
#endif
}
#endif // FILAMENT_COMMON_OCCLUSION