Ray reflection error

I am trying to implement a ray tracing algorithm, and I have some problems with calculating the reflected rays of spherical objects. For some specific rays, it seems that the reflected ray simply passes and is collinear to the traced ray. Bellow is how I record the intersection of rays:

bool Sphere::intersectLocal(const ray & r, isect & i) const {
    Vec3d P = r.getPosition();
    Vec3d D = r.getDirection();
    //D.normalize();
    double a = dot(D, D);
    double b = 2 * dot(P, D);
    double c = dot(P, P) - 1;
    double delta = b * b - 4 * a * c;
    if (delta < 0)
        return false;
    if (delta == 0) {
        double t = -b / 2 * a;
        Vec3d Q = P + t * D;
        Vec3d N = Q;
        N.normalize();
        i.setT(t);
        i.setN(N);
        i.setObject(this);
        return true;
    }
    if (delta > 0) {
        double t1 = (-b - sqrt(delta)) / 2 * a;
        double t2 = (-b + sqrt(delta)) / 2 * a;
        double t;
        if (t1 > 0) t = t1;
        else if (t2 > 0) t = t2;
        else return false;
        Vec3d N = P + t * D;
        N.normalize();
        i.setT(t);
        i.setN(N);
        i.setObject(this);
        return true;
    }
    return false;
}

And this is how I calculate the reflected ray for each intersection:

isect i;
if (scene - > intersect(r, i)) {
    // An intersection occured!  
    const Material & m = i.getMaterial();
    double t = i.t;
    Vec3d N = i.N;
    Vec3d I = m.shade(scene, r, i); //local illumination
    if (!m.kr(i).iszero() && depth >= 0) {
        // compute reflection direction
        Vec3d raydir = r.getDirection();
        Vec3d refldir = 2 * dot(-raydir, i.N) * i.N + raydir;
        refldir.normalize();
        ray reflectionRay = ray(r.at(i.t), refldir, ray::RayType::REFLECTION);
        Vec3d reflection = traceRay(reflectionRay, thresh, depth - 1);
        Vec3d R = reflection;
        I += R;
    }
    return I;
} else {
    // No intersection.  This ray travels to infinity, so we color
    // it according to the background color, which in this (simple) case
    // is just black.
    return Vec3d(0.0, 0.0, 0.0);
}

The code above seems to work fine for most points on a sphere where the rays intersect, but for others it doesn't reflect as I expected

enter image description here

enter image description here

enter image description here

+4
source share
1 answer

If I see correctly, this makes a normal face in the same direction as the beam. Thus, when ray==normal==reflected_raynothing is reflected.

Vec3d Q = P + t * D;
Vec3d N = Q;
0
source

Source: https://habr.com/ru/post/1690932/


All Articles