示例#1
0
Spectrum
VolumeIntegrator::Li(Ray ray, Spectrum *T) {

    int numSamples;

    double step;

    int numVolumes = mScene->getVolumeCount();
    VolumeRegion **volumes = mScene->getVolumes();

    if(numVolumes < 1) {
        return 0.;
    }

    double t1, t0 = 0;
    Vec3 n;
    Surface surface;
    if(!volumes[0]->bounds().test_intersect(ray, &t0, &t1, &n)) return 0;


    if(ray.maxt < t1)
        t1 = ray.maxt;


    numSamples = (int)((t1 - t0) / mStepSize);

    if(numSamples == 0) numSamples = 1;


    //printf("NumSamples: %d\n", numSamples);

    step = (t1 - t0) / (double)numSamples;

    t0 += ((rand() / (float)RAND_MAX)) * step;

    //printf("T02: %f\n", t0);
    //printf("step: %f\n", step);
    //TODO: NOTE: multiple volumes will need aggregators!
    //*T = *T * Color(0.5);

    Spectrum Lv(0);

    LightSource** lights = mScene->getLightSources();

    Vec3 p = ray(t0);
    Vec3 pPrev;
    Vec3 w = ray.direction * -1;

    Spectrum Tr(1.);
    for( int i = 0; i < numSamples; ++i, t0 += step )
    {
        pPrev = p;
        p = ray(t0);
        //printf("T03: %f\n", t0);
        //printf("Step: %f\n", step);
        //printf("Difference: %s %s\n", p.str(), ray(t0 + step).str());
        //printf("Curr T: %f\n", (p - pPrev).length());
        Ray tRay = Ray(pPrev, p - pPrev, 0.0, step);

        Spectrum stepTau = volumes[0]->tau(tRay, 0.5 * step, 0);
        
        Tr = Tr * Exp(stepTau * -1);

        if (Tr.toTrans() < 1e-3) {
            const float continueProb = .5f;
            if ((rand() / (float)RAND_MAX) > continueProb) break;
            Tr = Tr / continueProb;
        }//else if (stepTau.toTrans() > 0.99995)
        //   continue;


        Lv = Lv + volumes[0]->Lve(p);
        Spectrum ss = volumes[0]->sigma_s(p);
        if(!ss.isBlack()) {
            //printf("Lighting?\n");
            LightSource *light = lights[0];

            Vec3 wL = light->position - p;


            wL.norm();

            Ray shadRay = Ray(p, wL);

            if(!mScene->intersect(shadRay, &surface) || (surface.t > (p-wL).length()))
            {

                Spectrum lTr = Exp(volumes[0]->tau(shadRay, mStepSize * 2, 0.0) * -1);

                //printf("P: %s\n", p.str());
                //printf("LTR: %f, %f, %f\n", lTr.r(), lTr.g(), lTr.b());

                Spectrum Ld = lTr * lights[0]->color;

                //printf("Not black.\n\tcurloc: %f, %f, %f\n\tlightTrn: %.2f, %.2f, %.2f\n\tLightCol: %.2f, %.2f, %.2f\n\tSingleSc: %.2f, %.2f, %.2f\n\tCurTrans: %.2f, %.2f, %.2f\n", \
                p.x(), p.y(), p.z(), lTr.r(), lTr.g(), lTr.b(), lights[0]->color.r(), lights[0]->color.g(), lights[0]->color.b(), ss.r(), ss.g(), ss.b(), Tr.r(), Tr.g(), Tr.b());

                Lv = Lv + Ld * ss * Tr;// * volumes[0]->phase(p, w, wL * 1);

                //printf("Phase: %f\n", volumes[0]->phase(p, w, wL));
            }
        }
示例#2
0
Spectrum WhittedIntegrator::li(const Scene& scene, const Renderer& renderer, const Ray& ray,
                               const Intersection& intersection) const {
    Spectrum l(0.f);
    
    // If primitive is an area light, simply return its emited light
    AreaLight* areaLight = intersection.primitive->getAreaLight();
    if (areaLight) {
        return areaLight->le(ray, &intersection);
    }
    
    // Initialize common variables
    const vec3& n = intersection.normal;
    vec3 wo = -ray.direction;
    
    l += GetDirectLighting(scene, renderer, ray, intersection);
    
    // Trace rays for specular reflection and refraction
    if (ray.depth < _maxRayDepth) {

        Material::BxDFType type;
        // Reflected light
        {
            vec3 wi;
            Spectrum f = intersection.material->sampleBSDF(wo, &wi, intersection,
                                                           Material::BSDFReflection, &type);
            if (!f.isBlack() && glm::dot(wi, n) != 0.0f) {
                Ray reflectedRay;
                
                reflectedRay.origin = intersection.point;
                reflectedRay.direction = wi;
                reflectedRay.tmin = intersection.rayEpsilon;
                reflectedRay.depth = ray.depth + 1;
                Spectrum li = renderer.li(scene, reflectedRay);
                l += f * li;
            }
        }
        
        // Transmitted light
        {
            vec3 wi;
            Spectrum f = intersection.material->sampleBSDF(wo, &wi, intersection,
                                                           Material::BSDFTransmission, &type);
            if (!f.isBlack() && glm::dot(wi, n) != 0.0f) {
                Ray transmittedRay;
                
                transmittedRay.origin = intersection.point;
                transmittedRay.direction = wi;
                transmittedRay.tmin = intersection.rayEpsilon;
                transmittedRay.depth = ray.depth + 1;
                Spectrum li = renderer.li(scene, transmittedRay);
                
                // Absorbtion
                if (glm::dot(wi, n) < 0 && transmittedRay.tmax != INFINITY) {
                    li = li * intersection.material->transmittedLight(transmittedRay.tmax);
                }
                l += f * li;
            }
        }
        
    }
    
    return l;
}
示例#3
0
Spectrum Path::computeLi( const vec2f &pFilm, const SceneData &i_scene, const Camera &i_camera, const Sampler &i_sampler, int i_depth )
{
    Camera::CameraSample cameraSample;
    cameraSample.pixelSample = pFilm + i_sampler.sample2D();
    cameraSample.lensSample = i_sampler.sample2D();
    
    Ray ray;
    float weight = i_camera.generateRay( cameraSample, &ray );
    
    // Radiance
    Spectrum L = Spectrum( 0.0f );
    
    // Importance
    Spectrum beta = Spectrum( 1.0 );
    
    for ( int bounces = 0;; bounces++ ) {
        
        RayIntersection intersection;
        bool foundIntersection = i_scene.intersect( ray, intersection );
        
        float maxDepth = 5;
        if ( !foundIntersection || bounces >= maxDepth ) {
            break;
        }
        
        Spectrum Le = intersection.Le();
        if ( Le.isBlack() )
        {
            // Direct illumination sampling

            Spectrum Ld = beta * uniformSampleOneLight( intersection, i_sampler, i_scene );
            L += Ld;
            
            // BSDF Sampling
            const shading::BSDF &bsdf = intersection.getBSDF();
            const vec3f &surfacePosition = intersection.getSurfacePoint().pos;
            
            vec3f woLocal = -intersection.worldToSurface( -intersection.dir );
            vec3f wiLocal;
            float pdf = 1.0;
            
            const vec2f &bsdfSample = i_sampler.sample2D();
            Spectrum f = bsdf.sampleF( woLocal, &wiLocal, bsdfSample, &pdf );
            
            // No point of continuing if no color
            if ( f.isBlack() || pdf == 0.0 ) {
                break;
            }
            
            // Transform to world space
            vec3f wiWorld = intersection.surfaceToWorld( wiLocal );
            
            // Generate new ray
            ray = Ray( surfacePosition, wiWorld );
            
            beta *= ( f * absDot( wiWorld, intersection.getSurfacePoint().normal ) ) / pdf;
            
            // Russian Roulette
            if ( beta.y() < 1.0f && bounces > 3 ) {
                
                float q = std::max( .05f, 1 - beta.maxComponentValue() );
                
                if ( i_sampler.sample1D() > q ) {
                    beta /= ( 1.0 - q );
                }
                else {
                    break;
                }
            }
        }
        else {
            L += beta * intersection.Le() / 50.0;
            break;
        }
    }
    
    return weight * L;
}
示例#4
0
void KajiyaSampler
  ::evaluate(const Scene &scene,
             const Path &p,
             std::vector<Result> &results) const
{
  gpcpu::uint2 subpathLengths = p.getSubpathLengths();

  const PathVertex &light = p[subpathLengths.sum() - 1];
  Spectrum L;

  // note that we could start at eyeLength == 1 and connect
  // length-2 paths, which would get rid of the special case of eyeLength == 2
  // below.  however, we wouldn't get to take advantage of the stratified sampling
  // over the image plane, and we would also lose the nice property that this PathSampler's
  // Results always touch the same pixel
  for(size_t eyeLength = 2;
      eyeLength <= subpathLengths[0];
      ++eyeLength)
  {
    const PathVertex &e = p[eyeLength - 1];

    if(eyeLength == 2 || e.mFromDelta)
    {
      // evaluate the material's emission
      L = e.mThroughput * e.mEmission->evaluate(e.mToPrev, e.mDg);
      if(L != Spectrum::black())
      {
        // add a new result
        results.resize(results.size() + 1);
        Result &r = results.back();
        r.mThroughput = L;
        r.mPdf = e.mAccumulatedPdf;
        r.mWeight = 1.0f;
        r.mEyeLength = eyeLength;
        r.mLightLength = 0;
      } // end if
    } // end if

    if(!e.mScattering->isSpecular())
    {
      // connect a path
      // compute the throughput of the partial path
      L = e.mThroughput * light.mThroughput;
      
      // XXX make compute throughput take the connection vector and geometric term
      L *= p.computeThroughputAssumeVisibility(eyeLength, e,
                                               1, light);

      if(!L.isBlack()
         && !scene.intersect(Ray(e.mDg.getPoint(), light.mDg.getPoint())))
      {
        // add a new result
        results.resize(results.size() + 1);
        Result &r= results.back();

        // multiply by the connection throughput
        r.mThroughput = L;

        // set pdf, weight, and (s,t)
        r.mPdf = e.mAccumulatedPdf * light.mAccumulatedPdf;
        r.mWeight = 1.0f;
        r.mEyeLength = eyeLength;
        r.mLightLength = 1;
      } // end if
    } // end if
  } // end for eyeLength
} // end KajiyaSampler::evaluate()
示例#5
0
Spectrum Path::estimateDirectLighting( const RayIntersection i_intersection, RenderablePtr i_light, const Sampler &i_sampler, const SceneData &i_scene )
{
    // Direct contribution
    Spectrum Ld = Spectrum::black();
    
    float lightPdf = 0.0f;
    float surfacePdf = 0.0f;
    
    vec3f wiWorld;
    
    const vec3f &woWorld = -i_intersection.dir;
    const vec3f &woLocal = i_intersection.worldToSurface( woWorld );
    const vec3f &normal = i_intersection.getSurfacePoint().normal;
    const shading::BSDF &bsdf = i_intersection.getBSDF();
    
    /* ==================== */
    /*     Sample Light     */
    /* ==================== */
    {
        VisibilityTester visibilityTester;
        const vec3f &uLight = i_sampler.sample3D();
        
        Spectrum Li = i_light->sampleIncidenceRadiance( i_intersection, uLight, &wiWorld, &lightPdf, &visibilityTester );
        
        // Convert to local (surface) coords
        const vec3f &wiLocal = i_intersection.worldToSurface( wiWorld );
        
        // Sample light
        if ( !Li.isBlack() && lightPdf > 0.0f ) {
            
            const Spectrum &f = bsdf.computeF( woLocal, wiLocal ) * absDot( wiWorld, normal );
            surfacePdf = bsdf.pdf( woLocal, wiLocal );
            
            if ( !f.isBlack() ) {
                
                // Ray is in shadow
                if ( visibilityTester.isOccluded( i_scene ) ) {
                    Li = Spectrum::black();
                }
                
                if ( !Li.isBlack() ) {
                    
                    // Weight with MIS
                    float misWeight = powerHeuristic( lightPdf, surfacePdf );
                    Ld += ( Li * f * misWeight ) / lightPdf;
                }
            }
        }
    }
    
    /* ==================== */
    /*     Sample BSDF      */
    /* ==================== */
    {
        const vec2f &uSurface = i_sampler.sample2D();
        vec3f wiLocal;
        
        const Spectrum &f = bsdf.sampleF( woLocal, &wiLocal, uSurface, &surfacePdf ) * absDot( wiWorld, normal );
        
        if ( !f.isBlack() && surfacePdf > 0.0f ) {
            
            // TODO computer light PDF
            lightPdf = 0.0;
            
            // No contribution, return
            if ( lightPdf == 0.0 ) {
                return Ld;
            }

            // Convert to local (surface) coords
            vec3f wiWorld = i_intersection.surfaceToWorld( wiLocal );
            
            const Ray bsdfRay = Ray( i_intersection.getSurfacePoint().pos, wiWorld );
            RayIntersection lightIntersection;
            
            bool foundIntersection = i_scene.intersect( bsdfRay, lightIntersection );
            Spectrum Li = Spectrum::black();
            
            if ( foundIntersection ) {
                
                if ( lightIntersection.m_shapeId == i_light->getIdentifier() ) {
                    Li = i_light->computeRadiance( lightIntersection.getSurfacePoint(), wiWorld );
                }
            }
            
            if ( !Li.isBlack() ) {
                
                // Weight with MIS
                float misWeight = powerHeuristic( lightPdf, surfacePdf );
                Ld += ( Li * f * misWeight ) / surfacePdf;
            }
        }
    }
    
    return Ld;
}