Browse Source

Merge pull request #6374 from sebavan/master

Add support for irradiance map
sebavan 6 years ago
parent
commit
1150158d37

+ 4 - 2
dist/preview release/what's new.md

@@ -5,12 +5,14 @@
 ## Optimizations
 
 ## Updates
+
+### Core Engine
 - Support Vive Focus 3Dof controller ([TrevorDev](https://github.com/TrevorDev))
 - Planar positioning support for GizmoManager ([Balupg](https://github.com/balupg))
 - Individual gizmos can now be enabled/disabled ([Balupg](https://github.com/balupg))
-
 - Unify preparation of instance attributes. Added `MaterialHelper.PushAttributesForInstances` ([MarkusBillharz](https://github.com/MarkusBillharz))
- 
+- Added support for PBR [irradiance map](https://doc.babylonjs.com/how_to/physically_based_rendering_master#irradiance-map)
+
 ### Inspector
 - Added support for `ShadowGenerator` ([Deltakosh](https://github.com/deltakosh/))
 - Added support for scene normalization ([Deltakosh](https://github.com/deltakosh/))

+ 2 - 2
package.json

@@ -37,7 +37,6 @@
     "readmeFilename": "README.md",
     "dependencies": {},
     "devDependencies": {
-        "storm-react-diagrams": "^5.2.1",
         "@fortawesome/fontawesome-svg-core": "~1.2.8",
         "@fortawesome/free-regular-svg-icons": "~5.4.1",
         "@fortawesome/free-solid-svg-icons": "~5.4.1",
@@ -56,7 +55,7 @@
         "color-support": "^1.1.3",
         "css-loader": "^1.0.0",
         "del": "3.0.0",
-        "dependency-cruiser": "^4.13.2",
+        "dependency-cruiser": "^4.19.0",
         "dts-bundle": "^0.7.3",
         "file-loader": "~2.0.0",
         "fs-extra": "^5.0.0",
@@ -91,6 +90,7 @@
         "shelljs": "^0.7.8",
         "sinon": "^6.1.4",
         "split.js": "^1.5.9",
+        "storm-react-diagrams": "^5.2.1",
         "style-loader": "^0.21.0",
         "through2": "~2.0.3",
         "ts-loader": "^5.2.1",

+ 5 - 0
src/Engines/engine.ts

@@ -5218,6 +5218,11 @@ export class Engine {
             texture._lodTextureLow.dispose();
         }
 
+        // Integrated irradiance map.
+        if (texture._irradianceTexture) {
+            texture._irradianceTexture.dispose();
+        }
+
         // Set output texture of post process to null if the texture has been released/disposed
         this.scenes.forEach((scene) => {
             scene.postProcesses.forEach((postProcess) => {

+ 54 - 30
src/Materials/PBR/pbrBaseMaterial.ts

@@ -129,12 +129,14 @@ export class PBRMaterialDefines extends MaterialDefines
     public REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = false;
     public INVERTCUBICMAP = false;
     public USESPHERICALFROMREFLECTIONMAP = false;
+    public USEIRRADIANCEMAP = false;
     public SPHERICAL_HARMONICS = false;
     public USESPHERICALINVERTEX = false;
     public REFLECTIONMAP_OPPOSITEZ = false;
     public LODINREFLECTIONALPHA = false;
     public GAMMAREFLECTION = false;
     public RGBDREFLECTION = false;
+    public LINEARSPECULARREFLECTION = false;
     public RADIANCEOCCLUSION = false;
     public HORIZONOCCLUSION = false;
 
@@ -219,6 +221,7 @@ export class PBRMaterialDefines extends MaterialDefines
     public SS_LODINREFRACTIONALPHA = false;
     public SS_GAMMAREFRACTION = false;
     public SS_RGBDREFRACTION = false;
+    public SS_LINEARSPECULARREFRACTION = false;
     public SS_LINKREFRACTIONTOTRANSPARENCY = false;
 
     public SS_MASK_FROM_THICKNESS_TEXTURE = false;
@@ -932,6 +935,9 @@ export abstract class PBRBaseMaterial extends PushMaterial {
                     if (!reflectionTexture.isReadyOrNotBlocking()) {
                         return false;
                     }
+                    if (reflectionTexture.irradianceTexture && !reflectionTexture.irradianceTexture.isReadyOrNotBlocking()) {
+                        return false;
+                    }
                 }
 
                 if (this._lightmapTexture && MaterialFlags.LightmapTextureEnabled) {
@@ -1100,6 +1106,10 @@ export abstract class PBRBaseMaterial extends PushMaterial {
             fallbacks.addFallback(fallbackRank++, "USESPHERICALFROMREFLECTIONMAP");
         }
 
+        if (defines.USEIRRADIANCEMAP) {
+            fallbacks.addFallback(fallbackRank++, "USEIRRADIANCEMAP");
+        }
+
         if (defines.LIGHTMAP) {
             fallbacks.addFallback(fallbackRank++, "LIGHTMAP");
         }
@@ -1182,7 +1192,7 @@ export abstract class PBRBaseMaterial extends PushMaterial {
 
         var samplers = ["albedoSampler", "reflectivitySampler", "ambientSampler", "emissiveSampler",
             "bumpSampler", "lightmapSampler", "opacitySampler",
-            "reflectionSampler", "reflectionSamplerLow", "reflectionSamplerHigh",
+            "reflectionSampler", "reflectionSamplerLow", "reflectionSamplerHigh", "irradianceSampler",
             "microSurfaceSampler", "environmentBrdfSampler", "boneSampler"];
 
         var uniformBuffers = ["Material", "Scene"];
@@ -1277,6 +1287,7 @@ export abstract class PBRBaseMaterial extends PushMaterial {
                     defines.RGBDREFLECTION = reflectionTexture.isRGBD;
                     defines.REFLECTIONMAP_OPPOSITEZ = this.getScene().useRightHandedSystem ? !reflectionTexture.invertZ : reflectionTexture.invertZ;
                     defines.LODINREFLECTIONALPHA = reflectionTexture.lodLevelInAlpha;
+                    defines.LINEARSPECULARREFLECTION = reflectionTexture.linearSpecularLOD;
 
                     if (reflectionTexture.coordinatesMode === Texture.INVCUBIC_MODE) {
                         defines.INVERTCUBICMAP = true;
@@ -1329,8 +1340,13 @@ export abstract class PBRBaseMaterial extends PushMaterial {
                     }
 
                     if (reflectionTexture.coordinatesMode !== Texture.SKYBOX_MODE) {
-                        if (reflectionTexture.sphericalPolynomial) {
+                        if (reflectionTexture.irradianceTexture) {
+                            defines.USEIRRADIANCEMAP = true;
+                            defines.USESPHERICALFROMREFLECTIONMAP = false;
+                        }
+                        else if (reflectionTexture.sphericalPolynomial) {
                             defines.USESPHERICALFROMREFLECTIONMAP = true;
+                            defines.USEIRRADIANCEMAP = false;
                             if (this._forceIrradianceInFragment || scene.getEngine().getCaps().maxVaryingVectors <= 8) {
                                 defines.USESPHERICALINVERTEX = false;
                             }
@@ -1358,11 +1374,13 @@ export abstract class PBRBaseMaterial extends PushMaterial {
                     defines.REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = false;
                     defines.INVERTCUBICMAP = false;
                     defines.USESPHERICALFROMREFLECTIONMAP = false;
+                    defines.USEIRRADIANCEMAP = false;
                     defines.USESPHERICALINVERTEX = false;
                     defines.REFLECTIONMAP_OPPOSITEZ = false;
                     defines.LODINREFLECTIONALPHA = false;
                     defines.GAMMAREFLECTION = false;
                     defines.RGBDREFLECTION = false;
+                    defines.LINEARSPECULARREFLECTION = false;
                 }
 
                 if (this._lightmapTexture && MaterialFlags.LightmapTextureEnabled) {
@@ -1671,34 +1689,36 @@ export abstract class PBRBaseMaterial extends PushMaterial {
                             ubo.updateVector3("vReflectionSize", cubeTexture.boundingBoxSize);
                         }
 
-                        var polynomials = reflectionTexture.sphericalPolynomial;
-                        if (defines.USESPHERICALFROMREFLECTIONMAP && polynomials) {
-                            if (defines.SPHERICAL_HARMONICS) {
-                                const preScaledHarmonics = polynomials.preScaledHarmonics;
-                                this._activeEffect.setVector3("vSphericalL00", preScaledHarmonics.l00);
-                                this._activeEffect.setVector3("vSphericalL1_1", preScaledHarmonics.l1_1);
-                                this._activeEffect.setVector3("vSphericalL10", preScaledHarmonics.l10);
-                                this._activeEffect.setVector3("vSphericalL11", preScaledHarmonics.l11);
-                                this._activeEffect.setVector3("vSphericalL2_2", preScaledHarmonics.l2_2);
-                                this._activeEffect.setVector3("vSphericalL2_1", preScaledHarmonics.l2_1);
-                                this._activeEffect.setVector3("vSphericalL20", preScaledHarmonics.l20);
-                                this._activeEffect.setVector3("vSphericalL21", preScaledHarmonics.l21);
-                                this._activeEffect.setVector3("vSphericalL22", preScaledHarmonics.l22);
-                            }
-                            else {
-                                this._activeEffect.setFloat3("vSphericalX", polynomials.x.x, polynomials.x.y, polynomials.x.z);
-                                this._activeEffect.setFloat3("vSphericalY", polynomials.y.x, polynomials.y.y, polynomials.y.z);
-                                this._activeEffect.setFloat3("vSphericalZ", polynomials.z.x, polynomials.z.y, polynomials.z.z);
-                                this._activeEffect.setFloat3("vSphericalXX_ZZ", polynomials.xx.x - polynomials.zz.x,
-                                    polynomials.xx.y - polynomials.zz.y,
-                                    polynomials.xx.z - polynomials.zz.z);
-                                this._activeEffect.setFloat3("vSphericalYY_ZZ", polynomials.yy.x - polynomials.zz.x,
-                                    polynomials.yy.y - polynomials.zz.y,
-                                    polynomials.yy.z - polynomials.zz.z);
-                                this._activeEffect.setFloat3("vSphericalZZ", polynomials.zz.x, polynomials.zz.y, polynomials.zz.z);
-                                this._activeEffect.setFloat3("vSphericalXY", polynomials.xy.x, polynomials.xy.y, polynomials.xy.z);
-                                this._activeEffect.setFloat3("vSphericalYZ", polynomials.yz.x, polynomials.yz.y, polynomials.yz.z);
-                                this._activeEffect.setFloat3("vSphericalZX", polynomials.zx.x, polynomials.zx.y, polynomials.zx.z);
+                        if (!defines.USEIRRADIANCEMAP) {
+                            var polynomials = reflectionTexture.sphericalPolynomial;
+                            if (defines.USESPHERICALFROMREFLECTIONMAP && polynomials) {
+                                if (defines.SPHERICAL_HARMONICS) {
+                                    const preScaledHarmonics = polynomials.preScaledHarmonics;
+                                    this._activeEffect.setVector3("vSphericalL00", preScaledHarmonics.l00);
+                                    this._activeEffect.setVector3("vSphericalL1_1", preScaledHarmonics.l1_1);
+                                    this._activeEffect.setVector3("vSphericalL10", preScaledHarmonics.l10);
+                                    this._activeEffect.setVector3("vSphericalL11", preScaledHarmonics.l11);
+                                    this._activeEffect.setVector3("vSphericalL2_2", preScaledHarmonics.l2_2);
+                                    this._activeEffect.setVector3("vSphericalL2_1", preScaledHarmonics.l2_1);
+                                    this._activeEffect.setVector3("vSphericalL20", preScaledHarmonics.l20);
+                                    this._activeEffect.setVector3("vSphericalL21", preScaledHarmonics.l21);
+                                    this._activeEffect.setVector3("vSphericalL22", preScaledHarmonics.l22);
+                                }
+                                else {
+                                    this._activeEffect.setFloat3("vSphericalX", polynomials.x.x, polynomials.x.y, polynomials.x.z);
+                                    this._activeEffect.setFloat3("vSphericalY", polynomials.y.x, polynomials.y.y, polynomials.y.z);
+                                    this._activeEffect.setFloat3("vSphericalZ", polynomials.z.x, polynomials.z.y, polynomials.z.z);
+                                    this._activeEffect.setFloat3("vSphericalXX_ZZ", polynomials.xx.x - polynomials.zz.x,
+                                        polynomials.xx.y - polynomials.zz.y,
+                                        polynomials.xx.z - polynomials.zz.z);
+                                    this._activeEffect.setFloat3("vSphericalYY_ZZ", polynomials.yy.x - polynomials.zz.x,
+                                        polynomials.yy.y - polynomials.zz.y,
+                                        polynomials.yy.z - polynomials.zz.z);
+                                    this._activeEffect.setFloat3("vSphericalZZ", polynomials.zz.x, polynomials.zz.y, polynomials.zz.z);
+                                    this._activeEffect.setFloat3("vSphericalXY", polynomials.xy.x, polynomials.xy.y, polynomials.xy.z);
+                                    this._activeEffect.setFloat3("vSphericalYZ", polynomials.yz.x, polynomials.yz.y, polynomials.yz.z);
+                                    this._activeEffect.setFloat3("vSphericalZX", polynomials.zx.x, polynomials.zx.y, polynomials.zx.z);
+                                }
                             }
                         }
 
@@ -1800,6 +1820,10 @@ export abstract class PBRBaseMaterial extends PushMaterial {
                         ubo.setTexture("reflectionSamplerLow", reflectionTexture._lodTextureLow || reflectionTexture);
                         ubo.setTexture("reflectionSamplerHigh", reflectionTexture._lodTextureHigh || reflectionTexture);
                     }
+
+                    if (defines.USEIRRADIANCEMAP) {
+                        ubo.setTexture("irradianceSampler", reflectionTexture.irradianceTexture);
+                    }
                 }
 
                 if (defines.ENVIRONMENTBRDF) {

+ 3 - 0
src/Materials/PBR/pbrSubSurfaceConfiguration.ts

@@ -31,6 +31,7 @@ export interface IMaterialSubSurfaceDefines {
     SS_LODINREFRACTIONALPHA: boolean;
     SS_GAMMAREFRACTION: boolean;
     SS_RGBDREFRACTION: boolean;
+    SS_LINEARSPECULARREFRACTION: boolean;
     SS_LINKREFRACTIONTOTRANSPARENCY: boolean;
 
     SS_MASK_FROM_THICKNESS_TEXTURE: boolean;
@@ -242,6 +243,7 @@ export class PBRSubSurfaceConfiguration {
             defines.SS_REFRACTIONMAP_3D = false;
             defines.SS_GAMMAREFRACTION = false;
             defines.SS_RGBDREFRACTION = false;
+            defines.SS_LINEARSPECULARREFRACTION = false;
             defines.SS_REFRACTIONMAP_OPPOSITEZ = false;
             defines.SS_LODINREFRACTIONALPHA = false;
             defines.SS_LINKREFRACTIONTOTRANSPARENCY = false;
@@ -268,6 +270,7 @@ export class PBRSubSurfaceConfiguration {
                         defines.SS_REFRACTIONMAP_3D = refractionTexture.isCube;
                         defines.SS_GAMMAREFRACTION = refractionTexture.gammaSpace;
                         defines.SS_RGBDREFRACTION = refractionTexture.isRGBD;
+                        defines.SS_LINEARSPECULARREFRACTION = refractionTexture.linearSpecularLOD;
                         defines.SS_REFRACTIONMAP_OPPOSITEZ = refractionTexture.invertZ;
                         defines.SS_LODINREFRACTIONALPHA = refractionTexture.lodLevelInAlpha;
                         defines.SS_LINKREFRACTIONTOTRANSPARENCY = this._linkRefractionWithTransparency;

+ 31 - 1
src/Materials/Textures/baseTexture.ts

@@ -1,4 +1,4 @@
-import { serialize, SerializationHelper } from "../../Misc/decorators";
+import { serialize, SerializationHelper, serializeAsTexture } from "../../Misc/decorators";
 import { Observer, Observable } from "../../Misc/observable";
 import { Tools, IAnimatable } from "../../Misc/tools";
 import { CubeMapToSphericalPolynomialTools } from "../../Misc/HighDynamicRange/cubemapToSphericalPolynomial";
@@ -259,6 +259,36 @@ export class BaseTexture implements IAnimatable {
     }
 
     /**
+     * With prefiltered texture, defined if the specular generation is based on a linear ramp.
+     * By default we are using a log2 of the linear roughness helping to keep a better resolution for
+     * average roughness values.
+     */
+    @serialize()
+    public get linearSpecularLOD(): boolean {
+        if (this._texture) { return this._texture._linearSpecularLOD; }
+
+        return false;
+    }
+    public set linearSpecularLOD(value: boolean) {
+        if (this._texture) { this._texture._linearSpecularLOD = value; }
+    }
+
+    /**
+     * In case a better definition than spherical harmonics is required for the diffuse part of the environment.
+     * You can set the irradiance texture to rely on a texture instead of the spherical approach.
+     * This texture need to have the same characteristics than its parent (Cube vs 2d, coordinates mode, Gamma/Linear, RGBD).
+     */
+    @serializeAsTexture()
+    public get irradianceTexture(): Nullable<BaseTexture> {
+        if (this._texture) { return this._texture._irradianceTexture; }
+
+        return null;
+    }
+    public set irradianceTexture(value: Nullable<BaseTexture>) {
+        if (this._texture) { this._texture._irradianceTexture = value; }
+    }
+
+    /**
      * Define if the texture is a render target.
      */
     @serialize()

+ 12 - 0
src/Materials/Textures/internalTexture.ts

@@ -228,6 +228,11 @@ export class InternalTexture {
     public _isRGBD: boolean = false;
 
     /** @hidden */
+    public _linearSpecularLOD: boolean = false;
+    /** @hidden */
+    public _irradianceTexture: Nullable<BaseTexture> = null;
+
+    /** @hidden */
     public _webGLTexture: Nullable<WebGLTexture> = null;
     /** @hidden */
     public _references: number = 1;
@@ -437,6 +442,13 @@ export class InternalTexture {
             target._lodTextureLow = this._lodTextureLow;
         }
 
+        if (this._irradianceTexture) {
+            if (target._irradianceTexture) {
+                target._irradianceTexture.dispose();
+            }
+            target._irradianceTexture = this._irradianceTexture;
+        }
+
         let cache = this._engine.getLoadedTexturesCache();
         var index = cache.indexOf(this);
         if (index !== -1) {

+ 10 - 2
src/Shaders/ShadersInclude/pbrFragmentSamplersDeclaration.fx

@@ -149,6 +149,10 @@
             uniform samplerCube reflectionSamplerLow;
             uniform samplerCube reflectionSamplerHigh;
         #endif
+
+        #ifdef USEIRRADIANCEMAP
+            uniform samplerCube irradianceSampler;
+        #endif
     #else
         #define sampleReflection(s, c) texture2D(s, c)
 
@@ -157,8 +161,12 @@
         #ifdef LODBASEDMICROSFURACE
             #define sampleReflectionLod(s, c, l) texture2DLodEXT(s, c, l)
         #else
-            uniform samplerCube reflectionSamplerLow;
-            uniform samplerCube reflectionSamplerHigh;
+            uniform sampler2D reflectionSamplerLow;
+            uniform sampler2D reflectionSamplerHigh;
+        #endif
+
+        #ifdef USEIRRADIANCEMAP
+            uniform sampler2D irradianceSampler;
         #endif
     #endif
 

+ 6 - 1
src/Shaders/ShadersInclude/pbrIBLFunctions.fx

@@ -1,9 +1,14 @@
 #if defined(REFLECTION) || defined(SS_REFRACTION)
     float getLodFromAlphaG(float cubeMapDimensionPixels, float microsurfaceAverageSlope) {
-        float microsurfaceAverageSlopeTexels = microsurfaceAverageSlope * cubeMapDimensionPixels;
+        float microsurfaceAverageSlopeTexels = cubeMapDimensionPixels * microsurfaceAverageSlope;
         float lod = log2(microsurfaceAverageSlopeTexels);
         return lod;
     }
+
+    float getLinearLodFromRoughness(float cubeMapDimensionPixels, float roughness) {
+        float lod = log2(cubeMapDimensionPixels) * roughness;
+        return lod;
+    }
 #endif
 
 #if defined(ENVIRONMENTBRDF) && defined(RADIANCEOCCLUSION)

+ 34 - 3
src/Shaders/pbr.fragment.fx

@@ -341,6 +341,8 @@ void main(void) {
 
         #ifdef SS_LODINREFRACTIONALPHA
             float refractionLOD = getLodFromAlphaG(vRefractionMicrosurfaceInfos.x, alphaG, NdotVUnclamped);
+        #elif defined(SS_LINEARSPECULARREFRACTION)
+            float refractionLOD = getLinearLodFromRoughness(vRefractionMicrosurfaceInfos.x, roughness);
         #else
             float refractionLOD = getLodFromAlphaG(vRefractionMicrosurfaceInfos.x, alphaG);
         #endif
@@ -427,6 +429,8 @@ void main(void) {
 
         #if defined(LODINREFLECTIONALPHA) && !defined(REFLECTIONMAP_SKYBOX)
             float reflectionLOD = getLodFromAlphaG(vReflectionMicrosurfaceInfos.x, alphaG, NdotVUnclamped);
+        #elif defined(LINEARSPECULARREFLECTION)
+            float refractionLOD = getLinearLodFromRoughness(vReflectionMicrosurfaceInfos.x, roughness);
         #else
             float reflectionLOD = getLodFromAlphaG(vReflectionMicrosurfaceInfos.x, alphaG);
         #endif
@@ -498,6 +502,15 @@ void main(void) {
 
                 environmentIrradiance = computeEnvironmentIrradiance(irradianceVector);
             #endif
+        #elif defined(USEIRRADIANCEMAP)
+            environmentIrradiance = sampleReflection(irradianceSampler, reflectionCoords).rgb;
+            #ifdef RGBDREFLECTION
+                environmentIrradiance.rgb = fromRGBD(environmentIrradiance);
+            #endif
+
+            #ifdef GAMMAREFLECTION
+                environmentIrradiance.rgb = toLinearSpace(environmentIrradiance.rgb);
+            #endif
         #endif
 
         // _____________________________ Levels _____________________________________
@@ -555,6 +568,8 @@ void main(void) {
             // _____________________________ 2D vs 3D Maps ________________________________
             #if defined(LODINREFLECTIONALPHA) && !defined(REFLECTIONMAP_SKYBOX)
                 float sheenReflectionLOD = getLodFromAlphaG(vReflectionMicrosurfaceInfos.x, sheenAlphaG, NdotVUnclamped);
+            #elif defined(LINEARSPECULARREFLECTION)
+                float sheenReflectionLOD = getLinearLodFromRoughness(vReflectionMicrosurfaceInfos.x, sheenRoughness);
             #else
                 float sheenReflectionLOD = getLodFromAlphaG(vReflectionMicrosurfaceInfos.x, sheenAlphaG);
             #endif
@@ -696,6 +711,8 @@ void main(void) {
 
             #if defined(LODINREFLECTIONALPHA) && !defined(REFLECTIONMAP_SKYBOX)
                 float clearCoatReflectionLOD = getLodFromAlphaG(vReflectionMicrosurfaceInfos.x, clearCoatAlphaG, clearCoatNdotVUnclamped);
+            #elif defined(LINEARSPECULARREFLECTION)
+                float sheenReflectionLOD = getLinearLodFromRoughness(vReflectionMicrosurfaceInfos.x, clearCoatRoughness);
             #else
                 float clearCoatReflectionLOD = getLodFromAlphaG(vReflectionMicrosurfaceInfos.x, clearCoatAlphaG);
             #endif
@@ -975,7 +992,7 @@ void main(void) {
     #endif
 
     // _______________________________  IBL Translucency ________________________________
-    #if defined(REFLECTION) && defined(USESPHERICALFROMREFLECTIONMAP) && defined(SS_TRANSLUCENCY)
+    #if defined(REFLECTION) && defined(SS_TRANSLUCENCY)
         #if defined(USESPHERICALINVERTEX)
             vec3 irradianceVector = vec3(reflectionMatrix * vec4(normalW, 0)).xyz;
             #ifdef REFLECTIONMAP_OPPOSITEZ
@@ -983,7 +1000,21 @@ void main(void) {
             #endif
         #endif
 
-        vec3 refractionIrradiance = computeEnvironmentIrradiance(-irradianceVector);
+        #if defined(USESPHERICALFROMREFLECTIONMAP)
+            vec3 refractionIrradiance = computeEnvironmentIrradiance(-irradianceVector);
+        #elif defined(USEIRRADIANCEMAP)
+            vec3 refractionIrradiance = sampleReflection(irradianceSampler, -irradianceVector).rgb;
+            #ifdef RGBDREFLECTION
+                refractionIrradiance.rgb = fromRGBD(refractionIrradiance);
+            #endif
+
+            #ifdef GAMMAREFLECTION
+                refractionIrradiance.rgb = toLinearSpace(refractionIrradiance.rgb);
+            #endif
+        #else
+            vec3 refractionIrradiance = vec3(0.);
+        #endif
+
         refractionIrradiance *= transmittance;
     #endif
 
@@ -997,7 +1028,7 @@ void main(void) {
     // _____________________________ Irradiance ______________________________________
     #ifdef REFLECTION
         vec3 finalIrradiance = environmentIrradiance;
-        #if defined(USESPHERICALFROMREFLECTIONMAP) && defined(SS_TRANSLUCENCY)
+        #if defined(SS_TRANSLUCENCY)
             finalIrradiance += refractionIrradiance;
         #endif
         finalIrradiance *= surfaceAlbedo.rgb;