Sfoglia il codice sorgente

Merge pull request #2352 from yaRnMcDonuts/master

Updates, features, and refactoring for Modular PBR Shaders (redo PR)
Ryan McDonough 7 mesi fa
parent
commit
8ba6574ef6

+ 52 - 347
jme3-core/src/main/resources/Common/MatDefs/Light/PBRLighting.frag

@@ -1,365 +1,70 @@
 #import "Common/ShaderLib/GLSLCompat.glsllib"
-#import "Common/ShaderLib/PBR.glsllib"
-#import "Common/ShaderLib/Parallax.glsllib"
-#import "Common/ShaderLib/Lighting.glsllib"
 
-varying vec2 texCoord;
-#ifdef SEPARATE_TEXCOORD
-  varying vec2 texCoord2;
-#endif
-
-varying vec4 Color;
-
-uniform vec4 g_LightData[NB_LIGHTS];
-uniform vec3 g_CameraPosition;
-uniform vec4 g_AmbientLightColor;
-
-uniform float m_Roughness;
-uniform float m_Metallic;
-
-varying vec3 wPosition;    
-
-
-#if NB_PROBES >= 1
-  uniform samplerCube g_PrefEnvMap;
-  uniform vec3 g_ShCoeffs[9];
-  uniform mat4 g_LightProbeData;
-#endif
-#if NB_PROBES >= 2
-  uniform samplerCube g_PrefEnvMap2;
-  uniform vec3 g_ShCoeffs2[9];
-  uniform mat4 g_LightProbeData2;
-#endif
-#if NB_PROBES == 3
-  uniform samplerCube g_PrefEnvMap3;
-  uniform vec3 g_ShCoeffs3[9];
-  uniform mat4 g_LightProbeData3;
-#endif
-
-#ifdef BASECOLORMAP
-  uniform sampler2D m_BaseColorMap;
-#endif
-
-#ifdef USE_PACKED_MR
-  uniform sampler2D m_MetallicRoughnessMap;
-#else
-    #ifdef METALLICMAP
-      uniform sampler2D m_MetallicMap;
-    #endif
-    #ifdef ROUGHNESSMAP
-      uniform sampler2D m_RoughnessMap;
-    #endif
-#endif
+// enable apis and import PBRLightingUtils
+#define ENABLE_PBRLightingUtils_getWorldPosition 1
+//#define ENABLE_PBRLightingUtils_getLocalPosition 1
+#define ENABLE_PBRLightingUtils_getWorldNormal 1
+#define ENABLE_PBRLightingUtils_getWorldTangent 1
+#define ENABLE_PBRLightingUtils_getTexCoord 1
+#define ENABLE_PBRLightingUtils_readPBRSurface 1
+#define ENABLE_PBRLightingUtils_computeDirectLightContribution 1
+#define ENABLE_PBRLightingUtils_computeProbesContribution 1
 
-#ifdef EMISSIVE
-  uniform vec4 m_Emissive;
-#endif
-#ifdef EMISSIVEMAP
-  uniform sampler2D m_EmissiveMap;
-#endif
-#if defined(EMISSIVE) || defined(EMISSIVEMAP)
-    uniform float m_EmissivePower;
-    uniform float m_EmissiveIntensity;
-#endif 
-
-#ifdef SPECGLOSSPIPELINE
-
-  uniform vec4 m_Specular;
-  uniform float m_Glossiness;
-  #ifdef USE_PACKED_SG
-    uniform sampler2D m_SpecularGlossinessMap;
-  #else
-    uniform sampler2D m_SpecularMap;
-    uniform sampler2D m_GlossinessMap;
-  #endif
-#endif
-
-#ifdef PARALLAXMAP
-  uniform sampler2D m_ParallaxMap;  
-#endif
-#if (defined(PARALLAXMAP) || (defined(NORMALMAP_PARALLAX) && defined(NORMALMAP)))
-    uniform float m_ParallaxHeight;
-#endif
-
-#ifdef LIGHTMAP
-  uniform sampler2D m_LightMap;
-#endif
+#import "Common/ShaderLib/module/pbrlighting/PBRLightingUtils.glsllib"
 
-#ifdef AO_STRENGTH
-  uniform float m_AoStrength;
-#endif
-  
-#if defined(NORMALMAP) || defined(PARALLAXMAP)
-  uniform sampler2D m_NormalMap;   
-  varying vec4 wTangent;
-#endif
-#ifdef NORMALSCALE
-  uniform float m_NormalScale;
+#ifdef DEBUG_VALUES_MODE
+    uniform int m_DebugValuesMode;
 #endif
-varying vec3 wNormal;
 
-// Specular-AA
-#ifdef SPECULAR_AA_SCREEN_SPACE_VARIANCE
-  uniform float m_SpecularAASigma;
-#endif
-#ifdef SPECULAR_AA_THRESHOLD
-  uniform float m_SpecularAAKappa;
-#endif
+uniform vec4 g_LightData[NB_LIGHTS];
+uniform vec3 g_CameraPosition;
 
-#ifdef DISCARD_ALPHA
-  uniform float m_AlphaDiscardThreshold;
+#ifdef USE_FOG
+    #import "MatDefs/ShaderLib/MaterialFog.glsllib"
 #endif
 
 void main(){
-    vec2 newTexCoord;
-    vec3 viewDir = normalize(g_CameraPosition - wPosition);
-
-    vec3 norm = normalize(wNormal);
-    #if defined(NORMALMAP) || defined(PARALLAXMAP)
-        vec3 tan = normalize(wTangent.xyz);
-        mat3 tbnMat = mat3(tan, wTangent.w * cross( (norm), (tan)), norm);
-    #endif
-
-    #if (defined(PARALLAXMAP) || (defined(NORMALMAP_PARALLAX) && defined(NORMALMAP)))
-       vec3 vViewDir =  viewDir * tbnMat;  
-       #ifdef STEEP_PARALLAX
-           #ifdef NORMALMAP_PARALLAX
-               //parallax map is stored in the alpha channel of the normal map         
-               newTexCoord = steepParallaxOffset(m_NormalMap, vViewDir, texCoord, m_ParallaxHeight);
-           #else
-               //parallax map is a texture
-               newTexCoord = steepParallaxOffset(m_ParallaxMap, vViewDir, texCoord, m_ParallaxHeight);         
-           #endif
-       #else
-           #ifdef NORMALMAP_PARALLAX
-               //parallax map is stored in the alpha channel of the normal map         
-               newTexCoord = classicParallaxOffset(m_NormalMap, vViewDir, texCoord, m_ParallaxHeight);
-           #else
-               //parallax map is a texture
-               newTexCoord = classicParallaxOffset(m_ParallaxMap, vViewDir, texCoord, m_ParallaxHeight);
-           #endif
-       #endif
-    #else
-       newTexCoord = texCoord;    
-    #endif
+    vec3 wpos = PBRLightingUtils_getWorldPosition();
+    vec3 worldViewDir = normalize(g_CameraPosition - wpos);
     
-    #ifdef BASECOLORMAP
-        vec4 albedo = texture2D(m_BaseColorMap, newTexCoord) * Color;
-    #else
-        vec4 albedo = Color;
-    #endif
-
-    //ao in r channel, roughness in green channel, metallic in blue channel!
-    vec3 aoRoughnessMetallicValue = vec3(1.0, 1.0, 0.0);
-    #ifdef USE_PACKED_MR
-        aoRoughnessMetallicValue = texture2D(m_MetallicRoughnessMap, newTexCoord).rgb;
-        float Roughness = aoRoughnessMetallicValue.g * max(m_Roughness, 1e-4);
-        float Metallic = aoRoughnessMetallicValue.b * max(m_Metallic, 0.0);
-    #else
-        #ifdef ROUGHNESSMAP
-            float Roughness = texture2D(m_RoughnessMap, newTexCoord).r * max(m_Roughness, 1e-4);
-        #else
-            float Roughness =  max(m_Roughness, 1e-4);
-        #endif
-        #ifdef METALLICMAP
-            float Metallic = texture2D(m_MetallicMap, newTexCoord).r * max(m_Metallic, 0.0);
-        #else
-            float Metallic =  max(m_Metallic, 0.0);
-        #endif
-    #endif
- 
-    float alpha = albedo.a;
-
-    #ifdef DISCARD_ALPHA
-        if(alpha < m_AlphaDiscardThreshold){
-            discard;
-        }
-    #endif
- 
-    // ***********************
-    // Read from textures
-    // ***********************
-    #if defined(NORMALMAP)
-      vec4 normalHeight = texture2D(m_NormalMap, newTexCoord);
-      // Note we invert directx style normal maps to opengl style
-
-      #ifdef NORMALSCALE
-        vec3 normal = normalize((normalHeight.xyz * vec3(2.0, NORMAL_TYPE * 2.0, 2.0) - vec3(1.0, NORMAL_TYPE * 1.0, 1.0)) * vec3(m_NormalScale, m_NormalScale, 1.0));
-      #else
-        vec3 normal = normalize((normalHeight.xyz * vec3(2.0, NORMAL_TYPE * 2.0, 2.0) - vec3(1.0, NORMAL_TYPE * 1.0, 1.0)));
-      #endif
-      normal = normalize(tbnMat * normal);
-      //normal = normalize(normal * inverse(tbnMat));
-    #else
-      vec3 normal = norm;
-    #endif
-
-    #ifdef SPECGLOSSPIPELINE
-
-        #ifdef USE_PACKED_SG
-            vec4 specularColor = texture2D(m_SpecularGlossinessMap, newTexCoord);
-            float glossiness = specularColor.a * m_Glossiness;
-            specularColor *= m_Specular;
-        #else
-            #ifdef SPECULARMAP
-                vec4 specularColor = texture2D(m_SpecularMap, newTexCoord);
-            #else
-                vec4 specularColor = vec4(1.0);
-            #endif
-            #ifdef GLOSSINESSMAP
-                float glossiness = texture2D(m_GlossinessMap, newTexCoord).r * m_Glossiness;
-            #else
-                float glossiness = m_Glossiness;
-            #endif
-            specularColor *= m_Specular;
-        #endif
-        vec4 diffuseColor = albedo;// * (1.0 - max(max(specularColor.r, specularColor.g), specularColor.b));
-        Roughness = 1.0 - glossiness;
-        vec3 fZero = specularColor.xyz;
-    #else
-        vec4 specularColor = (0.04 - 0.04 * Metallic) + albedo * Metallic;  // 0.04 is the standard base specular reflectance for non-metallic surfaces in PBR. While values like 0.08 can be used for different implementations, 0.04 aligns with Khronos' PBR specification.
-        vec4 diffuseColor = albedo - albedo * Metallic;
-        vec3 fZero = mix(vec3(0.04), albedo.rgb, Metallic);
-    #endif
-
-    gl_FragColor.rgb = vec3(0.0);
-    vec3 ao = vec3(1.0);
-
-    #ifdef LIGHTMAP
-       vec3 lightMapColor;
-       #ifdef SEPARATE_TEXCOORD
-          lightMapColor = texture2D(m_LightMap, texCoord2).rgb;
-       #else
-          lightMapColor = texture2D(m_LightMap, texCoord).rgb;
-       #endif
-       #ifdef AO_MAP
-         lightMapColor.gb = lightMapColor.rr;
-         ao = lightMapColor;
-       #else
-         gl_FragColor.rgb += diffuseColor.rgb * lightMapColor;
-       #endif
-       specularColor.rgb *= lightMapColor;
-    #endif
-
-    #if defined(AO_PACKED_IN_MR_MAP) && defined(USE_PACKED_MR)
-       ao = aoRoughnessMetallicValue.rrr;
-    #endif
-
-    #ifdef AO_STRENGTH
-       ao = 1.0 + m_AoStrength * (ao - 1.0);
-       // sanity check
-       ao = clamp(ao, 0.0, 1.0);
-    #endif
-
-    #ifdef SPECULAR_AA
-        float sigma = 1.0;
-        float kappa = 0.18;
-        #ifdef SPECULAR_AA_SCREEN_SPACE_VARIANCE
-            sigma = m_SpecularAASigma;
-        #endif
-        #ifdef SPECULAR_AA_THRESHOLD
-            kappa = m_SpecularAAKappa;
-        #endif
-    #endif
-    float ndotv = max( dot( normal, viewDir ),0.0);
-    for( int i = 0;i < NB_LIGHTS; i+=3){
-        vec4 lightColor = g_LightData[i];
-        vec4 lightData1 = g_LightData[i+1];                
-        vec4 lightDir;
-        vec3 lightVec;            
-        lightComputeDir(wPosition, lightColor.w, lightData1, lightDir, lightVec);
-
-        float fallOff = 1.0;
-        #if __VERSION__ >= 110
-            // allow use of control flow
-        if(lightColor.w > 1.0){
-        #endif
-            fallOff =  computeSpotFalloff(g_LightData[i+2], lightVec);
-        #if __VERSION__ >= 110
-        }
-        #endif
-        //point light attenuation
-        fallOff *= lightDir.w;
-
-        lightDir.xyz = normalize(lightDir.xyz);            
-        vec3 directDiffuse;
-        vec3 directSpecular;
-
-        #ifdef SPECULAR_AA
-            float hdotv = PBR_ComputeDirectLightWithSpecularAA(
-                                normal, lightDir.xyz, viewDir,
-                                lightColor.rgb, fZero, Roughness, sigma, kappa, ndotv,
-                                directDiffuse,  directSpecular);
-        #else
-            float hdotv = PBR_ComputeDirectLight(
-                                normal, lightDir.xyz, viewDir,
-                                lightColor.rgb, fZero, Roughness, ndotv,
-                                directDiffuse,  directSpecular);
-        #endif
+    // Create a blank PBRSurface.
+    PBRSurface surface = PBRLightingUtils_createPBRSurface(worldViewDir);
+    
+    // Read surface data from standard PBR matParams. (note: matParams are declared in 'PBRLighting.j3md' and initialized as uniforms in 'PBRLightingUtils.glsllib')
+    PBRLightingUtils_readPBRSurface(surface);          
 
-        vec3 directLighting = diffuseColor.rgb *directDiffuse + directSpecular;
-        
-        gl_FragColor.rgb += directLighting * fallOff;
+    //Calculate necessary variables from pbr surface prior to applying lighting. Ensure all texture/param reading and blending occurrs prior to this being called!
+    PBRLightingUtils_calculatePreLightingValues(surface);
+    
+    // Calculate direct lights
+    for(int i = 0;i < NB_LIGHTS; i+=3){
+        vec4 lightData0 = g_LightData[i];
+        vec4 lightData1 = g_LightData[i+1];
+        vec4 lightData2 = g_LightData[i+2];    
+        PBRLightingUtils_computeDirectLightContribution(
+          lightData0, lightData1, lightData2, 
+          surface
+        );
     }
 
-    #if NB_PROBES >= 1
-        vec3 color1 = vec3(0.0);
-        vec3 color2 = vec3(0.0);
-        vec3 color3 = vec3(0.0);
-        float weight1 = 1.0;
-        float weight2 = 0.0;
-        float weight3 = 0.0;
 
-        float ndf = renderProbe(viewDir, wPosition, normal, norm, Roughness, diffuseColor, specularColor, ndotv, ao, g_LightProbeData, g_ShCoeffs, g_PrefEnvMap, color1);
-        #if NB_PROBES >= 2
-            float ndf2 = renderProbe(viewDir, wPosition, normal, norm, Roughness, diffuseColor, specularColor, ndotv, ao, g_LightProbeData2, g_ShCoeffs2, g_PrefEnvMap2, color2);
-        #endif
-        #if NB_PROBES == 3
-            float ndf3 = renderProbe(viewDir, wPosition, normal, norm, Roughness, diffuseColor, specularColor, ndotv, ao, g_LightProbeData3, g_ShCoeffs3, g_PrefEnvMap3, color3);
-        #endif
+    // Calculate env probes
+    PBRLightingUtils_computeProbesContribution(surface);
 
-        #if NB_PROBES >= 2
-            float invNdf =  max(1.0 - ndf,0.0);
-            float invNdf2 =  max(1.0 - ndf2,0.0);
-            float sumNdf = ndf + ndf2;
-            float sumInvNdf = invNdf + invNdf2;
-            #if NB_PROBES == 3
-                float invNdf3 = max(1.0 - ndf3,0.0);
-                sumNdf += ndf3;
-                sumInvNdf += invNdf3;
-                weight3 =  ((1.0 - (ndf3 / sumNdf)) / (NB_PROBES - 1)) *  (invNdf3 / sumInvNdf);
-            #endif
-
-            weight1 = ((1.0 - (ndf / sumNdf)) / (NB_PROBES - 1)) *  (invNdf / sumInvNdf);
-            weight2 = ((1.0 - (ndf2 / sumNdf)) / (NB_PROBES - 1)) *  (invNdf2 / sumInvNdf);
-
-            float weightSum = weight1 + weight2 + weight3;
-
-            weight1 /= weightSum;
-            weight2 /= weightSum;
-            weight3 /= weightSum;
-        #endif
-
-        #ifdef USE_AMBIENT_LIGHT
-            color1.rgb *= g_AmbientLightColor.rgb;
-            color2.rgb *= g_AmbientLightColor.rgb;
-            color3.rgb *= g_AmbientLightColor.rgb;
-        #endif
-        gl_FragColor.rgb += color1 * clamp(weight1,0.0,1.0) + color2 * clamp(weight2,0.0,1.0) + color3 * clamp(weight3,0.0,1.0);
-
-    #endif
-
-    #if defined(EMISSIVE) || defined (EMISSIVEMAP)
-        #ifdef EMISSIVEMAP
-            vec4 emissive = texture2D(m_EmissiveMap, newTexCoord);
-            #ifdef EMISSIVE
-                emissive *= m_Emissive;
-            #endif
-        #else
-            vec4 emissive = m_Emissive;
-        #endif
-        gl_FragColor += emissive * pow(emissive.a, m_EmissivePower) * m_EmissiveIntensity;
+    // Put it all together
+    gl_FragColor.rgb = vec3(0.0);
+    gl_FragColor.rgb += surface.bakedLightContribution;
+    gl_FragColor.rgb += surface.directLightContribution;
+    gl_FragColor.rgb += surface.envLightContribution;
+    gl_FragColor.rgb += surface.emission;
+    gl_FragColor.a = surface.alpha;    
+
+    #ifdef USE_FOG
+        gl_FragColor = MaterialFog_calculateFogColor(vec4(gl_FragColor));
     #endif
-    gl_FragColor.a = alpha;
-   
+    
+   //outputs the final value of the selected layer as a color for debug purposes. 
+    #ifdef DEBUG_VALUES_MODE
+        gl_FragColor = PBRLightingUtils_getColorOutputForDebugMode(m_DebugValuesMode, vec4(gl_FragColor.rgba), surface);
+    #endif   
 }

+ 32 - 0
jme3-core/src/main/resources/Common/MatDefs/Light/PBRLighting.j3md

@@ -132,6 +132,29 @@ MaterialDef PBR Lighting {
         Boolean UseVertexColor
 
         Boolean BackfaceShadows : false
+
+        Boolean UseFog
+        Color FogColor
+        Vector2 LinearFog
+        Float ExpFog
+        Float ExpSqFog
+
+        Texture2D SunLightExposureMap
+        Boolean UseVertexColorsAsSunIntensity
+        Float StaticSunIntensity
+        Boolean BrightenIndoorShadows  //should be set true when shadows are enabled, in order to prevent areas with low SunExposure from being way too dark when shadows are cast
+
+         // debug the final value of the selected layer as a color output            
+        Int DebugValuesMode
+            // Layers:
+            //   0 - albedo (un-shaded)
+            //   1 - normals
+            //   2 - roughness
+            //   3 - metallic
+            //   4 - ao
+            //   5  - emissive
+            //   6 - exposure
+            //   7 - alpha
     }
 
     Technique {
@@ -182,6 +205,15 @@ MaterialDef PBR Lighting {
             NUM_MORPH_TARGETS: NumberOfMorphTargets
             NUM_TARGETS_BUFFERS: NumberOfTargetsBuffers
             HORIZON_FADE: HorizonFade
+            EXPOSUREMAP : SunLightExposureMap
+            USE_VERTEX_COLORS_AS_SUN_INTENSITY : UseVertexColorsAsSunIntensity
+            STATIC_SUN_INTENSITY : StaticSunIntensity
+            BRIGHTEN_INDOOR_SHADOWS : BrightenIndoorShadows
+            DEBUG_VALUES_MODE : DebugValuesMode        
+            USE_FOG : UseFog
+            FOG_LINEAR : LinearFog
+            FOG_EXP : ExpFog
+            FOG_EXPSQ : ExpSqFog
         }
     }
 

+ 39 - 19
jme3-core/src/main/resources/Common/MatDefs/Light/PBRLighting.vert

@@ -4,12 +4,13 @@
 #import "Common/ShaderLib/MorphAnim.glsllib"
 
 uniform vec4 m_BaseColor;
+
 uniform vec4 g_AmbientLightColor;
 varying vec2 texCoord;
 
 #ifdef SEPARATE_TEXCOORD
-  varying vec2 texCoord2;
-  attribute vec2 inTexCoord2;
+   varying vec2 texCoord2;
+   attribute vec2 inTexCoord2;
 #endif
 
 varying vec4 Color;
@@ -18,25 +19,41 @@ attribute vec3 inPosition;
 attribute vec2 inTexCoord;
 attribute vec3 inNormal;
 
-#ifdef VERTEX_COLOR
-  attribute vec4 inColor;
+#if defined (VERTEX_COLOR) || defined(USE_VERTEX_COLORS_AS_SUN_INTENSITY)
+    attribute vec4 inColor;
+#endif
+
+#if defined(USE_VERTEX_COLORS_AS_SUN_INTENSITY)
+    varying vec4 vertColors;
 #endif
 
 varying vec3 wNormal;
 varying vec3 wPosition;
-#if defined(NORMALMAP) || defined(PARALLAXMAP)
-    attribute vec4 inTangent;
-    varying vec4 wTangent;
+
+varying vec4 lPosition;
+
+attribute vec4 inTangent;
+varying vec4 wTangent;
+
+#ifdef USE_FOG
+    varying float fogDistance;
+    uniform vec3 g_CameraPosition;
 #endif
 
-void main(){
+void main(){    
+    
     vec4 modelSpacePos = vec4(inPosition, 1.0);
     vec3 modelSpaceNorm = inNormal;
-
-    #if  ( defined(NORMALMAP) || defined(PARALLAXMAP)) && !defined(VERTEX_LIGHTING)
-         vec3 modelSpaceTan  = inTangent.xyz;
+    vec3 modelSpaceTan  = inTangent.xyz;
+    
+    lPosition = modelSpacePos;
+    
+    
+    #ifdef USE_VERTEX_COLORS_AS_SUN_INTENSITY
+        vertColors = inColor;
     #endif
 
+    
     #ifdef NUM_MORPH_TARGETS
          #if defined(NORMALMAP) && !defined(VERTEX_LIGHTING)
             Morph_Compute(modelSpacePos, modelSpaceNorm, modelSpaceTan);
@@ -47,9 +64,9 @@ void main(){
 
     #ifdef NUM_BONES
          #if defined(NORMALMAP) && !defined(VERTEX_LIGHTING)
-            Skinning_Compute(modelSpacePos, modelSpaceNorm, modelSpaceTan);
+         Skinning_Compute(modelSpacePos, modelSpaceNorm, modelSpaceTan);
          #else
-            Skinning_Compute(modelSpacePos, modelSpaceNorm);
+         Skinning_Compute(modelSpacePos, modelSpaceNorm);
          #endif
     #endif
 
@@ -59,16 +76,19 @@ void main(){
        texCoord2 = inTexCoord2;
     #endif
 
-    wPosition = TransformWorld(modelSpacePos).xyz;
+    wPosition = (g_WorldMatrix * vec4(inPosition, 1.0)).xyz;
     wNormal  = TransformWorldNormal(modelSpaceNorm);
-
-    #if defined(NORMALMAP) || defined(PARALLAXMAP)
-      wTangent = vec4(TransformWorldNormal(modelSpaceTan),inTangent.w);
-    #endif
+    
+    wTangent = vec4(TransformWorldNormal(modelSpaceTan),inTangent.w);
 
     Color = m_BaseColor;
     
-    #ifdef VERTEX_COLOR                    
+    #ifdef VERTEX_COLOR                
         Color *= inColor;
     #endif
+    
+    #ifdef USE_FOG
+        fogDistance = distance(g_CameraPosition, (g_WorldMatrix * modelSpacePos).xyz);
+    #endif
+
 }

+ 0 - 73
jme3-core/src/main/resources/Common/MatDefs/Light/modular/PBRLighting.frag

@@ -1,73 +0,0 @@
-#import "Common/ShaderLib/GLSLCompat.glsllib"
-
-// enable apis and import PBRLightingUtils
-#define ENABLE_PBRLightingUtils_getWorldPosition 1
-#define ENABLE_PBRLightingUtils_getWorldNormal 1
-#define ENABLE_PBRLightingUtils_getWorldTangent 1
-#define ENABLE_PBRLightingUtils_getTexCoord 1
-#define ENABLE_PBRLightingUtils_readPBRSurface 1
-#define ENABLE_PBRLightingUtils_computeDirectLightContribution 1
-#define ENABLE_PBRLightingUtils_computeProbesContribution 1
-
-#import "Common/ShaderLib/module/pbrlighting/PBRLightingUtils.glsllib"
-
-#ifdef DEBUG_VALUES_MODE
-    uniform int m_DebugValuesMode;
-#endif
-
-uniform vec4 g_LightData[NB_LIGHTS];
-uniform vec3 g_CameraPosition;
-
-void main(){
-    vec3 wpos = PBRLightingUtils_getWorldPosition();
-    vec3 worldViewDir = normalize(g_CameraPosition - wpos);
-    
-    // Load surface data
-    PBRSurface surface=PBRLightingUtils_readPBRSurface(worldViewDir);
-    
-    // Calculate direct lights
-    for(int i = 0;i < NB_LIGHTS; i+=3){
-        vec4 lightData0 = g_LightData[i];
-        vec4 lightData1 = g_LightData[i+1];
-        vec4 lightData2 = g_LightData[i+2];    
-        PBRLightingUtils_computeDirectLightContribution(
-          lightData0, lightData1, lightData2, 
-          surface
-        );
-    }
-
-
-    // Calculate env probes
-    PBRLightingUtils_computeProbesContribution(surface);
-
-    // Put it all together
-    gl_FragColor.rgb = vec3(0.0);
-    gl_FragColor.rgb += surface.bakedLightContribution;
-    gl_FragColor.rgb += surface.directLightContribution;
-    gl_FragColor.rgb += surface.envLightContribution;
-    gl_FragColor.rgb += surface.emission;
-    gl_FragColor.a = surface.alpha;
-
-  
-    // outputs the final value of the selected layer as a color for debug purposes. 
-    #ifdef DEBUG_VALUES_MODE
-        if(m_DebugValuesMode == 0){
-            gl_FragColor.rgb = vec3(surface.albedo);
-        }
-        else if(m_DebugValuesMode == 1){
-            gl_FragColor.rgb = vec3(surface.normal);
-        }
-        else if(m_DebugValuesMode == 2){
-            gl_FragColor.rgb = vec3(surface.roughness);
-        }
-        else if(m_DebugValuesMode == 3){
-            gl_FragColor.rgb = vec3(surface.metallic);
-        }
-        else if(m_DebugValuesMode == 4){
-            gl_FragColor.rgb = surface.ao.rgb;
-        }
-        else if(m_DebugValuesMode == 5){
-            gl_FragColor.rgb = vec3(surface.emission.rgb);          
-        }        
-    #endif   
-}

+ 0 - 321
jme3-core/src/main/resources/Common/MatDefs/Light/modular/PBRLighting.j3md

@@ -1,321 +0,0 @@
-MaterialDef PBR Lighting {
-
-    MaterialParameters {
-        Int BoundDrawBuffer
-
-        // Alpha threshold for fragment discarding
-        Float AlphaDiscardThreshold (AlphaTestFallOff)
-
-        //metallicity of the material
-        Float Metallic : 1.0
-        //Roughness of the material
-        Float Roughness : 1.0        
-        // Base material color
-        Color BaseColor : 1.0 1.0 1.0 1.0
-        // The emissive color of the object
-        Color Emissive        
-        // the emissive power
-        Float EmissivePower : 3.0        
-        // the emissive intensity
-        Float EmissiveIntensity : 2.0
-
-        // BaseColor map
-        Texture2D BaseColorMap
-
-        // Metallic map
-        Texture2D MetallicMap -LINEAR
-        
-        // Roughness Map
-        Texture2D RoughnessMap -LINEAR
-
-        //Metallic and Roughness are packed respectively in the b and g channel of a single map
-        // r: AO (if AoPackedInMRMap is true)
-        // g: Roughness
-        // b: Metallic
-        Texture2D MetallicRoughnessMap -LINEAR
-        
-        // Texture of the emissive parts of the material
-        Texture2D EmissiveMap
-
-        // Normal map
-        Texture2D NormalMap -LINEAR
-        // The scalar parameter applied to each normal vector of the normal map
-        Float NormalScale
-
-        //The type of normal map: -1.0 (DirectX), 1.0 (OpenGl)
-        Float NormalType : -1.0
-
-        // For Spec gloss pipeline
-        Boolean UseSpecGloss
-        Texture2D SpecularMap
-        Texture2D GlossinessMap
-        Texture2D SpecularGlossinessMap
-        Color Specular : 1.0 1.0 1.0 1.0
-        Float Glossiness : 1.0
-
-        // Parallax/height map
-        Texture2D ParallaxMap -LINEAR
-
-        // Specular-AA
-        Boolean UseSpecularAA : true
-        // screen space variance,Use the slider to set the strength of the geometric specular anti-aliasing effect between 0 and 1. Higher values produce a blurrier result with less aliasing.
-        Float SpecularAASigma
-        // clamping threshold,Use the slider to set a maximum value for the offset that HDRP subtracts from the smoothness value to reduce artifacts.
-        Float SpecularAAKappa
-
-        //Set to true if parallax map is stored in the alpha channel of the normal map
-        Boolean PackedNormalParallax   
-
-        //Sets the relief height for parallax mapping
-        Float ParallaxHeight : 0.05       
-
-        //Set to true to activate Steep Parallax mapping
-        Boolean SteepParallax
-
-        //Horizon fade
-        Boolean HorizonFade
-
-        // Set to Use Lightmap
-        Texture2D LightMap
-
-        // A scalar multiplier controlling the amount of occlusion applied.
-        // A value of `0.0` means no occlusion. A value of `1.0` means full occlusion.
-        Float AoStrength
-
-        // Set to use TexCoord2 for the lightmap sampling
-        Boolean SeparateTexCoord
-        // the light map is a grayscale ao map, only the r channel will be read.
-        Boolean LightMapAsAOMap
-        Boolean AoPackedInMRMap
-        //shadows
-        Int FilterMode
-        Boolean HardwareShadows
-
-        Texture2D ShadowMap0
-        Texture2D ShadowMap1
-        Texture2D ShadowMap2
-        Texture2D ShadowMap3
-        //pointLights
-        Texture2D ShadowMap4
-        Texture2D ShadowMap5
-        
-        Float ShadowIntensity
-        Vector4 Splits
-        Vector2 FadeInfo
-
-        Matrix4 LightViewProjectionMatrix0
-        Matrix4 LightViewProjectionMatrix1
-        Matrix4 LightViewProjectionMatrix2
-        Matrix4 LightViewProjectionMatrix3
-        //pointLight
-        Matrix4 LightViewProjectionMatrix4
-        Matrix4 LightViewProjectionMatrix5   
-        Vector3 LightPos
-        Vector3 LightDir
-
-        Float PCFEdge
-        Float ShadowMapSize
-
-        // For hardware skinning
-        Int NumberOfBones
-        Matrix4Array BoneMatrices
-
-        // For Morph animation
-        FloatArray MorphWeights
-        Int NumberOfMorphTargets
-        Int NumberOfTargetsBuffers
-                
-        // For instancing
-        Boolean UseInstancing
-
-        // For Vertex Color
-        Boolean UseVertexColor
-
-        Boolean BackfaceShadows : false
-
-        Boolean UseVertexColorsAsSunIntensity
-        Float StaticSunIntensity
-        Boolean BrightenIndoorShadows
-    
-        Int DebugValuesMode
-            // debugs the final value of the selected layer as a color output:         
-            // Layers:
-            //   0 - albedo (unshaded)
-            //   1 - normals
-            //   2 - roughness
-            //   3 - metallic
-            //   4 - ao
-            //   5 - emissive
-    }
-
-    Technique {
-        LightMode SinglePassAndImageBased
-        
-        VertexShader GLSL300 GLSL150 GLSL110:   Common/MatDefs/Light/modular/PBRLighting.vert
-        FragmentShader GLSL300 GLSL150 GLSL110: Common/MatDefs/Light/modular/PBRLighting.frag
-
-        WorldParameters {
-            WorldViewProjectionMatrix
-            CameraPosition
-            WorldMatrix
-            WorldNormalMatrix
-            ViewProjectionMatrix
-            ViewMatrix
-        }
-
-        Defines {  
-            BOUND_DRAW_BUFFER: BoundDrawBuffer       
-            BASECOLORMAP : BaseColorMap            
-            NORMALMAP : NormalMap
-            NORMALSCALE : NormalScale
-            METALLICMAP : MetallicMap
-            ROUGHNESSMAP : RoughnessMap
-            EMISSIVEMAP : EmissiveMap
-            EMISSIVE : Emissive
-            SPECGLOSSPIPELINE : UseSpecGloss
-            PARALLAXMAP : ParallaxMap
-            NORMALMAP_PARALLAX : PackedNormalParallax
-            STEEP_PARALLAX : SteepParallax
-            LIGHTMAP : LightMap
-            SEPARATE_TEXCOORD : SeparateTexCoord
-            DISCARD_ALPHA : AlphaDiscardThreshold                        
-            NUM_BONES : NumberOfBones                        
-            INSTANCING : UseInstancing
-            USE_PACKED_MR: MetallicRoughnessMap
-            USE_PACKED_SG: SpecularGlossinessMap
-            SPECULARMAP : SpecularMap
-            SPECULAR_AA : UseSpecularAA
-            SPECULAR_AA_SCREEN_SPACE_VARIANCE : SpecularAASigma
-            SPECULAR_AA_THRESHOLD : SpecularAAKappa
-            GLOSSINESSMAP : GlossinessMap
-            NORMAL_TYPE: NormalType
-            VERTEX_COLOR : UseVertexColor
-            AO_MAP: LightMapAsAOMap
-            AO_PACKED_IN_MR_MAP : AoPackedInMRMap
-            AO_STRENGTH : AoStrength
-            NUM_MORPH_TARGETS: NumberOfMorphTargets
-            NUM_TARGETS_BUFFERS: NumberOfTargetsBuffers
-            HORIZON_FADE: HorizonFade
-            USE_VERTEX_COLORS_AS_SUN_INTENSITY : UseVertexColorsAsSunIntensity
-            STATIC_SUN_INTENSITY : StaticSunIntensity
-            BRIGHTEN_INDOOR_SHADOWS : BrightenIndoorShadows
-            DEBUG_VALUES_MODE : DebugValuesMode
-        }
-    }
-
-
-    Technique PreShadow {
-
-        VertexShader   GLSL300 GLSL150 GLSL100:   Common/MatDefs/Shadow/PreShadow.vert
-        FragmentShader GLSL300 GLSL150 GLSL100: Common/MatDefs/Shadow/PreShadowPBR.frag
-
-        WorldParameters {
-            WorldViewProjectionMatrix
-            WorldViewMatrix
-            ViewProjectionMatrix
-            ViewMatrix
-        }
-
-        Defines {
-            BOUND_DRAW_BUFFER: BoundDrawBuffer
-            DISCARD_ALPHA : AlphaDiscardThreshold
-            NUM_BONES : NumberOfBones
-            INSTANCING : UseInstancing
-            NUM_MORPH_TARGETS: NumberOfMorphTargets
-            NUM_TARGETS_BUFFERS: NumberOfTargetsBuffers
-        }
-
-        ForcedRenderState {
-            FaceCull Off
-            DepthTest On
-            DepthWrite On
-            PolyOffset 5 3
-            ColorWrite Off
-        }
-
-    }
-
-
-    Technique PostShadow {
-        VertexShader   GLSL310 GLSL300 GLSL150 GLSL100:   Common/MatDefs/Shadow/PostShadow.vert
-        FragmentShader GLSL310 GLSL300 GLSL150 GLSL100: Common/MatDefs/Shadow/PostShadowPBR.frag
-
-        WorldParameters {
-            WorldViewProjectionMatrix
-            WorldMatrix
-            ViewProjectionMatrix
-            ViewMatrix
-        }
-
-        Defines {
-            BOUND_DRAW_BUFFER: BoundDrawBuffer
-            HARDWARE_SHADOWS : HardwareShadows
-            FILTER_MODE : FilterMode
-            PCFEDGE : PCFEdge
-            DISCARD_ALPHA : AlphaDiscardThreshold           
-            SHADOWMAP_SIZE : ShadowMapSize
-            FADE : FadeInfo
-            PSSM : Splits
-            POINTLIGHT : LightViewProjectionMatrix5
-            NUM_BONES : NumberOfBones
-            INSTANCING : UseInstancing
-            BACKFACE_SHADOWS: BackfaceShadows
-            NUM_MORPH_TARGETS: NumberOfMorphTargets
-            NUM_TARGETS_BUFFERS: NumberOfTargetsBuffers
-        }
-
-        ForcedRenderState {
-            Blend Modulate
-            DepthWrite Off                 
-            PolyOffset -0.1 0
-        }
-    }
-
-    Technique PreNormalPass {
-
-        VertexShader   GLSL300 GLSL150 GLSL100 :   Common/MatDefs/SSAO/normal.vert
-        FragmentShader GLSL300 GLSL150 GLSL100 : Common/MatDefs/SSAO/normal.frag
-
-        WorldParameters {
-            WorldViewProjectionMatrix
-            WorldViewMatrix
-            NormalMatrix
-            ViewProjectionMatrix
-            ViewMatrix
-        }
-
-        Defines {
-            BOUND_DRAW_BUFFER: BoundDrawBuffer
-            BASECOLORMAP_ALPHA : BaseColorMap            
-            NUM_BONES : NumberOfBones
-            INSTANCING : UseInstancing
-            NUM_MORPH_TARGETS: NumberOfMorphTargets
-            NUM_TARGETS_BUFFERS: NumberOfTargetsBuffers
-        }
-
-    }
-
-    Technique Glow {
-
-        VertexShader   GLSL300 GLSL150 GLSL100:   Common/MatDefs/Misc/Unshaded.vert
-        FragmentShader GLSL300 GLSL150 GLSL100: Common/MatDefs/Light/PBRGlow.frag
-
-        WorldParameters {
-            WorldViewProjectionMatrix
-            ViewProjectionMatrix
-            ViewMatrix
-        }
-
-        Defines {
-            HAS_EMISSIVEMAP : EmissiveMap
-            HAS_EMISSIVECOLOR : Emissive
-            BOUND_DRAW_BUFFER: BoundDrawBuffer
-            NEED_TEXCOORD1
-            NUM_BONES : NumberOfBones
-            INSTANCING : UseInstancing
-            NUM_MORPH_TARGETS: NumberOfMorphTargets
-            NUM_TARGETS_BUFFERS: NumberOfTargetsBuffers
-        }
-    }
-
-}

+ 0 - 75
jme3-core/src/main/resources/Common/MatDefs/Light/modular/PBRLighting.vert

@@ -1,75 +0,0 @@
-#import "Common/ShaderLib/GLSLCompat.glsllib"
-#import "Common/ShaderLib/Instancing.glsllib"
-#import "Common/ShaderLib/Skinning.glsllib"
-#import "Common/ShaderLib/MorphAnim.glsllib"
-
-uniform vec4 m_BaseColor;
-uniform vec4 g_AmbientLightColor;
-varying vec2 texCoord;
-
-#ifdef SEPARATE_TEXCOORD
-  varying vec2 texCoord2;
-  attribute vec2 inTexCoord2;
-#endif
-
-varying vec4 Color;
-
-attribute vec3 inPosition;
-attribute vec2 inTexCoord;
-attribute vec3 inNormal;
-
-#if defined (VERTEX_COLOR) || defined(USE_VERTEX_COLORS_AS_SUN_INTENSITY)
-    attribute vec4 inColor;
-#endif
-
-#if defined(USE_VERTEX_COLORS_AS_SUN_INTENSITY)
-    varying vec4 vertColors;
-#endif
-
-varying vec3 wNormal;
-varying vec3 wPosition;
-
-attribute vec4 inTangent;
-varying vec4 wTangent;
-
-void main(){
-    vec4 modelSpacePos = vec4(inPosition, 1.0);
-    vec3 modelSpaceNorm = inNormal;
-    vec3 modelSpaceTan  = inTangent.xyz;
-
-    #ifdef USE_VERTEX_COLORS_AS_SUN_INTENSITY
-        vertColors = inColor;
-    #endif
-
-    #ifdef NUM_MORPH_TARGETS
-         #if defined(NORMALMAP) && !defined(VERTEX_LIGHTING)
-            Morph_Compute(modelSpacePos, modelSpaceNorm, modelSpaceTan);
-         #else
-            Morph_Compute(modelSpacePos, modelSpaceNorm);
-         #endif
-    #endif
-
-    #ifdef NUM_BONES
-         #if defined(NORMALMAP) && !defined(VERTEX_LIGHTING)
-            Skinning_Compute(modelSpacePos, modelSpaceNorm, modelSpaceTan);
-         #else
-            Skinning_Compute(modelSpacePos, modelSpaceNorm);
-         #endif
-    #endif
-
-    gl_Position = TransformWorldViewProjection(modelSpacePos);
-    texCoord = inTexCoord;
-    #ifdef SEPARATE_TEXCOORD
-       texCoord2 = inTexCoord2;
-    #endif
-
-    wPosition = TransformWorld(modelSpacePos).xyz;
-    wNormal  = TransformWorldNormal(modelSpaceNorm);
-    wTangent = vec4(TransformWorldNormal(modelSpaceTan),inTangent.w);
-
-    Color = m_BaseColor;
-    
-    #ifdef VERTEX_COLOR                    
-        Color *= inColor;
-    #endif
-}

+ 51 - 16
jme3-core/src/main/resources/Common/ShaderLib/MaterialFog.glsllib

@@ -1,25 +1,60 @@
+#ifndef __MATERIAL_FOG_UTIL__
+    #define __MATERIAL_FOG_UTIL__
 
-vec4 getFogLinear(in vec4 diffuseColor, in vec4 fogColor, in float start, in float end, in float distance) {
 
-    float fogFactor = (end - distance) / (end - start);
-    fogFactor = clamp(fogFactor, 0.0, 1.0);
+    vec4 getFogLinear(in vec4 diffuseColor, in vec4 fogColor, in float start, in float end, in float distance) {
 
-    return mix(fogColor, diffuseColor, fogFactor);
-}
+        float fogFactor = (end - distance) / (end - start);
+        fogFactor = clamp(fogFactor, 0.0, 1.0);
 
-vec4 getFogExp(in vec4 diffuseColor, in vec4 fogColor, in float fogDensity, in float distance) {
+        return mix(fogColor, diffuseColor, fogFactor);
+    }
 
-    float fogFactor = 1.0 / exp(distance * fogDensity);
-    fogFactor = clamp( fogFactor, 0.0, 1.0 );
+    vec4 getFogExp(in vec4 diffuseColor, in vec4 fogColor, in float fogDensity, in float distance) {
 
-    return mix(fogColor, diffuseColor, fogFactor);
-}
+        float fogFactor = 1.0 / exp(distance * fogDensity);
+        fogFactor = clamp( fogFactor, 0.0, 1.0 );
 
-vec4 getFogExpSquare(in vec4 diffuseColor, in vec4 fogColor, in float fogDensity, in float distance) {
+        return mix(fogColor, diffuseColor, fogFactor);
+    }
 
-    float fogFactor = 1.0 / exp( (distance * fogDensity) * (distance * fogDensity));
-    fogFactor = clamp( fogFactor, 0.0, 1.0 );
+    vec4 getFogExpSquare(in vec4 diffuseColor, in vec4 fogColor, in float fogDensity, in float distance) {
 
-    vec4 finalColor = mix(fogColor, diffuseColor, fogFactor);
-    return finalColor;
-}
+        float fogFactor = 1.0 / exp( (distance * fogDensity) * (distance * fogDensity));
+        fogFactor = clamp( fogFactor, 0.0, 1.0 );
+
+        vec4 finalColor = mix(fogColor, diffuseColor, fogFactor);
+        return finalColor;
+    }
+
+    #if defined(USE_FOG)
+        uniform vec4 m_FogColor;
+        varying float fogDistance;
+
+        uniform vec2 m_LinearFog;
+
+        #ifdef FOG_EXP
+            uniform float m_ExpFog;
+        #endif
+
+        #ifdef FOG_EXPSQ
+            uniform float m_ExpSqFog;        
+        #endif
+        
+
+        vec4 MaterialFog_calculateFogColor(in vec4 fragColor){
+            #ifdef FOG_LINEAR
+                fragColor = getFogLinear(fragColor, m_FogColor, m_LinearFog.x, m_LinearFog.y, fogDistance);
+            #endif
+            #ifdef FOG_EXP
+                fragColor = getFogExp(fragColor, m_FogColor, m_ExpFog, fogDistance);
+            #endif
+            #ifdef FOG_EXPSQ
+                fragColor = getFogExpSquare(fragColor, m_FogColor, m_ExpSqFog, fogDistance);
+            #endif
+
+            return fragColor;
+        }           
+
+    #endif   
+#endif

+ 109 - 104
jme3-core/src/main/resources/Common/ShaderLib/NoiseLib.glsllib

@@ -1,107 +1,112 @@
-//2d noise functions
-float rand(float n){return fract(sin(n) * 43758.5453123);}
-float rand(vec2 n) { 
-	return fract(sin(dot(n, vec2(12.9898, 4.1414))) * 43758.5453);
-}
-
-float noise(vec2 n) {
-	const vec2 d = vec2(0.0, 1.0);
-  vec2 b = floor(n), f = smoothstep(vec2(0.0), vec2(1.0), fract(n));
-	return mix(mix(rand(b), rand(b + d.yx), f.x), mix(rand(b + d.xy), rand(b + d.yy), f.x), f.y);
-}
-
-
-float prand(vec2 c){
-	return fract(sin(dot(c.xy ,vec2(12.9898,78.233))) * 43758.5453);
-}
-
-float pnoise(vec2 p, float freqPct){
-	//float unit = circ/freq;
-        float unit = freqPct;
-
-	vec2 ij = floor(p/unit);
-	vec2 xy = mod(p,unit)/unit;
-	//xy = 3.*xy*xy-2.*xy*xy*xy;
-	xy = .5*(1.-cos(3.1415926535*xy));
-	float a = prand((ij+vec2(0.,0.)));
-	float b = prand((ij+vec2(1.,0.)));
-	float c = prand((ij+vec2(0.,1.)));
-	float d = prand((ij+vec2(1.,1.)));
-	float x1 = mix(a, b, xy.x);
-	float x2 = mix(c, d, xy.x);
-	return mix(x1, x2, xy.y);
-}
-    
-float rand2D(in vec2 co){
-    return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
-}
-
-// - - - - 
-
-//3d noise functions
-float rand3D(in vec3 co){
-    return fract(sin(dot(co.xyz ,vec3(12.9898,78.233,144.7272))) * 43758.5453);
-}
-    
-float simple_interpolate(in float a, in float b, in float x)
-{
-   return a + smoothstep(0.0,1.0,x) * (b-a);
-}
-float interpolatedNoise3D(in float x, in float y, in float z)
-{
-    float integer_x = x - fract(x);
-    float fractional_x = x - integer_x;
-
-    float integer_y = y - fract(y);
-    float fractional_y = y - integer_y;
-
-    float integer_z = z - fract(z);
-    float fractional_z = z - integer_z;
-
-    float v1 = rand3D(vec3(integer_x, integer_y, integer_z));
-    float v2 = rand3D(vec3(integer_x+1.0, integer_y, integer_z));
-    float v3 = rand3D(vec3(integer_x, integer_y+1.0, integer_z));
-    float v4 = rand3D(vec3(integer_x+1.0, integer_y +1.0, integer_z));
-
-    float v5 = rand3D(vec3(integer_x, integer_y, integer_z+1.0));
-    float v6 = rand3D(vec3(integer_x+1.0, integer_y, integer_z+1.0));
-    float v7 = rand3D(vec3(integer_x, integer_y+1.0, integer_z+1.0));
-    float v8 = rand3D(vec3(integer_x+1.0, integer_y +1.0, integer_z+1.0));
-
-    float i1 = simple_interpolate(v1,v5, fractional_z);
-    float i2 = simple_interpolate(v2,v6, fractional_z);
-    float i3 = simple_interpolate(v3,v7, fractional_z);
-    float i4 = simple_interpolate(v4,v8, fractional_z);
-
-    float ii1 = simple_interpolate(i1,i2,fractional_x);
-    float ii2 = simple_interpolate(i3,i4,fractional_x);
-
-    return simple_interpolate(ii1 , ii2 , fractional_y);
-}
-
-float Noise3D(in vec3 coord, in float wavelength)
-{
-   return interpolatedNoise3D(coord.x/wavelength, coord.y/wavelength, coord.z/wavelength);
-}
-
-
-//used to reference the same float generated by noise for all shaders, so affliction appears to spread and splat naturally
-float getStaticNoiseVar0(vec3 wPos, float afflictionVar){
-    float noiseVar0 = Noise3D(wPos, 28);
-    float noiseVar1 = Noise3D(wPos, 3);
-    float noiseVar2 = Noise3D(wPos, 0.8);
-
-    float noiseVar = ((noiseVar0 + noiseVar1) * 0.4) + (noiseVar2 * 0.2 * afflictionVar);
-
-
-    if(noiseVar > 0.7){
-        noiseVar -= noiseVar2 * 0.07;
-     //   noiseVar = min(noiseVar, 0.3);
+#ifndef __NOISE_UTILS_MODULE__
+    #define __NOISE_UTILS_MODULE__
 
+    //2d noise functions
+    float rand(float n){return fract(sin(n) * 43758.5453123);}
+    float rand(vec2 n) { 
+            return fract(sin(dot(n, vec2(12.9898, 4.1414))) * 43758.5453);
     }
 
-    noiseVar = min(noiseVar, 1.0);
-     noiseVar = max(noiseVar, 0.0);
-    
-    return noiseVar;
-}
+    float noise(vec2 n) {
+            const vec2 d = vec2(0.0, 1.0);
+    vec2 b = floor(n), f = smoothstep(vec2(0.0), vec2(1.0), fract(n));
+            return mix(mix(rand(b), rand(b + d.yx), f.x), mix(rand(b + d.xy), rand(b + d.yy), f.x), f.y);
+    }
+
+
+    float prand(vec2 c){
+            return fract(sin(dot(c.xy ,vec2(12.9898,78.233))) * 43758.5453);
+    }
+
+    float pnoise(vec2 p, float freqPct){
+            //float unit = circ/freq;
+            float unit = freqPct;
+
+            vec2 ij = floor(p/unit);
+            vec2 xy = mod(p,unit)/unit;
+            //xy = 3.*xy*xy-2.*xy*xy*xy;
+            xy = .5*(1.-cos(3.1415926535*xy));
+            float a = prand((ij+vec2(0.,0.)));
+            float b = prand((ij+vec2(1.,0.)));
+            float c = prand((ij+vec2(0.,1.)));
+            float d = prand((ij+vec2(1.,1.)));
+            float x1 = mix(a, b, xy.x);
+            float x2 = mix(c, d, xy.x);
+            return mix(x1, x2, xy.y);
+    }
+
+    float rand2D(in vec2 co){
+        return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
+    }
+
+    // - - - - 
+
+    //3d noise functions
+    float rand3D(in vec3 co){
+        return fract(sin(dot(co.xyz ,vec3(12.9898,78.233,144.7272))) * 43758.5453);
+    }
+
+    float simple_interpolate(in float a, in float b, in float x)
+    {
+       return a + smoothstep(0.0,1.0,x) * (b-a);
+    }
+    float interpolatedNoise3D(in float x, in float y, in float z)
+    {
+        float integer_x = x - fract(x);
+        float fractional_x = x - integer_x;
+
+        float integer_y = y - fract(y);
+        float fractional_y = y - integer_y;
+
+        float integer_z = z - fract(z);
+        float fractional_z = z - integer_z;
+
+        float v1 = rand3D(vec3(integer_x, integer_y, integer_z));
+        float v2 = rand3D(vec3(integer_x+1.0, integer_y, integer_z));
+        float v3 = rand3D(vec3(integer_x, integer_y+1.0, integer_z));
+        float v4 = rand3D(vec3(integer_x+1.0, integer_y +1.0, integer_z));
+
+        float v5 = rand3D(vec3(integer_x, integer_y, integer_z+1.0));
+        float v6 = rand3D(vec3(integer_x+1.0, integer_y, integer_z+1.0));
+        float v7 = rand3D(vec3(integer_x, integer_y+1.0, integer_z+1.0));
+        float v8 = rand3D(vec3(integer_x+1.0, integer_y +1.0, integer_z+1.0));
+
+        float i1 = simple_interpolate(v1,v5, fractional_z);
+        float i2 = simple_interpolate(v2,v6, fractional_z);
+        float i3 = simple_interpolate(v3,v7, fractional_z);
+        float i4 = simple_interpolate(v4,v8, fractional_z);
+
+        float ii1 = simple_interpolate(i1,i2,fractional_x);
+        float ii2 = simple_interpolate(i3,i4,fractional_x);
+
+        return simple_interpolate(ii1 , ii2 , fractional_y);
+    }
+
+    float Noise3D(in vec3 coord, in float wavelength)
+    {
+       return interpolatedNoise3D(coord.x/wavelength, coord.y/wavelength, coord.z/wavelength);
+    }
+
+
+    //used to reference the same float generated by noise for all shaders, so afflictionness appears to spread and splat naturally
+    float getStaticNoiseVar0(vec3 wPos, float afflictionVar){
+        float noiseVar0 = Noise3D(wPos, 28);
+        float noiseVar1 = Noise3D(wPos, 3);
+        float noiseVar2 = Noise3D(wPos, 0.8);
+
+        float noiseVar = ((noiseVar0 + noiseVar1) * 0.4) + (noiseVar2 * 0.2 * afflictionVar);
+
+
+        if(noiseVar > 0.7){
+            noiseVar -= noiseVar2 * 0.07;
+         //   noiseVar = min(noiseVar, 0.3);
+
+        }
+
+        noiseVar = min(noiseVar, 1.0);
+        noiseVar = max(noiseVar, 0.0);
+
+        return noiseVar;
+    }
+
+#endif

+ 21 - 0
jme3-core/src/main/resources/Common/ShaderLib/TangentUtils.glsllib

@@ -0,0 +1,21 @@
+#ifndef __TANGENT_UTILS_MODULE__
+    #define __TANGENT_UTILS_MODULE__
+
+    //used for calculating tangents in-shader
+   
+
+    //primarily used for terrains, since jme terrains do not store pre-calculated tangents by default (thus the tbnMat cannot be used for PBR light calculation like it is in jme's stock PBR shader)
+    vec3 calculateTangentsAndApplyToNormals(in vec3 normalIn, in vec3 worldNorm){
+        vec3 returnNorm = normalize((normalIn.xyz * vec3(2.0) - vec3(1.0)));
+
+        vec3 baseNorm = worldNorm.rgb + vec3(0, 0, 1);
+        returnNorm *= vec3(-1, -1, 1);
+        returnNorm = baseNorm.rgb*dot(baseNorm.rgb, returnNorm.rgb)/baseNorm.z - returnNorm.rgb;
+
+        returnNorm = normalize(returnNorm);
+
+
+        return returnNorm;
+    }
+
+#endif

+ 34 - 0
jme3-core/src/main/resources/Common/ShaderLib/TriPlanarUtils.glsllib

@@ -0,0 +1,34 @@
+#ifndef __TRIPLANAR_UTILS_MODULE__
+    #define __TRIPLANAR_UTILS_MODULE__
+    
+    vec3 triBlending;
+    
+    void TriPlanarUtils_calculateBlending(vec3 geometryNormal){
+        triBlending = abs( geometryNormal );
+        triBlending = (triBlending -0.2) * 0.7;
+        triBlending = normalize(max(triBlending, 0.00001));      // Force weights to sum to 1.0 (very important!)
+        float b = (triBlending.x + triBlending.y + triBlending.z);
+        triBlending /= vec3(b, b, b);
+    }    
+
+    vec4 getTriPlanarBlend(in vec4 coords, in sampler2D map, in float scale) {
+        vec4 col1 = texture2D( map, coords.yz * scale);
+        vec4 col2 = texture2D( map, coords.xz * scale);
+        vec4 col3 = texture2D( map, coords.xy * scale); 
+        // blend the results of the 3 planar projections.
+        vec4 tex = col1 * triBlending.x + col2 * triBlending.y + col3 * triBlending.z;
+
+        return tex;
+    }
+
+    vec4 getTriPlanarBlendFromTexArray(in vec4 coords, in int idInTexArray, in float scale, in sampler2DArray texArray) {
+        vec4 col1 = texture2DArray( texArray, vec3((coords.yz * scale), idInTexArray ) );
+        vec4 col2 = texture2DArray( texArray, vec3((coords.xz * scale), idInTexArray ) );
+        vec4 col3 = texture2DArray( texArray, vec3((coords.xy * scale), idInTexArray ) );
+        // blend the results of the 3 planar projections.
+        vec4 tex = col1 * triBlending.x + col2 * triBlending.y + col3 * triBlending.z;
+
+        return tex;
+    }
+
+#endif

+ 9 - 5
jme3-core/src/main/resources/Common/ShaderLib/module/PBRSurface.glsl

@@ -11,19 +11,23 @@
         bool frontFacing; //gl_FrontFacing
         float depth;
         mat3 tbnMat;
+        bool hasTangents;
 
-        // from texture
+        // from texture/param reads
         vec3 albedo;
         float alpha;
         float metallic;              // metallic value at the surface
         float roughness;
-        vec3 diffuseColor;
-        vec3 specularColor;
-        vec3 fZero;
         vec3 ao;
+        vec3 lightMapColor;
+        bool hasBasicLightMap;
         float exposure;
         vec3 emission;
 
+        //from post param-read calculations
+        vec3 diffuseColor;
+        vec3 specularColor;
+        vec3 fZero;
 
         // computed
         float NdotV;
@@ -33,7 +37,7 @@
         vec3 directLightContribution; // light from direct light sources
         vec3 envLightContribution; // light from environment 
 
-        float brightestLightStrength;
+        float brightestNonGlobalLightStrength;
     #endstruct
     #define PBRSurface StdPBRSurface    
 #endif

+ 553 - 485
jme3-core/src/main/resources/Common/ShaderLib/module/pbrlighting/PBRLightingUtils.glsllib

@@ -1,593 +1,661 @@
 #ifndef __PBR_LIGHT_UTILS_MODULE__
-#define __PBR_LIGHT_UTILS_MODULE__
-
-#import "Common/ShaderLib/Math.glsllib"
-#import "Common/ShaderLib/PBR.glsllib"
-#import "Common/ShaderLib/Parallax.glsllib"
-
-#import "Common/ShaderLib/module/Light.glsl"
-#import "Common/ShaderLib/module/PBRSurface.glsl"
-
-// enable all apis
-// #define ENABLE_PBRLightingUtils_getWorldPosition 1
-// #define ENABLE_PBRLightingUtils_getWorldNormal 1
-// #define ENABLE_PBRLightingUtils_getWorldTangent 1
-// #define ENABLE_PBRLightingUtils_getTexCoord 1
-// #define ENABLE_PBRLightingUtils_newLight 1
-// #define ENABLE_PBRLightingUtils_computeLightInWorldSpace 1
-// #define ENABLE_PBRLightingUtils_readPBRSurface 1
-// #define ENABLE_PBRLightingUtils_computeDirectLight 1
-// #define ENABLE_PBRLightingUtils_computeDirectLightContribution 1
-// #define ENABLE_PBRLightingUtils_computeProbesContribution 1
-
-#if defined(ENABLE_PBRLightingUtils_readPBRSurface)||defined(ENABLE_PBRLightingUtils_getWorldPosition)
-    varying vec3 wPosition;
-#endif 
-
-#if defined(ENABLE_PBRLightingUtils_readPBRSurface)||defined(ENABLE_PBRLightingUtils_getWorldNormal)
-    varying vec3 wNormal;
-#endif 
-
-#if (defined(ENABLE_PBRLightingUtils_readPBRSurface)&&(defined(NORMALMAP)||defined(PARALLAXMAP)))||defined(ENABLE_PBRLightingUtils_getWorldTangent)
-    varying vec4 wTangent;
-#endif 
-
-#if defined(ENABLE_PBRLightingUtils_readPBRSurface)||defined(ENABLE_PBRLightingUtils_getTexCoord)
-    varying vec2 texCoord;
-    #ifdef SEPARATE_TEXCOORD
-        varying vec2 texCoord2;
-    #endif
-#endif
-
+    #define __PBR_LIGHT_UTILS_MODULE__
 
+    #import "Common/ShaderLib/Math.glsllib"
+    #import "Common/ShaderLib/PBR.glsllib"
+    #import "Common/ShaderLib/Parallax.glsllib"
 
-#ifdef ENABLE_PBRLightingUtils_readPBRSurface   
-    varying vec4 Color;
+    #import "Common/ShaderLib/module/Light.glsl"
+    #import "Common/ShaderLib/module/PBRSurface.glsl"
     
-    uniform vec4 g_AmbientLightColor;   
-    uniform float m_Roughness;
-    uniform float m_Metallic;
+    // enable all apis
+    // #define ENABLE_PBRLightingUtils_getWorldPosition 1
+    // #define ENABLE_PBRLightingUtils_getLocalPosition 1
+    // #define ENABLE_PBRLightingUtils_getWorldNormal 1
+    // #define ENABLE_PBRLightingUtils_getWorldTangent 1
+    // #define ENABLE_PBRLightingUtils_getTexCoord 1
+    // #define ENABLE_PBRLightingUtils_newLight 1
+    // #define ENABLE_PBRLightingUtils_computeLightInWorldSpace 1
+    // #define ENABLE_PBRLightingUtils_readPBRSurface 1
+    // #define ENABLE_PBRLightingUtils_computeDirectLight 1
+    // #define ENABLE_PBRLightingUtils_computeDirectLightContribution 1
+    // #define ENABLE_PBRLightingUtils_computeProbesContribution 1
+
+    #if defined(ENABLE_PBRLightingUtils_readPBRSurface)||defined(ENABLE_PBRLightingUtils_getWorldPosition)
+        varying vec3 wPosition;
+    #endif 
 
+    #if defined(ENABLE_PBRLightingUtils_readPBRSurface)||defined(ENABLE_PBRLightingUtils_getWorldNormal)
+        varying vec3 wNormal;
+    #endif 
 
-    #ifdef BASECOLORMAP
-        uniform sampler2D m_BaseColorMap;
-    #endif
+    #if (defined(ENABLE_PBRLightingUtils_readPBRSurface)&&(defined(NORMALMAP)||defined(PARALLAXMAP)))||defined(ENABLE_PBRLightingUtils_getWorldTangent)
+        varying vec4 wTangent;
+    #endif 
 
-    #ifdef USE_PACKED_MR
-        uniform sampler2D m_MetallicRoughnessMap;
-    #else
-        #ifdef METALLICMAP
-            uniform sampler2D m_MetallicMap;
-        #endif
-        #ifdef ROUGHNESSMAP
-            uniform sampler2D m_RoughnessMap;
+    #if defined(ENABLE_PBRLightingUtils_readPBRSurface)||defined(ENABLE_PBRLightingUtils_getTexCoord)
+        varying vec2 texCoord;
+        #ifdef SEPARATE_TEXCOORD
+            varying vec2 texCoord2;
         #endif
     #endif
-
-    #ifdef EMISSIVE
-        uniform vec4 m_Emissive;
-    #endif
-    #ifdef EMISSIVEMAP
-        uniform sampler2D m_EmissiveMap;
-    #endif
-    #if defined(EMISSIVE) || defined(EMISSIVEMAP)
-        uniform float m_EmissivePower;
-        uniform float m_EmissiveIntensity;
+    
+    #if defined(ENABLE_PBRLightingUtils_getLocalPosition)
+        varying vec4 lPosition;
     #endif 
 
 
 
-    #ifdef SPECGLOSSPIPELINE
-        uniform vec4 m_Specular;
-        uniform float m_Glossiness;
-        #ifdef USE_PACKED_SG
-            uniform sampler2D m_SpecularGlossinessMap;
+    #ifdef ENABLE_PBRLightingUtils_readPBRSurface   
+        varying vec4 Color;
+
+        uniform float m_Roughness;
+        uniform float m_Metallic;
+
+
+        #ifdef BASECOLORMAP
+            uniform sampler2D m_BaseColorMap;
+        #endif
+
+        #ifdef USE_PACKED_MR
+            uniform sampler2D m_MetallicRoughnessMap;
         #else
-            uniform sampler2D m_SpecularMap;
-            uniform sampler2D m_GlossinessMap;
+            #ifdef METALLICMAP
+                uniform sampler2D m_MetallicMap;
+            #endif
+            #ifdef ROUGHNESSMAP
+                uniform sampler2D m_RoughnessMap;
+            #endif
         #endif
-    #endif
 
-    #ifdef PARALLAXMAP
-        uniform sampler2D m_ParallaxMap;  
-    #endif
-    #if (defined(PARALLAXMAP) || (defined(NORMALMAP_PARALLAX) && defined(NORMALMAP)))
-        uniform float m_ParallaxHeight;
-    #endif
+        #ifdef EMISSIVE
+            uniform vec4 m_Emissive;
+        #endif
+        #ifdef EMISSIVEMAP
+            uniform sampler2D m_EmissiveMap;
+        #endif
+        #if defined(EMISSIVE) || defined(EMISSIVEMAP)
+            uniform float m_EmissivePower;
+            uniform float m_EmissiveIntensity;
+        #endif 
 
-    #ifdef LIGHTMAP
-        uniform sampler2D m_LightMap;
-    #endif
 
-    #ifdef AO_STRENGTH
-        uniform float m_AoStrength;
-    #endif
-    
-    #if defined(NORMALMAP) || defined(PARALLAXMAP)
-        uniform sampler2D m_NormalMap;       
-    #endif
-    #ifdef NORMALSCALE
-        uniform float m_NormalScale;
-    #endif
 
-    #ifdef DISCARD_ALPHA
-        uniform float m_AlphaDiscardThreshold;
-    #endif
+        #ifdef SPECGLOSSPIPELINE
+            uniform vec4 m_Specular;
+            uniform float m_Glossiness;
+            #ifdef USE_PACKED_SG
+                uniform sampler2D m_SpecularGlossinessMap;
+            #else
+                uniform sampler2D m_SpecularMap;
+                uniform sampler2D m_GlossinessMap;
+            #endif
+        #endif
 
-    #if defined(USE_VERTEX_COLORS_AS_SUN_INTENSITY)
-        varying vec4 vertColors;
-    #endif
-    #ifdef STATIC_SUN_INTENSITY
-        uniform float m_StaticSunIntensity;
-    #endif
+        #ifdef PARALLAXMAP
+            uniform sampler2D m_ParallaxMap;  
+        #endif
+        #if (defined(PARALLAXMAP) || (defined(NORMALMAP_PARALLAX) && defined(NORMALMAP)))
+            uniform float m_ParallaxHeight;
+        #endif
 
-#endif
+        #ifdef LIGHTMAP
+            uniform sampler2D m_LightMap;
+        #endif
 
-#if defined(ENABLE_PBRLightingUtils_computeDirectLight) || defined(ENABLE_PBRLightingUtils_computeDirectLightContribution)
-    // Specular-AA
-    #ifdef SPECULAR_AA_SCREEN_SPACE_VARIANCE
-        uniform float m_SpecularAASigma;
-    #endif
-    #ifdef SPECULAR_AA_THRESHOLD
-        uniform float m_SpecularAAKappa;
+        #ifdef AO_STRENGTH
+            uniform float m_AoStrength;
+        #endif
+
+        #if defined(NORMALMAP) || defined(PARALLAXMAP)
+            uniform sampler2D m_NormalMap;       
+        #endif
+        #ifdef NORMALSCALE
+            uniform float m_NormalScale;
+        #endif
+        
+        #ifdef DISCARD_ALPHA
+            uniform float m_AlphaDiscardThreshold;
+        #endif        
     #endif
-#endif
 
+    #if defined(ENABLE_PBRLightingUtils_computeDirectLight) || defined(ENABLE_PBRLightingUtils_computeDirectLightContribution)
+    
+        // Specular-AA
+        #ifdef SPECULAR_AA_SCREEN_SPACE_VARIANCE
+            uniform float m_SpecularAASigma;
+        #endif
+        #ifdef SPECULAR_AA_THRESHOLD
+            uniform float m_SpecularAAKappa;
+        #endif
+        
+        // DirectionalLight Exposure
+        #if defined(EXPOSUREMAP)
+            uniform sampler2D m_SunLightExposureMap;
+        #endif
+        #if defined(USE_VERTEX_COLORS_AS_SUN_EXPOSURE)
+            varying vec4 vertColors;
+        #endif
+        #ifdef STATIC_SUN_EXPOSURE
+            uniform float m_StaticSunIntensity;
+        #endif
+        
+        void PBRLightingUtils_readSunLightExposureParams(inout PBRSurface surface){
+            
+            surface.exposure = 1.0; //default value
+            #ifdef EXPOSUREMAP
+                surface.exposure *= texture2D(m_SunLightExposureMap, newTexCoord;
+            #endif
+            #ifdef STATIC_SUN_EXPOSURE
+                surface.exposure *= m_StaticSunIntensity; //single float value to indicate percentage of sunlight hitting the model (only suitable for small models or models with equal sunlight exposure accross the entire model
+            #endif
+            #ifdef USE_VERTEX_COLORS_AS_SUN_EXPOSURE
+                surface.exposure *= vertColors.r;    // use red channel of vertexColors for non-uniform sunlighting accross a single model                          
+            #endif 
+        }    
+
+    #endif
 
 
+    
+    #ifdef ENABLE_PBRLightingUtils_computeProbesContribution
+        #if NB_PROBES >= 1
+            uniform samplerCube g_PrefEnvMap;
+            uniform vec3 g_ShCoeffs[9];
+            uniform mat4 g_LightProbeData;
+        #endif
+        #if NB_PROBES >= 2
+            uniform samplerCube g_PrefEnvMap2;
+            uniform vec3 g_ShCoeffs2[9];
+            uniform mat4 g_LightProbeData2;
+        #endif
+        #if NB_PROBES == 3
+            uniform samplerCube g_PrefEnvMap3;
+            uniform vec3 g_ShCoeffs3[9];
+            uniform mat4 g_LightProbeData3;
+        #endif
+    #endif
 
-#ifdef ENABLE_PBRLightingUtils_computeProbesContribution
-    #if NB_PROBES >= 1
-        uniform samplerCube g_PrefEnvMap;
-        uniform vec3 g_ShCoeffs[9];
-        uniform mat4 g_LightProbeData;
+    #ifdef ENABLE_PBRLightingUtils_getWorldPosition
+        vec3 PBRLightingUtils_getWorldPosition(){
+            return wPosition.xyz;
+        }
     #endif
-    #if NB_PROBES >= 2
-        uniform samplerCube g_PrefEnvMap2;
-        uniform vec3 g_ShCoeffs2[9];
-        uniform mat4 g_LightProbeData2;
+
+    #ifdef ENABLE_PBRLightingUtils_getWorldNormal
+        vec3 PBRLightingUtils_getWorldNormal(){
+            return normalize(wNormal.xyz);
+        }
     #endif
-    #if NB_PROBES == 3
-        uniform samplerCube g_PrefEnvMap3;
-        uniform vec3 g_ShCoeffs3[9];
-        uniform mat4 g_LightProbeData3;
+
+    #ifdef ENABLE_PBRLightingUtils_getWorldTangent
+        vec4 PBRLightingUtils_getWorldTangent(){
+            return wTangent;
+        }
     #endif
-#endif
 
-#ifdef ENABLE_PBRLightingUtils_getWorldPosition
-    vec3 PBRLightingUtils_getWorldPosition(){
-        return wPosition.xyz;
-    }
-#endif
+    #ifdef ENABLE_PBRLightingUtils_getTexCoord
+        vec2 PBRLightingUtils_getTexCoord(){
+            return texCoord;
+        }
 
-#ifdef ENABLE_PBRLightingUtils_getWorldNormal
-    vec3 PBRLightingUtils_getWorldNormal(){
-        return normalize(wNormal.xyz);
-    }
-#endif
+        #ifdef SEPARATE_TEXCOORD
+            vec2 PBRLightingUtils_getTexCoord2(){
+                return texCoord2;
+            }
+        #endif
+    #endif
 
-#ifdef ENABLE_PBRLightingUtils_getWorldTangent
-    vec4 PBRLightingUtils_getWorldTangent(){
-        return wTangent;
-    }
-#endif
 
-#ifdef ENABLE_PBRLightingUtils_getTexCoord
-    vec2 PBRLightingUtils_getTexCoord(){
-        return texCoord;
-    }
 
-    #ifdef SEPARATE_TEXCOORD
-        vec2 PBRLightingUtils_getTexCoord2(){
-            return texCoord2;
+    #if defined(ENABLE_PBRLightingUtils_computeDirectLightContribution) || defined(ENABLE_PBRLightingUtils_newLight)
+        Light PBRLightingUtils_newLight(vec4 color, vec3 position, float type, float invRadius, float spotAngleCos, vec3 spotDirection){
+            Light l;
+            l.color = color;
+            l.position = position;
+            l.type = type;
+            l.invRadius = invRadius;
+            l.spotAngleCos = spotAngleCos;
+            l.spotDirection = spotDirection;
+            l.ready = false;
+            return l;
         }
     #endif
-#endif
-
-
-
-#if defined(ENABLE_PBRLightingUtils_computeDirectLightContribution) || defined(ENABLE_PBRLightingUtils_newLight)
-    Light PBRLightingUtils_newLight(vec4 color, vec3 position, float type, float invRadius, float spotAngleCos, vec3 spotDirection){
-        Light l;
-        l.color = color;
-        l.position = position;
-        l.type = type;
-        l.invRadius = invRadius;
-        l.spotAngleCos = spotAngleCos;
-        l.spotDirection = spotDirection;
-        l.ready = false;
-        return l;
-    }
-#endif
 
 
-#if  defined(ENABLE_PBRLightingUtils_computeDirectLightContribution) || defined(ENABLE_PBRLightingUtils_computeLightInWorldSpace)
-    void PBRLightingUtils_computeLightInWorldSpace(vec3 worldPos,vec3 worldNormal, vec3 viewDir, inout Light light){
-        if(light.ready) return;
+    #if  defined(ENABLE_PBRLightingUtils_computeDirectLightContribution) || defined(ENABLE_PBRLightingUtils_computeLightInWorldSpace)
+        void PBRLightingUtils_computeLightInWorldSpace(vec3 worldPos,vec3 worldNormal, vec3 viewDir, inout Light light){
+            if(light.ready) return;
 
-        // lightComputeDir
-        float posLight = step(0.5, light.type);     
-        light.vector = light.position.xyz * sign(posLight - 0.5) - (worldPos * posLight); //tempVec lightVec
+            // lightComputeDir
+            float posLight = step(0.5, light.type);     
+            light.vector = light.position.xyz * sign(posLight - 0.5) - (worldPos * posLight); //tempVec lightVec
 
-        vec3 L; // lightDir
-        float dist;
-        Math_lengthAndNormalize(light.vector,dist,L);
+            vec3 L; // lightDir
+            float dist;
+            Math_lengthAndNormalize(light.vector,dist,L);
 
-        float invRange=light.invRadius; // position.w
-        const float light_threshold=0.01;
+            float invRange=light.invRadius; // position.w
+            const float light_threshold=0.01;
 
-        #ifdef SRGB
-            light.fallOff = (1.0 - invRange * dist) / (1.0 + invRange * dist * dist); // lightDir.w
-            light.fallOff = clamp(light.fallOff, 1.0 - posLight, 1.0);
-        #else
-            light.fallOff = clamp(1.0 - invRange * dist * posLight, 0.0, 1.0);
-        #endif
-        
-        // computeSpotFalloff
-        if(light.type>1.){
-            vec3 spotdir = normalize(light.spotDirection);
-            float curAngleCos = dot(-L, spotdir);    
-            float innerAngleCos = floor(light.spotAngleCos) * 0.001;
-            float outerAngleCos = fract(light.spotAngleCos);
-            float innerMinusOuter = innerAngleCos - outerAngleCos;
-            float falloff = clamp((curAngleCos - outerAngleCos) / innerMinusOuter, 0.0, 1.0);
             #ifdef SRGB
-                // Use quadratic falloff (notice the ^4)
-                falloff = pow(clamp((curAngleCos - outerAngleCos) / innerMinusOuter, 0.0, 1.0), 4.0);
+                light.fallOff = (1.0 - invRange * dist) / (1.0 + invRange * dist * dist); // lightDir.w
+                light.fallOff = clamp(light.fallOff, 1.0 - posLight, 1.0);
+            #else
+                light.fallOff = clamp(1.0 - invRange * dist * posLight, 0.0, 1.0);
             #endif
-            light.fallOff*=falloff;
-        }
 
+            // computeSpotFalloff
+            if(light.type>1.){
+                vec3 spotdir = normalize(light.spotDirection);
+                float curAngleCos = dot(-L, spotdir);    
+                float innerAngleCos = floor(light.spotAngleCos) * 0.001;
+                float outerAngleCos = fract(light.spotAngleCos);
+                float innerMinusOuter = innerAngleCos - outerAngleCos;
+                float falloff = clamp((curAngleCos - outerAngleCos) / innerMinusOuter, 0.0, 1.0);
+                #ifdef SRGB
+                    // Use quadratic falloff (notice the ^4)
+                    falloff = pow(clamp((curAngleCos - outerAngleCos) / innerMinusOuter, 0.0, 1.0), 4.0);
+                #endif
+                light.fallOff*=falloff;
+            }
 
-        vec3 h=normalize(L+viewDir);
-        light.dir=L;
-        light.NdotL = max(dot(worldNormal, L), 0.0);
-        light.NdotH = max(dot(worldNormal, h), 0.0);
-        light.LdotH = max(dot(L, h), 0.0);
-        light.HdotV = max(dot(viewDir,h), 0.);
-    }
-#endif
 
+            vec3 h=normalize(L+viewDir);
+            light.dir=L;
+            light.NdotL = max(dot(worldNormal, L), 0.0);
+            light.NdotH = max(dot(worldNormal, h), 0.0);
+            light.LdotH = max(dot(L, h), 0.0);
+            light.HdotV = max(dot(viewDir,h), 0.);
+        }
+    #endif
+
+    PBRSurface PBRLightingUtils_createPBRSurface(in vec3 wViewDir){
 
-#ifdef ENABLE_PBRLightingUtils_readPBRSurface
-    PBRSurface PBRLightingUtils_readPBRSurface(    
-        in vec3 wViewDir
-    ){
-        
         PBRSurface surface;
         surface.position = wPosition;
         surface.viewDir = wViewDir;
         surface.geometryNormal = normalize(wNormal);
 
-        surface.bakedLightContribution = vec3(0);
-        surface.directLightContribution = vec3(0);
-        surface.envLightContribution = vec3(0);
+        return surface;
+    }
 
-        #if defined(NORMALMAP) || defined(PARALLAXMAP)
-            vec3 tan = normalize(wTangent.xyz);
-            mat3 tbnMat = mat3(tan, wTangent.w * cross( surface.geometryNormal, tan), surface.geometryNormal);
-            surface.tbnMat = tbnMat;
-        #endif
-        
+    #ifdef ENABLE_PBRLightingUtils_readPBRSurface
         vec2 newTexCoord;
-        #if (defined(PARALLAXMAP) || (defined(NORMALMAP_PARALLAX) && defined(NORMALMAP)))
-            vec3 vViewDir =  wViewDir * tbnMat;  
-            #ifdef STEEP_PARALLAX
-                #ifdef NORMALMAP_PARALLAX
-                    //parallax map is stored in the alpha channel of the normal map         
-                    newTexCoord = steepParallaxOffset(m_NormalMap, vViewDir, texCoord, m_ParallaxHeight);
-                #else
-                    //parallax map is a texture
-                    newTexCoord = steepParallaxOffset(m_ParallaxMap, vViewDir, texCoord, m_ParallaxHeight);         
-                #endif
-            #else
-                #ifdef NORMALMAP_PARALLAX
-                    //parallax map is stored in the alpha channel of the normal map         
-                    newTexCoord = classicParallaxOffset(m_NormalMap, vViewDir, texCoord, m_ParallaxHeight);
-                #else
-                //parallax map is a texture
-                newTexCoord = classicParallaxOffset(m_ParallaxMap, vViewDir, texCoord, m_ParallaxHeight);
-            #endif
-        #endif
-        #else
-        newTexCoord = texCoord;    
-        #endif
-        
-        #ifdef BASECOLORMAP
-            vec4 baseColor = texture2D(m_BaseColorMap, newTexCoord) * Color;
-        #else
-            vec4 baseColor = Color;
-        #endif
         
-        #ifdef DISCARD_ALPHA
-            if( baseColor.a < m_AlphaDiscardThreshold) discard;        
-        #endif
+        void PBRLightingUtils_readPBRSurface(inout PBRSurface surface){
 
-        surface.albedo = baseColor.rgb;
-        surface.alpha = baseColor.a;
+            surface.bakedLightContribution = vec3(0);
+            surface.directLightContribution = vec3(0);
+            surface.envLightContribution = vec3(0);
 
-        
+            #ifdef ENABLE_PBRLightingUtils_getWorldTangent
+                vec3 tan = normalize(wTangent.xyz); 
+                surface.tbnMat = mat3(tan, wTangent.w * cross( surface.geometryNormal, tan), surface.geometryNormal);
+                surface.hasTangents = true;
+            #endif
 
-        //ao in r channel, roughness in green channel, metallic in blue channel!
-        vec3 aoRoughnessMetallicValue = vec3(1.0, 1.0, 0.0);
-        #ifdef USE_PACKED_MR
-            aoRoughnessMetallicValue = texture2D(m_MetallicRoughnessMap, newTexCoord).rgb;
-            surface.roughness = aoRoughnessMetallicValue.g * max(m_Roughness, 1e-4);
-            surface.metallic = aoRoughnessMetallicValue.b * max(m_Metallic, 0.0);
-        #else
-            #ifdef ROUGHNESSMAP
-                surface.roughness = texture2D(m_RoughnessMap, newTexCoord).r * max(m_Roughness, 1e-4);
-            #else
-                surface.roughness =  max(m_Roughness, 1e-4);
+            
+            #if (defined(PARALLAXMAP) || (defined(NORMALMAP_PARALLAX) && defined(NORMALMAP)))
+                vec3 vViewDir =  wViewDir * surface.tbnMat;  
+                #ifdef STEEP_PARALLAX
+                    #ifdef NORMALMAP_PARALLAX
+                        //parallax map is stored in the alpha channel of the normal map         
+                        newTexCoord = steepParallaxOffset(m_NormalMap, vViewDir, texCoord, m_ParallaxHeight);
+                    #else
+                        //parallax map is a texture
+                        newTexCoord = steepParallaxOffset(m_ParallaxMap, vViewDir, texCoord, m_ParallaxHeight);         
+                    #endif
+                #else
+                    #ifdef NORMALMAP_PARALLAX
+                        //parallax map is stored in the alpha channel of the normal map         
+                        newTexCoord = classicParallaxOffset(m_NormalMap, vViewDir, texCoord, m_ParallaxHeight);
+                    #else
+                    //parallax map is a texture
+                    newTexCoord = classicParallaxOffset(m_ParallaxMap, vViewDir, texCoord, m_ParallaxHeight);
+                #endif
             #endif
-            #ifdef METALLICMAP
-                surface.metallic = texture2D(m_MetallicMap, newTexCoord).r * max(m_Metallic, 0.0);
             #else
-                surface.metallic =  max(m_Metallic, 0.0);
+            newTexCoord = texCoord;    
             #endif
-        #endif
-    
 
-        
-        #if defined(NORMALMAP)
-            vec4 normalHeight = texture2D(m_NormalMap, newTexCoord);
-            // Note we invert directx style normal maps to opengl style
-            #ifdef NORMALSCALE
-                vec3 normal = normalize((normalHeight.xyz * vec3(2.0, NORMAL_TYPE * 2.0, 2.0) - vec3(1.0, NORMAL_TYPE * 1.0, 1.0)) * vec3(m_NormalScale, m_NormalScale, 1.0));
+            #ifdef BASECOLORMAP
+                vec4 baseColor = texture2D(m_BaseColorMap, newTexCoord) * Color;
             #else
-                vec3 normal = normalize((normalHeight.xyz * vec3(2.0, NORMAL_TYPE * 2.0, 2.0) - vec3(1.0, NORMAL_TYPE * 1.0, 1.0)));
+                vec4 baseColor = Color;
             #endif
-            surface.normal = normalize(tbnMat * normal);
-        #else 
-            surface.normal = surface.geometryNormal;
-        #endif
-        
-        //spec gloss tex reads:
-        
-        #ifdef SPECGLOSSPIPELINE
-            #ifdef USE_PACKED_SG
-                vec4 specularColor = texture2D(m_SpecularGlossinessMap, newTexCoord);
-                float glossiness = specularColor.a * m_Glossiness;
-                specularColor *= m_Specular;
+
+            #ifdef DISCARD_ALPHA
+                if( baseColor.a < m_AlphaDiscardThreshold) discard;        
+            #endif
+
+            surface.albedo = baseColor.rgb;
+            surface.alpha = baseColor.a;
+
+            //ao in r channel, roughness in green channel, metallic in blue channel!
+            vec3 aoRoughnessMetallicValue = vec3(1.0, 1.0, 0.0);
+            #ifdef USE_PACKED_MR
+                aoRoughnessMetallicValue = texture2D(m_MetallicRoughnessMap, newTexCoord).rgb;
+                surface.roughness = aoRoughnessMetallicValue.g * max(m_Roughness, 1e-4);
+                surface.metallic = aoRoughnessMetallicValue.b * max(m_Metallic, 0.0);
             #else
-                #ifdef SPECULARMAP
-                    vec4 specularColor = texture2D(m_SpecularMap, newTexCoord);
+                #ifdef ROUGHNESSMAP
+                    surface.roughness = texture2D(m_RoughnessMap, newTexCoord).r * max(m_Roughness, 1e-4);
                 #else
-                    vec4 specularColor = vec4(1.0);
+                    surface.roughness =  max(m_Roughness, 1e-4);
                 #endif
-                #ifdef GLOSSINESSMAP
-                    float glossiness = texture2D(m_GlossinesMap, newTexCoord).r * m_Glossiness;
+                #ifdef METALLICMAP
+                    surface.metallic = texture2D(m_MetallicMap, newTexCoord).r * max(m_Metallic, 0.0);
                 #else
-                    float glossiness = m_Glossiness;
+                    surface.metallic =  max(m_Metallic, 0.0);
                 #endif
-                specularColor *= m_Specular;
             #endif
-            surface.diffuseColor = surface.albedo;// * (1.0 - max(max(specularColor.r, specularColor.g), specularColor.b));
-            surface.roughness = 1.0 - glossiness;
-            surface.fZero = specularColor.xyz;
-            surface.specularColor = specularColor;
-        #else
-            float specular = 0.5;
-            float nonMetalSpec = 0.08 * specular;
-            surface.specularColor = (nonMetalSpec - nonMetalSpec * surface.metallic) + surface.albedo * surface.metallic;
-            surface.diffuseColor = surface.albedo - surface.albedo * surface.metallic;
-            surface.fZero = vec3(specular);
-        #endif
-        
 
-        vec3 ao=vec3(1.0);
-        #ifdef LIGHTMAP
-            vec3 lightMapColor;
-            #ifdef SEPARATE_TEXCOORD
-                lightMapColor = texture2D(m_LightMap, texCoord2).rgb;
+
+
+            #if defined(NORMALMAP)
+                vec4 normalHeight = texture2D(m_NormalMap, newTexCoord);
+                // Note we invert directx style normal maps to opengl style
+                #ifdef NORMALSCALE
+                    vec3 normal = normalize((normalHeight.xyz * vec3(2.0, NORMAL_TYPE * 2.0, 2.0) - vec3(1.0, NORMAL_TYPE * 1.0, 1.0)) * vec3(m_NormalScale, m_NormalScale, 1.0));
+                #else
+                    vec3 normal = normalize((normalHeight.xyz * vec3(2.0, NORMAL_TYPE * 2.0, 2.0) - vec3(1.0, NORMAL_TYPE * 1.0, 1.0)));
+                #endif
+                surface.normal = normalize(surface.tbnMat * normal);
             #else
-                lightMapColor = texture2D(m_LightMap, texCoord).rgb;
-            #endif               
-            #ifdef AO_MAP
-                lightMapColor.gb = lightMapColor.rr; 
-                ao = lightMapColor;
-            #else  
-                surface.bakedLightContribution +=  diffuseColor.rgb * lightMapColor;
+                surface.normal = surface.geometryNormal;
             #endif
-            surface.specularColor.rgb *= lightMapColor;
-        #endif
-        
-        #if defined(AO_PACKED_IN_MR_MAP) && defined(USE_PACKED_MR) 
-            ao = aoRoughnessMetallicValue.rrr; //note that this will override the AO value if it was previously read from a lightMap that is being used as AO_Map above. so don't try to use an AO map packed in metallic roughness while also using lightmap as ao map
-        #endif
 
-        #ifdef AO_STRENGTH
-            ao = 1.0 + m_AoStrength * (ao - 1.0);
-            // sanity check
-            ao = clamp(ao, 0.0, 1.0);
-        #endif
-        surface.ao=ao;
-        
-        #if defined(EMISSIVE) || defined (EMISSIVEMAP)
-            #ifdef EMISSIVEMAP
-                vec4 emissive = texture2D(m_EmissiveMap, newTexCoord);
-                #ifdef EMISSIVE
-                    emissive *= m_Emissive;
+            //spec gloss tex reads:
+
+            #ifdef SPECGLOSSPIPELINE
+                #ifdef USE_PACKED_SG
+                    vec4 specularColor = texture2D(m_SpecularGlossinessMap, newTexCoord);
+                    float glossiness = specularColor.a * m_Glossiness;
+                    specularColor *= m_Specular;
+                #else
+                    #ifdef SPECULARMAP
+                        vec4 specularColor = texture2D(m_SpecularMap, newTexCoord);
+                    #else
+                        vec4 specularColor = vec4(1.0);
+                    #endif
+                    #ifdef GLOSSINESSMAP
+                        float glossiness = texture2D(m_GlossinesMap, newTexCoord).r * m_Glossiness;
+                    #else
+                        float glossiness = m_Glossiness;
+                    #endif
+                    specularColor *= m_Specular;
+                    surface.specularColor = specularColor;
                 #endif
-            #else
-                vec4 emissive = m_Emissive;
             #endif
-            surface.emission = emissive.rgb * pow(emissive.a, m_EmissivePower) * m_EmissiveIntensity;
-        #else 
-            surface.emission = vec3(0);
-        #endif
-        
-        #if defined(STATIC_SUN_INTENSITY)
-            surface.exposure = m_StaticSunIntensity; //single float value to indicate percentage of sunlight hitting the model (only suitable for small models or models with equal sunlight exposure accross the entire model
-        #elif defined(USE_VERTEX_COLORS_AS_SUN_INTENSITY)
-            surface.exposure = vertColors.r;    // use red channel of vertexColors for non-uniform sunlighting accross a single model
-        #else 
-            surface.exposure = 1.0; //default value
-        #endif 
-        
-        surface.frontFacing = gl_FrontFacing;
-        surface.depth = gl_FragCoord.z;
 
 
-        // surface.alphaRoughness = clamp(surface.roughness * surface.roughness, minRoughness, 1.0);
-        surface.NdotV = clamp(abs(dot(!surface.frontFacing?-surface.normal:surface.normal, surface.viewDir)), 0.001, 1.0);
-        // surface.reflectedVec = normalize(reflect(-surface.viewDir, surface.normal));
 
-        surface.brightestLightStrength=0.0;
-        return surface;
-    }
-#endif
+            vec3 ao = vec3(1.0);
+            #ifdef LIGHTMAP
+                vec3 lightMapColor;
+                #ifdef SEPARATE_TEXCOORD
+                    lightMapColor = texture2D(m_LightMap, texCoord2).rgb;
+                #else
+                    lightMapColor = texture2D(m_LightMap, texCoord).rgb;
+                #endif               
+                #ifdef AO_MAP
+                    ao = lightMapColor.rrr;
+                #else  
+                    surface.lightMapColor = lightMapColor;
+                    surface.hasBasicLightMap = true;
+                #endif
+            #endif
 
+            #if defined(AO_PACKED_IN_MR_MAP) && defined(USE_PACKED_MR) 
+                ao = aoRoughnessMetallicValue.rrr; //note that this will override the AO value if it was previously read from a lightMap that is being used as AO_Map above. so don't try to use an AO map packed in metallic roughness while also using lightmap as ao map
+            #endif
 
-#if defined(ENABLE_PBRLightingUtils_computeDirectLight) || defined(ENABLE_PBRLightingUtils_computeDirectLightContribution)
-    void PBRLightingUtils_computeDirectLight(in Light light, in PBRSurface surface, inout vec3 directDiffuse, inout vec3 directSpecular, out float hdotv){
+            #ifdef AO_STRENGTH
+                ao = 1.0 + m_AoStrength * (ao - 1.0);
+                // sanity check
+                ao = clamp(ao, 0.0, 1.0);
+            #endif
+            surface.ao = ao;
 
-        #ifdef SPECULAR_AA
-            #ifdef SPECULAR_AA_SCREEN_SPACE_VARIANCE
-                float sigma = m_SpecularAASigma;
+            #if defined(EMISSIVE) || defined (EMISSIVEMAP)
+                #ifdef EMISSIVEMAP
+                    vec4 emissive = texture2D(m_EmissiveMap, newTexCoord);
+                    #ifdef EMISSIVE
+                        emissive *= m_Emissive;
+                    #endif
+                #else
+                    vec4 emissive = m_Emissive;
+                #endif
+                surface.emission = emissive.rgb * pow(emissive.a, m_EmissivePower) * m_EmissiveIntensity;
             #else 
-                float sigma = 1.0;
+                surface.emission = vec3(0);
             #endif
-            
-            #ifdef SPECULAR_AA_THRESHOLD
-                float kappa = m_SpecularAAKappa;
+
+            PBRLightingUtils_readSunLightExposureParams(surface);
+
+            surface.frontFacing = gl_FrontFacing;
+            surface.depth = gl_FragCoord.z;
+
+
+            // surface.alphaRoughness = clamp(surface.roughness * surface.roughness, minRoughness, 1.0);
+            surface.NdotV = clamp(abs(dot(!surface.frontFacing?-surface.normal:surface.normal, surface.viewDir)), 0.001, 1.0);
+            // surface.reflectedVec = normalize(reflect(-surface.viewDir, surface.normal));
+
+            surface.brightestNonGlobalLightStrength = 0.0;
+        }    
+    #endif
+
+
+    #if defined(ENABLE_PBRLightingUtils_computeDirectLight) || defined(ENABLE_PBRLightingUtils_computeDirectLightContribution)
+    
+
+        void PBRLightingUtils_calculatePreLightingValues(inout PBRSurface surface){
+
+            if(surface.hasBasicLightMap == true){ 
+                surface.bakedLightContribution += surface.diffuseColor.rgb * surface.lightMapColor;
+                surface.specularColor.rgb *= surface.lightMapColor;
+            }        
+            surface.specularColor.rgb *= surface.ao;     
+
+            #ifdef SPECGLOSSPIPELINE      
+                surface.diffuseColor = surface.albedo;// * (1.0 - max(max(specularColor.r, specularColor.g), specularColor.b));
+                surface.roughness = 1.0 - m_Glossiness;
+                surface.fZero = surface.specularColor.xyz;
             #else
-                float kappa = 0.18;
-            #endif    
-            
-            hdotv = PBR_ComputeDirectLightWithSpecularAA(
-                                    surface.normal,
-                                    light.dir.xyz, 
-                                    surface.viewDir,
-                                    light.color.rgb, 
-                                    surface.fZero, 
-                                    surface.roughness, 
-                                    sigma,
-                                    kappa, 
-                                    surface.NdotV,
-                                    directDiffuse,  
-                                    directSpecular
-                    );
-        #else
-            hdotv = PBR_ComputeDirectLight(
-                                    surface.normal, 
-                                    light.dir.xyz, 
-                                    surface.viewDir,
-                                    light.color.rgb, 
-                                    surface.fZero, 
-                                    surface.roughness, 
-                                    surface.NdotV,
-                                    directDiffuse,  
-                                    directSpecular
-                    );
-        #endif
+                surface.specularColor = (0.04 - 0.04 * surface.metallic) + surface.albedo * surface.metallic;  // 0.04 is the standard base specular reflectance for non-metallic surfaces in PBR. While values like 0.08 can be used for different implementations, 0.04 aligns with Khronos' PBR specification.
+                surface.diffuseColor = surface.albedo - surface.albedo * surface.metallic;
+                surface.fZero = mix(vec3(0.04), surface.albedo.rgb, surface.metallic);        
+            #endif
+        }
 
-    }
-#endif
+        void PBRLightingUtils_computeDirectLight(in Light light, in PBRSurface surface, inout vec3 directDiffuse, inout vec3 directSpecular, out float hdotv){
 
- 
-#ifdef ENABLE_PBRLightingUtils_computeDirectLightContribution
-    void PBRLightingUtils_computeDirectLightContribution(
-        in vec4 lightData0, 
-        in vec4 lightData1, 
-        in vec4 lightData2,
-        inout PBRSurface surface
-    ){
-        vec4 lightColor = vec4(lightData0.rgb,1.0);
-        float lightType = lightData0.w;  
-
-        vec3 lightPosition = lightData1.xyz;
-        float lightInvRadius = lightData1.w;
-        
-        vec3 spotDirection = lightData2.xyz;
-        float spotAngleCos = lightData2.w;
+            #ifdef SPECULAR_AA
+                #ifdef SPECULAR_AA_SCREEN_SPACE_VARIANCE
+                    float sigma = m_SpecularAASigma;
+                #else 
+                    float sigma = 1.0;
+                #endif
+
+                #ifdef SPECULAR_AA_THRESHOLD
+                    float kappa = m_SpecularAAKappa;
+                #else
+                    float kappa = 0.18;
+                #endif    
+
+                hdotv = PBR_ComputeDirectLightWithSpecularAA(
+                                        surface.normal,
+                                        light.dir.xyz, 
+                                        surface.viewDir,
+                                        light.color.rgb, 
+                                        surface.fZero, 
+                                        surface.roughness, 
+                                        sigma,
+                                        kappa, 
+                                        surface.NdotV,
+                                        directDiffuse,  
+                                        directSpecular
+                        );
+            #else
+                hdotv = PBR_ComputeDirectLight(
+                                        surface.normal, 
+                                        light.dir.xyz, 
+                                        surface.viewDir,
+                                        light.color.rgb, 
+                                        surface.fZero, 
+                                        surface.roughness, 
+                                        surface.NdotV,
+                                        directDiffuse,  
+                                        directSpecular
+                        );
+            #endif
+
+        }
+    #endif
+
+
+    #ifdef ENABLE_PBRLightingUtils_computeDirectLightContribution
+        void PBRLightingUtils_computeDirectLightContribution(
+            in vec4 lightData0, 
+            in vec4 lightData1, 
+            in vec4 lightData2,
+            inout PBRSurface surface
+        ){
+            vec4 lightColor = vec4(lightData0.rgb,1.0);
+            float lightType = lightData0.w;  
+
+            vec3 lightPosition = lightData1.xyz;
+            float lightInvRadius = lightData1.w;
 
-        Light light = PBRLightingUtils_newLight(lightColor, lightPosition, lightType, lightInvRadius, spotAngleCos, spotDirection);
-        PBRLightingUtils_computeLightInWorldSpace(surface.position, surface.normal, surface.viewDir, light);
+            vec3 spotDirection = lightData2.xyz;
+            float spotAngleCos = lightData2.w;
 
-        vec3 directDiffuse;
-        vec3 directSpecular;
-        float hdotv;
-        PBRLightingUtils_computeDirectLight(light, surface, directDiffuse, directSpecular, hdotv); 
+            Light light = PBRLightingUtils_newLight(lightColor, lightPosition, lightType, lightInvRadius, spotAngleCos, spotDirection);
+            PBRLightingUtils_computeLightInWorldSpace(surface.position, surface.normal, surface.viewDir, light);
 
-        vec3 directLighting = surface.diffuseColor.rgb * directDiffuse + directSpecular;
 
-        #if defined(USE_VERTEX_COLORS_AS_SUN_INTENSITY) || defined(STATIC_SUN_INTENSITY)         
+            vec3 directDiffuse;
+            vec3 directSpecular;
+            float hdotv;
+            PBRLightingUtils_computeDirectLight(light, surface, directDiffuse, directSpecular, hdotv); 
+
+            vec3 directLighting = surface.diffuseColor.rgb * directDiffuse + directSpecular;
+
             if(light.fallOff == 1.0){
-                directLighting.rgb *= surface.exposure;//  used to scale down how intense just the sun is indoors, and so the ambientLighting can be scaled back up indoors based on nearest pointlight intensity (ambient and direct light are 1.0 fallOff)                
-            } else{
-                surface.brightestLightStrength = max(light.fallOff, surface.brightestLightStrength);
+                directLighting.rgb *= surface.exposure;// is used to scale down how intense just the sun is indoors, and so the ambientLighting can be scaled back up indoors based on nearest pointlight intensity (ambient and direct light are 1.0 fallOff)                
+            }
+            else{
+                surface.brightestNonGlobalLightStrength = max(light.fallOff, surface.brightestNonGlobalLightStrength);
             }
-        #endif
 
-        surface.directLightContribution.rgb += directLighting * light.fallOff;
-    }
-#endif
+            surface.directLightContribution.rgb += directLighting * light.fallOff;
+        }
+    #endif
 
-#ifdef ENABLE_PBRLightingUtils_computeProbesContribution
-    void PBRLightingUtils_computeProbesContribution(inout PBRSurface surface){   
+    #ifdef ENABLE_PBRLightingUtils_computeProbesContribution
 
-        #ifdef BRIGHTEN_INDOOR_SHADOWS
-            float minVertLighting = 0.0833; //enable this when using shadows, in order to brighten indoor areas (which are naturally covered from the DL shadows) so that indoor areas are not way too dark when using IndoorLighting with shadows compared to when shadows are off
-        #else
-            float minVertLighting = 0.0533;
+        #ifdef USE_AMBIENT_LIGHT
+            uniform vec4 g_AmbientLightColor; 
         #endif
-        
-        float finalLightingScale=1.0;
-        finalLightingScale = max(finalLightingScale, surface.brightestLightStrength);    
-        finalLightingScale = max(finalLightingScale, minVertLighting); //essentially just the vertColors.r (aka indoor light exposure) multiplied by the time of day scale.   
 
+        void PBRLightingUtils_computeProbesContribution(inout PBRSurface surface){   
 
-        #if NB_PROBES > 0
-            float probeNdfSum=0;
-            float invProbeNdfSum=0;    
-            
-            #for i=1..4 ( #if NB_PROBES >= $i $0 #endif )
-                vec3 probeColor$i;
-                float probeNdf$i = renderProbe(
-                    surface.viewDir, 
-                    surface.position, 
-                    surface.normal,
-                    surface.geometryNormal,
-                    surface.roughness,
-                    vec4(surface.diffuseColor,1.0),
-                    vec4(surface.specularColor,1.0), 
-                    surface.NdotV, 
-                    surface.ao, 
-                    #if $i == 1
-                        g_LightProbeData, 
-                    #else  
-                        g_LightProbeData$i,
+            #ifdef BRIGHTEN_INDOOR_SHADOWS
+                float minVertLighting = 0.0833; //enable this when using shadows, in order to brighten indoor areas (which are naturally covered from the DL shadows) so that indoor areas are not way too dark when using IndoorLighting with shadows compared to when shadows are off
+            #else
+                float minVertLighting = 0.0533;
+            #endif
+
+            float finalLightingScale = surface.exposure;
+            finalLightingScale = max(finalLightingScale, surface.brightestNonGlobalLightStrength);    
+            finalLightingScale = max(finalLightingScale, minVertLighting); //essentially just the vertColors.r (aka indoor light exposure) multiplied by the time of day scale.   
+
+
+            #if NB_PROBES > 0
+                float probeNdfSum=0;
+                float invProbeNdfSum=0;    
+
+                #for i=1..4 ( #if NB_PROBES >= $i $0 #endif )
+                    vec3 probeColor$i;
+                    float probeNdf$i = renderProbe(
+                        surface.viewDir, 
+                        surface.position, 
+                        surface.normal,
+                        surface.geometryNormal,
+                        surface.roughness,
+                        vec4(surface.diffuseColor,1.0),
+                        vec4(surface.specularColor,1.0), 
+                        surface.NdotV, 
+                        surface.ao, 
+                        #if $i == 1
+                            g_LightProbeData, 
+                        #else  
+                            g_LightProbeData$i,
+                        #endif
+                        g_ShCoeffs,
+                        g_PrefEnvMap,
+                        probeColor$i
+                    );
+                    float probeInvNdf$i =  max(1.0 - probeNdf$i,0.0);
+                    probeNdfSum += probeNdf$i;
+                    invProbeNdfSum += probeInvNdf$i;
+                    #ifdef USE_AMBIENT_LIGHT
+                        probeColor$i.rgb *= g_AmbientLightColor.rgb;
                     #endif
-                    g_ShCoeffs,
-                    g_PrefEnvMap,
-                    probeColor$i
-                );
-                float probeInvNdf$i =  max(1.0 - probeNdf$i,0.0);
-                probeNdfSum += probeNdf$i;
-                invProbeNdfSum += probeInvNdf$i;
-                #ifdef USE_AMBIENT_LIGHT
-                    probeColor$i.rgb *= g_AmbientLightColor.rgb;
+                    probeColor$i.rgb *= finalLightingScale;
+                #endfor
+
+                #if NB_PROBES > 1
+                    float probeWeightSum=0;
+                    #for i=1..4 ( #if NB_PROBES >= $i $0 #endif )
+                        float probeWeight$i = ((1.0 - (probeNdf$i / probeNdfSum)) / (NB_PROBES - 1)) *  ( probeInvNdf$i / invProbeNdfSum);
+                        probeWeightSum += probeWeight$i;    
+                    #endfor 
+
+                    #for i=1..4 ( #if NB_PROBES >= $i $0 #endif )       
+                        surface.envLightContribution.rgb += probeColor$i * clamp( probeWeight$i / probeWeightSum, 0., 1.);
+                    #endfor 
+                #else
+                    surface.envLightContribution.rgb += probeColor1;
                 #endif
-                probeColor$i.rgb *= finalLightingScale;
-            #endfor
+            #endif
+        }
+    #endif
 
-            #if NB_PROBES > 1
-                float probeWeightSum=0;
-                #for i=1..4 ( #if NB_PROBES >= $i $0 #endif )
-                    float probeWeight$i = ((1.0 - (probeNdf$i / probeNdfSum)) / (NB_PROBES - 1)) *  ( probeInvNdf$i / invProbeNdfSum);
-                    probeWeightSum += probeWeight$i;    
-                #endfor 
 
-                #for i=1..4 ( #if NB_PROBES >= $i $0 #endif )       
-                    surface.envLightContribution.rgb += probeColor$i * clamp( probeWeight$i / probeWeightSum, 0., 1.);
-                #endfor 
-            #else
-                surface.envLightContribution.rgb += probeColor1;
-            #endif
-        #endif
-    }
-#endif
+    vec4 PBRLightingUtils_getColorOutputForDebugMode(in int debugValuesMode, in vec4 finalRenderColor, in PBRSurface surface){
+        vec4 outputColorForLayer = finalRenderColor;
+        if(debugValuesMode == 0){
+            outputColorForLayer.rgb = vec3(surface.albedo);
+        }
+        else if(debugValuesMode == 1){
+            outputColorForLayer.rgb = vec3(surface.normal);
+        }
+        else if(debugValuesMode == 2){
+            outputColorForLayer.rgb = vec3(surface.roughness);
+        }
+        else if(debugValuesMode == 3){
+            outputColorForLayer.rgb = vec3(surface.metallic);
+        }
+        else if(debugValuesMode == 4){
+            outputColorForLayer.rgb = surface.ao.rgb;
+        }
+        else if(debugValuesMode == 5){
+            outputColorForLayer.rgb = vec3(surface.emission.rgb);          
+        }      
+        else if(debugValuesMode == 6){
+            outputColorForLayer.rgb = vec3(surface.exposure);          
+        }  
+        else if(debugValuesMode == 7){
+            outputColorForLayer.rgb = vec3(surface.alpha);          
+        } 
+
+        if(debugValuesMode >= 0){
+            gl_FragColor.a = 1.0;
+        }
 
+        return outputColorForLayer;
+    }
 
 #endif