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

med3d

02-15-2006, 11: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!

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-16-2006, 12:04 AM

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-16-2006, 12:08 AM

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-16-2006, 12:21 AM

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-16-2006, 12:31 AM

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-16-2006, 12:40 AM

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, 01: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, 10: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, 01: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, 01:48 AM

Thank you ,Klaus.I will have another try.

med3d

02-17-2006, 05:20 AM

I still cann't solve this problem :( :(

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, 08: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.

Powered by vBulletin® Version 4.2.3 Copyright © 2017 vBulletin Solutions, Inc. All rights reserved.