overte-HifiExperiments/libraries/render-utils/src/LightAmbient.slh

141 lines
5.3 KiB
Text

// Generated on <$_SCRIBE_DATE$>
//
// Created by Sam Gateau on 7/5/16.
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
<@include render-utils/ShaderConstants.h@>
<@func declareSkyboxMap()@>
// declareSkyboxMap
LAYOUT(binding=RENDER_UTILS_TEXTURE_SKYBOX) uniform samplerCube skyboxMap;
vec4 evalSkyboxLight(vec3 direction, float lod) {
// textureQueryLevels is not available until #430, so we require explicit lod
// float mipmapLevel = lod * textureQueryLevels(skyboxMap);
#if !defined(GL_ES)
float filterLod = textureQueryLod(skyboxMap, direction).x;
// Keep texture filtering LOD as limit to prevent aliasing on specular reflection, but add
// a bias to limit overblurring with convolved maps
lod = max(lod, filterLod-2);
#endif
return textureLod(skyboxMap, direction, lod);
}
<@endfunc@>
<@func declareEvalAmbientSpecularIrradiance(supportAmbientSphere, supportAmbientMap, supportIfAmbientMapElseAmbientSphere)@>
LAYOUT(binding=RENDER_UTILS_TEXTURE_AMBIENT_FRESNEL) uniform sampler2D ambientFresnelLUT;
vec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float roughness) {
#if RENDER_UTILS_ENABLE_AMBIENT_FRESNEL_LUT
vec2 ambientFresnel = texture(ambientFresnelLUT, vec2(roughness, ndotd)).xy;
return fresnelColor * ambientFresnel.x + vec3(ambientFresnel.y);
#else
float gloss = 1.0-roughness;
float f = pow(1.0 - ndotd, 5.0);
return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;
#endif
}
<@if supportAmbientMap@>
<$declareSkyboxMap()$>
<@endif@>
float getMipLevelFromRoughness(float roughness, float lodCount) {
// This should match the value in the CubeMap::convolveForGGX method (CubeMap.cpp)
float ROUGHNESS_1_MIP_RESOLUTION = 1.5;
float deltaLod = lodCount - ROUGHNESS_1_MIP_RESOLUTION;
return deltaLod * (sqrt(1.0+24.0*roughness)-1.0) / 4.0;
}
vec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {
vec3 specularLight;
<@if supportIfAmbientMapElseAmbientSphere@>
if (getLightHasAmbientMap(ambient))
<@endif@>
<@if supportAmbientMap@>
{
float levelCount = getLightAmbientMapNumMips(ambient);
float lod = getMipLevelFromRoughness(surface.roughness, levelCount);
lod = max(lod, 0.0);
specularLight = evalSkyboxLight(lightDir, lod).xyz;
}
<@endif@>
<@if supportIfAmbientMapElseAmbientSphere@>
else
<@endif@>
<@if supportAmbientSphere@>
{
specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;
}
<@endif@>
return specularLight;
}
<@endfunc@>
<@func declareLightingAmbient(supportAmbientSphere, supportAmbientMap, supportIfAmbientMapElseAmbientSphere, supportScattering)@>
<$declareEvalAmbientSpecularIrradiance($supportAmbientSphere$, $supportAmbientMap$, $supportIfAmbientMapElseAmbientSphere$)$>
<@if supportScattering@>
float curvatureAO(in float k) {
return 1.0f - (0.0022f * k * k) + (0.0776f * k) + 0.7369f;
}
<@endif@>
void evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface,
float metallic, vec3 fresnelF0, vec3 albedo, float obscurance
<@if supportScattering@>
, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature
<@endif@>
) {
// Rotate surface normal and eye direction
vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;
vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;
<@if supportScattering@>
vec3 ambientSpaceLowNormal = (ambient.transform * vec4(lowNormalCurvature.xyz, 0.0)).xyz;
<@endif@>
vec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, surface.roughness);
diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) *
sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;
// Specular highlight from ambient
vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);
specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;
<@if supportScattering@>
if (scattering * isScatteringEnabled() > 0.0) {
float ambientOcclusion = curvatureAO(lowNormalCurvature.w * 20.0f) * 0.5f;
float ambientOcclusionHF = curvatureAO(midNormalCurvature.w * 8.0f) * 0.5f;
ambientOcclusion = min(ambientOcclusion, ambientOcclusionHF);
obscurance = min(obscurance, ambientOcclusion);
// Diffuse from ambient
diffuse = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceLowNormal).xyz;
// Scattering ambient specular is the same as non scattering for now
// TODO: we should use the same specular answer as for direct lighting
}
<@endif@>
obscurance = mix(1.0, obscurance, isObscuranceEnabled());
float lightEnergy = obscurance * getLightAmbientIntensity(ambient);
diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());
lightEnergy *= isAmbientEnabled();
diffuse *= lightEnergy * isDiffuseEnabled();
specular *= lightEnergy * isSpecularEnabled();
}
<@endfunc@>