// 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@>