Problems simulating 3D volume with 2D textures + ray casting

• 11-13-2012, 02:43 PM
glYUNoWork
Problems simulating 3D volume with 2D textures + ray casting
Hello everybody.

So I'm doing a iOS application where I have volume information stored in a kind of 3D texture. To render it, I'm using OpenGL ES, and as it does not support 3D textures, I'm forced to simulate 3D textures using multiple 2D textures (every 2D texture contains some slices of the 3D texture).

To do this I have 1x1 cube and a fragment shader that, for every fragment, throws a ray from the observer to it and looks up for its color to one of the 2D textures. If the color found is the color i've defined as transparent, it should keep looking for a color in the ray direction. With this a volume can be simulated.

The algorithm can be found here (the fragment shader at the end of the page).

The problem I have is that this not seem to work. I'll paste some code from the fragment shader:

Code :

```vec4 getColorFromTextures(in vec3 coordinates) { //This function simulates that we have a 3D texture. To test the ray-casting part, I've replaced the actual code for this: if((coordinates.z < 0.25) || (coordinates.z > 0.5 && coordinates.z < 0.75)) return vec4(1.0); else return vec4(vec3(0.0), 1.0); } //So it's supposed to have the cube sepparated in 4 parts: black-white-black-white.```

Then, the main:

Code :

```/* eye_position is an uniform vec3 that is supposed to have the camera position in it. It's initialized with the first 3 values of the last column of the ModelView Matrix, changing their sign. (I'm not sure this is ok, maybe this is is the root of all the problems).   frag_position is a varying initialized in the vertex shader with gl_Vertex.xyz. */ void main() { highp vec3 ray_dir = normalize(eye_position - frag_position); //ray direction = observer-fragment_position. highp vec3 ray_pos = textureVarying.xyz;   highp vec4 frag_color = vec4(0.0); highp vec4 color = getColorFromTextures(ray_pos); highp vec4 transparent_color = vec4(0.0, 0.0, 0.0, 1.0);   bool continue = true;   if(color != transparent_color) { frag_color = color; continue = false; }   while (continue) { ray_pos += ray_dir * sample_step; //sample_step is, for example, 1.0/50.0   if (any(greaterThan(ray_pos,pos111))) //Out of the cube -> out of the "3D texture" continue = false;   if (any(lessThan(ray_pos,pos000))) //Out of the cube -> out of the "3D texture" continue = false;   if(continue) { color = getColorFromTextures(ray_pos);   if(color != transparent_color) { frag_color = color; continue = false; } } }   if (frag_color == vec4(0.0)) //Not color found => in the direction of the ray, all is transparent. discard; else gl_FragColor = frag_color; }```

And that's the result:
http://img843.imageshack.us/img843/9528/fronttt.png
http://img43.imageshack.us/img43/8895/sidefo.png

As you can see, something's wrong. The "empty white slice" should be filled with white :/

Any idea of what's wrong? I'd really appreciate any help you can give me, I'm really blocked with this... I hope I've explained well enough too.

• 11-14-2012, 09:34 AM
Brandon J. Van Every
Why don't you try cleaning up and simplifying all those conditionals? You've got an awful lot of them, almost to the point of spaghetti code. I bet your bug is simple and you just can't see it.
• 11-14-2012, 12:42 PM
glYUNoWork
Thanks for responding so soon.

I'm sorry, I agree that this code is kind of awful right now, but my priority now is to make it work. After that I'll look for optimizations. Besides, if you look closely most of the ifs are necessary.

And no, I'm afraid my error is not because of the code. Maybe it's something really simple, a misunderstanding of how OpenGL works, but not the code.
• 11-14-2012, 01:29 PM
Brandon J. Van Every
Quote:

Originally Posted by glYUNoWork
Thanks for responding so soon.

No prob, even though I doubt I'm helpful.

Quote:

I'm sorry, I agree that this code is kind of awful right now, but my priority now is to make it work. After that I'll look for optimizations.
The point is not making it faster. The point is making the case logic more straightforward so you'll have an easier time debugging it. Big missing region suggests to me that one of your "if's" isn't doing what you think it's doing, and you're having trouble tracing it because there are too many convoluted branching points to consider.

You say you just want to "get it working," but there's a time cost in not just dealing with it "straight on." Perhaps you are working on other things while you hope the answer suddenly appears before you, but at some point this bug will become a blocker, then you'll have no choice but to figure it out. Unless of course you really don't have to write this code and can do something else, that's always another solution.

Quote:

Besides, if you look closely most of the ifs are necessary.
But.. but.. but.. I'm not going to look more closely at it. :-) I'm not paid enough to do that!

The other thing I considered, is the possibility of those conditionals creating some "undetermined" behavior. I read something in TFM about that the other day, about branching access to texture functions resulting in indeterminate behavior. But looking at your code again, you don't seem to have any texturing functions. Unless the bug is in some code that you're not showing.

Have you tested this on some other machine to eliminate a driver bug?

Quote:

And no, I'm afraid my error is not because of the code. Maybe it's something really simple, a misunderstanding of how OpenGL works, but not the code.
Quite often, when someone posts to a public forum saying there's "nothing wrong with their code," they slap their head 24 hours later and realize exactly what minor glitch is wrong with their code. Then they write a sheepish "oh, I figured it out" post. So call me skeptical.