光线跟踪器-实现阴影

Raytracer - implementing shadows

本文关键字:阴影 实现 光线跟踪      更新时间:2023-10-16

我正在为一项本应实现光线跟踪器的任务而苦苦挣扎。我已经完成了一个基本的光线跟踪器,但我几乎不知道如何实现阴影。我将包括我们必须编程的一些函数和我们给出的一些数据结构。我想我在理论上知道该做什么,但我完全不知道如何正确实施这些。

void Raytracer::computeShading( Ray3D& ray ) {
LightListNode* curLight = _lightSource;
Ray3D shadowRay;
for (;;) {
    if (curLight == NULL) break;
    // Each lightSource provides its own shading function.
    // Implement shadows here if needed.
    if (!ray.intersection.none) {
        shadowRay.origin = ray.intersection.point + 0.01 * ray.dir;
        shadowRay.dir = (curLight->light->get_position() - ray.intersection.point);
        shadowRay.dir.normalize();
        
    }
        curLight->light->shade(ray);
        curLight = curLight->next;
    }
    
}

}

Colour Raytracer::shadeRay( Ray3D& ray ) {
Colour col(0.0, 0.0, 0.0);
traverseScene(_root, ray);
// Don't bother shading if the ray didn't hit 
// anything.
if (!ray.intersection.none) {
    
    computeShading(ray); 
    col = ray.col;  
}

// You'll want to call shadeRay recursively (with a different ray, 
// of course) here to implement reflection/refraction effects.  
return col; 

}

struct Intersection {
// Location of intersection.
Point3D point;
// Normal at the intersection.
Vector3D normal;
// Material at the intersection.
Material* mat;
// Position of the intersection point on your ray.
// (i.e. point = ray.origin + t_value * ray.dir)
// This is used when you need to intersect multiply objects and
// only want to keep the nearest intersection.
double t_value; 
// Set to true when no intersection has occured.
bool none;

};

// Ray structure. 
struct Ray3D {
Ray3D() {
    intersection.none = true; 
}
Ray3D( Point3D p, Vector3D v ) : origin(p), dir(v) {
    intersection.none = true;
}
// Origin and direction of the ray.
Point3D origin;
Vector3D dir;
// Intersection status, should be computed by the intersection
// function.
Intersection intersection;
// Current colour of the ray, should be computed by the shading
// function.
Colour col;

};

endif

我们应该在computerShading中实现阴影,尽管我认为我们也必须在shadeRay中做一些事情,但我真的不确定。我不确定在computerShading中,我应该在计算光线交点之前还是之后计算光线交点或创建新光线,或者我必须先计算新光线并计算交点。我们还有一个颜色函数。我还为单位正方形和球体实现了一些相交函数,两者都有效,但我只是不知道如何获得阴影!我真的很失落。请提供任何帮助都将是伟大的!

编辑:好的,所以我添加了一些东西,但我没有得到任何阴影,或者我得到了一个完整的黑色图像,这取决于参数的变化:

void Raytracer::computeShading( Ray3D& ray ) {
LightListNode* curLight = _lightSource;
for (;;) {
    Ray3D shadowRay;
    if (curLight == NULL) break;
    // Each lightSource provides its own shading function.
    // Implement shadows here if needed.
    shadowRay.origin = ray.intersection.point + 0.01*ray.dir;
    shadowRay.dir = curLight->light->get_position() - ray.intersection.point;
    shadowRay.dir.normalize();
    traverseScene(_root, shadowRay);
    if (shadowRay.intersection.t_value >= 0.0 && shadowRay.intersection.t_value <= 1.0) {
        shadowRay.col = Colour(0,0,0);
    }
    else {
        curLight->light->shade(ray);
    }
    
     curLight = curLight->next;
                
}

}

其中遍历遍历每个对象并进行交集,并放置适当的值。也许我没有把这些东西放在合适的地方。

您应该在代码中的某个位置有一个函数来进行交集,即在Ray3D::intersection中填充正确的值,对吗?创建shadowRay后,必须调用该函数来检查shadowRay是否与场景中的任何对象相交,并且该相交点位于原点和灯光位置之间。如果存在这样的交点,则当前点不会被该灯光照亮。

哪里有

// You'll want to call shadeRay recursively (with a different ray, 
// of course) here to implement reflection/refraction effects.  

你应该有射线击中的点的位置。您应该在该点和光源之间构建光线。如果光线与某个点相交(无论在哪里),则该点处于阴影中,如果不相交,则它将被照亮。一旦您有了这些信息,就将其传递给计算着色,以了解您是否应用了全乒乓模型(或您正在使用的任何模型),是否没有交集,或者只有环境色(如果有)。