예제 #1
0
Radiance3 RayTracer::L_indirectImpulses(const shared_ptr<Surfel>& surfel, const Vector3& wo, ThreadData& threadData, int bouncesLeft) const {
    Surfel::ImpulseArray impulseArray;
    surfel->getImpulses(PathDirection::EYE_TO_SOURCE, wo, impulseArray);

    Radiance3 L;
    for (int i = 0; i < impulseArray.size(); ++i) {
        const Surfel::Impulse& impulse = impulseArray[i];
        L += L_in(bump(surfel, impulse.direction), impulse.direction, threadData, bouncesLeft) * impulse.magnitude;
    }

    return L;
}
예제 #2
0
Radiance3 App::rayTrace(const Ray& ray, World* world, int bounce) {
    Radiance3 radiance = Radiance3::zero();
    const float BUMP_DISTANCE = 0.0001f;

    float dist = (float)inf();
    const shared_ptr<Surfel>& surfel = world->intersect(ray, dist);
	
	if (notNull(surfel)) {

        // Shade this point (direct illumination)
        for (int L = 0; L < world->lightArray.size(); ++L) {
            const shared_ptr<Light>& light = world->lightArray[L];

            // Shadow rays
            if (world->lineOfSight(surfel->location + surfel->geometricNormal * BUMP_DISTANCE, light->position().xyz())) {
                Vector3 w_i = light->position().xyz() - surfel->location;
                const float distance2 = w_i.squaredLength();
                w_i /= sqrt(distance2);

                // Biradiance
                const Biradiance3& B_i = light->color / (4.0f * pif() * distance2);
				
                radiance += 
                    surfel->finiteScatteringDensity(w_i, -ray.direction()) * 
                    B_i *
                    max(0.0f, w_i.dot(surfel->shadingNormal));
				
                debugAssert(radiance.isFinite());
            }
        }

        // Indirect illumination
        // Ambient
        radiance += surfel->reflectivity(m_rng) * world->ambient;

        // Specular
        if (bounce < m_maxBounces) {
            // Perfect reflection and refraction
            Surfel::ImpulseArray impulseArray;
            surfel->getImpulses(PathDirection::EYE_TO_SOURCE, -ray.direction(), impulseArray);
                
            for (int i = 0; i < impulseArray.size(); ++i) {
                const Surfel::Impulse& impulse = impulseArray[i];
                // Bump along normal *in the outgoing ray direction*. 
                const Vector3& offset = surfel->geometricNormal * sign(impulse.direction.dot(surfel->geometricNormal)) * BUMP_DISTANCE;
                const Ray& secondaryRay = Ray::fromOriginAndDirection(surfel->location + offset, impulse.direction);
                debugAssert(secondaryRay.direction().isFinite());
                radiance += rayTrace(secondaryRay, world, bounce + 1) * impulse.magnitude;
                debugAssert(radiance.isFinite());
            }
        }

		// Add radiance proportional to the distance and fogginess. Divide by 2 so that there isn't too much fog
		radiance += (radiance.one() * dist * m_fogginess)/2;

    } else {
        // Hit the sky
        radiance = world->ambient;

		// Add radiance proportional to fogginess. Multiply by 10 so the fog is noticeable
		radiance += (radiance.one() * m_fogginess * 10);
	}

	return radiance;
}