Пример #1
0
Vec3f TraceBase::attenuatedEmission(PathSampleGenerator &sampler,
                         const Primitive &light,
                         const Medium *medium,
                         float expectedDist,
                         IntersectionTemporary &data,
                         IntersectionInfo &info,
                         int bounce,
                         bool startsOnSurface,
                         Ray &ray,
                         Vec3f *transmittance)
{
    CONSTEXPR float fudgeFactor = 1.0f + 1e-3f;

    if (light.isDirac()) {
        ray.setFarT(expectedDist);
    } else {
        if (!light.intersect(ray, data) || ray.farT()*fudgeFactor < expectedDist)
            return Vec3f(0.0f);
    }
    info.p = ray.pos() + ray.dir()*ray.farT();
    info.w = ray.dir();
    light.intersectionInfo(data, info);

    Vec3f shadow = generalizedShadowRay(sampler, ray, medium, &light, startsOnSurface, true, bounce);
    if (transmittance)
        *transmittance = shadow;
    if (shadow == 0.0f)
        return Vec3f(0.0f);

    return shadow*light.evalDirect(data, info);
}
Пример #2
0
bool Cube::intersect(Ray &ray, IntersectionTemporary &data) const
{
    Vec3f p = _invRot*(ray.pos() - _pos);
    Vec3f d = _invRot*ray.dir();

    Vec3f invD = 1.0f/d;
    Vec3f relMin((-_scale - p));
    Vec3f relMax(( _scale - p));

    float ttMin = ray.nearT(), ttMax = ray.farT();
    for (int i = 0; i < 3; ++i) {
        if (invD[i] >= 0.0f) {
            ttMin = max(ttMin, relMin[i]*invD[i]);
            ttMax = min(ttMax, relMax[i]*invD[i]);
        } else {
            ttMax = min(ttMax, relMin[i]*invD[i]);
            ttMin = max(ttMin, relMax[i]*invD[i]);
        }
    }

    if (ttMin <= ttMax) {
        if (ttMin > ray.nearT() && ttMin < ray.farT()) {
            data.primitive = this;
            ray.setFarT(ttMin);
            data.as<CubeIntersection>()->backSide = false;
        } else if (ttMax > ray.nearT() && ttMax < ray.farT()) {
            data.primitive = this;
            ray.setFarT(ttMax);
            data.as<CubeIntersection>()->backSide = true;
        }
        return true;
    }
    return false;
}
Пример #3
0
bool Sphere::intersect(Ray &ray, IntersectionTemporary &data) const
{
    Vec3f p = ray.pos() - _pos;
    float B = p.dot(ray.dir());
    float C = p.lengthSq() - _radius*_radius;
    float detSq = B*B - C;
    if (detSq >= 0.0f) {
        float det = std::sqrt(detSq);
        float t = -B - det;
        if (t < ray.farT() && t > ray.nearT()) {
            ray.setFarT(t);
            data.primitive = this;
            data.as<SphereIntersection>()->backSide = false;
            return true;
        }
        t = -B + det;
        if (t < ray.farT() && t > ray.nearT()) {
            ray.setFarT(t);
            data.primitive = this;
            data.as<SphereIntersection>()->backSide = true;
            return true;
        }
    }

    return false;
}
Пример #4
0
Vec3f HomogeneousMedium::transmittance(PathSampleGenerator &/*sampler*/, const Ray &ray) const
{
    if (ray.farT() == Ray::infinity())
        return Vec3f(0.0f);
    else {
        return std::exp(-_sigmaT*ray.farT());
    }
}
Пример #5
0
Vec3f ExponentialMedium::transmittance(PathSampleGenerator &/*sampler*/, const Ray &ray) const
{
    float  x = _falloffScale*(ray.pos() - _unitPoint).dot(_unitFalloffDirection);
    float dx = _falloffScale*ray.dir().dot(_unitFalloffDirection);

    if (ray.farT() == Ray::infinity() && dx <= 0.0f)
        return Vec3f(0.0f);
    else
        return std::exp(-_sigmaT*densityIntegral(x, dx, ray.farT()));
}
Пример #6
0
float HomogeneousMedium::pdf(PathSampleGenerator &/*sampler*/, const Ray &ray, bool onSurface) const
{
    if (_absorptionOnly) {
        return 1.0f;
    } else {
        if (onSurface)
            return std::exp(-ray.farT()*_sigmaT).avg();
        else
            return (_sigmaT*std::exp(-ray.farT()*_sigmaT)).avg();
    }
}
Пример #7
0
float ExponentialMedium::pdf(PathSampleGenerator &/*sampler*/, const Ray &ray, bool onSurface) const
{
    if (_absorptionOnly) {
        return 1.0f;
    } else {
        float  x = _falloffScale*(ray.pos() - _unitPoint).dot(_unitFalloffDirection);
        float dx = _falloffScale*ray.dir().dot(_unitFalloffDirection);

        Vec3f transmittance = std::exp(-_sigmaT*densityIntegral(x, dx, ray.farT()));
        if (onSurface) {
            return transmittance.avg();
        } else {
            return (density(x, dx, ray.farT())*_sigmaT*transmittance).avg();
        }
    }
}
Пример #8
0
Vec3f HomogeneousMedium::transmittanceAndPdfs(PathSampleGenerator &/*sampler*/, const Ray &ray, bool startOnSurface,
        bool endOnSurface, float &pdfForward, float &pdfBackward) const
{
    if (ray.farT() == Ray::infinity()) {
        pdfForward = pdfBackward = 0.0f;
        return Vec3f(0.0f);
    } else if (_absorptionOnly) {
        pdfForward = pdfBackward = 1.0f;
        return std::exp(-_sigmaT*ray.farT());
    } else {
        Vec3f weight = std::exp(-_sigmaT*ray.farT());
        pdfForward  =   endOnSurface ? weight.avg() : (_sigmaT*weight).avg();
        pdfBackward = startOnSurface ? weight.avg() : (_sigmaT*weight).avg();
        return weight;
    }
}
Пример #9
0
bool Quad::intersect(Ray &ray, IntersectionTemporary &data) const
{
    float nDotW = ray.dir().dot(_frame.normal);
    if (std::abs(nDotW) < 1e-6f)
        return false;

    float t = _frame.normal.dot(_base - ray.pos())/nDotW;
    if (t < ray.nearT() || t > ray.farT())
        return false;

    Vec3f q = ray.pos() + t*ray.dir();
    Vec3f v = q - _base;
    float l0 = v.dot(_edge0)*_invUvSq.x();
    float l1 = v.dot(_edge1)*_invUvSq.y();

    if (l0 < 0.0f || l0 > 1.0f || l1 < 0.0f || l1 > 1.0f)
        return false;

    ray.setFarT(t);
    QuadIntersection *isect = data.as<QuadIntersection>();
    isect->p = q;
    isect->u = l0;
    isect->v = 1.0f - l1;
    isect->backSide = nDotW >= 0.0f;
    data.primitive = this;

    return true;
}
Пример #10
0
Vec3f AtmosphericMedium::transmittance(PathSampleGenerator &/*sampler*/, const Ray &ray) const
{
    Vec3f p = (ray.pos() - _center);
    float t0 = p.dot(ray.dir());
    float t1 = ray.farT() + t0;
    float  h = (p - t0*ray.dir()).length();

    return std::exp(-_sigmaT*densityIntegral(h, t0, t1));
}
Пример #11
0
bool Sphere::occluded(const Ray &ray) const
{
    Vec3f p = ray.pos() - _pos;
    float B = p.dot(ray.dir());
    float C = p.lengthSq() - _radius*_radius;
    float detSq = B*B - C;
    if (detSq >= 0.0f) {
        float det = std::sqrt(detSq);
        float t = -B - det;
        if (t < ray.farT() && t > ray.nearT())
            return true;
        t = -B + det;
        if (t < ray.farT() && t > ray.nearT())
            return true;
    }

    return false;
}
Пример #12
0
bool MultiQuadLight::intersect(Ray &ray, IntersectionTemporary &data) const
{
    QuadLightIntersection *isect = data.as<QuadLightIntersection>();
    isect->wasPrimary = ray.isPrimaryRay();

    float farT = ray.farT();

    _bvh->trace(ray, [&](Ray &ray, uint32 idx, float /*tMin*/) {
        _geometry.intersect(ray, idx, isect->isect);
    });

    if (ray.farT() < farT) {
        data.primitive = this;
        return true;
    }

    return false;
}
Пример #13
0
bool ExponentialMedium::sampleDistance(PathSampleGenerator &sampler, const Ray &ray,
        MediumState &state, MediumSample &sample) const
{
    if (state.bounce > _maxBounce)
        return false;

    float  x = _falloffScale*(ray.pos() - _unitPoint).dot(_unitFalloffDirection);
    float dx = _falloffScale*ray.dir().dot(_unitFalloffDirection);

    float maxT = ray.farT();
    if (_absorptionOnly) {
        if (maxT == Ray::infinity() && dx <= 0.0f)
            return false;
        sample.t = maxT;
        sample.weight = std::exp(-_sigmaT*densityIntegral(x, dx, ray.farT()));
        sample.pdf = 1.0f;
        sample.exited = true;
    } else {
        int component = sampler.nextDiscrete(3);
        float sigmaTc = _sigmaT[component];
        float xi = 1.0f - sampler.next1D();
        float logXi = std::log(xi);

        float t = inverseOpticalDepth(x, dx, sigmaTc, logXi);
        sample.t = min(t, maxT);
        sample.weight = std::exp(-_sigmaT*densityIntegral(x, dx, sample.t));
        sample.exited = (t >= maxT);
        if (sample.exited) {
            sample.pdf = sample.weight.avg();
        } else {
            float rho = density(x, dx, sample.t);
            sample.pdf = (rho*_sigmaT*sample.weight).avg();
            sample.weight *= rho*_sigmaS;
        }
        sample.weight /= sample.pdf;

        state.advance();
    }
    sample.p = ray.pos() + sample.t*ray.dir();
    sample.phase = _phaseFunction.get();

    return true;
}
Пример #14
0
bool AtmosphericMedium::sampleDistance(PathSampleGenerator &sampler, const Ray &ray,
        MediumState &state, MediumSample &sample) const
{
    if (state.bounce > _maxBounce)
        return false;

    Vec3f p = (ray.pos() - _center);
    float t0 = p.dot(ray.dir());
    float  h = (p - t0*ray.dir()).length();

    float maxT = ray.farT() + t0;
    if (_absorptionOnly) {
        sample.t = ray.farT();
        sample.weight = std::exp(-_sigmaT*densityIntegral(h, t0, maxT));
        sample.pdf = 1.0f;
        sample.exited = true;
    } else {
        int component = sampler.nextDiscrete(3);
        float sigmaTc = _sigmaT[component];
        float xi = 1.0f - sampler.next1D();

        float t = inverseOpticalDepth(h, t0, sigmaTc, xi);
        sample.t = min(t, maxT);
        sample.weight = std::exp(-_sigmaT*densityIntegral(h, t0, sample.t));
        sample.exited = (t >= maxT);
        if (sample.exited) {
            sample.pdf = sample.weight.avg();
        } else {
            float rho = density(h, sample.t);
            sample.pdf = (rho*_sigmaT*sample.weight).avg();
            sample.weight *= rho*_sigmaS;
        }
        sample.weight /= sample.pdf;
        sample.t -= t0;

        state.advance();
    }
    sample.p = ray.pos() + sample.t*ray.dir();
    sample.phase = _phaseFunction.get();

    return true;
}
Пример #15
0
Vec3f ExponentialMedium::transmittanceAndPdfs(PathSampleGenerator &/*sampler*/, const Ray &ray, bool startOnSurface,
        bool endOnSurface, float &pdfForward, float &pdfBackward) const
{
    float  x = _falloffScale*(ray.pos() - _unitPoint).dot(_unitFalloffDirection);
    float dx = _falloffScale*ray.dir().dot(_unitFalloffDirection);

    if (ray.farT() == Ray::infinity() && dx <= 0.0f) {
        pdfForward = pdfBackward = 0.0f;
        return Vec3f(0.0f);
    }

    Vec3f transmittance = std::exp(-_sigmaT*densityIntegral(x, dx, ray.farT()));

    if (_absorptionOnly) {
        pdfForward = pdfBackward = 1.0f;
    } else {
        pdfForward  =   endOnSurface ? transmittance.avg() : (density(x, dx, ray.farT())*_sigmaT*transmittance).avg();
        pdfBackward = startOnSurface ? transmittance.avg() : (density(x, dx,       0.0f)*_sigmaT*transmittance).avg();
    }

    return transmittance;
}
Пример #16
0
inline RTCRay convert(const Ray &r)
{
    RTCRay ray;
    ray.org[0] = r.pos().x();
    ray.org[1] = r.pos().y();
    ray.org[2] = r.pos().z();
    ray.dir[0] = r.dir().x();
    ray.dir[1] = r.dir().y();
    ray.dir[2] = r.dir().z();
    ray.tnear = r.nearT();
    ray.tfar  = r.farT();
    ray.geomID = RTC_INVALID_GEOMETRY_ID;
    ray.primID = RTC_INVALID_GEOMETRY_ID;
    return ray;
}
Пример #17
0
bool Quad::occluded(const Ray &ray) const
{
    float nDotW = ray.dir().dot(_frame.normal);

    float t = _frame.normal.dot(_base - ray.pos())/nDotW;
    if (t < ray.nearT() || t > ray.farT())
        return false;

    Vec3f q = ray.pos() + t*ray.dir();
    Vec3f v = q - _base;
    float l0 = v.dot(_edge0)*_invUvSq.x();
    float l1 = v.dot(_edge1)*_invUvSq.y();

    if (l0 < 0.0f || l0 > 1.0f || l1 < 0.0f || l1 > 1.0f)
        return false;
    return true;
}
Пример #18
0
float AtmosphericMedium::pdf(PathSampleGenerator &/*sampler*/, const Ray &ray, bool onSurface) const
{
    if (_absorptionOnly) {
        return 1.0f;
    } else {
        Vec3f p = (ray.pos() - _center);
        float t0 = p.dot(ray.dir());
        float t1 = ray.farT() + t0;
        float  h = (p - t0*ray.dir()).length();

        Vec3f transmittance = std::exp(-_sigmaT*densityIntegral(h, t0, t1));
        if (onSurface) {
            return transmittance.avg();
        } else {
            return (density(h, t0)*_sigmaT*transmittance).avg();
        }
    }
}
Пример #19
0
Vec3f AtmosphericMedium::transmittanceAndPdfs(PathSampleGenerator &/*sampler*/, const Ray &ray, bool startOnSurface,
        bool endOnSurface, float &pdfForward, float &pdfBackward) const
{
    Vec3f p = (ray.pos() - _center);
    float t0 = p.dot(ray.dir());
    float t1 = ray.farT() + t0;
    float  h = (p - t0*ray.dir()).length();

    Vec3f transmittance = std::exp(-_sigmaT*densityIntegral(h, t0, t1));

    if (_absorptionOnly) {
        pdfForward = pdfBackward = 1.0f;
    } else {
        pdfForward  =   endOnSurface ? transmittance.avg() : (density(h, t1)*_sigmaT*transmittance).avg();
        pdfBackward = startOnSurface ? transmittance.avg() : (density(h, t0)*_sigmaT*transmittance).avg();
    }

    return transmittance;
}
Пример #20
0
bool Cube::occluded(const Ray &ray) const
{
    Vec3f p = _invRot*(ray.pos() - _pos);
    Vec3f d = _invRot*ray.dir();

    Vec3f invD = 1.0f/d;
    Vec3f relMin((-_scale - p));
    Vec3f relMax(( _scale - p));

    float ttMin = ray.nearT(), ttMax = ray.farT();
    for (int i = 0; i < 3; ++i) {
        if (invD[i] >= 0.0f) {
            ttMin = max(ttMin, relMin[i]*invD[i]);
            ttMax = min(ttMax, relMax[i]*invD[i]);
        } else {
            ttMax = min(ttMax, relMin[i]*invD[i]);
            ttMin = max(ttMin, relMax[i]*invD[i]);
        }
    }

    return ttMin <= ttMax;
}
Пример #21
0
bool HomogeneousMedium::sampleDistance(PathSampleGenerator &sampler, const Ray &ray,
        MediumState &state, MediumSample &sample) const
{
    if (state.bounce > _maxBounce)
        return false;

    float maxT = ray.farT();
    if (_absorptionOnly) {
        if (maxT == Ray::infinity())
            return false;
        sample.t = maxT;
        sample.weight = std::exp(-_sigmaT*maxT);
        sample.pdf = 1.0f;
        sample.exited = true;
    } else {
        int component = sampler.nextDiscrete(3);
        float sigmaTc = _sigmaT[component];

        float t = -std::log(1.0f - sampler.next1D())/sigmaTc;
        sample.t = min(t, maxT);
        sample.weight = std::exp(-sample.t*_sigmaT);
        sample.exited = (t >= maxT);
        if (sample.exited) {
            sample.pdf = sample.weight.avg();
        } else {
            sample.pdf = (_sigmaT*sample.weight).avg();
            sample.weight *= _sigmaS;
        }
        sample.weight /= sample.pdf;

        state.advance();
    }
    sample.p = ray.pos() + sample.t*ray.dir();
    sample.phase = _phaseFunction.get();

    return true;
}
Пример #22
0
inline Vec3f TraceBase::generalizedShadowRayImpl(PathSampleGenerator &sampler,
                           Ray &ray,
                           const Medium *medium,
                           const Primitive *endCap,
                           int bounce,
                           bool startsOnSurface,
                           bool endsOnSurface,
                           float &pdfForward,
                           float &pdfBackward) const
{
    IntersectionTemporary data;
    IntersectionInfo info;

    float initialFarT = ray.farT();
    Vec3f throughput(1.0f);
    do {
        bool didHit = _scene->intersect(ray, data, info) && info.primitive != endCap;
        if (didHit) {
            if (!info.bsdf->lobes().hasForward())
                return Vec3f(0.0f);

            SurfaceScatterEvent event = makeLocalScatterEvent(data, info, ray, nullptr);

            // For forward events, the transport direction does not matter (since wi = -wo)
            Vec3f transparency = info.bsdf->eval(event.makeForwardEvent(), false);
            if (transparency == 0.0f)
                return Vec3f(0.0f);

            if (ComputePdfs) {
                float transparencyScalar = transparency.avg();
                pdfForward  *= transparencyScalar;
                pdfBackward *= transparencyScalar;
            }

            throughput *= transparency;
            bounce++;

            if (bounce >= _settings.maxBounces)
                return Vec3f(0.0f);
        }

        if (medium) {
            if (ComputePdfs) {
                float forward, backward;
                throughput *= medium->transmittanceAndPdfs(sampler, ray, startsOnSurface, didHit || endsOnSurface, forward, backward);
                pdfForward *= forward;
                pdfBackward *= backward;
            } else {
                throughput *= medium->transmittance(sampler, ray, startsOnSurface, endsOnSurface);
            }
        }
        if (info.primitive == nullptr || info.primitive == endCap)
            return bounce >= _settings.minBounces ? throughput : Vec3f(0.0f);
        medium = info.primitive->selectMedium(medium, !info.primitive->hitBackside(data));
        startsOnSurface = true;

        ray.setPos(ray.hitpoint());
        initialFarT -= ray.farT();
        ray.setNearT(info.epsilon);
        ray.setFarT(initialFarT);
    } while(true);
    return Vec3f(0.0f);
}