浏览代码

Modularize PBRLighting

Addresses this issue: https://github.com/jMonkeyEngine/jmonkeyengine/issues/2122

To re-summarize:

This PR extracts all of the texture reads and basematParam assignment into a .glslib file (currently named PBRLightingParamReads.glsllib)

And then it also extracts all of the lighting calculation into a .glslib file (currently named PBRLighting.glsllib)

I also fixed alot of formatting and indentation mistakes, and overall reorganized the shader.

This should now make it as easy as possible for jme devs to fork PBRLighting to make changes, and they will no longer have to update the lighting or texReads to stay on par with master, as all future changes will all be in the glsllibs. This also reduces the chances that a lesser-skilled shader dev (or even skilled shader devs on a bad day) mistakenly mess up the lighting calculations when forking the shader.

Any feedback and review is greatly appreciated.
Ryan McDonough 1 年之前
父节点
当前提交
67cdede9f4
共有 1 个文件被更改,包括 59 次插入341 次删除
  1. 59 341
      jme3-core/src/main/resources/Common/MatDefs/Light/PBRLighting.frag

+ 59 - 341
jme3-core/src/main/resources/Common/MatDefs/Light/PBRLighting.frag

@@ -1,367 +1,85 @@
 #import "Common/ShaderLib/GLSLCompat.glsllib"
-#import "Common/ShaderLib/PBR.glsllib"
-#import "Common/ShaderLib/Parallax.glsllib"
-#import "Common/ShaderLib/Lighting.glsllib"
 
 varying vec2 texCoord;
+vec2 newTexCoord; 
 #ifdef SEPARATE_TEXCOORD
-  varying vec2 texCoord2;
+    varying vec2 texCoord2;
 #endif
 
-varying vec4 Color;
-
-uniform vec4 g_LightData[NB_LIGHTS];
-uniform vec3 g_CameraPosition;
-uniform vec4 g_AmbientLightColor;
+#ifdef DISCARD_ALPHA
+    uniform float m_AlphaDiscardThreshold;
+#endif
 
-uniform float m_Roughness;
-uniform float m_Metallic;
 
 varying vec3 wPosition;    
 
+varying vec3 wNormal;
+varying vec4 wTangent;
 
-#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
+#import "MatDefs/ShaderLib/PBRLightingParamReads.glsllib"
+#import "MatDefs/ShaderLib/PBRLighting.glsllib"
+//Important that these 2 ^ glsllibs are referenced AFTER other variables are declared above. 
+// any variables above are declared there (rather than in a glslib) to reduce rendundancy, because these vars likely to used by more than 1 glslib.
+// Only lighting vars are declared in PBRLighting.glslib, and only basePBR matParams are declared in PBRLightingParamReads.glslib
+//This allows jme devs to fork this shader and make their own changes before the base PBR param-reads or before the final lighting calculation.
+//For example, you could move texCoords based on g_Time prior to texReads for a simple moving water/lava effect. or blend values like albedo/roughness after tex reads but before the final lighting calculations to do things like dynamic texture splatting
 
-#ifdef USE_PACKED_MR
-  uniform sampler2D m_MetallicRoughnessMap;
-#else
-    #ifdef METALLICMAP
-      uniform sampler2D m_MetallicMap;
-    #endif
-    #ifdef ROUGHNESSMAP
-      uniform sampler2D m_RoughnessMap;
-    #endif
-#endif
+vec4 albedo = vec4(1.0);
+float alpha = 1.0;
 
-#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 
+float Metallic = 0.0;
+float Roughness = 0.0;
 
-#ifdef SPECGLOSSPIPELINE
+float emissiveIntensity = 0.0;
+float emissivePower = 0.0;
+vec4 emissive = vec4(0.0);
 
-  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
+vec3 ao = vec3(1.0);
+vec3 lightMapColor = vec3(0.0);
 
-#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
-
-#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;
-#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
-
-#ifdef DISCARD_ALPHA
-  uniform float m_AlphaDiscardThreshold;
-#endif
+float indoorSunLightExposure = 1.0;
 
 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 normal = norm;
+    vec3 viewDir = normalize(g_CameraPosition - wPosition);
     
-    #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
-        float specular = 0.5;
-        float nonMetalSpec = 0.08 * specular;
-        vec4 specularColor = (nonMetalSpec - nonMetalSpec * Metallic) + albedo * Metallic;
-        vec4 diffuseColor = albedo - albedo * Metallic;
-        vec3 fZero = vec3(specular);
-    #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;
+    vec3 tan = normalize(wTangent.xyz);
+    mat3 tbnMat = mat3(tan, wTangent.w * cross( (norm), (tan)), norm); //note: these are intentionaly not surroudned by ifDefs relating to normal and parallax maps being defined, because
+    vec3 vViewDir =  viewDir * tbnMat;                                 //other .glslibs may require normal or parallax mapping even if the base model does not hvae those maps
 
-        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
-
-        vec3 directLighting = diffuseColor.rgb *directDiffuse + directSpecular;
-        
-        gl_FragColor.rgb += directLighting * fallOff;
-    }
-
-    #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
-
-        #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);
+    //base PBR params and tex reads:
+    readMatParamsAndTextures(tbnMat, vViewDir, albedo, Metallic, Roughness, lightMapColor, ao, normal, emissive, alpha);
+    
+    // Lighting calculation:    
+    vec3 finalLightingValue = calculatePBRLighting(albedo, Metallic, Roughness, lightMapColor, ao, indoorSunLightExposure, normal, norm, viewDir);
+    gl_FragColor.rgb += finalLightingValue;
 
-    #endif
+    //apply final emissive value after lighting
+    gl_FragColor += emissive;  //no need for #ifdef check because emissive will be 0,0,0,0 if emissive vars werent defined.
 
-    #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;
-    #endif
     gl_FragColor.a = 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(albedo);
+        }
+        else if(m_DebugValuesMode == 1){
+            gl_FragColor.rgb = vec3(normal);
+        }
+        else if(m_DebugValuesMode == 2){
+            gl_FragColor.rgb = vec3(Roughness);
+        }
+        else if(m_DebugValuesMode == 3){
+            gl_FragColor.rgb = vec3(Metallic);
+        }
+        else if(m_DebugValuesMode == 4){
+            gl_FragColor.rgb = ao.rgb;
+        }
+        else if(m_DebugValuesMode == 5){
+            gl_FragColor.rgb = vec3(emissive.rgb);          
+        }        
+    #endif   
 }