Revision control
++ // Copyright (C) 2014 NVIDIA Corporation.
++ // Copyright (C) 2023 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
++
++ #include "bsdf.glsllib"
++
++ #ifndef SAMPLE_REFLECTION_PROBE_GLSLLIB
++ #define SAMPLE_REFLECTION_PROBE_GLSLLIB 1
++
++ #ifdef QQ3D_SHADER_META
++ /*{
++ "uniforms": [
++ { "type": "samplerCube", "name": "qt_reflectionMap" },
++ { "type": "vec3", "name": "qt_reflectionProbeCubeMapCenter" },
++ { "type": "vec3", "name": "qt_reflectionProbeBoxMin" },
++ { "type": "vec3", "name": "qt_reflectionProbeBoxMax" },
++ { "type": "int", "name": "qt_reflectionProbeCorrection" }
++ ]
++ }*/
++ #endif // QQ3D_SHADER_META
++
++ vec3 qt_textureReflectionProbe(samplerCube reflectionProbe, vec3 dir, float lod)
++ {
++ return textureLod(reflectionProbe, dir, lod).rgb;
++ }
++
++ vec3 qt_reflectionParallaxCorrection(vec3 reflectionVector)
++ {
++ if (qt_reflectionProbeCorrection > 0) {
++ vec3 intersectionFirst = (qt_reflectionProbeBoxMax - qt_varWorldPos) / reflectionVector;
++ vec3 intersectionSecond = (qt_reflectionProbeBoxMin - qt_varWorldPos) / reflectionVector;
++ vec3 furthest = max(intersectionFirst, intersectionSecond);
++ float distance = min(min(furthest.x, furthest.y), furthest.z);
++ vec3 intersectionPosition = qt_varWorldPos + reflectionVector * distance;
++ reflectionVector = intersectionPosition - qt_reflectionProbeCubeMapCenter;
++ }
++
++ return reflectionVector;
++ }
++
++ vec3 qt_sampleDiffuseReflection(samplerCube reflectionProbe, vec3 normal)
++ {
++
++ vec3 smpDir = normal;
++ float baseLevel = 5;
++ smpDir = qt_reflectionParallaxCorrection(smpDir);
++ // Irradiance map is contained in mip at baseLevel
++ vec3 val = qt_textureReflectionProbe(reflectionProbe, smpDir, baseLevel);
++ return val;
++ }
++
++ // This method is used by DefaultMaterial for the specular term
++ vec4 qt_sampleGlossyReflection(samplerCube reflectionProbe, vec3 normal, vec3 viewDir, float rough)
++ {
++ float sigma = smoothstep(0.0, 1.0, clamp(rough, 0.0001, 1.0));
++ vec3 ret = vec3(0, 0, 0);
++ vec3 smpDir = reflect(-viewDir, normal);
++
++ // Compute the Geometric occlusion/self-shadowing term
++ float NdotL = clamp(dot(smpDir, normal), 0.0, 0.999995);
++ float k = sigma * 0.31830988618; // roughness / pi
++ float Gl = clamp((NdotL / (NdotL*(1.0-k) + k) + (1.0 - k*k)) * 0.5, 0.0, 1.0 );
++ float levels = 4;
++
++ smpDir = qt_reflectionParallaxCorrection(smpDir);
++ vec3 outColor = qt_textureReflectionProbe(reflectionProbe, smpDir, sigma * levels);
++
++ return vec4(Gl * outColor, 1.0);
++ }
++
++ // This method is used by the PrincipledMaterial for the IBL specular term.
++ vec4 qt_sampleGlossyReflectionPrincipled(samplerCube reflectionProbe, vec3 normal, vec3 viewDir, vec3 F, float roughness)
++ {
++ float levels = 4;
++
++ float lod = clamp((roughness * 5), 0.0, levels);
++ vec3 smpDir = normalize(reflect(-viewDir, normal));
++
++ smpDir = qt_reflectionParallaxCorrection(smpDir);
++ vec3 specularSample = qt_textureReflectionProbe(reflectionProbe, smpDir, lod);
++ vec2 brdf = qt_brdfApproximation(normal, viewDir, roughness);
++
++ return vec4(specularSample * (F * brdf.x + brdf.y), 1.0);
++ }
++
++ #if QSSG_ENABLE_ANISOTROPY
++ // Reflection probe counterpart of qt_sampleGlossyAnisotropic()
++ vec4 qt_sampleGlossyAnisotropicReflectionProbe(samplerCube reflectionProbe, vec3 normal, vec3 bentNormal,
++ vec3 viewDir, vec3 F, float roughness)
++ {
++ float levels = 4;
++
++ float lod = clamp((roughness * 5), 0.0, levels);
++ vec3 smpDir = normalize(reflect(-viewDir, bentNormal));
++
++ smpDir = qt_reflectionParallaxCorrection(smpDir);
++ vec3 specularSample = qt_textureReflectionProbe(reflectionProbe, smpDir, lod);
++ vec2 brdf = qt_brdfApproximation(normal, viewDir, roughness);
++
++ return vec4(specularSample * (F * brdf.x + brdf.y), 1.0);
++ }
++ #endif // QSSG_ENABLE_ANISOTROPY
++
++ #if QSSG_ENABLE_SHEEN
++ #include "sheen.glsllib"
++
++ // Reflection probe counterpart of qt_sampleGlossySheen()
++ vec4 qt_sampleGlossySheenReflectionProbe(samplerCube reflectionProbe, vec3 normal, vec3 viewDir, vec3 sheenColor, float sheenRoughness)
++ {
++ float levels = 4;
++
++ float lod = clamp(1.0 + sheenRoughness * (levels - 1.0), 0.0, levels);
++ vec3 smpDir = normalize(reflect(-viewDir, normal));
++
++ smpDir = qt_reflectionParallaxCorrection(smpDir);
++ vec3 sheenSample = qt_textureReflectionProbe(reflectionProbe, smpDir, lod);
++
++ float NdotV = clamp(dot(normal, viewDir), 0.0, 1.0);
++ return vec4(sheenSample * sheenColor * qt_E_sheen(NdotV, sheenRoughness), 1.0);
++ }
++ #endif // QSSG_ENABLE_SHEEN
++
++ #endif