Maxwell0star

09-05-2014, 11:11 AM

Hello,

I've been working on direct volume rendering using a simple ray caster and I wanted to expand it slightly to include basic (Phong) shading.

To do the light I calculate surface gradients on the fly using simple forward-backwards approximation. This is where I run into the problem.

To display the model (that is without lighting) I set the filters of the 3D texture to GL_NEAREST. This way when a ray hits the surface it returns the value of the closest point, if that turns out to be 0 it goes a little deeper and tries again.

However, to get my gradient (normal) approximation to work I need to use a GL_LINEAR filter. This way once I'm on a point I can move forward and backwards just a bit and the linear filtering will still change the sampled value enough to produce a non-zero gradient. If I use GL_NEAREST I run into problems where the small step might be too small and round to the same voxel or too big and round to a voxel two away.

I can't use GL_LINEAR because it messes up the boundaries of the model. If a ray nearly hits a surface voxel with value 120 say, it'll be filtered with the 0 of the empty space and you end up with a random effect across boundaries.

With GL_LINEAR

1423

With GL_NEAREST

1424

Just noticed the front surface is green instead of the blue it should be. That shows the linear problem, the surface value is 255(blue) but it gets interpolated with empty space value 0 and ends up around 128 which is green.

So I suppose the question is, is there anyway to sample the same texture using GL_LINEAR and GL_NEAREST.

I tried manually rounding the sample location to produce a nearest type response from a linear filter using:

vec3 voxCorrect = vec3((round(voxCoord.x * 256.0))/256.0, (round(voxCoord.y * 256.0))/256.0, (round(voxCoord.z * 128.0))/128.0);

It helped but it was still far from good.

Thanks for any help,

Maxwell.

I've been working on direct volume rendering using a simple ray caster and I wanted to expand it slightly to include basic (Phong) shading.

To do the light I calculate surface gradients on the fly using simple forward-backwards approximation. This is where I run into the problem.

To display the model (that is without lighting) I set the filters of the 3D texture to GL_NEAREST. This way when a ray hits the surface it returns the value of the closest point, if that turns out to be 0 it goes a little deeper and tries again.

However, to get my gradient (normal) approximation to work I need to use a GL_LINEAR filter. This way once I'm on a point I can move forward and backwards just a bit and the linear filtering will still change the sampled value enough to produce a non-zero gradient. If I use GL_NEAREST I run into problems where the small step might be too small and round to the same voxel or too big and round to a voxel two away.

I can't use GL_LINEAR because it messes up the boundaries of the model. If a ray nearly hits a surface voxel with value 120 say, it'll be filtered with the 0 of the empty space and you end up with a random effect across boundaries.

With GL_LINEAR

1423

With GL_NEAREST

1424

Just noticed the front surface is green instead of the blue it should be. That shows the linear problem, the surface value is 255(blue) but it gets interpolated with empty space value 0 and ends up around 128 which is green.

So I suppose the question is, is there anyway to sample the same texture using GL_LINEAR and GL_NEAREST.

I tried manually rounding the sample location to produce a nearest type response from a linear filter using:

vec3 voxCorrect = vec3((round(voxCoord.x * 256.0))/256.0, (round(voxCoord.y * 256.0))/256.0, (round(voxCoord.z * 128.0))/128.0);

It helped but it was still far from good.

Thanks for any help,

Maxwell.