PDA

View Full Version : Light direction


Puppet
December 26th, 2005, 14:30
How can I get direction toward light?
I try to use mi_query(miQ_LIGHT_DIRECTION, ...) but it always return null vector.

What's wrong?

while (mi_sample_light(&color, &dir, &dot_nl, mod_state, *light, &samples))
{
...
if(mi_trace_probe(state, &dir, &mod_state->point))
{

miState *childState;
miState *grandChildState = new miState;
childState = mod_state->child;
childState->child = grandChildState;
int new_samples = 0;
miVector new_dir;

miVector ldir;
miTag ltag;

miTag new_tag = *light;
ltag = ((miInstance *)mi_db_access(new_tag))->item;
mi_db_unpin(new_tag);
mi_query(miQ_LIGHT_DIRECTION, childState, ltag, &ldir);
mi_vector_to_object(childState, &new_dir, &ldir);
mi_vector_normalize(&new_dir);

if(mi_trace_probe(childState, &new_dir, &childState->point))
{
...
}
}
...
}

dlanier
December 26th, 2005, 16:51
Hi,

The light direction is in the "dir" variable. It is filled by the mi_sample_light automatically.

In your expression :

mi_sample_light(&color, &dir, &dot_nl, mod_state, *light, &samples)

"dir" contains the direction.

Are you trying to get the direction to another light than the light you're sampling ? If so, you should rather use :

miMatrix *T;
mi_query(miQ_INST_LOCAL_TO_GLOBAL, state, light, &T);


Then with its transformation matrix, you can compute the direction to the state->point.
Regards,

bart
December 26th, 2005, 17:59
BTW, you don't need to do the db_access to get the light tag from a light instance tag. You can use:

mi_query(miQ_INST_ITEM, miNULL, light_instance_tag, &light_tag);

Note that since state is ignored, I put miNULL in there, so it is clear by reading it. I noticed that you actually put childState in as an arg to the query for the direction.

Have you done mi_data_type checks to see that you have the correct tags everywhere?

ctrl_studio
December 26th, 2005, 21:16
Hi guys I'm on holidays right now so I cannot check this. 8)

but look maybe if it is a directional light or what... miQ_LIGHT_TYPE().
I do think you need to work out the light direction by yourself if it is
not a directional light that's why maybe you get a null vector from
other lights.

I'd do the light dir check in the init function of the shader instead to do it
from within the light sample loop. that said from there I'd check also
directly if it is a directional light or what... taking the direction or its origin.
if dir I'd invert its direction there if you wanna the 'get direction toward light'
if not I'd work out that in the render loop considering the point being traced.
infact I don't think you can use directly the 'dir' from the sampled light as
dlanier suggested doing what you're gonna do infact your approach seems
correct as the probed point it is already not the one where dir was eval..
so just work out manually your new direction with vector math starting
from there considering the light origin.

max

dlanier
December 27th, 2005, 08:16
Hi,

Yes if you are computing light direction on a point that is not state->point you are stuck to using what I said previously with mi_query.

You could have computed the light direction with vector maths to the new point if the dir vector was not normalized but it is.

Regards,

thepilot
December 27th, 2005, 08:59
not tested, but it will work better with

mi_query(miQ_LIGHT_DIRECTION, childState, *light, &ldir);

(no need to use db_access... )

by the way, you must check if the light have an origin (if it's a directionnal light or not) with something like

if &#40;mi_vector_norm&#40;ldir&#41;<0&#46;001&#41; &#123;
isdir = 0;
mi_query&#40;miQ_LIGHT_ORIGIN,state,*light,&lightPos&#41;;
&#125; else
isdir = 1;

because if the light is not directionnal, you have to compute the vector yourself :

if &#40;!isdir&#41; &#123;
miVector point = state->point;
mi_vector_sub&#40;&ldir,&point,&lightPos&#41;;
mi_vector_normalize&#40;&ldir&#41;;
&#125;

by the way, having the light type may be possible directly with something like

mi_query&#40;miQ_LIGHT_TYPE,state,*light,&type&#41;

but for some reason, the last time I've tried, it returned 0 all the time.

Don't use sample_light is you dont need to compute the light shader itself, it's time consuming.

Puppet
December 27th, 2005, 10:04
you don't need to do the db_access to get the light tag from a light instance tag. You can use:

Thanks!

I do think you need to work out the light direction by yourself if it is
not a directional light that's why maybe you get a null vector from
other lights.

Yes, my problem was that I had try to get geometric light direction instead of light direction. And I had try it on Point light, it's cause I always get null vector :)
Now I use mi_query(miQ_LIGHT_DIRECTION, ...) only for directional lights.
For point lights I use:
mi_query(miQ_LIGHT_ORIGIN, childState, *light, &ldir); mi_vector_sub(&ldir, &childState->point, &ldir);

Looks like it work fine now...

Then with its transformation matrix, you can compute the direction to the state->point.

Sorry, but I don't know how to use matrix for computing vector. I'm not real programmer :) Now I just use Origin of light.

Thanks for all!

to thepilot:

Thanks, my code now works similar way. I check light type by mi_query(miQ_LIGHT_TYPE, ...) and compure light direction or use mi_query(miQ_LIGHT_DIRECTION, ...) for directional lights.

Look like miQ_LIGHT_TYPE works fine mi_query&#40;miQ_INST_ITEM, NULL, *light, &ltag&#41;;
mi_query&#40;miQ_LIGHT_TYPE, childState, ltag, &light_type&#41;;

bart
December 27th, 2005, 20:09
thepilot reminded me that you can run these two query codes on both the light _and_ the light instance.

miQ_LIGHT_ORIGIN
miQ_LIGHT_DIRECTION

Both the state and the tag must be passed to the mi_query, the only two query modes where this is the case. In the others, only one or the other is used.

If it is the light instance, then the resulting vector will be in internal space, which is typically world space, though it is not guaranteed.

If it is the light, then the resulting vector will be in the object space of the light, or light space as it is referred to in the documentation. The doc also calls it local space in the mi_query documentation.

Now I see why you were using db_access, as it is used in the documented spot light example. Fortunately, it is simpler than that now.

Puppet
December 28th, 2005, 08:28
If someone interest it now my code look like this:

mi_query&#40;miQ_INST_ITEM, NULL, *light, &ltag&#41;;
int light_type;
mi_query&#40;miQ_LIGHT_TYPE, childState, ltag, &light_type&#41;;
switch&#40;light_type&#41;
&#123;
case 0&#58; //point
mi_query&#40;miQ_LIGHT_ORIGIN, childState, *light, &ldir&#41;;
mi_vector_sub&#40;&ldir, &childState->point, &ldir&#41;;
break;
case 1&#58; //direct
mi_query&#40;miQ_LIGHT_DIRECTION, childState, *light, &ldir&#41;;
break;
case 2&#58; //spot
mi_query&#40;miQ_LIGHT_ORIGIN, childState, *light, &ldir&#41;;
mi_vector_sub&#40;&ldir, &childState->point, &ldir&#41;;
break;
default&#58; //point
mi_query&#40;miQ_LIGHT_ORIGIN, childState, *light, &ldir&#41;;
mi_vector_sub&#40;&ldir, &childState->point, &ldir&#41;;
break;
&#125;

mi_vector_neg&#40;&ldir&#41;;
mi_vector_to_object&#40;childState, &new_dir, &ldir&#41;;
mi_vector_normalize&#40;&new_dir&#41;;

I don't know, is it correct converting of vector to object?

Now I see why you were using db_access, as it is used in the documented spot light example.

Yes, I'd take it from spot_light example :)

Puppet
December 28th, 2005, 10:39
Does anyone know what space is origin retuned by mi_query(miQ_LIGHT_ORIGIN, ...)?
Light space? world?

bart
December 28th, 2005, 18:18
Because you are now using the light instance instead of the light, the origin and the dir are in internal space.

So if you need the vector in the local object space of the object referred to by state->instance, then use mi_vector_to_object() as you have. But if you need the vector in the local object space of the light referred to by state->light_instance, then use mi_vector_to_light().

dlanier
December 29th, 2005, 08:23
Probably a silly question, but I am interested in knowing the difference between the light tag and the light instance tag ?

Thanks.
Regards,

bart
December 29th, 2005, 09:02
It is much like an object and an instance of an object. The light tag is the tag for the light element, while the light instance tag is the tag for the instance of the light element. The instance contains the transform which may place the light in the scene.

Some applications don't use it all that much when the light origin and direction for the light uses world space. The instance then contains an identity transform.

An instance can place several kinds of elements in the scene. The element can be an object, a camera, a light, or an instance group. The group enables hierarchical scene graphs.

The miQ_INST_ITEM mi_query will return the element that the instance is transforming.

dlanier
December 29th, 2005, 09:34
Thanks Bart, that's clear now :-)