Raytracer - 实现阴影

时间:2013-12-03 21:31:04

标签: c++ raytracing

我正在努力进行一项任务,我应该实施一个光线跟踪器。我有一个基本的光线跟踪器,但我几乎不知道如何实现阴影。我将包括我们编程的一些函数以及我们给出的一些数据结构。我想我在理论上知道该怎么做,但我完全不知道如何正确地实现这一点。

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中做一些事情,但我不太确定。我不确定在计算机中是否应该计算光线交叉点或在计算光线交点之前或之后创建新光线或者我必须先计算新光线并计算交点。我们还有一个颜色功能。我还为单位正方形和球体实现了一些交叉函数,两者都有效,但我只是不明白如何获得阴影!我真的真的迷路了。请任何帮助都会很棒!

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

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;


}

}

traversescene遍历每个对象并进行交集并输出正确的值。也许我没有将这些东西放在适当的区域。

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

你在哪里

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

你应该拥有射线击中点的位置。您应该在此点和光源之间构建光线。如果光线与某些东西相交(在哪里不重要),那么该点就在阴影中,如果没有,那么它就会被照亮。一旦你有这个信息传递到计算着色,知道你是否应用完整的乒乓模型(或任何你正在使用的),如果没有交集,或只有环境颜色,如果有。