|
| 1 | +struct reflectivityOutParams |
| 2 | +{ |
| 3 | + float roughness; |
| 4 | + float diffuseRoughness; |
| 5 | + float reflectanceF0; |
| 6 | + vec3 reflectanceF90; |
| 7 | + vec3 colorReflectanceF0; |
| 8 | + vec3 colorReflectanceF90; |
| 9 | + float metallic; |
| 10 | + float specularWeight; |
| 11 | + vec3 dielectricColorF0; |
| 12 | +#if defined(METALLIC_ROUGHNESS) && defined(AOSTOREINMETALMAPRED) |
| 13 | + vec3 ambientOcclusionColor; |
| 14 | +#endif |
| 15 | +#if DEBUGMODE > 0 |
| 16 | + #ifdef METALLIC_ROUGHNESS |
| 17 | + vec4 surfaceMetallicColorMap; |
| 18 | + #endif |
| 19 | + vec3 metallicF0; |
| 20 | +#endif |
| 21 | +}; |
| 22 | + |
| 23 | +#define pbr_inline |
| 24 | +reflectivityOutParams reflectivityBlock( |
| 25 | + in vec4 reflectanceInfo |
| 26 | + , in vec3 surfaceAlbedo |
| 27 | + , in vec4 specularColor |
| 28 | + , in float baseDiffuseRoughness |
| 29 | +#ifdef BASE_DIFFUSE_ROUGHNESS |
| 30 | + , in float baseDiffuseRoughnessTexture |
| 31 | + , in vec2 baseDiffuseRoughnessInfos |
| 32 | +#endif |
| 33 | +#ifdef METALLIC_ROUGHNESS |
| 34 | + , in vec3 reflectivityInfos |
| 35 | + , in vec4 metallicRoughnessFromTexture |
| 36 | +#endif |
| 37 | +#if defined(METALLIC_ROUGHNESS) && defined(AOSTOREINMETALMAPRED) |
| 38 | + , in vec3 ambientOcclusionColorIn |
| 39 | +#endif |
| 40 | +#ifdef DETAIL |
| 41 | + , in vec4 detailColor |
| 42 | + , in vec4 vDetailInfos |
| 43 | +#endif |
| 44 | +) |
| 45 | +{ |
| 46 | + reflectivityOutParams outParams; |
| 47 | + vec2 metallicRoughness = reflectanceInfo.rg; |
| 48 | + float ior = reflectanceInfo.b; |
| 49 | + #ifdef METALLIC_ROUGHNESS |
| 50 | + #if DEBUGMODE > 0 |
| 51 | + outParams.surfaceMetallicColorMap = metallicRoughnessFromTexture; |
| 52 | + #endif |
| 53 | + |
| 54 | + #ifdef AOSTOREINMETALMAPRED |
| 55 | + vec3 aoStoreInMetalMap = vec3(metallicRoughnessFromTexture.r, metallicRoughnessFromTexture.r, metallicRoughnessFromTexture.r); |
| 56 | + outParams.ambientOcclusionColor = mix(ambientOcclusionColorIn, aoStoreInMetalMap, reflectivityInfos.z); |
| 57 | + #endif |
| 58 | + |
| 59 | + metallicRoughness.r *= metallicRoughnessFromTexture.b; |
| 60 | + metallicRoughness.g *= metallicRoughnessFromTexture.g; |
| 61 | + #endif |
| 62 | + |
| 63 | + #ifdef DETAIL |
| 64 | + float detailRoughness = mix(0.5, detailColor.b, vDetailInfos.w); |
| 65 | + float loLerp = mix(0., metallicRoughness.g, detailRoughness * 2.); |
| 66 | + float hiLerp = mix(metallicRoughness.g, 1., (detailRoughness - 0.5) * 2.); |
| 67 | + metallicRoughness.g = mix(loLerp, hiLerp, step(detailRoughness, 0.5)); |
| 68 | + #endif |
| 69 | + |
| 70 | + #define CUSTOM_FRAGMENT_UPDATE_METALLICROUGHNESS |
| 71 | + |
| 72 | + outParams.metallic = metallicRoughness.r; |
| 73 | + outParams.roughness = metallicRoughness.g; |
| 74 | + outParams.specularWeight = specularColor.a; |
| 75 | + const float outsideIOR = 1.0; |
| 76 | + float dielectricF0 = pow((ior - outsideIOR) / (ior + outsideIOR), 2.0) * outParams.specularWeight; |
| 77 | + |
| 78 | + #if DEBUGMODE > 0 |
| 79 | + outParams.metallicF0 = vec3(dielectricF0) * specularColor.rgb; |
| 80 | + #endif |
| 81 | + |
| 82 | + // Compute non-coloured reflectance. |
| 83 | + // reflectanceF0 is the non-coloured reflectance used for blending between the diffuse and specular components. |
| 84 | + // It represents the total percentage of light reflected by the specular lobe at normal incidence. |
| 85 | + // In glTF's material model, the F0 value is multiplied by the maximum component of the specular colour. |
| 86 | + |
| 87 | + #if DIELECTRIC_SPECULAR_MODEL == DIELECTRIC_SPECULAR_MODEL_GLTF |
| 88 | + float maxF0 = max(specularColor.r, max(specularColor.g, specularColor.b)); |
| 89 | + outParams.reflectanceF0 = mix(dielectricF0 * maxF0, 1.0, outParams.metallic); |
| 90 | + #else |
| 91 | + outParams.reflectanceF0 = mix(dielectricF0, 1.0, outParams.metallic); |
| 92 | + #endif |
| 93 | + |
| 94 | + |
| 95 | + // Scale the reflectanceF90 by the IOR for values less than 1.5. |
| 96 | + // This is an empirical hack to account for the fact that Schlick is tuned for IOR = 1.5 |
| 97 | + // and an IOR of 1.0 should result in no visible glancing specular. |
| 98 | + float f90Scale = clamp(2.0 * (ior - 1.0), 0.0, 1.0); |
| 99 | + outParams.reflectanceF90 = vec3(mix(outParams.specularWeight * f90Scale, 1.0, outParams.metallic)); |
| 100 | + |
| 101 | + // Compute the coloured F0 reflectance. |
| 102 | + // The coloured reflectance is the percentage of light reflected by the specular lobe at normal incidence. |
| 103 | + // In glTF and OpenPBR, it is not the same thing as the percentage of light blocked from penetrating |
| 104 | + // down to the diffuse lobe. The non-coloured F0 will be used for this (see below). |
| 105 | + outParams.dielectricColorF0 = vec3(dielectricF0 * specularColor.rgb); |
| 106 | + vec3 metallicColorF0 = surfaceAlbedo.rgb; |
| 107 | + outParams.colorReflectanceF0 = mix(outParams.dielectricColorF0, metallicColorF0, outParams.metallic); |
| 108 | + |
| 109 | + // Now, compute the coloured reflectance at glancing angles based on the specular model. |
| 110 | + #if (DIELECTRIC_SPECULAR_MODEL == DIELECTRIC_SPECULAR_MODEL_OPENPBR) |
| 111 | + // In OpenPBR, the F90 is coloured using the specular colour for dielectrics. |
| 112 | + vec3 dielectricColorF90 = specularColor.rgb * vec3(outParams.specularWeight) * vec3(f90Scale); |
| 113 | + #else |
| 114 | + // In glTF, the F90 is white for dielectrics. |
| 115 | + vec3 dielectricColorF90 = vec3(outParams.specularWeight * f90Scale); |
| 116 | + #endif |
| 117 | + #if (CONDUCTOR_SPECULAR_MODEL == CONDUCTOR_SPECULAR_MODEL_OPENPBR) |
| 118 | + // In OpenPBR, we use the "F82" model for conductors. |
| 119 | + // We'll use the F90 value to hold the F82 tint which will be used in the computation later. |
| 120 | + vec3 conductorColorF90 = specularColor.rgb; |
| 121 | + #else |
| 122 | + // In glTF, the F90 colour for metals is white. |
| 123 | + vec3 conductorColorF90 = vec3(1.0); |
| 124 | + #endif |
| 125 | + outParams.colorReflectanceF90 = mix(dielectricColorF90, conductorColorF90, outParams.metallic); |
| 126 | + |
| 127 | + float diffuseRoughness = baseDiffuseRoughness; |
| 128 | +#ifdef BASE_DIFFUSE_ROUGHNESS |
| 129 | + diffuseRoughness *= baseDiffuseRoughnessTexture * baseDiffuseRoughnessInfos.y; |
| 130 | +#endif |
| 131 | + |
| 132 | + outParams.diffuseRoughness = diffuseRoughness; |
| 133 | + |
| 134 | + return outParams; |
| 135 | +} |
0 commit comments