光线追踪:来自多个光源的阴影
Ray Tracing: Shadows from Multiple Lights
[编辑] 作为编程中的典型做法,我在发布后不久就想通了!如果您有兴趣,请看我的回答:)
我正在使用 C++ 开发光线追踪器,需要一些帮助。我的场景中有 2 盏灯,一个点光源和一个定向光源,以及一堆球体(以及一个充当 "floor" 的平面)。
如果我 运行 光线追踪器存在其中一个光(但另一个光不存在),它会产生预期的阴影(见下图)。
Directional light shadows image
Point light shadows image
麻烦的是,当我 运行 我的光线追踪器同时存在两个灯时,只有点灯阴影出现,我可以判断灯是 "on" 因为场景更亮:
请参阅下面的代码来检测阴影:
bool Scene::shadowtrace( Ray &ray, double t )
{
Object *obj = obj_list;
Light *lt = light_list;
Vector v1, v2; // hit -> light vector
Hit hit;
Vertex intersect = (ray.position( t ));
intersect.plus( ray.D, -0.001 ); // offset intersection ever so slightly away from object, to avoid self-shadowing
v1.set( 0.0, 0.0, 0.0 );
v2.set( 0.0, 0.0, 0.0 ); // initialise
while (lt != (Light *)0)
{
Ray shadowRay;
shadowRay.P = (intersect);
Vertex lightPos = Vertex( 0.0, 0.0, 0.0, 0.0 );
lt->getPosition( lightPos ); // sets value of lightPos
if (lightPos.x > T_LIMIT) // If set absurdly high, we're dealing with a directional light
{
lt->getDirection( v1 ); // sets v1 to light direction (reversed)
v1.normalise( );
shadowRay.D = v1; // set hit-to-light vector as shadowray direction
while (obj != (Object *)0)
{
if (obj->intersect( shadowRay, &hit ) == true)
{
if (!((hit.t * hit.t) < 0.001)) // Self-shadow if very very small t number
{
return true; // ray hits an onject, and the object occurs before the light
}
}
obj = obj->next( );
}
}
else // otherwise, it's a point light :)
{
v1 = (lightPos.minus( intersect )); // find vector from intersection to light
v2 = v1; // keep un-normalised version for preventing mis-shadowing from objects behind the light source
v1.normalise( );
shadowRay.D = v1; // set ray direction to hit-to-light vector
while (obj != (Object *)0)
{
if (obj->intersect( shadowRay, &hit ) == true)
{
if (!((hit.t * hit.t) > (v2.lengthSq( )))) // Check hit.t against magnitude of (un-normalised) intersection-to-light vector
if (!((hit.t * hit.t) < 0.001)) // Self-shadow if very very small t number
{ // Used hit.t^2 to avoid having to SQRT the length. Is acceptable for comparisons
return true; // ray hits an onject, and the object occurs before the light
}
}
obj = obj->next( );
}
}
lt = lt->next( );
}
return false;
}
如果检测到阴影,则仅将环境光归因于该点,否则将归因于环境光 + 漫反射(我还没有考虑添加镜面反射)。
任何建议都会很棒!
虚惊各位!
我想通了!!
在我添加的每个对象列表循环之前:
obj = obj_list;
重置为第一个对象,这解决了问题:)
[编辑] 作为编程中的典型做法,我在发布后不久就想通了!如果您有兴趣,请看我的回答:)
我正在使用 C++ 开发光线追踪器,需要一些帮助。我的场景中有 2 盏灯,一个点光源和一个定向光源,以及一堆球体(以及一个充当 "floor" 的平面)。
如果我 运行 光线追踪器存在其中一个光(但另一个光不存在),它会产生预期的阴影(见下图)。
Directional light shadows image
Point light shadows image
麻烦的是,当我 运行 我的光线追踪器同时存在两个灯时,只有点灯阴影出现,我可以判断灯是 "on" 因为场景更亮:
请参阅下面的代码来检测阴影:
bool Scene::shadowtrace( Ray &ray, double t )
{
Object *obj = obj_list;
Light *lt = light_list;
Vector v1, v2; // hit -> light vector
Hit hit;
Vertex intersect = (ray.position( t ));
intersect.plus( ray.D, -0.001 ); // offset intersection ever so slightly away from object, to avoid self-shadowing
v1.set( 0.0, 0.0, 0.0 );
v2.set( 0.0, 0.0, 0.0 ); // initialise
while (lt != (Light *)0)
{
Ray shadowRay;
shadowRay.P = (intersect);
Vertex lightPos = Vertex( 0.0, 0.0, 0.0, 0.0 );
lt->getPosition( lightPos ); // sets value of lightPos
if (lightPos.x > T_LIMIT) // If set absurdly high, we're dealing with a directional light
{
lt->getDirection( v1 ); // sets v1 to light direction (reversed)
v1.normalise( );
shadowRay.D = v1; // set hit-to-light vector as shadowray direction
while (obj != (Object *)0)
{
if (obj->intersect( shadowRay, &hit ) == true)
{
if (!((hit.t * hit.t) < 0.001)) // Self-shadow if very very small t number
{
return true; // ray hits an onject, and the object occurs before the light
}
}
obj = obj->next( );
}
}
else // otherwise, it's a point light :)
{
v1 = (lightPos.minus( intersect )); // find vector from intersection to light
v2 = v1; // keep un-normalised version for preventing mis-shadowing from objects behind the light source
v1.normalise( );
shadowRay.D = v1; // set ray direction to hit-to-light vector
while (obj != (Object *)0)
{
if (obj->intersect( shadowRay, &hit ) == true)
{
if (!((hit.t * hit.t) > (v2.lengthSq( )))) // Check hit.t against magnitude of (un-normalised) intersection-to-light vector
if (!((hit.t * hit.t) < 0.001)) // Self-shadow if very very small t number
{ // Used hit.t^2 to avoid having to SQRT the length. Is acceptable for comparisons
return true; // ray hits an onject, and the object occurs before the light
}
}
obj = obj->next( );
}
}
lt = lt->next( );
}
return false;
}
如果检测到阴影,则仅将环境光归因于该点,否则将归因于环境光 + 漫反射(我还没有考虑添加镜面反射)。
任何建议都会很棒!
虚惊各位! 我想通了!!
在我添加的每个对象列表循环之前:
obj = obj_list;
重置为第一个对象,这解决了问题:)