Problem with return/discard

Hello everybody,

i am currently working on a raycasting shader and after an update of
my graphic card driver (OpenGL version 3.3.0 NVIDIA 270.41.19) i
discovered a strange behaviour of the fragment shader. I first thought
it was a bug but yesterday i observered the same behaviour on a ati
graphic card.

Here is the problem. I will just post the ray marching loop.
First the non working version:


void main() {
....
do
	{
		prev_pos = ray_pos;
		ray_pos += ray_dir * sample;
		
		if (any(greaterThan(ray_pos,pos111))) {
			break;
		}

		if (any(lessThan(ray_pos,pos000))){
			break;
		}
		
		val = texture(volumeTexture, ray_pos).r;
		bool sign_cur = val > 0.5f;

		if (sign_cur != sign_prev) {
			vec3 iso_pos = (prev_pos+ray_pos)*0.5;
			out_color = computeFragColor(iso_pos);
			return; //Set fragment to color and end
		}
	} while(true);

	discard; //

}


The volume is not rendered. The problem has to do with the
return/discard keywords. Discard seems to throw away every fragment.
So i concluded that maybe the return statement has no effect.
Switching to this code, and the problem is solved:


void main() {
....
out_color = vec4(1.0f,1.0f,1.0f,1.0f); //<----set default color 		
do
	{
		prev_pos = ray_pos;
		ray_pos += ray_dir * sample;
		
		if (any(greaterThan(ray_pos,pos111))) {
			break;
		}

		if (any(lessThan(ray_pos,pos000))){
			break;
		}
		
		val = texture(volumeTexture, ray_pos).r;
		bool sign_cur = val > 0.5f;

		if (sign_cur != sign_prev) {
			vec3 iso_pos = (prev_pos+ray_pos)*0.5;
			out_color = computeFragColor(iso_pos);
			break;  //return; <---- change return to break;
			
		}
	} while(true);
	//discard; <--- remove discard

}

When i change this version for a third time, by exchanging the
“return” through a “break” but still without calling discard, i get
the volume rendered, but the framerate breaks in (around 10x) and
the color is messed up. For me another indication that the return-
statement has no effect inside a the loop. Calling return before
the loop immediately abort the shader.

Has anybody a clue why the first version is not working? It was
working before a system update.

Where do you assign sign_prev? Is it uninitialized, perhaps?

No, it is initialized with false.
Here the complete code!


mat4 inv = inverse(modelviewMatrix);
light_position = mat3(inv) * light_position;
eye_position =  vec3(inv[3]);

vec3 ray_dir = normalize(frag_position - eye_position);
vec3 ray_pos = texCoord.xyz; // the current ray position
vec3 pos111 = vec3(1.0, 1.0, 1.0);
vec3 pos000 = vec3(0, 0, 0);
	

float val = texture(volumeTexture,texCoord.xyz).r;
bool sign_prev = val > 0.5f;
	
vec3 prev_pos = ray_pos;

out_color = vec4(1.0f,1.0f,1.0f,1.0f);
		
do
{
  prev_pos = ray_pos;
  ray_pos += ray_dir * sample;
		
  if (any(greaterThan(ray_pos,pos111))) {
    break;
  }

  if (any(lessThan(ray_pos,pos000))){
     break;
  }
		
  val = texture(volumeTexture, ray_pos).r;
  bool sign_cur = val > 0.5f;
 
  if (sign_cur != sign_prev) {
    vec3 iso_pos = (prev_pos+ray_pos)*0.5;
    out_color = computeFragColor(iso_pos);
    break;		
    }
} while(true);

}


This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.