|
@@ -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
|
|
|
}
|