Bug: Cannot use SSAO and Waterfilter together when multisampling is enabled

Hi,

Found this anoying bug in current git master: when you use SSAOFilter and Waterfilter at the same time while multisampling is enabled the engine crashes with a shader compile error.
Example:

public class Bug extends SimpleApplication {

@Override
public void simpleInitApp() {
	FilterPostProcessor fpp = new FilterPostProcessor(getAssetManager());
	fpp.setNumSamples(2);
	getViewPort().addProcessor(fpp);

	SSAOFilter ssao = new SSAOFilter();
	WaterFilter water = new WaterFilter(getRootNode(), new Vector3f(-1, -1,
			1));

	fpp.addFilter(ssao);
	fpp.addFilter(water);
}

public static void main(String[] args) {
	Bug app = new Bug();
	AppSettings settings = new AppSettings(true);
	settings.setSamples(2);
	app.setSettings(settings);
	app.start();
}
}

Depending on which filter is added later, one of the two following errors occur:

Mai 06, 2015 1:18:21 PM com.jme3.renderer.opengl.GLRenderer updateShaderSourceData
WARNUNG: Bad compile of:
1	#version 150 core
2	#define RESOLVE_DEPTH_MS 2
3	#define USE_AO 1
4	// -- begin import Common/ShaderLib/MultiSample.glsllib --
5	#extension GL_ARB_texture_multisample : enable
6	
7	uniform int m_NumSamples;
8	uniform int m_NumSamplesDepth;
9	
10	#ifdef RESOLVE_MS
11	    #define COLORTEXTURE sampler2DMS
12	#else
13	    #define COLORTEXTURE sampler2D
14	#endif
15	
16	#ifdef RESOLVE_DEPTH_MS
17	    #define DEPTHTEXTURE sampler2DMS
18	#else
19	    #define DEPTHTEXTURE sampler2D
20	#endif
21	
22	// NOTE: Only define multisample functions if multisample is available and is being used!
23	#if defined(GL_ARB_texture_multisample) && (defined(RESOLVE_MS) || defined(RESOLVE_DEPTH_MS))
24	vec4 textureFetch(in sampler2DMS tex,in vec2 texC, in int numSamples){
25	      ivec2 iTexC = ivec2(texC * vec2(textureSize(tex)));
26	      vec4 color = vec4(0.0);
27	      for (int i = 0; i < numSamples; i++){
28	         color += texelFetch(tex, iTexC, i);
29	      }
30	      return color / float(numSamples);
31	}
32	
33	vec4 fetchTextureSample(in sampler2DMS tex,in vec2 texC,in int sample){
34	    ivec2 iTexC = ivec2(texC * vec2(textureSize(tex)));
35	    return texelFetch(tex, iTexC, sample);
36	}
37	
38	vec4 getColor(in sampler2DMS tex, in vec2 texC){
39	      return textureFetch(tex, texC, m_NumSamples);
40	}
41	
42	vec4 getColorSingle(in sampler2DMS tex, in vec2 texC){
43	    ivec2 iTexC = ivec2(texC * vec2(textureSize(tex)));
44	    return texelFetch(tex, iTexC, 0);
45	}
46	
47	vec4 getDepth(in sampler2DMS tex,in vec2 texC){
48	      return textureFetch(tex,texC,m_NumSamplesDepth);
49	}
50	
51	#elif __VERSION__ >= 150
52	
53	vec4 fetchTextureSample(in sampler2D tex,in vec2 texC,in int sample){
54	    return texture(tex,texC);
55	}
56	
57	vec4 getColor(in sampler2D tex, in vec2 texC){
58	    return texture(tex,texC);
59	}
60	
61	vec4 getColorSingle(in sampler2D tex, in vec2 texC){
62	    return texture(tex, texC);
63	}
64	
65	vec4 getDepth(in sampler2D tex,in vec2 texC){
66	    return texture(tex,texC);
67	}
68	
69	#else
70	
71	vec4 fetchTextureSample(in sampler2D tex,in vec2 texC,in int sample){
72	    return texture2D(tex,texC);
73	}
74	
75	vec4 getColor(in sampler2D tex, in vec2 texC){
76	    return texture2D(tex,texC);
77	}
78	
79	vec4 getColorSingle(in sampler2D tex, in vec2 texC){
80	    return texture2D(tex, texC);
81	}
82	
83	vec4 getDepth(in sampler2D tex,in vec2 texC){
84	    return texture2D(tex,texC);
85	}
86	
87	#endif
88	// -- end import Common/ShaderLib/MultiSample.glsllib --
89	
90	uniform COLORTEXTURE m_Texture;
91	uniform DEPTHTEXTURE m_DepthTexture;
92	uniform sampler2D m_SSAOMap;
93	uniform bool m_UseOnlyAo;
94	uniform bool m_UseAo;
95	uniform float m_XScale;
96	uniform float m_YScale;
97	uniform vec2 m_FrustumNearFar;
98	
99	in vec2 texCoord;
100	
101	vec4 getResult(vec4 color){
102	 
103	    #ifdef USE_ONLY_AO
104	        return color;
105	    #endif
106	    #ifdef USE_AO
107	        return getColor(m_Texture,texCoord)* color;
108	    #endif
109	    
110	    return getColor(m_Texture,texCoord);
111	
112	}
113	
114	float readDepth(in vec2 uv){
115	    float depthv =fetchTextureSample(m_DepthTexture,uv,0).r;
116	    return (2.0 * m_FrustumNearFar.x) / (m_FrustumNearFar.y + m_FrustumNearFar.x - depthv* (m_FrustumNearFar.y-m_FrustumNearFar.x));
117	}
118	
119	 const float epsilon = 0.005;
120	
121	
122	    vec4 convolutionFilter(){
123	           vec4 sum = vec4(0.0);
124	
125	            float x = texCoord.x;
126	            float y = texCoord.y;
127	
128	            float xScale = m_XScale;
129	            float yScale = m_YScale;
130	       
131	            float zsum = 1.0;
132	        float Zp =readDepth(texCoord);
133	
134	
135	        vec2 sample = vec2(x - 2.0 * xScale, y - 2.0 * yScale);           
136	        float zTmp =readDepth(sample);
137	        float coefZ = 1.0 / (epsilon + abs(Zp - zTmp));               
138	        zsum += coefZ;
139	        sum += coefZ* texture2D( m_SSAOMap, sample);
140	
141	        sample = vec2(x - 0.0 * xScale, y - 2.0 * yScale);           
142	        zTmp =readDepth(sample);
143	        coefZ = 1.0 / (epsilon + abs(Zp - zTmp));               
144	        zsum += coefZ;
145	        sum += coefZ* texture2D( m_SSAOMap, sample);
146	
147	        sample = vec2(x + 2.0 * xScale, y - 2.0 * yScale);           
148	        zTmp =readDepth(sample);
149	        coefZ = 1.0 / (epsilon + abs(Zp - zTmp));               
150	        zsum += coefZ;
151	        sum += coefZ* texture2D( m_SSAOMap, sample);
152	
153	        sample = vec2(x - 1.0 * xScale, y - 1.0 * yScale);           
154	        zTmp =readDepth(sample);
155	        coefZ = 1.0 / (epsilon + abs(Zp - zTmp));               
156	        zsum += coefZ;
157	        sum += coefZ* texture2D( m_SSAOMap, sample);
158	
159	        sample = vec2(x + 1.0 * xScale, y - 1.0 * yScale);           
160	        zTmp =readDepth(sample);
161	        coefZ = 1.0 / (epsilon + abs(Zp - zTmp));               
162	        zsum += coefZ;
163	        sum += coefZ* texture2D( m_SSAOMap, sample);
164	  
165	        sample = vec2(x - 2.0 * xScale, y - 0.0 * yScale);           
166	        zTmp =readDepth(sample);
167	        coefZ = 1.0 / (epsilon + abs(Zp - zTmp));               
168	        zsum += coefZ;
169	        sum += coefZ* texture2D( m_SSAOMap, sample);
170	
171	        sample = vec2(x + 2.0 * xScale, y - 0.0 * yScale);           
172	        zTmp =readDepth(sample);
173	        coefZ = 1.0 / (epsilon + abs(Zp - zTmp));               
174	        zsum += coefZ;
175	        sum += coefZ* texture2D( m_SSAOMap, sample);
176	
177	        sample = vec2(x - 1.0 * xScale, y + 1.0 * yScale);           
178	        zTmp =readDepth(sample);
179	        coefZ = 1.0 / (epsilon + abs(Zp - zTmp));               
180	        zsum += coefZ;
181	        sum += coefZ* texture2D( m_SSAOMap, sample);
182	   
183	        sample = vec2(x + 1.0 * xScale, y + 1.0 * yScale);           
184	        zTmp =readDepth(sample);
185	        coefZ = 1.0 / (epsilon + abs(Zp - zTmp));               
186	        zsum += coefZ;
187	        sum += coefZ* texture2D( m_SSAOMap, sample);
188	
189	        sample = vec2(x - 2.0 * xScale, y + 2.0 * yScale);           
190	        zTmp =readDepth(sample);
191	        coefZ = 1.0 / (epsilon + abs(Zp - zTmp));               
192	        zsum += coefZ;
193	        sum += coefZ* texture2D( m_SSAOMap, sample);
194	  
195	        sample = vec2(x - 0.0 * xScale, y + 2.0 * yScale);           
196	        zTmp =readDepth(sample);
197	        coefZ = 1.0 / (epsilon + abs(Zp - zTmp));               
198	        zsum += coefZ;
199	        sum += coefZ* texture2D( m_SSAOMap, sample);
200	
201	        sample = vec2(x + 2.0 * xScale, y + 2.0 * yScale);           
202	        zTmp =readDepth(sample);
203	        coefZ = 1.0 / (epsilon + abs(Zp - zTmp));               
204	        zsum += coefZ;
205	        sum += coefZ* texture2D( m_SSAOMap, sample);
206	
207	
208	        return  sum / zsum;
209	    }
210	
211	
212	    void main(){
213	        //  float depth =texture2D(m_DepthTexture,uv).r;
214	
215	       gl_FragColor=getResult(convolutionFilter());
216	      // gl_FragColor=getResult(bilateralFilter());
217	      //  gl_FragColor=getColor(m_SSAOMap,texCoord);
218	
219	    }

Mai 06, 2015 1:18:21 PM com.jme3.app.Application handleError
SCHWERWIEGEND: Uncaught exception thrown in Thread[jME3 Main,5,main]
com.jme3.renderer.RendererException: compile error in: ShaderSource[name=Common/MatDefs/SSAO/ssaoBlur15.frag, defines, type=Fragment, language=GLSL150]
0(107) : error C1102: incompatible type for parameter #1 ("tex")
0(110) : error C1102: incompatible type for parameter #1 ("tex")
0(215) : warning C7533: global variable gl_FragColor is deprecated after version 120

Or

Mai 06, 2015 1:27:17 PM com.jme3.renderer.opengl.GLRenderer updateShaderSourceData
WARNUNG: Bad compile of:
1	#version 150 core
2	#define ENABLE_CAUSTICS 1
3	#define ENABLE_FOAM 1
4	#define ENABLE_HQ_SHORELINE 1
5	#define ENABLE_REFRACTION 1
6	#define ENABLE_RIPPLES 1
7	#define ENABLE_SPECULAR 1
8	#define RESOLVE_DEPTH_MS 2
9	// -- begin import Common/ShaderLib/MultiSample.glsllib --
10	#extension GL_ARB_texture_multisample : enable
11	
12	uniform int m_NumSamples;
13	uniform int m_NumSamplesDepth;
14	
15	#ifdef RESOLVE_MS
16	    #define COLORTEXTURE sampler2DMS
17	#else
18	    #define COLORTEXTURE sampler2D
19	#endif
20	
21	#ifdef RESOLVE_DEPTH_MS
22	    #define DEPTHTEXTURE sampler2DMS
23	#else
24	    #define DEPTHTEXTURE sampler2D
25	#endif
26	
27	// NOTE: Only define multisample functions if multisample is available and is being used!
28	#if defined(GL_ARB_texture_multisample) && (defined(RESOLVE_MS) || defined(RESOLVE_DEPTH_MS))
29	vec4 textureFetch(in sampler2DMS tex,in vec2 texC, in int numSamples){
30	      ivec2 iTexC = ivec2(texC * vec2(textureSize(tex)));
31	      vec4 color = vec4(0.0);
32	      for (int i = 0; i < numSamples; i++){
33	         color += texelFetch(tex, iTexC, i);
34	      }
35	      return color / float(numSamples);
36	}
37	
38	vec4 fetchTextureSample(in sampler2DMS tex,in vec2 texC,in int sample){
39	    ivec2 iTexC = ivec2(texC * vec2(textureSize(tex)));
40	    return texelFetch(tex, iTexC, sample);
41	}
42	
43	vec4 getColor(in sampler2DMS tex, in vec2 texC){
44	      return textureFetch(tex, texC, m_NumSamples);
45	}
46	
47	vec4 getColorSingle(in sampler2DMS tex, in vec2 texC){
48	    ivec2 iTexC = ivec2(texC * vec2(textureSize(tex)));
49	    return texelFetch(tex, iTexC, 0);
50	}
51	
52	vec4 getDepth(in sampler2DMS tex,in vec2 texC){
53	      return textureFetch(tex,texC,m_NumSamplesDepth);
54	}
55	
56	#elif __VERSION__ >= 150
57	
58	vec4 fetchTextureSample(in sampler2D tex,in vec2 texC,in int sample){
59	    return texture(tex,texC);
60	}
61	
62	vec4 getColor(in sampler2D tex, in vec2 texC){
63	    return texture(tex,texC);
64	}
65	
66	vec4 getColorSingle(in sampler2D tex, in vec2 texC){
67	    return texture(tex, texC);
68	}
69	
70	vec4 getDepth(in sampler2D tex,in vec2 texC){
71	    return texture(tex,texC);
72	}
73	
74	#else
75	
76	vec4 fetchTextureSample(in sampler2D tex,in vec2 texC,in int sample){
77	    return texture2D(tex,texC);
78	}
79	
80	vec4 getColor(in sampler2D tex, in vec2 texC){
81	    return texture2D(tex,texC);
82	}
83	
84	vec4 getColorSingle(in sampler2D tex, in vec2 texC){
85	    return texture2D(tex, texC);
86	}
87	
88	vec4 getDepth(in sampler2D tex,in vec2 texC){
89	    return texture2D(tex,texC);
90	}
91	
92	#endif
93	// -- end import Common/ShaderLib/MultiSample.glsllib --
94	// -- begin import Common/ShaderLib/WaterUtil.glsllib --
95	#ifdef ENABLE_AREA        
96	bool isOverExtent(vec3 position,vec3 center,float radius){
97	        vec2 dist = position.xz-center.xz;
98	        #ifdef SQUARE_AREA 
99	                return dist.x*dist.x >radius || dist.y*dist.y >radius;
100	        #else
101	                return dot(dist,dist)>radius;
102	        #endif
103	}
104	#endif
105	// -- end import Common/ShaderLib/WaterUtil.glsllib --
106	
107	// Water pixel shader
108	// Copyright (C) JMonkeyEngine 3.0
109	// by Remy Bouquet (nehon) for JMonkeyEngine 3.0
110	// original HLSL version by Wojciech Toman 2009
111	
112	uniform COLORTEXTURE m_Texture;
113	uniform DEPTHTEXTURE m_DepthTexture;
114	
115	
116	uniform sampler2D m_HeightMap;
117	uniform sampler2D m_NormalMap;
118	uniform sampler2D m_FoamMap;
119	uniform sampler2D m_CausticsMap;
120	uniform sampler2D m_ReflectionMap;
121	
122	uniform mat4 g_ViewProjectionMatrixInverse;
123	uniform mat4 m_TextureProjMatrix;
124	uniform vec3 m_CameraPosition;
125	
126	uniform float m_WaterHeight;
127	uniform float m_Time;
128	uniform float m_WaterTransparency;
129	uniform float m_NormalScale;
130	uniform float m_R0;
131	uniform float m_MaxAmplitude;
132	uniform vec3 m_LightDir;
133	uniform vec4 m_LightColor;
134	uniform float m_ShoreHardness;
135	uniform float m_FoamHardness;
136	uniform float m_RefractionStrength;
137	uniform vec3 m_FoamExistence;
138	uniform vec3 m_ColorExtinction;
139	uniform float m_Shininess;
140	uniform vec4 m_WaterColor;
141	uniform vec4 m_DeepWaterColor;
142	uniform vec2 m_WindDirection;
143	uniform float m_SunScale;
144	uniform float m_WaveScale;
145	uniform float m_UnderWaterFogDistance;
146	uniform float m_CausticsIntensity;
147	
148	#ifdef ENABLE_AREA
149	uniform vec3 m_Center;
150	uniform float m_Radius;
151	#endif
152	
153	
154	vec2 scale = vec2(m_WaveScale, m_WaveScale);
155	float refractionScale = m_WaveScale;
156	
157	// Modifies 4 sampled normals. Increase first values to have more
158	// smaller "waves" or last to have more bigger "waves"
159	const vec4 normalModifier = vec4(3.0, 2.0, 4.0, 10.0);
160	// Strength of displacement along normal.
161	uniform float m_ReflectionDisplace;
162	// Water transparency along eye vector.
163	const float visibility = 3.0;
164	// foam intensity
165	uniform float m_FoamIntensity ;
166	
167	in vec2 texCoord;
168	out vec4 outFragColor;
169	
170	mat3 MatrixInverse(in mat3 inMatrix){
171	    float det = dot(cross(inMatrix[0], inMatrix[1]), inMatrix[2]);
172	    mat3 T = transpose(inMatrix);
173	    return mat3(cross(T[1], T[2]),
174	        cross(T[2], T[0]),
175	        cross(T[0], T[1])) / det;
176	}
177	
178	
179	mat3 computeTangentFrame(in vec3 N, in vec3 P, in vec2 UV) {
180	    vec3 dp1 = dFdx(P);
181	    vec3 dp2 = dFdy(P);
182	    vec2 duv1 = dFdx(UV);
183	    vec2 duv2 = dFdy(UV);
184	
185	    // solve the linear system
186	    vec3 dp1xdp2 = cross(dp1, dp2);
187	    mat2x3 inverseM = mat2x3(cross(dp2, dp1xdp2), cross(dp1xdp2, dp1));
188	
189	    vec3 T = inverseM * vec2(duv1.x, duv2.x);
190	    vec3 B = inverseM * vec2(duv1.y, duv2.y);
191	
192	    // construct tangent frame
193	    float maxLength = max(length(T), length(B));
194	    T = T / maxLength;
195	    B = B / maxLength;
196	
197	    return mat3(T, B, N);
198	}
199	
200	float saturate(in float val){
201	    return clamp(val,0.0,1.0);
202	}
203	
204	vec3 saturate(in vec3 val){
205	    return clamp(val,vec3(0.0),vec3(1.0));
206	}
207	
208	vec3 getPosition(in float depth, in vec2 uv){
209	    vec4 pos = vec4(uv, depth, 1.0) * 2.0 - 1.0;
210	    pos = g_ViewProjectionMatrixInverse * pos;
211	    return pos.xyz / pos.w;
212	}
213	
214	// Function calculating fresnel term.
215	// - normal - normalized normal vector
216	// - eyeVec - normalized eye vector
217	float fresnelTerm(in vec3 normal,in vec3 eyeVec){
218	    float angle = 1.0 - max(0.0, dot(normal, eyeVec));
219	    float fresnel = angle * angle;
220	    fresnel = fresnel * fresnel;
221	    fresnel = fresnel * angle;
222	    return saturate(fresnel * (1.0 - saturate(m_R0)) + m_R0 - m_RefractionStrength);
223	}
224	
225	vec2 m_FrustumNearFar=vec2(1.0,m_UnderWaterFogDistance);
226	const float LOG2 = 1.442695;
227	
228	vec4 underWater(int sampleNum){
229	
230	
231	    float sceneDepth = fetchTextureSample(m_DepthTexture, texCoord, sampleNum).r;
232	    vec3 color2 = fetchTextureSample(m_Texture, texCoord, sampleNum).rgb;
233	    
234	    vec3 position = getPosition(sceneDepth, texCoord);  
235	    float level = m_WaterHeight;
236	
237	    vec3 eyeVec = position - m_CameraPosition;    
238	 
239	    // Find intersection with water surface
240	    vec3 eyeVecNorm = normalize(eyeVec);
241	    float t = (level - m_CameraPosition.y) / eyeVecNorm.y;
242	    vec3 surfacePoint = m_CameraPosition + eyeVecNorm * t;
243	
244	    vec2 texC = vec2(0.0);
245	
246	    float cameraDepth = length(m_CameraPosition - surfacePoint);  
247	    texC = (surfacePoint.xz + eyeVecNorm.xz) * scale + m_Time * 0.03 * m_WindDirection;
248	    float bias = texture(m_HeightMap, texC).r;
249	    level += bias * m_MaxAmplitude;
250	    t = (level - m_CameraPosition.y) / eyeVecNorm.y;
251	    surfacePoint = m_CameraPosition + eyeVecNorm * t; 
252	    eyeVecNorm = normalize(m_CameraPosition - surfacePoint);
253	
254	    // Find normal of water surface
255	    float normal1 = textureOffset(m_HeightMap, texC, ivec2(-1.0,  0.0)).r;
256	    float normal2 = textureOffset(m_HeightMap, texC, ivec2( 1.0,  0.0)).r;
257	    float normal3 = textureOffset(m_HeightMap, texC, ivec2( 0.0, -1.0)).r;
258	    float normal4 = textureOffset(m_HeightMap, texC, ivec2( 0.0,  1.0)).r;
259	
260	    vec3 myNormal = normalize(vec3((normal1 - normal2) * m_MaxAmplitude,m_NormalScale,(normal3 - normal4) * m_MaxAmplitude));
261	    vec3 normal = myNormal*-1.0;
262	    float fresnel = fresnelTerm(normal, eyeVecNorm); 
263	
264	    vec3 refraction = color2;
265	    #ifdef ENABLE_REFRACTION
266	        texC = texCoord.xy *sin (fresnel+1.0);
267	        texC = clamp(texC,0.0,1.0);
268	        #ifdef RESOLVE_MS
269	            ivec2 iTexC = ivec2(texC * textureSize(m_Texture));
270	            refraction = texelFetch(m_Texture, iTexC, sampleNum).rgb;
271	        #else
272	            ivec2 iTexC = ivec2(texC * textureSize(m_Texture, 0));
273	            refraction = texelFetch(m_Texture, iTexC, 0).rgb;
274	        #endif
275	    #endif 
276	
277	   float waterCol = saturate(length(m_LightColor.rgb) / m_SunScale);
278	   refraction = mix(mix(refraction, m_DeepWaterColor.rgb * waterCol, m_WaterTransparency),  m_WaterColor.rgb* waterCol,m_WaterTransparency);
279	
280	    vec3 foam = vec3(0.0);
281	    #ifdef ENABLE_FOAM    
282	        texC = (surfacePoint.xz + eyeVecNorm.xz * 0.1) * 0.05 + m_Time * 0.05 * m_WindDirection + sin(m_Time * 0.001 + position.x) * 0.005;
283	        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;
284	
285	        if(m_MaxAmplitude - m_FoamExistence.z> 0.0001){
286	            foam += ((texture2D(m_FoamMap, texC) + texture2D(m_FoamMap, texCoord2)) * m_FoamIntensity  * m_FoamIntensity * 0.3 *
287	               saturate((level - (m_WaterHeight + m_FoamExistence.z)) / (m_MaxAmplitude - m_FoamExistence.z))).rgb;
288	        }
289	        foam *= m_LightColor.rgb;    
290	    #endif
291	
292	
293	
294	    vec3 specular = vec3(0.0);   
295	    vec3 color ;
296	    float fogFactor;
297	
298	    if(position.y>level){
299	        #ifdef ENABLE_SPECULAR
300	            if(step(0.9999,sceneDepth)==1.0){
301	                vec3 lightDir=normalize(m_LightDir);
302	                vec3 mirrorEye = (2.0 * dot(eyeVecNorm, normal) * normal - eyeVecNorm);
303	                float dotSpec = saturate(dot(mirrorEye.xyz, -lightDir) * 0.5 + 0.5);
304	                specular = vec3((1.0 - fresnel) * saturate(-lightDir.y) * ((pow(dotSpec, 512.0)) * (m_Shininess * 1.8 + 0.2)));
305	                specular += specular * 25.0 * saturate(m_Shininess - 0.05);
306	                specular=specular * m_LightColor.rgb * 100.0;
307	            }
308	        #endif
309	        float fogIntensity= 8.0 * m_WaterTransparency;
310	        fogFactor = exp2( -fogIntensity * fogIntensity * cameraDepth * 0.03 * LOG2 );
311	        fogFactor = clamp(fogFactor, 0.0, 1.0);        
312	        color =mix(m_DeepWaterColor.rgb,refraction,fogFactor);   
313	        specular=specular*fogFactor;    
314	        color = saturate(color + max(specular, foam ));
315	    }else{
316	        vec3 caustics = vec3(0.0);
317	        #ifdef ENABLE_CAUSTICS 
318	            vec2 windDirection=m_WindDirection;
319	            texC = (position.xz + eyeVecNorm.xz * 0.1) * 0.05 + m_Time * 0.05 * windDirection + sin(m_Time  + position.x) * 0.01;
320	            vec2 texCoord2 = (position.xz + eyeVecNorm.xz * 0.1) * 0.05 + m_Time * 0.05 * windDirection + sin(m_Time  + position.z) * 0.01;
321	            caustics += (texture2D(m_CausticsMap, texC)+ texture2D(m_CausticsMap, texCoord2)).rgb;                  
322	            caustics=saturate(mix(m_WaterColor.rgb,caustics,m_CausticsIntensity));            
323	            color=mix(color2,caustics,m_CausticsIntensity);
324	        #else
325	            color=color2;
326	        #endif
327	                
328	        float fogDepth= (2.0 * m_FrustumNearFar.x) / (m_FrustumNearFar.y + m_FrustumNearFar.x - sceneDepth* (m_FrustumNearFar.y-m_FrustumNearFar.x));
329	        float fogIntensity= 18 * m_WaterTransparency;
330	        fogFactor = exp2( -fogIntensity * fogIntensity * fogDepth *  fogDepth * LOG2 );
331	        fogFactor = clamp(fogFactor, 0.0, 1.0);
332	        color =mix(m_DeepWaterColor.rgb,color,fogFactor);
333	    }
334	
335	    return vec4(color, 1.0);   
336	}
337	
338	
339	// NOTE: This will be called even for single-sampling
340	vec4 main_multiSample(int sampleNum){
341	    // If we are underwater let's call the underwater function
342	    if(m_WaterHeight >= m_CameraPosition.y){
343	        #ifdef ENABLE_AREA      
344	            if(isOverExtent(m_CameraPosition, m_Center, m_Radius)){            
345	                return fetchTextureSample(m_Texture, texCoord, sampleNum);
346	            }   
347	        #endif
348	        return underWater(sampleNum);
349	    }
350	
351	    float sceneDepth = fetchTextureSample(m_DepthTexture, texCoord, sampleNum).r;
352	    vec3 color2 = fetchTextureSample(m_Texture, texCoord, sampleNum).rgb;
353	
354	    vec3 color = color2;
355	    vec3 position = getPosition(sceneDepth, texCoord);
356	
357	    #ifdef ENABLE_AREA               
358	        if(isOverExtent(position, m_Center, m_Radius)){         
359	            return vec4(color2, 1.0);
360	        }
361	    #endif
362	
363	    float level = m_WaterHeight;
364	    
365	    float isAtFarPlane = step(0.99998, sceneDepth);
366	    //#ifndef ENABLE_RIPPLES
367	    // This optimization won't work on NVIDIA cards if ripples are enabled
368	    if(position.y > level + m_MaxAmplitude + isAtFarPlane * 100.0){
369	
370	        return vec4(color2, 1.0);
371	    }
372	    //#endif
373	
374	    vec3 eyeVec = position - m_CameraPosition;    
375	    float cameraDepth = m_CameraPosition.y - position.y;
376	
377	    // Find intersection with water surface
378	    vec3 eyeVecNorm = normalize(eyeVec);
379	    float t = (level - m_CameraPosition.y) / eyeVecNorm.y;
380	    vec3 surfacePoint = m_CameraPosition + eyeVecNorm * t;
381	
382	    vec2 texC = vec2(0.0);
383	    int samples = 1;
384	    #ifdef ENABLE_HQ_SHORELINE
385	        samples = 10;
386	    #endif
387	
388	    float biasFactor = 1.0 / samples;
389	    for (int i = 0; i < samples; i++){
390	        texC = (surfacePoint.xz + eyeVecNorm.xz * biasFactor) * scale + m_Time * 0.03 * m_WindDirection;
391	
392	        float bias = texture(m_HeightMap, texC).r;
393	
394	        bias *= biasFactor;
395	        level += bias * m_MaxAmplitude;
396	        t = (level - m_CameraPosition.y) / eyeVecNorm.y;
397	        surfacePoint = m_CameraPosition + eyeVecNorm * t;
398	    }
399	
400	    float depth = length(position - surfacePoint);
401	    float depth2 = surfacePoint.y - position.y;
402	
403	    // XXX: HACK ALERT: Increase water depth to infinity if at far plane
404	    // Prevents "foam on horizon" issue
405	    // For best results, replace the "100.0" below with the
406	    // highest value in the m_ColorExtinction vec3
407	    depth  += isAtFarPlane * 100.0;
408	    depth2 += isAtFarPlane * 100.0;
409	
410	    eyeVecNorm = normalize(m_CameraPosition - surfacePoint);
411	
412	    // Find normal of water surface
413	    float normal1 = textureOffset(m_HeightMap, texC, ivec2(-1.0,  0.0)).r;
414	    float normal2 = textureOffset(m_HeightMap, texC, ivec2( 1.0,  0.0)).r;
415	    float normal3 = textureOffset(m_HeightMap, texC, ivec2( 0.0, -1.0)).r;
416	    float normal4 = textureOffset(m_HeightMap, texC, ivec2( 0.0,  1.0)).r;
417	
...

Mai 06, 2015 1:27:17 PM com.jme3.app.Application handleError
SCHWERWIEGEND: Uncaught exception thrown in Thread[jME3 Main,5,main]
com.jme3.renderer.RendererException: compile error in: ShaderSource[name=Common/MatDefs/Water/Water15.frag, defines, type=Fragment, language=GLSL150]
0(232) : error C1102: incompatible type for parameter #1 ("tex")
0(352) : error C1102: incompatible type for parameter #1 ("tex")

Works fine if either one of the filters is disabled or samples are set to 1.

Thanks for he test case and report. I’m gonna use into it.

Just fixed it myself:

From d3f263f6b710a384a053483e32c7b220a0c0ce68 Mon Sep 17 00:00:00 2001
Date: Fri, 8 May 2015 09:03:52 +0200
Subject: [PATCH] Fix filters when using multisample

---
 jme3-core/src/main/java/com/jme3/post/Filter.java              | 4 ++--
 jme3-core/src/main/java/com/jme3/post/FilterPostProcessor.java | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/jme3-core/src/main/java/com/jme3/post/Filter.java b/jme3-core/src/main/java/com/jme3/post/Filter.java
index a6e2e3c..1ea08c4 100644
--- a/jme3-core/src/main/java/com/jme3/post/Filter.java
+++ b/jme3-core/src/main/java/com/jme3/post/Filter.java
@@ -234,10 +234,10 @@ public abstract class Filter implements Savable {
      * @param w the width
      * @param h the height
      */
-    protected final void init(AssetManager manager, RenderManager renderManager, ViewPort vp, int w, int h) {
+    protected final void init(AssetManager manager, RenderManager renderManager, ViewPort vp, int w, int h, int numSamples) {
         //  cleanup(renderManager.getRenderer());
         defaultPass = new Pass();
-        defaultPass.init(renderManager.getRenderer(), w, h, getDefaultPassTextureFormat(), getDefaultPassDepthFormat());
+        defaultPass.init(renderManager.getRenderer(), w, h, getDefaultPassTextureFormat(), getDefaultPassDepthFormat(), numSamples);
         initFilter(manager, renderManager, vp, w, h);
     }
 
diff --git a/jme3-core/src/main/java/com/jme3/post/FilterPostProcessor.java b/jme3-core/src/main/java/com/jme3/post/FilterPostProcessor.java
index 2cd8b83..462f033 100644
--- a/jme3-core/src/main/java/com/jme3/post/FilterPostProcessor.java
+++ b/jme3-core/src/main/java/com/jme3/post/FilterPostProcessor.java
@@ -170,10 +170,10 @@ public class FilterPostProcessor implements SceneProcessor, Savable {
                 renderFrameBuffer.setDepthTexture(depthTexture);
             }
             computeDepth = true;
-            filter.init(assetManager, renderManager, vp, width, height);
+            filter.init(assetManager, renderManager, vp, width, height, numSamples);
             filter.setDepthTexture(depthTexture);
         } else {
-            filter.init(assetManager, renderManager, vp, width, height);
+            filter.init(assetManager, renderManager, vp, width, height, numSamples);
         }
     }
 
-- 
2.4.0
3 Likes

oh doh…that’s a dumb error
Thanks a lot, I’ll commit this

Edit : And now I wonder how it ever worked actually…

I commited the patch, thanks again.

@qxCsXO1 Could you please test if your use case still work?
I reverted the fix because it was not valid in the end, and introduced other issues. however I committed a fix that should aleviate the issue.

Now I got it :stuck_out_tongue:

Looks like the new fix works. Thanks