Răsfoiți Sursa

Add files via upload

Ryan McDonough 7 luni în urmă
părinte
comite
b70c9cf0cd

+ 515 - 0
jme3-terrain/src/main/resources/Common/MatDefs/Terrain/Modular/AfflictionLib.glsllib

@@ -0,0 +1,515 @@
+#ifndef __AFFLICTION_LIB__
+    #define __AFFLICTION_LIB__
+    
+    #import "Common/ShaderLib/NoiseLib.glsllib"
+    #import "Common/ShaderLib/TangentUtils.glsllib"
+
+    #import "Common/ShaderLib/TriPlanarUtils.glsllib"
+
+    #ifdef AFFLICTIONTEXTURE
+        uniform sampler2D m_AfflictionAlphaMap;
+    #endif
+    #ifdef AFFLICTIONALBEDOMAP
+        uniform sampler2D m_SplatAlbedoMap ;
+    #endif
+    #ifdef AFFLICTIONNORMALMAP
+        uniform sampler2D m_SplatNormalMap ;
+    #endif
+    #ifdef AFFLICTIONROUGHNESSMETALLICMAP
+        uniform sampler2D m_SplatRoughnessMetallicMap;
+    #endif
+    #ifdef AFFLICTIONEMISSIVEMAP
+        uniform sampler2D m_SplatEmissiveMap;
+    #endif
+    #ifdef USE_SPLAT_NOISE
+         uniform float m_SplatNoiseVar;
+    #endif
+    
+    #ifdef TILELOCATION
+       uniform float m_TileWidth;
+       uniform vec3 m_TileLocation;
+   #endif
+
+
+    uniform int m_AfflictionSplatScale;
+    uniform float m_AfflictionRoughnessValue;
+    uniform float m_AfflictionMetallicValue;
+    uniform float m_AfflictionEmissiveValue;
+    uniform vec4 m_AfflictionEmissiveColor;
+
+
+
+
+    vec4 afflictionVector;
+    float noiseHash;
+    float livelinessValue;
+    float afflictionValue;
+    int afflictionMode = 1;
+
+
+    //temporarily here, move triplanar import + define back to .frag shader soon:
+
+    vec4 desaturate(vec4 albedo, float deathVar){
+
+        vec3 gray = vec3(dot(vec3(0.2126,0.7152,0.0722), albedo.rgb));
+        albedo = vec4(mix(albedo.rgb, gray, deathVar), 0.0);
+
+        return albedo;
+    }
+
+    vec3 alterLiveliness(vec3 color, float liveVal, int mode){
+
+        float deathVar = (1.0 - (liveVal));
+
+    //0 means dont scale to be desaturated (bricks, stones, etc)
+        if(mode > 0){ //1 means almost fully desaturated.. 1 is less alive, and 2 is slightly less, etc etc
+            deathVar -= mode * 0.033;
+
+            deathVar = max(0.0, deathVar);
+            deathVar = min(0.99, deathVar);
+
+            float hueVar = (deathVar) * 0.34;
+            color.r += color.r*hueVar * 1.8;
+            color.g -= color.g*hueVar;
+            color.b -= color.b*hueVar * 5.0 ;
+
+
+            color = desaturate(vec4(color, 1.0), deathVar).rgb;
+
+        }
+
+
+
+        return color;
+
+    }
+
+
+    vec3 alterLiveliness(vec3 color, float livelinessValue){
+
+
+        float deathVar = (1.0 - (livelinessValue));
+
+        float hueVar = (deathVar) * 0.34;
+        color.r += color.r*hueVar * 1.8;
+        color.g -= color.g*hueVar;
+        color.b -= color.b*hueVar*5.0 ;
+
+
+        color = desaturate(vec4(color, 1.0), deathVar).rgb;
+
+
+        return color;
+    }
+
+
+    //methods for death and afflictionness applied to all other types of affliction shaders
+
+
+    vec4 alterBarkLiveliness(vec4 albedo, float livelinessValue){
+        float deathVar = 1.0 - livelinessValue;
+
+        float hueVar = (deathVar) * 0.97;
+        albedo.r += albedo.r*hueVar * 0.21;
+        albedo.g += albedo.g*hueVar*0.84;
+        albedo.b -= albedo.b*hueVar*1.9;
+
+        albedo *= 0.1 + (0.9 * livelinessValue);
+
+        return albedo;
+    }
+
+    vec4 alterPlantLiveliness(vec4 albedo, float livelinessValue){
+        float deathVar = 1.0 - livelinessValue;
+
+        float hueVar = (deathVar) * 0.77;
+        albedo.r += albedo.r*hueVar * 1.8;
+        albedo.g -= albedo.g*hueVar;
+        albedo.b -= albedo.b*hueVar*5.0 ;
+
+        return albedo;
+    }
+
+    vec4 alterStoneLiveliness(vec4 albedo, float livelinessValue){
+        livelinessValue = 0.56 + (0.44 * livelinessValue); //stone and rock has an 80% minimum, and scales up from there
+
+        float deathVar = 1.0 - livelinessValue;
+
+
+        float hueVar = (deathVar);
+        albedo.r += albedo.r*hueVar * 1.2;
+        albedo.g += albedo.g*hueVar;
+        albedo.b -= albedo.b*hueVar*3.14 ;
+
+        albedo = desaturate(albedo, deathVar * 1.7);
+
+
+
+        return albedo;
+    }
+
+    vec3 desaturateVec(vec3 albedo, float deathVar){
+
+        vec3 gray = vec3(dot(vec3(0.2126,0.7152,0.0722), albedo.rgb));
+        albedo = mix(albedo, gray, deathVar);
+
+        return albedo;
+    }
+    vec3 alterStoneLivelinessVar(vec3 albedo, float livelinessValue){
+        livelinessValue = 0.56 + (0.44 * livelinessValue); //stone and rock has an 80% minimum, and scales up from there
+
+        float deathVar = 1.0 - livelinessValue;
+
+
+        float hueVar = (deathVar);
+        albedo.r += albedo.r*hueVar * 1.2;
+        albedo.g += albedo.g*hueVar;
+        albedo.b -= albedo.b*hueVar*3.14 ;
+
+        albedo = desaturateVec(albedo, deathVar * 1.7);
+
+
+
+        return albedo;
+    }
+
+
+
+    //AFFLICTION METHODS
+
+    //adjusts the affliction value for the best visual representation (since 0.0 - 1.0 is not as visually linear as it is numerically)
+    float getAdjustedAfflictionVar(float afflictionVar){
+
+        float adjustedVar = afflictionVar;
+            if(afflictionVar > 0.02){
+                adjustedVar = mix(0.02, 0.53, afflictionVar);
+            }
+            else{
+                adjustedVar = 0;
+            }
+
+        return adjustedVar;
+    }
+
+    float getAfflictionEdgeTaper(float noiseVar, float afflictionVar){
+
+        float amt = noiseVar - (0.4 * afflictionVar) - .04;
+
+        if(amt <= 0.05){
+            amt = 0.05;
+        }
+
+
+        return amt;
+    }
+
+    vec4 alterAfflictionColor(float afflictionVar, vec4 albedo, vec4 afflictionAlbedo, float noiseVar){    
+
+        float originalAlpha = albedo.a;     
+
+        float edgeTaper = getAfflictionEdgeTaper(noiseVar, afflictionVar);  
+
+        if(afflictionVar >= noiseVar){
+            float albedoOpacity = min((afflictionVar * 0.2) + 0.8 , 1.0);
+            albedo.rgba = mix(albedo.rgba, afflictionAlbedo.rgba, albedoOpacity);
+        }
+        else if(afflictionVar > edgeTaper){
+            float edgeDiff = noiseVar - afflictionVar;
+            edgeDiff = edgeDiff / afflictionVar;
+
+
+            albedo.rgba = mix(afflictionAlbedo.rgba, albedo.rgba, edgeDiff);
+        }
+       else{
+
+            albedo.rgba = mix(albedo.rgba, afflictionAlbedo.rgba, afflictionVar);
+        }
+
+        albedo.a = albedo.a * originalAlpha; //ensures alpha blending is always done based on original texture so
+                                             //avoid artifacts on edge of transparent leaves and similar materials
+
+        return albedo;
+    }
+    vec4 alterAfflictionGlow(float afflictionVar, vec4 emissive, vec4 afflictionGlowColor, float noiseVar){    
+
+
+        emissive = mix(emissive, afflictionGlowColor, afflictionVar);
+
+        return emissive;
+    }
+
+    float alterAfflictionEmissiveIntensity(float afflictionVar, float emissiveIntensity, float afflictionEmissiveIntensity, float noiseVar){
+
+
+       emissiveIntensity = mix(emissiveIntensity, afflictionEmissiveIntensity, afflictionVar);
+
+        return emissiveIntensity;
+    }
+
+    vec3 alterAfflictionNormals(float afflictionVar, vec3 normal, vec3 afflictionNormal, float noiseVar){
+
+        vec3 originalNorm = normal;
+
+        float edgeTaper = getAfflictionEdgeTaper(noiseVar, afflictionVar);      
+
+        if(afflictionVar >= noiseVar){
+            normal = afflictionNormal;
+        }
+        else if(afflictionVar > edgeTaper){
+            float edgeDiff = noiseVar - afflictionVar;
+            edgeDiff = edgeDiff / afflictionVar;
+            normal = mix(afflictionNormal, normal, edgeDiff);
+        }
+        else{
+            normal = mix(normal, afflictionNormal,  afflictionVar);
+        }
+
+
+        return normalize(normal);
+    }
+
+    vec3 alterAfflictionNormalsForTerrain(float afflictionVar, vec3 normal, vec3 afflictionNormal, float noiseVar, vec3 worldNorm){
+
+
+        float edgeTaper = getAfflictionEdgeTaper(noiseVar, afflictionVar);  
+
+
+        vec3 blendedNormal = normal;
+
+        float blendValue = afflictionVar;
+
+        if(afflictionVar >= noiseVar){
+            blendValue = 1.0;
+        }
+        else if(afflictionVar > edgeTaper){
+            float edgeDiff = noiseVar - afflictionVar;
+            edgeDiff = edgeDiff / afflictionVar;
+
+            blendValue = edgeDiff;
+
+        }
+         else{
+             float blendAmt = noiseVar * afflictionVar;
+             blendAmt = max(0.0, blendAmt);
+             blendAmt = min(1.0, blendAmt);
+
+             blendValue = blendAmt;
+
+        }
+
+        afflictionNormal = calculateTangentsAndApplyToNormals(afflictionNormal, worldNorm);
+        blendedNormal = mix(normal, afflictionNormal, blendValue);
+
+        return blendedNormal;
+    }
+
+    vec3 alterAfflictionAo(float afflictionVar, vec3 ao, vec3 afflictionAo, float noiseVar){
+
+        float edgeTaper = getAfflictionEdgeTaper(noiseVar, afflictionVar);  
+
+        if(afflictionVar >= noiseVar){
+            ao = afflictionAo;
+        }
+        else if(afflictionVar > edgeTaper){
+            float edgeDiff = noiseVar - afflictionVar;
+            edgeDiff = edgeDiff / afflictionVar;
+
+             ao = mix(afflictionAo, ao, edgeDiff);
+        }
+        else{
+            ao = mix(ao, afflictionAo, afflictionVar);
+       }
+
+        return ao;
+    }
+
+    float alterAfflictionRoughness(float afflictionVar, float originalRoughness, float afflictionRoughness, float noiseVar){
+
+
+        float edgeTaper = getAfflictionEdgeTaper(noiseVar, afflictionVar);  
+        if(afflictionVar >= noiseVar){
+            originalRoughness = afflictionRoughness;
+        }
+        else if(afflictionVar > edgeTaper){
+            float edgeDiff = noiseVar - afflictionVar;
+            edgeDiff = edgeDiff / afflictionVar;
+
+             originalRoughness = mix(afflictionRoughness, originalRoughness, edgeDiff);
+        }
+
+
+        originalRoughness = min(originalRoughness, 1.0);
+
+
+        return originalRoughness;
+    }
+
+    float alterAfflictionMetallic(float afflictionVar, float originalMetallic, float afflictionMetallic, float noiseVar){
+
+
+        float edgeTaper = getAfflictionEdgeTaper(noiseVar, afflictionVar);  
+        if(afflictionVar >= noiseVar){
+            originalMetallic = afflictionMetallic;
+        }
+        else if(afflictionVar > edgeTaper){
+            float edgeDiff = noiseVar - afflictionVar;
+            edgeDiff = edgeDiff / afflictionVar;
+
+             originalMetallic = mix(afflictionMetallic, originalMetallic, edgeDiff);
+        }
+
+
+        originalMetallic = min(originalMetallic, 1.0);
+        return originalMetallic;
+    }
+
+    #ifndef __SURFACE_MODULE__
+        #import "Common/ShaderLib/module/PBRSurface.glsl"
+    #endif
+    
+    void AfflictionLib_readAfflictionVector(){
+         #ifdef AFFLICTIONTEXTURE
+        
+            afflictionVector = vec4(1.0, 0.0, 1.0, 0.0); //r channel is sturation, g channel is affliction splat texture intensity, b and a unused (might use b channel for wetness eventually)
+    
+        
+            #ifdef TILELOCATION 
+            //subterrains that are not centred in tile or equal to tile width in total size need to have m_TileWidth pre-set. (tileWidth is the x,z dimesnions that the AfflictionAlphaMap represents)..
+                vec2 tileCoords;
+                float xPos, zPos;
+
+                vec3 locInTile = (wPosition - m_TileLocation);
+
+                 locInTile += vec3(m_TileWidth/2, 0, m_TileWidth/2);
+
+                 xPos = (locInTile.x / m_TileWidth);
+                 zPos = 1 - (locInTile.z / m_TileWidth);
+
+                tileCoords = vec2(xPos, zPos);
+
+                afflictionVector = texture2D(m_AfflictionAlphaMap, tileCoords).rgba;
+                
+            #else
+               // ..othrewise when terrain size matches tileWidth, the terrain's texCoords can be used for simple texel fetching of the AfflictionAlphaMap
+                afflictionVector = texture2D(m_AfflictionAlphaMap, texCoord.xy).rgba;
+            #endif
+
+            livelinessValue = afflictionVector.r;
+            afflictionValue = afflictionVector.g;
+        #endif
+        
+    }
+
+    void AfflictionLib_blendSplatLayers(inout PBRSurface surface){
+        
+        TriPlanarUtils_calculateBlending(surface.geometryNormal);
+
+
+        #ifdef AFFLICTIONTEXTURE
+       
+
+            vec4 afflictionAlbedo;    
+            
+            float newAfflictionScale = m_AfflictionSplatScale; 
+            vec2 newScaledCoords;
+            
+            #ifdef AFFLICTIONALBEDOMAP
+                #ifdef TRI_PLANAR_MAPPING
+                    newAfflictionScale = newAfflictionScale / 256;
+                    afflictionAlbedo = getTriPlanarBlend(lPosition, m_SplatAlbedoMap , newAfflictionScale);
+                #else
+                    newScaledCoords = mod(wPosition.xz / m_AfflictionSplatScale, 0.985);
+                    afflictionAlbedo = texture2D(m_SplatAlbedoMap , newScaledCoords);
+                #endif
+
+            #else
+                afflictionAlbedo = vec4(1.0, 1.0, 1.0, 1.0);
+            #endif
+
+            vec3 afflictionNormal;
+            #ifdef AFFLICTIONNORMALMAP
+                #ifdef TRI_PLANAR_MAPPING
+
+                    afflictionNormal = getTriPlanarBlend(lPosition, m_SplatNormalMap , newAfflictionScale).rgb;
+
+                #else
+                    afflictionNormal = texture2D(m_SplatNormalMap , newScaledCoords).rgb;
+                #endif
+                afflictionNormal = normalize((afflictionNormal * vec3(2.0,2.0, 2.0) - vec3(1.0, 1.0, 1.0)));
+                
+                if(surface.hasTangents == true){                    
+                    afflictionNormal = normalize(surface.tbnMat * afflictionNormal);
+                }
+            #else
+                afflictionNormal = surface.geometryNormal; 
+
+            #endif
+            float afflictionMetallic = m_AfflictionMetallicValue;
+            float afflictionRoughness = m_AfflictionRoughnessValue;
+            float afflictionAo = 1.0;
+
+
+            vec4 afflictionEmissive = m_AfflictionEmissiveColor;
+            float afflictionEmissiveIntensity = m_AfflictionEmissiveValue;
+
+            #ifdef AFFLICTIONROUGHNESSMETALLICMAP    
+                vec4 metallicRoughnessAoEiVec;
+                #ifdef TRI_PLANAR_MAPPING
+                    metallicRoughnessAoEiVec = texture2D(m_SplatRoughnessMetallicMap, newScaledCoords);
+                #else
+                    metallicRoughnessAoEiVec = getTriPlanarBlend(lPosition, m_SplatRoughnessMetallicMap, newAfflictionScale);
+                #endif
+
+                afflictionRoughness *= metallicRoughnessAoEiVec.g;
+                afflictionMetallic *= metallicRoughnessAoEiVec.b;
+                afflictionAo = metallicRoughnessAoEiVec.r;
+                afflictionEmissiveIntensity *= metallicRoughnessAoEiVec.a; //important not to leave this channel all black by accident when creating the mraoei map if using affliction emissiveness    
+
+            #endif
+
+            #ifdef AFFLICTIONEMISSIVEMAP
+                vec4 emissiveMapColor;
+                #ifdef TRI_PLANAR_MAPPING
+                    emissiveMapColor = texture2D(m_SplatEmissiveMap, newScaledCoords);
+                #else
+                    emissiveMapColor = getTriPlanarBlend(lPosition, m_SplatEmissiveMap, newAfflictionScale);
+                #endif
+                afflictionEmissive *= emissiveMapColor;
+            #endif
+
+            float adjustedAfflictionValue = afflictionValue;
+            #ifdef USE_SPLAT_NOISE
+                noiseHash = getStaticNoiseVar0(wPosition, afflictionValue * m_SplatNoiseVar); //VERY IMPORTANT to replace this with a noiseMap texture, as calculating noise per pixel in-shader like this does lower framerate a lot
+
+                adjustedAfflictionValue = getAdjustedAfflictionVar(afflictionValue);
+                if(afflictionValue >= 0.99){
+                    adjustedAfflictionValue = afflictionValue;
+                }
+            #else
+                noiseHash = 1.0;
+            #endif           
+
+            surface.roughness = alterAfflictionRoughness(afflictionValue, surface.roughness, afflictionRoughness, noiseHash);
+            surface.metallic = alterAfflictionMetallic(afflictionValue, surface.metallic,  afflictionMetallic, noiseHash);
+            surface.albedo = alterAfflictionColor(afflictionValue, vec4(surface.albedo, 1.0), afflictionAlbedo, noiseHash).rgb;
+            surface.emission = alterAfflictionGlow(afflictionValue, vec4(surface.emission, 1.0), afflictionEmissive, noiseHash).rgb;
+            surface.ao = alterAfflictionAo(afflictionValue, surface.ao, vec3(afflictionAo), noiseHash); 
+            
+            if(surface.hasTangents == true){
+                surface.normal = alterAfflictionNormals(afflictionValue, surface.normal, afflictionNormal, noiseHash);      
+            }    
+            else{
+                surface.normal = alterAfflictionNormalsForTerrain(afflictionValue, surface.normal, afflictionNormal, noiseHash, surface.geometryNormal);
+            }    
+
+        #endif
+
+
+    }
+
+#endif
+
+
+
+
+