Run Time Error When Adding Water Filter

Hello Guys,
I’m trying to add the Water filter to my game using the below code:

    float initialWaterHeight = 90f;//0.8f;
    Vector3f lightDir = new Vector3f(-4.9236743f, -1.27054665f, 5.896916f);

    //Water Filter
    water = new WaterFilter(rootNode, lightDir);
    water.setWaterColor(new ColorRGBA().setAsSrgb(0.0078f, 0.3176f, 0.5f, 1.0f));
    water.setDeepWaterColor(new ColorRGBA().setAsSrgb(0.0039f, 0.00196f, 0.145f, 1.0f));
    water.setUnderWaterFogDistance(80);
    water.setWaterTransparency(0.12f);
    water.setFoamIntensity(0.4f);
    water.setFoamHardness(0.3f);
    water.setFoamExistence(new Vector3f(0.8f, 8f, 1f));
    water.setReflectionDisplace(50);
    water.setRefractionConstant(0.25f);
    water.setColorExtinction(new Vector3f(30, 50, 70));
    water.setCausticsIntensity(0.4f);
    water.setWaveScale(0.003f);
    water.setMaxAmplitude(2f);
    water.setFoamTexture((Texture2D) assetManager.loadTexture("Common/MatDefs/Water/Textures/foam2.jpg"));
    water.setRefractionStrength(0.2f);
    water.setWaterHeight(initialWaterHeight);


    //Bloom Filter
    BloomFilter bloom = new BloomFilter();
    bloom.setExposurePower(55);
    bloom.setBloomIntensity(1.0f);

    //Light Scattering Filter
    LightScatteringFilter lsf = new LightScatteringFilter(lightDir.mult(-300));
    lsf.setLightDensity(0.5f);

    //Depth of field Filter
    DepthOfFieldFilter dof = new DepthOfFieldFilter();
    dof.setFocusDistance(0);
    dof.setFocusRange(100);


    FilterPostProcessor fpp = new FilterPostProcessor(assetManager);
    fpp.addFilter(water);
    fpp.addFilter(bloom);
    fpp.addFilter(dof);
    fpp.addFilter(lsf);
    fpp.addFilter(new FXAAFilter());

    //fpp.setNumSamples(0);// test other than 0
    viewPort.addProcessor(fpp);

And I get the following exception:
SEVERE: Uncaught exception thrown in Thread[jME3 Main,6,main]
com.jme3.renderer.RendererException: compile error in: ShaderSource[name=Common/MatDefs/Water/Water.frag, defines, type=Fragment, language=GLSL120]
ERROR: 0:207: ‘=’ : cannot convert from ‘2-component vector of float’ to ‘3-component vector of float’
ERROR: 0:208: ‘=’ : cannot convert from ‘2-component vector of float’ to ‘3-component vector of float’

at com.jme3.renderer.opengl.GLRenderer.updateShaderSourceData(GLRenderer.java:1269)
at com.jme3.renderer.opengl.GLRenderer.updateShaderData(GLRenderer.java:1296)
at com.jme3.renderer.opengl.GLRenderer.setShader(GLRenderer.java:1360)
at com.jme3.material.logic.DefaultTechniqueDefLogic.render(DefaultTechniqueDefLogic.java:94)
at com.jme3.material.Technique.render(Technique.java:166)
at com.jme3.material.Material.render(Material.java:974)
at com.jme3.renderer.RenderManager.renderGeometry(RenderManager.java:614)
at com.jme3.post.FilterPostProcessor.renderProcessing(FilterPostProcessor.java:230)
at com.jme3.post.FilterPostProcessor.renderFilterChain(FilterPostProcessor.java:314)
at com.jme3.post.FilterPostProcessor.postFrame(FilterPostProcessor.java:334)
at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:1114)
at com.jme3.renderer.RenderManager.render(RenderManager.java:1158)
at com.jme3.app.SimpleApplication.update(SimpleApplication.java:253)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:151)
at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:197)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:232)
at java.lang.Thread.run(Thread.java:745)

Any thoughts on what can be done to fix this?
Thanks a lot!
Adi

What OS and what GPU?

It’s Window 10 with Inter ® HD Graphics 3000

i think before this error it might show you all shader source.

can you tell what is in line 0:207 / 0:208 (line 207 and 208)

based on error there is some vec3 something = vec2()

207 vec3 T = inverseM * vec2(duv1.x, duv2.x);
208 vec3 B = inverseM * vec2(duv1.y, duv2.y);

ok so this is about line:

86 / 87 line in file:

will need to think why its wrong.
im not shader master but mat2x3 * vec2 was intended to give vec3, but it returned vec2

@RiccardoBlb any thoughts? its about tangents, so you might know.

:man_shrugging: the code looks fine.
It seems like there might be some sort of bug in the glsl compiler of the driver… is it updated to the latest available version?
We can probably find a workaround, but this is very weird.

It is updated to latest version of this driver and this is the manufacturer’s driver.
One thing - is it possible that it is related somehow to the texture: “Common/MatDefs/Water/Textures/foam2.jpg” ?
Because I don’t have this JPG file in my project. I assumed it is bundled in some JME library…

I guess it has nothing to do with the texture file…
I changed the name to something which is not existent and got an error from the assets manager so the previous foam2.jpg probably exists and loads fine

foam2.jpg is bundled in jme3-effects

If those two lines are what is causing the issue as you reported,

then it looks like a multiplication between a mat2x3 and a vec2 is returning a vec2 in your system, when it is supposed to return a vec3…

This is more a shot in the dark than anything, but if you want to try it out, I made some modifications to the shader, maybe your compiler will like this one better.

Water.frag

#import "Common/ShaderLib/GLSLCompat.glsllib"
#import "Common/ShaderLib/MultiSample.glsllib"
#import "Common/ShaderLib/WaterUtil.glsllib"

// Water pixel shader
// Copyright (C) JMonkeyEngine 3.0
// by Remy Bouquet (nehon) for JMonkeyEngine 3.0
// original HLSL version by Wojciech Toman 2009

uniform COLORTEXTURE m_Texture;
uniform DEPTHTEXTURE m_DepthTexture;


uniform sampler2D m_HeightMap;
uniform sampler2D m_NormalMap;
uniform sampler2D m_FoamMap;
uniform sampler2D m_CausticsMap;
uniform sampler2D m_ReflectionMap;

uniform mat4 g_ViewProjectionMatrixInverse;
uniform mat4 m_TextureProjMatrix;
uniform vec3 m_CameraPosition;

uniform float m_WaterHeight;
uniform float m_Time;
uniform float m_WaterTransparency;
uniform float m_NormalScale;
uniform float m_R0;
uniform float m_MaxAmplitude;
uniform vec3 m_LightDir;
uniform vec4 m_LightColor;
uniform float m_ShoreHardness;
uniform float m_FoamHardness;
uniform float m_RefractionStrength;
uniform vec3 m_FoamExistence;
uniform vec3 m_ColorExtinction;
uniform float m_Shininess;
uniform vec4 m_WaterColor;
uniform vec4 m_DeepWaterColor;
uniform vec2 m_WindDirection;
uniform float m_SunScale;
uniform float m_WaveScale;
uniform float m_UnderWaterFogDistance;
uniform float m_CausticsIntensity;

#ifdef ENABLE_AREA
uniform vec3 m_Center;
uniform float m_Radius;
#endif


vec2 scale = vec2(m_WaveScale, m_WaveScale);
float refractionScale = m_WaveScale;

// Modifies 4 sampled normals. Increase first values to have more
// smaller "waves" or last to have more bigger "waves"
const vec4 normalModifier = vec4(3.0, 2.0, 4.0, 10.0);
// Strength of displacement along normal.
uniform float m_ReflectionDisplace;
// Water transparency along eye vector.
const float visibility = 3.0;
// foam intensity
uniform float m_FoamIntensity ;

varying vec2 texCoord;

mat3 MatrixInverse(in mat3 inMatrix){
    float det = dot(cross(inMatrix[0], inMatrix[1]), inMatrix[2]);
    mat3 T = transpose(inMatrix);
    return mat3(cross(T[1], T[2]),
        cross(T[2], T[0]),
        cross(T[0], T[1])) / det;
}


mat3 computeTangentFrame(in vec3 N, in vec3 P, in vec2 UV) {
    vec3 dp1 = dFdx(P);
    vec3 dp2 = dFdy(P);
    vec2 duv1 = dFdx(UV);
    vec2 duv2 = dFdy(UV);

    // solve the linear system
    vec3 dp1xdp2 = cross(dp1, dp2);
    mat2x3 inverseM = mat2x3(cross(dp2, dp1xdp2), cross(dp1xdp2, dp1));

    vec2 dxx=vec2(duv1.x, duv2.x);
    vec2 dyy= vec2(duv1.y, duv2.y);
    vec3 T = vec3(inverseM * dxx);
    vec3 B = vec3(inverseM * dyy);

    // construct tangent frame
    float maxLength = max(length(T), length(B));
    T = T / maxLength;
    B = B / maxLength;

    return mat3(T, B, N);
}

float saturate(in float val){
    return clamp(val,0.0,1.0);
}

vec3 saturate(in vec3 val){
    return clamp(val,vec3(0.0),vec3(1.0));
}

vec3 getPosition(in float depth, in vec2 uv){
    vec4 pos = vec4(uv, depth, 1.0) * 2.0 - 1.0;
    pos = g_ViewProjectionMatrixInverse * pos;
    return pos.xyz / pos.w;
}

// Function calculating fresnel term.
// - normal - normalized normal vector
// - eyeVec - normalized eye vector
float fresnelTerm(in vec3 normal,in vec3 eyeVec){
    float angle = 1.0 - max(0.0, dot(normal, eyeVec));
    float fresnel = angle * angle;
    fresnel = fresnel * fresnel;
    fresnel = fresnel * angle;
    return saturate(fresnel * (1.0 - saturate(m_R0)) + m_R0 - m_RefractionStrength);
}

vec2 m_FrustumNearFar=vec2(1.0,m_UnderWaterFogDistance);
const float LOG2 = 1.442695;

vec4 underWater(int sampleNum){


    float sceneDepth = fetchTextureSample(m_DepthTexture, texCoord, sampleNum).r;
    vec3 color2 = fetchTextureSample(m_Texture, texCoord, sampleNum).rgb;
    
    vec3 position = getPosition(sceneDepth, texCoord);  
    float level = m_WaterHeight;

    vec3 eyeVec = position - m_CameraPosition;    
 
    // Find intersection with water surface
    vec3 eyeVecNorm = normalize(eyeVec);
    float t = (level - m_CameraPosition.y) / eyeVecNorm.y;
    vec3 surfacePoint = m_CameraPosition + eyeVecNorm * t;

    vec2 texC = vec2(0.0);

    float cameraDepth = length(m_CameraPosition - surfacePoint);  
    texC = (surfacePoint.xz + eyeVecNorm.xz) * scale + m_Time * 0.03 * m_WindDirection;
    float bias = texture2D(m_HeightMap, texC).r;
    level += bias * m_MaxAmplitude;
    t = (level - m_CameraPosition.y) / eyeVecNorm.y;
    surfacePoint = m_CameraPosition + eyeVecNorm * t; 
    eyeVecNorm = normalize(m_CameraPosition - surfacePoint);

    #if __VERSION__ >= 130
        // Find normal of water surface
        float normal1 = textureOffset(m_HeightMap, texC, ivec2(-1.0,  0.0)).r;
        float normal2 = textureOffset(m_HeightMap, texC, ivec2( 1.0,  0.0)).r;
        float normal3 = textureOffset(m_HeightMap, texC, ivec2( 0.0, -1.0)).r;
        float normal4 = textureOffset(m_HeightMap, texC, ivec2( 0.0,  1.0)).r;
    #else
        // Find normal of water surface
        float normal1 = texture2D(m_HeightMap, (texC + vec2(-1.0, 0.0) / 256.0)).r;
        float normal2 = texture2D(m_HeightMap, (texC + vec2(1.0, 0.0) / 256.0)).r;
        float normal3 = texture2D(m_HeightMap, (texC + vec2(0.0, -1.0) / 256.0)).r;
        float normal4 = texture2D(m_HeightMap, (texC + vec2(0.0, 1.0) / 256.0)).r;
    #endif

    vec3 myNormal = normalize(vec3((normal1 - normal2) * m_MaxAmplitude,m_NormalScale,(normal3 - normal4) * m_MaxAmplitude));
    vec3 normal = myNormal*-1.0;
    float fresnel = fresnelTerm(normal, eyeVecNorm); 

    vec3 refraction = color2;
    #ifdef ENABLE_REFRACTION
        texC = texCoord.xy *sin (fresnel+1.0);
        texC = clamp(texC,0.0,1.0);
        refraction = fetchTextureSample(m_Texture, texC, sampleNum).rgb;
    #endif

   float waterCol = saturate(length(m_LightColor.rgb) / m_SunScale);
   refraction = mix(mix(refraction, m_DeepWaterColor.rgb * waterCol, m_WaterTransparency),  m_WaterColor.rgb* waterCol,m_WaterTransparency);

    vec3 foam = vec3(0.0);
    #ifdef ENABLE_FOAM    
        texC = (surfacePoint.xz + eyeVecNorm.xz * 0.1) * 0.05 + m_Time * 0.05 * m_WindDirection + sin(m_Time * 0.001 + position.x) * 0.005;
        vec2 texCoord2 = (surfacePoint.xz + eyeVecNorm.xz * 0.1) * 0.05 + m_Time * 0.1 * m_WindDirection + sin(m_Time * 0.001 + position.z) * 0.005;

        if(m_MaxAmplitude - m_FoamExistence.z> 0.0001){
            foam += ((texture2D(m_FoamMap, texC) + texture2D(m_FoamMap, texCoord2)) * m_FoamIntensity  * m_FoamIntensity * 0.3 *
               saturate((level - (m_WaterHeight + m_FoamExistence.z)) / (m_MaxAmplitude - m_FoamExistence.z))).rgb;
        }
        foam *= m_LightColor.rgb;    
    #endif



    vec3 specular = vec3(0.0);   
    vec3 color ;
    float fogFactor;

    if(position.y>level){
        #ifdef ENABLE_SPECULAR
            if(step(0.9999,sceneDepth)==1.0){
                vec3 lightDir=normalize(m_LightDir);
                vec3 mirrorEye = (2.0 * dot(eyeVecNorm, normal) * normal - eyeVecNorm);
                float dotSpec = saturate(dot(mirrorEye.xyz, -lightDir) * 0.5 + 0.5);
                specular = vec3((1.0 - fresnel) * saturate(-lightDir.y) * ((pow(dotSpec, 512.0)) * (m_Shininess * 1.8 + 0.2)));
                specular += specular * 25.0 * saturate(m_Shininess - 0.05);
                specular=specular * m_LightColor.rgb * 100.0;
            }
        #endif
        float fogIntensity= 8.0 * m_WaterTransparency;
        fogFactor = exp2( -fogIntensity * fogIntensity * cameraDepth * 0.03 * LOG2 );
        fogFactor = clamp(fogFactor, 0.0, 1.0);        
        color =mix(m_DeepWaterColor.rgb,refraction,fogFactor);   
        specular=specular*fogFactor;    
        color = saturate(color + max(specular, foam ));
    }else{
        vec3 caustics = vec3(0.0);
        #ifdef ENABLE_CAUSTICS 
            vec2 windDirection=m_WindDirection;
            texC = (position.xz + eyeVecNorm.xz * 0.1) * 0.05 + m_Time * 0.05 * windDirection + sin(m_Time  + position.x) * 0.01;
            vec2 texCoord2 = (position.xz + eyeVecNorm.xz * 0.1) * 0.05 + m_Time * 0.05 * windDirection + sin(m_Time  + position.z) * 0.01;
            caustics += (texture2D(m_CausticsMap, texC)+ texture2D(m_CausticsMap, texCoord2)).rgb;                  
            caustics=saturate(mix(m_WaterColor.rgb,caustics,m_CausticsIntensity));            
            color=mix(color2,caustics,m_CausticsIntensity);
        #else
            color=color2;
        #endif
                
        float fogDepth= (2.0 * m_FrustumNearFar.x) / (m_FrustumNearFar.y + m_FrustumNearFar.x - sceneDepth* (m_FrustumNearFar.y-m_FrustumNearFar.x));
        float fogIntensity= 18 * m_WaterTransparency;
        fogFactor = exp2( -fogIntensity * fogIntensity * fogDepth *  fogDepth * LOG2 );
        fogFactor = clamp(fogFactor, 0.0, 1.0);
        color =mix(m_DeepWaterColor.rgb,color,fogFactor);
    }

    return vec4(color, 1.0);   
}


// NOTE: This will be called even for single-sampling
vec4 main_multiSample(int sampleNum){
    // If we are underwater let's call the underwater function
    if(m_WaterHeight >= m_CameraPosition.y){
        #ifdef ENABLE_AREA      
            if(isOverExtent(m_CameraPosition, m_Center, m_Radius)){            
                return fetchTextureSample(m_Texture, texCoord, sampleNum);
            }   
        #endif
        return underWater(sampleNum);
    }

    float sceneDepth = fetchTextureSample(m_DepthTexture, texCoord, sampleNum).r;
    vec3 color2 = fetchTextureSample(m_Texture, texCoord, sampleNum).rgb;

    vec3 color = color2;
    vec3 position = getPosition(sceneDepth, texCoord);

    #ifdef ENABLE_AREA               
        if(isOverExtent(position, m_Center, m_Radius)){         
            return vec4(color2, 1.0);
        }
    #endif

    float level = m_WaterHeight;
    
    float isAtFarPlane = step(0.99998, sceneDepth);
    //#ifndef ENABLE_RIPPLES
    // This optimization won't work on NVIDIA cards if ripples are enabled
    if(position.y > level + m_MaxAmplitude + isAtFarPlane * 100.0){

        return vec4(color2, 1.0);
    }
    //#endif

    vec3 eyeVec = position - m_CameraPosition;    
    float cameraDepth = m_CameraPosition.y - position.y;

    // Find intersection with water surface
    vec3 eyeVecNorm = normalize(eyeVec);
    float t = (level - m_CameraPosition.y) / eyeVecNorm.y;
    vec3 surfacePoint = m_CameraPosition + eyeVecNorm * t;

    vec2 texC = vec2(0.0);
    int samples = 1;
    #ifdef ENABLE_HQ_SHORELINE
        samples = 10;
    #endif

    float biasFactor = 1.0 / samples;
    for (int i = 0; i < samples; i++){
        texC = (surfacePoint.xz + eyeVecNorm.xz * biasFactor) * scale + m_Time * 0.03 * m_WindDirection;

        float bias = texture2D(m_HeightMap, texC).r;

        bias *= biasFactor;
        level += bias * m_MaxAmplitude;
        t = (level - m_CameraPosition.y) / eyeVecNorm.y;
        surfacePoint = m_CameraPosition + eyeVecNorm * t;
    }

    float depth = length(position - surfacePoint);
    float depth2 = surfacePoint.y - position.y;

    // XXX: HACK ALERT: Increase water depth to infinity if at far plane
    // Prevents "foam on horizon" issue
    // For best results, replace the "100.0" below with the
    // highest value in the m_ColorExtinction vec3
    depth  += isAtFarPlane * 100.0;
    depth2 += isAtFarPlane * 100.0;

    eyeVecNorm = normalize(m_CameraPosition - surfacePoint);

    #if __VERSION__ >= 130
        // Find normal of water surface
        float normal1 = textureOffset(m_HeightMap, texC, ivec2(-1.0,  0.0)).r;
        float normal2 = textureOffset(m_HeightMap, texC, ivec2( 1.0,  0.0)).r;
        float normal3 = textureOffset(m_HeightMap, texC, ivec2( 0.0, -1.0)).r;
        float normal4 = textureOffset(m_HeightMap, texC, ivec2( 0.0,  1.0)).r;
    #else
        // Find normal of water surface
        float normal1 = texture2D(m_HeightMap, (texC + vec2(-1.0, 0.0) / 256.0)).r;
        float normal2 = texture2D(m_HeightMap, (texC + vec2(1.0, 0.0) / 256.0)).r;
        float normal3 = texture2D(m_HeightMap, (texC + vec2(0.0, -1.0) / 256.0)).r;
        float normal4 = texture2D(m_HeightMap, (texC + vec2(0.0, 1.0) / 256.0)).r;
    #endif

    vec3 myNormal = normalize(vec3((normal1 - normal2) * m_MaxAmplitude,m_NormalScale,(normal3 - normal4) * m_MaxAmplitude));
    vec3 normal = vec3(0.0);

    #ifdef ENABLE_RIPPLES
        texC = surfacePoint.xz * 0.8 + m_WindDirection * m_Time* 1.6;
        mat3 tangentFrame = computeTangentFrame(myNormal, eyeVecNorm, texC);
        vec3 normal0a = normalize(tangentFrame*(2.0 * texture2D(m_NormalMap, texC).xyz - 1.0));

        texC = surfacePoint.xz * 0.4 + m_WindDirection * m_Time* 0.8;
        tangentFrame = computeTangentFrame(myNormal, eyeVecNorm, texC);
        vec3 normal1a = normalize(tangentFrame*(2.0 * texture2D(m_NormalMap, texC).xyz - 1.0));

        texC = surfacePoint.xz * 0.2 + m_WindDirection * m_Time * 0.4;
        tangentFrame = computeTangentFrame(myNormal, eyeVecNorm, texC);
        vec3 normal2a = normalize(tangentFrame*(2.0 * texture2D(m_NormalMap, texC).xyz - 1.0));

        texC = surfacePoint.xz * 0.1 + m_WindDirection * m_Time * 0.2;
        tangentFrame = computeTangentFrame(myNormal, eyeVecNorm, texC);
        vec3 normal3a = normalize(tangentFrame*(2.0 * texture2D(m_NormalMap, texC).xyz - 1.0));

        normal = normalize(normal0a * normalModifier.x + normal1a * normalModifier.y +normal2a * normalModifier.z + normal3a * normalModifier.w);

         #if __VERSION__ >= 130
            // XXX: Here's another way to fix the terrain edge issue,
            // But it requires GLSL 1.3 and still looks kinda incorrect
            // around edges
            normal = isnan(normal.x) ? myNormal : normal;
        #else
            // To make the shader 1.2 compatible we use a trick :
            // we clamp the x value of the normal and compare it to it's former value instead of using isnan.
            normal = clamp(normal.x,0.0,1.0)!=normal.x ? myNormal : normal;
        #endif

    #else
        normal = myNormal;
    #endif

    vec3 refraction = color2;
    #ifdef ENABLE_REFRACTION
       // texC = texCoord.xy+ m_ReflectionDisplace * normal.x;
        texC = texCoord.xy;
        texC += sin(m_Time*1.8 + 3.0 * abs(position.y))* (refractionScale * min(depth2, 1.0));
        texC = clamp(texC,vec2(0.0),vec2(0.999));
        refraction = fetchTextureSample(m_Texture, texC, sampleNum).rgb;
    #endif
    vec3 waterPosition = surfacePoint.xyz;
    waterPosition.y -= (level - m_WaterHeight);
    vec4 texCoordProj = m_TextureProjMatrix * vec4(waterPosition, 1.0);

    texCoordProj.x = texCoordProj.x + m_ReflectionDisplace * normal.x;
    texCoordProj.z = texCoordProj.z + m_ReflectionDisplace * normal.z;
    texCoordProj /= texCoordProj.w;
    texCoordProj.y = 1.0 - texCoordProj.y;

    vec3 reflection = texture2D(m_ReflectionMap, texCoordProj.xy).rgb;

    float fresnel = fresnelTerm(normal, eyeVecNorm);

    float depthN = depth * m_WaterTransparency;
    float waterCol = saturate(length(m_LightColor.rgb) / m_SunScale);
    refraction = mix(mix(refraction, m_WaterColor.rgb * waterCol, saturate(depthN / visibility)),
        m_DeepWaterColor.rgb * waterCol, saturate(depth2 / m_ColorExtinction));


    vec3 foam = vec3(0.0);
    #ifdef ENABLE_FOAM
        texC = (surfacePoint.xz + eyeVecNorm.xz * 0.1) * 0.05 + m_Time * 0.05 * m_WindDirection + sin(m_Time * 0.001 + position.x) * 0.005;
        vec2 texCoord2 = (surfacePoint.xz + eyeVecNorm.xz * 0.1) * 0.05 + m_Time * 0.1 * m_WindDirection + sin(m_Time * 0.001 + position.z) * 0.005;

        vec4 foam1 = texture2D(m_FoamMap, texC);
        vec4 foam2 = texture2D(m_FoamMap, texCoord2);

        if(depth2 < m_FoamExistence.x){
            foam = (foam1.r + foam2).rgb * vec3(m_FoamIntensity);
        }else if(depth2 < m_FoamExistence.y){
            foam = mix((foam1 + foam2) * m_FoamIntensity , vec4(0.0),
                (depth2 - m_FoamExistence.x) / (m_FoamExistence.y - m_FoamExistence.x)).rgb;
        }

        
        if(m_MaxAmplitude - m_FoamExistence.z> 0.0001){
            foam += ((foam1 + foam2) * m_FoamIntensity  * m_FoamIntensity * 0.3 *
               saturate((level - (m_WaterHeight + m_FoamExistence.z)) / (m_MaxAmplitude - m_FoamExistence.z))).rgb;
        }
        foam *= m_LightColor.rgb;
    #endif

    vec3 specular = vec3(0.0);
    #ifdef ENABLE_SPECULAR
        vec3 lightDir=normalize(m_LightDir);
        vec3 mirrorEye = (2.0 * dot(eyeVecNorm, normal) * normal - eyeVecNorm);
        float dotSpec = saturate(dot(mirrorEye.xyz, -lightDir) * 0.5 + 0.5);
        specular = vec3((1.0 - fresnel) * saturate(-lightDir.y) * ((pow(dotSpec, 512.0)) * (m_Shininess * 1.8 + 0.2)));
        specular += specular * 25.0 * saturate(m_Shininess - 0.05);
        //foam does not shine
        specular=specular * m_LightColor.rgb - (5.0 * foam);
    #endif

    color = mix(refraction, reflection, fresnel);
    color = mix(refraction, color, saturate(depth * m_ShoreHardness));
    color = saturate(color + max(specular, foam ));
    color = mix(refraction, color, saturate(depth* m_FoamHardness));


    // XXX: HACK ALERT:
    // We trick the GeForces to think they have
    // to calculate the derivatives for all these pixels by using step()!
    // That way we won't get pixels around the edges of the terrain,
    // Where the derivatives are undefined
    return vec4(mix(color, color2, step(level, position.y)), 1.0);
}

void main(){
    #ifdef RESOLVE_MS
        vec4 color = vec4(0.0);
        for (int i = 0; i < m_NumSamples; i++){
            color += main_multiSample(i);
        }
        gl_FragColor = color / m_NumSamples;
    #else
        gl_FragColor = main_multiSample(0);
    #endif
}

I will do my best to give it a try. So, in order to do that I need to download the source code (latest or my specific version?), change only this file and run the gradle right?
Should I run gradle for the entire JME or just for that specific module?

No, you can just add that file as Water.frag in your project, but need to copy the j3md file as well and then reference the frag from your j3md

As @Darkchaos said, or you can

Clone the master branch from here: GitHub - jMonkeyEngine/jmonkeyengine: A complete 3D game development suite written purely in Java.
Load it in your favorite ide that supports gradle projects.
Replace the code in jme3-effects/src/main/resources/Common/MatDefs/Water/Water.frag
Build and run jme3-examples/src/main/java/jme3test/water/TestPostWater.java

I have changed the water.frag file and compiled the entire engine, then ran the tests and got this error when running the test project:

Sep 08, 2019 11:19:59 PM com.jme3.app.LegacyApplication handleError
SEVERE: Uncaught exception thrown in Thread[jME3 Main,6,main]
com.jme3.renderer.RendererException: compile error in: ShaderSource[name=Common/MatDefs/Water/Water.frag, defines, type=Fragment, language=GLSL120]
ERROR: 0:209: ‘constructor’ : not enough data provided for construction
ERROR: 0:210: ‘constructor’ : not enough data provided for construction

    at com.jme3.renderer.opengl.GLRenderer.updateShaderSourceData(GLRenderer.java:1269)
    at com.jme3.renderer.opengl.GLRenderer.updateShaderData(GLRenderer.java:1296)
    at com.jme3.renderer.opengl.GLRenderer.setShader(GLRenderer.java:1360)
    at com.jme3.material.logic.DefaultTechniqueDefLogic.render(DefaultTechniqueDefLogic.java:94)
    at com.jme3.material.Technique.render(Technique.java:166)
    at com.jme3.material.Material.render(Material.java:974)
    at com.jme3.renderer.RenderManager.renderGeometry(RenderManager.java:614)
    at com.jme3.post.FilterPostProcessor.renderProcessing(FilterPostProcessor.java:230)
    at com.jme3.post.FilterPostProcessor.renderFilterChain(FilterPostProcessor.java:314)
    at com.jme3.post.FilterPostProcessor.postFrame(FilterPostProcessor.java:334)

<============-> 97% EXECUTING [16m 40s]ger.renderViewPort(RenderManager.java:1114)
<============-> 97% EXECUTING [16m 29s]ger.render(RenderManager.java:1158)
<============-> 97% EXECUTING [16m 23s]on.update(SimpleApplication.java:253)

:jme3-examples:runsystem.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:151)
:jme3-examples:runEXECUTING [16m 23s]isplay.runLoop(LwjglDisplay.java:197)
:jme3-examples:runEXECUTING [16m 23s]bstractDisplay.run(LwjglAbstractDisplay.java:232)
at java.lang.Thread.run(Thread.java:745)

I guess these are the lines:
209 vec3 T = vec3(inverseM * dxx);
210 vec3 B = vec3(inverseM * dyy);

Ok, can you try this?

#import "Common/ShaderLib/GLSLCompat.glsllib"
#import "Common/ShaderLib/MultiSample.glsllib"
#import "Common/ShaderLib/WaterUtil.glsllib"

// Water pixel shader
// Copyright (C) JMonkeyEngine 3.0
// by Remy Bouquet (nehon) for JMonkeyEngine 3.0
// original HLSL version by Wojciech Toman 2009

uniform COLORTEXTURE m_Texture;
uniform DEPTHTEXTURE m_DepthTexture;


uniform sampler2D m_HeightMap;
uniform sampler2D m_NormalMap;
uniform sampler2D m_FoamMap;
uniform sampler2D m_CausticsMap;
uniform sampler2D m_ReflectionMap;

uniform mat4 g_ViewProjectionMatrixInverse;
uniform mat4 m_TextureProjMatrix;
uniform vec3 m_CameraPosition;

uniform float m_WaterHeight;
uniform float m_Time;
uniform float m_WaterTransparency;
uniform float m_NormalScale;
uniform float m_R0;
uniform float m_MaxAmplitude;
uniform vec3 m_LightDir;
uniform vec4 m_LightColor;
uniform float m_ShoreHardness;
uniform float m_FoamHardness;
uniform float m_RefractionStrength;
uniform vec3 m_FoamExistence;
uniform vec3 m_ColorExtinction;
uniform float m_Shininess;
uniform vec4 m_WaterColor;
uniform vec4 m_DeepWaterColor;
uniform vec2 m_WindDirection;
uniform float m_SunScale;
uniform float m_WaveScale;
uniform float m_UnderWaterFogDistance;
uniform float m_CausticsIntensity;

#ifdef ENABLE_AREA
uniform vec3 m_Center;
uniform float m_Radius;
#endif


vec2 scale = vec2(m_WaveScale, m_WaveScale);
float refractionScale = m_WaveScale;

// Modifies 4 sampled normals. Increase first values to have more
// smaller "waves" or last to have more bigger "waves"
const vec4 normalModifier = vec4(3.0, 2.0, 4.0, 10.0);
// Strength of displacement along normal.
uniform float m_ReflectionDisplace;
// Water transparency along eye vector.
const float visibility = 3.0;
// foam intensity
uniform float m_FoamIntensity ;

varying vec2 texCoord;

mat3 MatrixInverse(in mat3 inMatrix){
    float det = dot(cross(inMatrix[0], inMatrix[1]), inMatrix[2]);
    mat3 T = transpose(inMatrix);
    return mat3(cross(T[1], T[2]),
        cross(T[2], T[0]),
        cross(T[0], T[1])) / det;
}


// http://www.thetenthplanet.de/archives/1180
mat3 computeTangentFrame(vec3 N, vec3 p, vec2 uv){
	// get edge vectors of the pixel triangle
	vec3 dp1 = dFdx( p );
	vec3 dp2 = dFdy( p );
	vec2 duv1 = dFdx( uv );
	vec2 duv2 = dFdy( uv );
	 
	// solve the linear system
	vec3 dp2perp = cross( dp2, N );
	vec3 dp1perp = cross( N, dp1 );
	vec3 T = dp2perp * duv1.x + dp1perp * duv2.x;
	vec3 B = dp2perp * duv1.y + dp1perp * duv2.y;
	 
	// construct a scale-invariant frame 
	float invmax = 1.0/sqrt( max( dot(T,T), dot(B,B) ) );
	return mat3( T * invmax, B * invmax, N );
}

float saturate(in float val){
    return clamp(val,0.0,1.0);
}

vec3 saturate(in vec3 val){
    return clamp(val,vec3(0.0),vec3(1.0));
}

vec3 getPosition(in float depth, in vec2 uv){
    vec4 pos = vec4(uv, depth, 1.0) * 2.0 - 1.0;
    pos = g_ViewProjectionMatrixInverse * pos;
    return pos.xyz / pos.w;
}

// Function calculating fresnel term.
// - normal - normalized normal vector
// - eyeVec - normalized eye vector
float fresnelTerm(in vec3 normal,in vec3 eyeVec){
    float angle = 1.0 - max(0.0, dot(normal, eyeVec));
    float fresnel = angle * angle;
    fresnel = fresnel * fresnel;
    fresnel = fresnel * angle;
    return saturate(fresnel * (1.0 - saturate(m_R0)) + m_R0 - m_RefractionStrength);
}

vec2 m_FrustumNearFar=vec2(1.0,m_UnderWaterFogDistance);
const float LOG2 = 1.442695;

vec4 underWater(int sampleNum){


    float sceneDepth = fetchTextureSample(m_DepthTexture, texCoord, sampleNum).r;
    vec3 color2 = fetchTextureSample(m_Texture, texCoord, sampleNum).rgb;
    
    vec3 position = getPosition(sceneDepth, texCoord);  
    float level = m_WaterHeight;

    vec3 eyeVec = position - m_CameraPosition;    
 
    // Find intersection with water surface
    vec3 eyeVecNorm = normalize(eyeVec);
    float t = (level - m_CameraPosition.y) / eyeVecNorm.y;
    vec3 surfacePoint = m_CameraPosition + eyeVecNorm * t;

    vec2 texC = vec2(0.0);

    float cameraDepth = length(m_CameraPosition - surfacePoint);  
    texC = (surfacePoint.xz + eyeVecNorm.xz) * scale + m_Time * 0.03 * m_WindDirection;
    float bias = texture2D(m_HeightMap, texC).r;
    level += bias * m_MaxAmplitude;
    t = (level - m_CameraPosition.y) / eyeVecNorm.y;
    surfacePoint = m_CameraPosition + eyeVecNorm * t; 
    eyeVecNorm = normalize(m_CameraPosition - surfacePoint);

    #if __VERSION__ >= 130
        // Find normal of water surface
        float normal1 = textureOffset(m_HeightMap, texC, ivec2(-1.0,  0.0)).r;
        float normal2 = textureOffset(m_HeightMap, texC, ivec2( 1.0,  0.0)).r;
        float normal3 = textureOffset(m_HeightMap, texC, ivec2( 0.0, -1.0)).r;
        float normal4 = textureOffset(m_HeightMap, texC, ivec2( 0.0,  1.0)).r;
    #else
        // Find normal of water surface
        float normal1 = texture2D(m_HeightMap, (texC + vec2(-1.0, 0.0) / 256.0)).r;
        float normal2 = texture2D(m_HeightMap, (texC + vec2(1.0, 0.0) / 256.0)).r;
        float normal3 = texture2D(m_HeightMap, (texC + vec2(0.0, -1.0) / 256.0)).r;
        float normal4 = texture2D(m_HeightMap, (texC + vec2(0.0, 1.0) / 256.0)).r;
    #endif

    vec3 myNormal = normalize(vec3((normal1 - normal2) * m_MaxAmplitude,m_NormalScale,(normal3 - normal4) * m_MaxAmplitude));
    vec3 normal = myNormal*-1.0;
    float fresnel = fresnelTerm(normal, eyeVecNorm); 

    vec3 refraction = color2;
    #ifdef ENABLE_REFRACTION
        texC = texCoord.xy *sin (fresnel+1.0);
        texC = clamp(texC,0.0,1.0);
        refraction = fetchTextureSample(m_Texture, texC, sampleNum).rgb;
    #endif

   float waterCol = saturate(length(m_LightColor.rgb) / m_SunScale);
   refraction = mix(mix(refraction, m_DeepWaterColor.rgb * waterCol, m_WaterTransparency),  m_WaterColor.rgb* waterCol,m_WaterTransparency);

    vec3 foam = vec3(0.0);
    #ifdef ENABLE_FOAM    
        texC = (surfacePoint.xz + eyeVecNorm.xz * 0.1) * 0.05 + m_Time * 0.05 * m_WindDirection + sin(m_Time * 0.001 + position.x) * 0.005;
        vec2 texCoord2 = (surfacePoint.xz + eyeVecNorm.xz * 0.1) * 0.05 + m_Time * 0.1 * m_WindDirection + sin(m_Time * 0.001 + position.z) * 0.005;

        if(m_MaxAmplitude - m_FoamExistence.z> 0.0001){
            foam += ((texture2D(m_FoamMap, texC) + texture2D(m_FoamMap, texCoord2)) * m_FoamIntensity  * m_FoamIntensity * 0.3 *
               saturate((level - (m_WaterHeight + m_FoamExistence.z)) / (m_MaxAmplitude - m_FoamExistence.z))).rgb;
        }
        foam *= m_LightColor.rgb;    
    #endif



    vec3 specular = vec3(0.0);   
    vec3 color ;
    float fogFactor;

    if(position.y>level){
        #ifdef ENABLE_SPECULAR
            if(step(0.9999,sceneDepth)==1.0){
                vec3 lightDir=normalize(m_LightDir);
                vec3 mirrorEye = (2.0 * dot(eyeVecNorm, normal) * normal - eyeVecNorm);
                float dotSpec = saturate(dot(mirrorEye.xyz, -lightDir) * 0.5 + 0.5);
                specular = vec3((1.0 - fresnel) * saturate(-lightDir.y) * ((pow(dotSpec, 512.0)) * (m_Shininess * 1.8 + 0.2)));
                specular += specular * 25.0 * saturate(m_Shininess - 0.05);
                specular=specular * m_LightColor.rgb * 100.0;
            }
        #endif
        float fogIntensity= 8.0 * m_WaterTransparency;
        fogFactor = exp2( -fogIntensity * fogIntensity * cameraDepth * 0.03 * LOG2 );
        fogFactor = clamp(fogFactor, 0.0, 1.0);        
        color =mix(m_DeepWaterColor.rgb,refraction,fogFactor);   
        specular=specular*fogFactor;    
        color = saturate(color + max(specular, foam ));
    }else{
        vec3 caustics = vec3(0.0);
        #ifdef ENABLE_CAUSTICS 
            vec2 windDirection=m_WindDirection;
            texC = (position.xz + eyeVecNorm.xz * 0.1) * 0.05 + m_Time * 0.05 * windDirection + sin(m_Time  + position.x) * 0.01;
            vec2 texCoord2 = (position.xz + eyeVecNorm.xz * 0.1) * 0.05 + m_Time * 0.05 * windDirection + sin(m_Time  + position.z) * 0.01;
            caustics += (texture2D(m_CausticsMap, texC)+ texture2D(m_CausticsMap, texCoord2)).rgb;                  
            caustics=saturate(mix(m_WaterColor.rgb,caustics,m_CausticsIntensity));            
            color=mix(color2,caustics,m_CausticsIntensity);
        #else
            color=color2;
        #endif
                
        float fogDepth= (2.0 * m_FrustumNearFar.x) / (m_FrustumNearFar.y + m_FrustumNearFar.x - sceneDepth* (m_FrustumNearFar.y-m_FrustumNearFar.x));
        float fogIntensity= 18 * m_WaterTransparency;
        fogFactor = exp2( -fogIntensity * fogIntensity * fogDepth *  fogDepth * LOG2 );
        fogFactor = clamp(fogFactor, 0.0, 1.0);
        color =mix(m_DeepWaterColor.rgb,color,fogFactor);
    }

    return vec4(color, 1.0);   
}


// NOTE: This will be called even for single-sampling
vec4 main_multiSample(int sampleNum){
    // If we are underwater let's call the underwater function
    if(m_WaterHeight >= m_CameraPosition.y){
        #ifdef ENABLE_AREA      
            if(isOverExtent(m_CameraPosition, m_Center, m_Radius)){            
                return fetchTextureSample(m_Texture, texCoord, sampleNum);
            }   
        #endif
        return underWater(sampleNum);
    }

    float sceneDepth = fetchTextureSample(m_DepthTexture, texCoord, sampleNum).r;
    vec3 color2 = fetchTextureSample(m_Texture, texCoord, sampleNum).rgb;

    vec3 color = color2;
    vec3 position = getPosition(sceneDepth, texCoord);

    #ifdef ENABLE_AREA               
        if(isOverExtent(position, m_Center, m_Radius)){         
            return vec4(color2, 1.0);
        }
    #endif

    float level = m_WaterHeight;
    
    float isAtFarPlane = step(0.99998, sceneDepth);
    //#ifndef ENABLE_RIPPLES
    // This optimization won't work on NVIDIA cards if ripples are enabled
    if(position.y > level + m_MaxAmplitude + isAtFarPlane * 100.0){

        return vec4(color2, 1.0);
    }
    //#endif

    vec3 eyeVec = position - m_CameraPosition;    
    float cameraDepth = m_CameraPosition.y - position.y;

    // Find intersection with water surface
    vec3 eyeVecNorm = normalize(eyeVec);
    float t = (level - m_CameraPosition.y) / eyeVecNorm.y;
    vec3 surfacePoint = m_CameraPosition + eyeVecNorm * t;

    vec2 texC = vec2(0.0);
    int samples = 1;
    #ifdef ENABLE_HQ_SHORELINE
        samples = 10;
    #endif

    float biasFactor = 1.0 / samples;
    for (int i = 0; i < samples; i++){
        texC = (surfacePoint.xz + eyeVecNorm.xz * biasFactor) * scale + m_Time * 0.03 * m_WindDirection;

        float bias = texture2D(m_HeightMap, texC).r;

        bias *= biasFactor;
        level += bias * m_MaxAmplitude;
        t = (level - m_CameraPosition.y) / eyeVecNorm.y;
        surfacePoint = m_CameraPosition + eyeVecNorm * t;
    }

    float depth = length(position - surfacePoint);
    float depth2 = surfacePoint.y - position.y;

    // XXX: HACK ALERT: Increase water depth to infinity if at far plane
    // Prevents "foam on horizon" issue
    // For best results, replace the "100.0" below with the
    // highest value in the m_ColorExtinction vec3
    depth  += isAtFarPlane * 100.0;
    depth2 += isAtFarPlane * 100.0;

    eyeVecNorm = normalize(m_CameraPosition - surfacePoint);

    #if __VERSION__ >= 130
        // Find normal of water surface
        float normal1 = textureOffset(m_HeightMap, texC, ivec2(-1.0,  0.0)).r;
        float normal2 = textureOffset(m_HeightMap, texC, ivec2( 1.0,  0.0)).r;
        float normal3 = textureOffset(m_HeightMap, texC, ivec2( 0.0, -1.0)).r;
        float normal4 = textureOffset(m_HeightMap, texC, ivec2( 0.0,  1.0)).r;
    #else
        // Find normal of water surface
        float normal1 = texture2D(m_HeightMap, (texC + vec2(-1.0, 0.0) / 256.0)).r;
        float normal2 = texture2D(m_HeightMap, (texC + vec2(1.0, 0.0) / 256.0)).r;
        float normal3 = texture2D(m_HeightMap, (texC + vec2(0.0, -1.0) / 256.0)).r;
        float normal4 = texture2D(m_HeightMap, (texC + vec2(0.0, 1.0) / 256.0)).r;
    #endif

    vec3 myNormal = normalize(vec3((normal1 - normal2) * m_MaxAmplitude,m_NormalScale,(normal3 - normal4) * m_MaxAmplitude));
    vec3 normal = vec3(0.0);

    #ifdef ENABLE_RIPPLES
        texC = surfacePoint.xz * 0.8 + m_WindDirection * m_Time* 1.6;
        mat3 tangentFrame = computeTangentFrame(myNormal, eyeVecNorm, texC);
        vec3 normal0a = normalize(tangentFrame*(2.0 * texture2D(m_NormalMap, texC).xyz - 1.0));

        texC = surfacePoint.xz * 0.4 + m_WindDirection * m_Time* 0.8;
        tangentFrame = computeTangentFrame(myNormal, eyeVecNorm, texC);
        vec3 normal1a = normalize(tangentFrame*(2.0 * texture2D(m_NormalMap, texC).xyz - 1.0));

        texC = surfacePoint.xz * 0.2 + m_WindDirection * m_Time * 0.4;
        tangentFrame = computeTangentFrame(myNormal, eyeVecNorm, texC);
        vec3 normal2a = normalize(tangentFrame*(2.0 * texture2D(m_NormalMap, texC).xyz - 1.0));

        texC = surfacePoint.xz * 0.1 + m_WindDirection * m_Time * 0.2;
        tangentFrame = computeTangentFrame(myNormal, eyeVecNorm, texC);
        vec3 normal3a = normalize(tangentFrame*(2.0 * texture2D(m_NormalMap, texC).xyz - 1.0));

        normal = normalize(normal0a * normalModifier.x + normal1a * normalModifier.y +normal2a * normalModifier.z + normal3a * normalModifier.w);

         #if __VERSION__ >= 130
            // XXX: Here's another way to fix the terrain edge issue,
            // But it requires GLSL 1.3 and still looks kinda incorrect
            // around edges
            normal = isnan(normal.x) ? myNormal : normal;
        #else
            // To make the shader 1.2 compatible we use a trick :
            // we clamp the x value of the normal and compare it to it's former value instead of using isnan.
            normal = clamp(normal.x,0.0,1.0)!=normal.x ? myNormal : normal;
        #endif

    #else
        normal = myNormal;
    #endif

    vec3 refraction = color2;
    #ifdef ENABLE_REFRACTION
       // texC = texCoord.xy+ m_ReflectionDisplace * normal.x;
        texC = texCoord.xy;
        texC += sin(m_Time*1.8 + 3.0 * abs(position.y))* (refractionScale * min(depth2, 1.0));
        texC = clamp(texC,vec2(0.0),vec2(0.999));
        refraction = fetchTextureSample(m_Texture, texC, sampleNum).rgb;
    #endif
    vec3 waterPosition = surfacePoint.xyz;
    waterPosition.y -= (level - m_WaterHeight);
    vec4 texCoordProj = m_TextureProjMatrix * vec4(waterPosition, 1.0);

    texCoordProj.x = texCoordProj.x + m_ReflectionDisplace * normal.x;
    texCoordProj.z = texCoordProj.z + m_ReflectionDisplace * normal.z;
    texCoordProj /= texCoordProj.w;
    texCoordProj.y = 1.0 - texCoordProj.y;

    vec3 reflection = texture2D(m_ReflectionMap, texCoordProj.xy).rgb;

    float fresnel = fresnelTerm(normal, eyeVecNorm);

    float depthN = depth * m_WaterTransparency;
    float waterCol = saturate(length(m_LightColor.rgb) / m_SunScale);
    refraction = mix(mix(refraction, m_WaterColor.rgb * waterCol, saturate(depthN / visibility)),
        m_DeepWaterColor.rgb * waterCol, saturate(depth2 / m_ColorExtinction));


    vec3 foam = vec3(0.0);
    #ifdef ENABLE_FOAM
        texC = (surfacePoint.xz + eyeVecNorm.xz * 0.1) * 0.05 + m_Time * 0.05 * m_WindDirection + sin(m_Time * 0.001 + position.x) * 0.005;
        vec2 texCoord2 = (surfacePoint.xz + eyeVecNorm.xz * 0.1) * 0.05 + m_Time * 0.1 * m_WindDirection + sin(m_Time * 0.001 + position.z) * 0.005;

        vec4 foam1 = texture2D(m_FoamMap, texC);
        vec4 foam2 = texture2D(m_FoamMap, texCoord2);

        if(depth2 < m_FoamExistence.x){
            foam = (foam1.r + foam2).rgb * vec3(m_FoamIntensity);
        }else if(depth2 < m_FoamExistence.y){
            foam = mix((foam1 + foam2) * m_FoamIntensity , vec4(0.0),
                (depth2 - m_FoamExistence.x) / (m_FoamExistence.y - m_FoamExistence.x)).rgb;
        }

        
        if(m_MaxAmplitude - m_FoamExistence.z> 0.0001){
            foam += ((foam1 + foam2) * m_FoamIntensity  * m_FoamIntensity * 0.3 *
               saturate((level - (m_WaterHeight + m_FoamExistence.z)) / (m_MaxAmplitude - m_FoamExistence.z))).rgb;
        }
        foam *= m_LightColor.rgb;
    #endif

    vec3 specular = vec3(0.0);
    #ifdef ENABLE_SPECULAR
        vec3 lightDir=normalize(m_LightDir);
        vec3 mirrorEye = (2.0 * dot(eyeVecNorm, normal) * normal - eyeVecNorm);
        float dotSpec = saturate(dot(mirrorEye.xyz, -lightDir) * 0.5 + 0.5);
        specular = vec3((1.0 - fresnel) * saturate(-lightDir.y) * ((pow(dotSpec, 512.0)) * (m_Shininess * 1.8 + 0.2)));
        specular += specular * 25.0 * saturate(m_Shininess - 0.05);
        //foam does not shine
        specular=specular * m_LightColor.rgb - (5.0 * foam);
    #endif

    color = mix(refraction, reflection, fresnel);
    color = mix(refraction, color, saturate(depth * m_ShoreHardness));
    color = saturate(color + max(specular, foam ));
    color = mix(refraction, color, saturate(depth* m_FoamHardness));


    // XXX: HACK ALERT:
    // We trick the GeForces to think they have
    // to calculate the derivatives for all these pixels by using step()!
    // That way we won't get pixels around the edges of the terrain,
    // Where the derivatives are undefined
    return vec4(mix(color, color2, step(level, position.y)), 1.0);
}

void main(){
    #ifdef RESOLVE_MS
        vec4 color = vec4(0.0);
        for (int i = 0; i < m_NumSamples; i++){
            color += main_multiSample(i);
        }
        gl_FragColor = color / m_NumSamples;
    #else
        gl_FragColor = main_multiSample(0);
    #endif
}

This doesn’t use mat3x2 so it should work.

2 Likes

OK, Thank you. Now it’s working. I’ll do some more tests other than running the test projects. Is this fix good for production? performance wise?

1 Like

Yes, if you look at the instructions of the previous one, this is probably faster… not that it will be noticeable anyway

1 Like

The water filter seems to work fine but now I have a problem with the scene lights (see attached video)

Anyone can think what might be the problem? it happens only after adding the water filter. It also happens in the JME test: TestPostWater

And here are JME’s test apps in action with the Water filter. The “TestPostWater” doesn’t work good but the “TestMultiPostWater” seems fine…