Shader not rendering correctly

This is driving me mad… I have a fragment shader that generates up to 4 ripples on the screen, but it doesn’t render correctly. The ripples go about halfway, then flash to the edge of the screen.

I used to have all the code (repeated 4 times) in main(). In that version, only one of my waves would render incorrectly. After moving the code to a function they all do. Also, performance is much worse with the function…


precision mediump float;

uniform vec4 u_Wave0;
uniform vec4 u_Wave1;
uniform vec4 u_Wave2;
uniform vec4 u_Wave3;

varying vec3 v_Position;
varying vec4 v_Color;

vec4 getColor(in vec4 wave, in vec3 coord, in vec4 vcolor) {
	vec4 newColor = vec4(0.1, 0.2, 0.4, 1.0);
	vec4 white = vec4(1, 1, 1, 1);
	float distance = distance(coord.xy, wave.xy);
	float wave1 = abs(distance - wave.z); 
	wave1 = clamp(wave1, 0.0, 25.0);  
	wave1 = (25.0 - wave1) / 35.0;
	vec4 color = mix(vcolor, white, newColor.rrra);
	color = mix(vcolor, color, wave1);
	return color;
}

void main()                    		
{
	vec3 coord = gl_FragCoord.xyz;
	
	vec4 color = getColor(u_Wave0, coord, v_Color);
	vec4 color1 = getColor(u_Wave1, coord, v_Color);
	vec4 color2 = getColor(u_Wave2, coord, v_Color);
	vec4 color3 = getColor(u_Wave3, coord, v_Color);
	
	color3 = max(color3, color);
	color3 = max(color3, color1);
	color3 = max(color3, color2);
	
	gl_FragColor = color3;                             		
}                                                                     	

I would guess that you need to interpolate them, instead of maxing them. (a+b) / 2 should do the trick I think :smiley:

I changed to max() only to see if that had an effect, before that I was doing another mix(). There is no difference between the two versions, they both show the flash to edge bug.

EDIT: It is definitely a bug in my Asus Memo Pad HD GPU. simply duplicating the function changes the behavior (the copied function behaves correctly)… In this I cut it down to two ripples, with a duplicate function only one has the flash bug.


precision mediump float;

uniform vec4 u_Wave0;
uniform vec4 u_Wave1;
uniform vec4 u_Wave2;
uniform vec4 u_Wave3;

varying vec3 v_Position;
varying vec4 v_Color;

vec4 getColor(in vec4 wave, in vec3 coord, in vec4 vcolor) {
   vec4 newColor = vec4(0.1, 0.2, 0.4, 1.0);
   vec4 white = vec4(1, 1, 1, 1);
   float distance = distance(coord.xy, wave.xy);
   float wave1 = abs(distance - wave.z); 
   wave1 = clamp(wave1, 0.0, 25.0);  
   wave1 = (25.0 - wave1) / 35.0;
   vec4 color = mix(vcolor, white, newColor.rrra);
   color = mix(vcolor, color, wave1);
   return color;
}

vec4 getColorD(in vec4 wave, in vec3 coord, in vec4 vcolor) {
   vec4 newColor = vec4(0.1, 0.2, 0.4, 1.0);
   vec4 white = vec4(1, 1, 1, 1);
   float distance = distance(coord.xy, wave.xy);
   float wave1 = abs(distance - wave.z); 
   wave1 = clamp(wave1, 0.0, 25.0);  
   wave1 = (25.0 - wave1) / 35.0;
   vec4 color = mix(vcolor, white, newColor.bbba);
   color = mix(vcolor, color, wave1);
   return color;
}

void main()                          
{
   vec3 coord = gl_FragCoord.xyz;
   
   vec4 color = getColor(u_Wave0, coord, v_Color);
   vec4 color1 = getColor(u_Wave1, coord, v_Color);
   //vec4 color2 = getColor(u_Wave2, coord, v_Color);
   //vec4 color3 = getColor(u_Wave3, coord, v_Color);
   
   vec4 color3 = max(color, color1);
   //color3 = max(color3, color1);
   //color3 = max(color3, color2);
   
   gl_FragColor = color3;                                   
}                              

Are you sure it’s a bug? The duplicate function is not the same

vec4 color = mix(vcolor, white, newColor.bbba);

vs

vec4 color = mix(vcolor, white, newColor.rrra);

I don’t think that caused your problem though. Could you post a pic?

I introduced that small difference to ensure the compiler didn’t optimize out the duplicate. Since then I optimised the function like this:

[s]vec4 [/s]float get[s]Color[/s]Wave(in vec4 wave, in vec3 coord[s], in vec4 vcolor[/s]) { [s]vec4 newColor = vec4(0.1, 0.2, 0.4, 1.0); vec4 white = vec4(1, 1, 1, 1);[/s] float distance = distance(coord.xy, wave.xy); float wave1 = abs(distance - wave.z); [s]wave1 = [/s]return clamp(wave1, 0.0, 25.0); [s]wave1 = (25.0 - wave1) / 35.0; vec4 color = mix(vcolor, white, newColor.rrra); color = mix(vcolor, color, wave1); return color;[/s] }

So all the color processing is only done once in main()… which gets me 5fps more on my tablet, but which also means the two functions really are identical now.

I have it working now - I call the duplicate function, discard its results then call the real function and it all works ok.

Hmmmm, that’s a bummer :-. Well cool that you got it working!