PDA

View Full Version : Problem with return/discard



icepic1984
06-08-2011, 03:09 AM
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.

malexander
06-08-2011, 06:35 AM
Where do you assign sign_prev? Is it uninitialized, perhaps?

icepic1984
06-08-2011, 06:56 AM
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);

}