PDA

View Full Version : some questions about a volume rendering project:



med3d
02-15-2006, 10:21 PM
some questions about a volume rendering project:
1.I need to use a joystick instead of keyboard for input events. Is there any opengl-related lib handling joystick?
2.In my volume rendering project, I manually set the light position and pass it into the fragment shader. But there is a problem: this light position seems to be rotating when I rotate the volume
object! :( so the light is always shining on the same place.
I very appreciate your kindly help!

jide
02-15-2006, 10:30 PM
1. This is not related to GL. Anyway, try glut or SDL.

2. Call Lightfv in your rendering routine, as if it is a 'normal' object.

Klaus
02-15-2006, 11:04 PM
1. Freeglut, GLFW, SDL: http://www.opengl.org/resources/libraries/windowtoolkits.html

2. Are you passing the lightsource direction into your fragment program as a constant? In this case, if your light source is defined in world space, multiply the light source direction with the inverse of the modelmatrix. This is required since your gradients are defined in model space. So you need to transform the light source direction from world space into model space. This is what the inverse of the modelmatrix does ...

If you want a headlight, you can use the following line in GLSL:

vec3 lightdir = vec3(-gl_NormalMatrix[0][2],-gl_NormalMatrix[1][2],-gl_NormalMatrix[2][2]);- Klaus

med3d
02-15-2006, 11:08 PM
thank you jide,
I'm now reading SDL specification. It really helps a lot.
But I still have problem about the second question:
I do a precomputation to get gradient for all voxels, then I store the gradient in a RGB texture for light-computing in fragment shader.I use PHONG mode, so I need the light position to calculate the
light vector per-voxel. I cann't use any OPENGL fixed function like glLight.
My pseudocode is like this:
void OnDraw()
{
....
glPushMatrix();
glMultiMatrixf(mat); // 'mat' is a 4*4 matrix, I manually calculate the tranlation and rotation and
//scale ,and store then in this matrix.
shader->Begin();
shader->SetLightUniform(0.0 , 1.0f , 0.0); //set light position for shader
...
shader->End();
glPopMatrix();

I beat my head but I cann't solve the problem.

med3d
02-15-2006, 11:21 PM
thank you ,Klaus
Do you mean that I have to multiply the light position with the inverse of the modelview matrix?
In my vertex shader ,I get voxel position like this:
// vertext shader with phong light
varying vec3 ecPosition;
void main(void)
{
gl_TexCoord[0] = gl_MultiTexCoord0;

ecPosition = vec3 (gl_ModelViewMatrix * gl_Vertex);

gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
// fragment shader
uniform vec3 LightPosition;
varying vec3 ecPosition;
void main
{
vec4 texVolume = texture3D(my3DTexture , gl_TexCoord[0]);
texVolume.xyz *= 255;
texVolume.xyz -= 128;
vec3 normal = normalize(texVolume.xyz);
vec3 tnorm = normalize(gl_NormalMatrix * normal);//normal
vec3 lightVec = normalize(LightPosition - ecPosition); //get ligth direction
vec3 reflectVec = reflect(-lightVec, tnorm);
vec3 viewVec = normalize(-ecPosition);
float diffuse = max(dot(lightVec, tnorm), 0.0);
...}

Thank you again ,klaus ,I have learn a lot from you .

med3d
02-15-2006, 11:31 PM
Can you explain more why use (-gl_NormalMatrix[0][2],-gl_NormalMatrix[1][2],-gl_NormalMatrix[2][2])?
But it really seems to be a good idea.
I guest your code is likely dealing with parallel light :)If I need spot light effect, how can I achieve that?
Thank you Klaus.

Klaus
02-15-2006, 11:40 PM
Since your gradients are defined in model space, i would recommend to compute the lighting in model space instead of computing your lighting in eye space. You just need to pass a model space light direction into the fragment program - no need to transform every normal into eye space.

I would also recommend to store normalized gradients in your gradient texture. This way you don't need to normalize the gradients in the fragment program.

With a headlight, your code might look like this:


void main
{
vec4 texVolume = texture3D(my3DTexture , gl_TexCoord[0]);
vec3 normal = expand(texVolume.xyz);
vec3 lightVec = vec3(-gl_NormalMatrix[0][2],-gl_NormalMatrix[1][2],-gl_NormalMatrix[2][2]);
float diffuse = max(dot(lightVec, normal), 0.0);
...
}



- Klaus

Klaus
02-16-2006, 12:00 AM
The NormalMatrix transforms normals from model to eye space. If want to transform the viewing direction from eye space to model space, you multiply the eye space viewing direction (0,0,-1) with the transpose of the NormalMatrix, resulting in (-gl_NormalMatrix[0][2],-gl_NormalMatrix[1][2],-gl_NormalMatrix[2][2]).

For a spot light i would compute the light
direction per vertex in the vertex stage. Then renormalize the interpolated light direction in the fragment stage.

- Klaus

med3d
02-16-2006, 09:53 PM
Thank you Klaus.
I have made a change in my shader, but the light still rotate when rotating the object,so the light
always shines on the same face of the object. How can I make the light hold still when rotating the
object?
my current fragment shader is like this:
void main()
{
...
vec4 texVolume = texture3D(my3DTexture , gl_TexCoord[0]);
texVolume.xyz *= 255;
texVolume.xyz -= 128;

const float specularExp = 128.0;

vec3 NN = normalize(texVolume.xyz);
vec3 NL = vec3(-gl_NormalMatrix[0][2],-gl_NormalMatrix[1][2],-gl_NormalMatrix[2][2]); //klaus light dir

vec3 lightCol; //light color
lightCol = vec3(1.0 , 1.0 , 1.0); //white light
gl_FragColor = vec4(0.0);

vec3 NH = normalize(NL + vec3(0.0 , 0.0 , 1.0));
//diffuse
gl_FragColor.rgb += texVolume.aaa * lightCol * max(0.0,dot(NN,NL));
//specular
gl_FragColor.rgb += lightCol * pow(max(0.0,dot(NN,NH)),specularExp);
gl_FragColor.a = texVolume.a;
...
}
PS: I have no other choice but to normal the gradient in the shader.Because 3-bytes are used for storing the
gradient(GL_RGBA format is used for the 3d texture), and each graident is ranging from -255 to +255. I devide them by 2,and add 128 to each of them.

I still don't know what is expand(...) , is it a build-in function? I can't find this function
in the GLSL specification and there will be an runtime-error when I use this function. :(

Klaus
02-17-2006, 12:28 AM
You are right, expand does not exist in GLSL. You can use the following code:


vec3 expand(vec3 v) { return (v - 0.5) * 2; }It is possible to store a normalized gradient in an RGB8 texture. Compute the normal from your volume data, normalize it and then map the range [-1,1] to [0,255].

In the fragment stage, data values in the range[0,255] from the RGB8 texture will be mapped to [0,1], so expand will give you your normalized gradients again in the range [-1,1].

For a headlight using the normalmatrix, the halfway vector is the same as the light vector, so you should have


vec3 NH = NL;- Klaus

med3d
02-17-2006, 12:48 AM
Thank you ,Klaus.I will have another try.

med3d
02-17-2006, 04:20 AM
I still cann't solve this problem :( :(

jide
02-17-2006, 06:53 AM
For the light not to move with your object, simply don't multiply it by the matrix of the object transformation. I'm not really sure what you are doing inside your shader.

med3d
02-17-2006, 07:17 PM
thank you jide! I will post a new topic about this light problem in detail. All the relative codes and
issues are listed in it.Please do help me.