Example #1
0
CrossNLMFilter::CrossNLMFilter(
            int _searchRadius,
            int _patchRadius,            
            vector<float> &sigmaR,
            const Feature &sigmaF, 
            int w, int h
            ) {  
    searchRadius = _searchRadius;
    searchWidth = 2*searchRadius+1;
    patchRadius = _patchRadius;
    patchWidth = 2*patchRadius+1;
    invPatchWidth = 1.f/patchWidth;
    invPatchSize = 1.f/(float)(patchWidth*patchWidth);
    for(size_t i = 0; i < sigmaR.size(); i++) {
        scaleR.push_back(sigmaR[i] <= 0.f ? 
                0.f : -0.5f/(sigmaR[i]*sigmaR[i]));
    }
    for(int i = 0; i < sigmaF.Size(); i++) {
        scaleF[i] = sigmaF[i] <= 0.f ?
            0.f : -0.5f/(sigmaF[i]*sigmaF[i]);
    }
    width = w; height = h;
    int nPixels = width*height;
    nTasks = max(32 * NumSystemCores(), nPixels / (16*16));
    nTasks = RoundUpPow2(nTasks);
}
Example #2
0
void TasksCleanup() {
#ifdef PBRT_USE_GRAND_CENTRAL_DISPATCH
    return;
#else // // PBRT_USE_GRAND_CENTRAL_DISPATCH
    {   MutexLock lock(*taskQueueMutex);
        Assert(taskQueue.size() == 0);
    }

    static const int nThreads = NumSystemCores();
    workerSemaphore.Post(nThreads);

    if (threads != NULL) {
#ifdef PBRT_HAS_PTHREADS
        for (int i = 0; i < nThreads; ++i) {
            int err = pthread_join(threads[i], NULL);
            if (err != 0)
                Severe("Error from pthread_join: %s", strerror(err));
        }
#endif
#ifdef WIN32
        WaitForMultipleObjects(nThreads, threads, TRUE, INFINITE);
        for (int i = 0; i < nThreads; ++i) {
            CloseHandle(threads[i]);
        }
#endif // WIN32
        delete[] threads;
        threads = NULL;
    }
#endif // PBRT_USE_GRAND_CENTRAL_DISPATCH
}
Example #3
0
void SamplerRenderer::Render(const Scene *scene) {
    PBRT_FINISHED_PARSING();
    // Allow integrators to do pre-processing for the scene
    PBRT_STARTED_PREPROCESSING();
    surfaceIntegrator->Preprocess(scene, camera, this);
    volumeIntegrator->Preprocess(scene, camera, this);
    PBRT_FINISHED_PREPROCESSING();
    PBRT_STARTED_RENDERING();
    // Allocate and initialize _sample_
    Sample *sample = new Sample(sampler, surfaceIntegrator,
                                volumeIntegrator, scene);

    // Create and launch _SamplerRendererTask_s for rendering image

    // Compute number of _SamplerRendererTask_s to create for rendering
    int nPixels = camera->film->xResolution * camera->film->yResolution;
    int nTasks = max(32 * NumSystemCores(), nPixels / (16*16));
    nTasks = RoundUpPow2(nTasks);
    ProgressReporter reporter(nTasks, "Rendering");
    vector<Task *> renderTasks;
    for (int i = 0; i < nTasks; ++i)
        renderTasks.push_back(new SamplerRendererTask(scene, this, camera, sampler,
                                             reporter,
                                             sample, nTasks-1-i, nTasks));
    EnqueueTasks(renderTasks);
    WaitForAllTasks();
    for (uint32_t i = 0; i < renderTasks.size(); ++i)
        delete renderTasks[i];
    reporter.Done();
    PBRT_FINISHED_RENDERING();
    // Clean up after rendering and store final image
    delete sample;
    camera->film->WriteImage();
}
Example #4
0
// main program
int main(int argc, char *argv[]) {
    Options options;
    vector<string> filenames;
    // Process command-line arguments
    for (int i = 1; i < argc; ++i) {
        if (!strcmp(argv[i], "--ncores")) options.nCores = atoi(argv[++i]);
        else if (!strcmp(argv[i], "--outfile")) options.imageFile = argv[++i];
        else if (!strcmp(argv[i], "--quick")) options.quickRender = true;
        else if (!strcmp(argv[i], "--topng")){ options.topng = true;
        options.pngFile = argv[++i];
        }
        else if (!strcmp(argv[i], "--background")){ options.withBackground = true;
        options.backgroundImage = argv[++i];
        //This is neccesary to prevent exceptions caused by Magick++
        //@TODO: Mail the Magick++ list about this.
        options.nCores = 1;
        }
        else if (!strcmp(argv[i], "--quiet")) options.quiet = false;
        else if (!strcmp(argv[i], "--verbose")) options.verbose = true;
        else if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h")) {
            printf("usage: pbrt [--ncores n] [--outfile filename] [--quick] [--quiet] "
                   "[--verbose] [--topng png_filename] [--help] <filename.pbrt> ...\n");
            return 0;
        }
        else filenames.push_back(argv[i]);
    }

    // Print welcome banner
    // Disabled, enable later.
    if (!options.quiet) {
        printf("pbrt version %s of %s at %s [Detected %d core(s)]\n",
               PBRT_VERSION, __DATE__, __TIME__, NumSystemCores());
        printf("Relativistic Rendering, Alex, Allwin, Sanchit\n");
        /*
        printf("Copyright (c)1998-2010 Matt Pharr and Greg Humphreys.\n");
        printf("The source code to pbrt (but *not* the book contents) is covered by the GNU GPL.\n");
        printf("See the file COPYING.txt for the conditions of the license.\n");
        */
        fflush(stdout);

    }
    pbrtInit(options);

    //extern Background bground;
    // Process scene description
    PBRT_STARTED_PARSING();
    if (filenames.size() == 0) {
        // Parse scene from standard input
        ParseFile("-");
    } else {
        // Parse scene from input files
        for (u_int i = 0; i < filenames.size(); i++)
            if (!ParseFile(filenames[i]))
                Error("Couldn't open scene file \"%s\"", filenames[i].c_str());
    }
    pbrtCleanup();
    return 0;
}
Example #5
0
void SurfacePointsRenderer::Render(const Scene &scene) {
    // Declare shared variables for Poisson point generation
    BBox octBounds = scene.WorldBound();
    octBounds.Expand(.001f * powf(octBounds.Volume(), 1.f/3.f));
    Octree<SurfacePoint> pointOctree(octBounds);

    // Create scene bounding sphere to catch rays that leave the scene
    Point sceneCenter;
    float sceneRadius;
    scene.WorldBound().BoundingSphere(&sceneCenter, &sceneRadius);
    Transform ObjectToWorld(Translate(sceneCenter - Point(0,0,0)));
    Transform WorldToObject(Inverse(ObjectToWorld));
    Reference<Shape> sph = new Sphere(&ObjectToWorld, &WorldToObject,
        true, sceneRadius, -sceneRadius, sceneRadius, 360.f);
    //Reference<Material> nullMaterial = Reference<Material>(NULL);
    Material nullMaterial;
    GeometricPrimitive sphere(sph, nullMaterial, NULL);
    int maxFails = 2000, repeatedFails = 0, maxRepeatedFails = 0;
    if (PbrtOptions.quickRender) maxFails = max(10, maxFails / 10);
    int totalPathsTraced = 0, totalRaysTraced = 0, numPointsAdded = 0;
    ProgressReporter prog(maxFails, "Depositing samples");
    // Launch tasks to trace rays to find Poisson points
    PBRT_SUBSURFACE_STARTED_RAYS_FOR_POINTS();
    vector<Task *> tasks;
    RWMutex *mutex = RWMutex::Create();
    int nTasks = NumSystemCores();
    for (int i = 0; i < nTasks; ++i)
        tasks.push_back(new SurfacePointTask(scene, pCamera, time, i,
            minDist, maxFails, *mutex, repeatedFails, maxRepeatedFails,
            totalPathsTraced, totalRaysTraced, numPointsAdded, sphere, pointOctree,
            points, prog));
    EnqueueTasks(tasks);
    WaitForAllTasks();
    for (uint32_t i = 0; i < tasks.size(); ++i)
        delete tasks[i];
    RWMutex::Destroy(mutex);
    prog.Done();
    PBRT_SUBSURFACE_FINISHED_RAYS_FOR_POINTS(totalRaysTraced, numPointsAdded);
    if (filename != "") {
        // Write surface points to file
        FILE *f = fopen(filename.c_str(), "w");
        if (!f) {
            Error("Unable to open output file \"%s\" (%s)", filename.c_str(),
                  strerror(errno));
            return;
        }

        fprintf(f, "# points generated by SurfacePointsRenderer\n");
        fprintf(f, "# position (x,y,z), normal (x,y,z), area, rayEpsilon\n");
        for (u_int i = 0; i < points.size(); ++i) {
            const SurfacePoint &sp = points[i];
            fprintf(f, "%g %g %g %g %g %g %g %g\n", sp.p.x, sp.p.y, sp.p.z,
                sp.n.x, sp.n.y, sp.n.z, sp.area, sp.rayEpsilon);
        }
        fclose(f);
    }
}
Example #6
0
File: main.cpp Project: BachiLi/dpt
void DptInit() {
    TextureSystem::Init();
    std::cout << "Running with " << NumSystemCores() << " threads." << std::endl;
    if (getenv("DPT_LIBPATH") == nullptr) {
        std::cout
            << "Environment variable DPT_LIBPATH not set."
               "Please set it to a directory (e.g. export DPT_LIBPATH=/dir/to/dpt/src/bin) so "
               "that I can write/find the dynamic libraries." << std::endl;
        exit(0);
    }
}
Example #7
0
// main program
int main(int argc, char *argv[]) {
    Options options;
    vector<string> filenames;

    /************* TWEAKS *************/

    if(chdir("source_files/pbrt"));

    argc = 4;
    argv[1] = "--ncores";
    argv[2] = "1";
    argv[3] = "cornell-ML.pbrt";
    /***********************************/

    // Process command-line arguments
    for (int i = 1; i < argc; ++i) {
        if (!strcmp(argv[i], "--ncores")) options.nCores = atoi(argv[++i]);
        else if (!strcmp(argv[i], "--outfile")) options.imageFile = argv[++i];
        else if (!strcmp(argv[i], "--quick")) options.quickRender = true;
        else if (!strcmp(argv[i], "--quiet")) options.quiet = true;
        else if (!strcmp(argv[i], "--verbose")) options.verbose = true;
        else if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h")) {
            printf("usage: pbrt [--ncores n] [--outfile filename] [--quick] [--quiet] "
                   "[--verbose] [--help] <filename.pbrt> ...\n");
            return 0;
        }
        else filenames.push_back(argv[i]);
    }

    // Print welcome banner
    if (!options.quiet) {
        printf("pbrt version %s of %s at %s [Detected %d core(s)]\n",
               PBRT_VERSION, __DATE__, __TIME__, NumSystemCores());
        printf("Copyright (c)1998-2014 Matt Pharr and Greg Humphreys.\n");
        printf("The source code to pbrt (but *not* the book contents) is covered by the BSD License.\n");
        printf("See the file LICENSE.txt for the conditions of the license.\n");
        fflush(stdout);
    }
    pbrtInit(options);
    // Process scene description
    PBRT_STARTED_PARSING();
    if (filenames.size() == 0) {
        // Parse scene from standard input
        ParseFile("-");
    } else {
        // Parse scene from input files
        for (u_int i = 0; i < filenames.size(); i++)
            if (!ParseFile(filenames[i]))
                Error("Couldn't open scene file \"%s\"", filenames[i].c_str());
    }
    pbrtCleanup();
    return 0;
}
Example #8
0
// main program
int main(int argc, char *argv[]) {
    Options options;
    std::vector<std::string> filenames;
    // Process command-line arguments
    for (int i = 1; i < argc; ++i) {
        if (!strcmp(argv[i], "--ncores") || !strcmp(argv[i], "--nthreads"))
            options.nThreads = atoi(argv[++i]);
        else if (!strcmp(argv[i], "--outfile"))
            options.imageFile = argv[++i];
        else if (!strcmp(argv[i], "--quick"))
            options.quickRender = true;
        else if (!strcmp(argv[i], "--quiet"))
            options.quiet = true;
        else if (!strcmp(argv[i], "--verbose"))
            options.verbose = true;
        else if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h")) {
            printf(
                "usage: pbrt [--nthreads n] [--outfile filename] [--quick] "
                "[--quiet] "
                "[--verbose] [--help] <filename.pbrt> ...\n");
            return 0;
        } else
            filenames.push_back(argv[i]);
    }

    // Print welcome banner
    if (!options.quiet) {
        printf("pbrt version 3 (built %s at %s) [Detected %d cores]\n",
               __DATE__, __TIME__, NumSystemCores());
        printf(
            "Copyright (c)1998-2015 Matt Pharr, Greg Humphreys, and Wenzel "
            "Jakob.\n");
        printf(
            "The source code to pbrt (but *not* the book contents) is covered "
            "by the BSD License.\n");
        printf("See the file LICENSE.txt for the conditions of the license.\n");
        fflush(stdout);
    }
    pbrtInit(options);
    // Process scene description
    if (filenames.size() == 0) {
        // Parse scene from standard input
        ParseFile("-");
    } else {
        // Parse scene from input files
        for (const std::string &f : filenames)
            if (!ParseFile(f))
                Error("Couldn't open scene file \"%s\"", f.c_str());
    }
    pbrtCleanup();
    return 0;
}
Example #9
0
void LightTracerRenderer::Render(const Scene *scene) {
    // Compute light power CDF for photon shooting
    Distribution1D *lightDistribution = ComputeLightSamplingCDF(scene);

    vector<Task *> lightShootingTasks;
    int nTasks = NumSystemCores();
    //iteratively increase fidelity of the image
    for (int iter=0; iter<niter; iter++) {
        //multi tasking one for each processor
        for (int i = 0; i < nTasks; ++i)
            lightShootingTasks.push_back(new LightShootingTask(scene,camera,lightDistribution, camera ? camera->shutterOpen : 0.f,maxPathCount,seed*(i+1)));
        EnqueueTasks(lightShootingTasks);
        WaitForAllTasks();
        for (uint32_t i = 0; i < lightShootingTasks.size(); ++i)
            delete lightShootingTasks[i];
        //write image
        camera->film->WriteImage();
    }


}
Example #10
0
void TasksInit() {
#ifdef PBRT_USE_GRAND_CENTRAL_DISPATCH
    return;
#else // PBRT_USE_GRAND_CENTRAL_DISPATCH
    static const int nThreads = NumSystemCores();
#ifdef PBRT_HAS_PTHREADS
    threads = new pthread_t[nThreads];
    for (int i = 0; i < nThreads; ++i) {
        int err = pthread_create(&threads[i], NULL, &taskEntry, reinterpret_cast<void *>(i));
        if (err != 0)
            Severe("Error from pthread_create: %s", strerror(err));
    }
#endif // !PBRT_HAS_PTHREADS
#ifdef WIN32
    threads = new HANDLE[nThreads];
    for (int i = 0; i < nThreads; ++i) {
        threads[i] = CreateThread(NULL, 0, taskEntry, reinterpret_cast<void *>(i), 0, NULL);
        if (threads[i] == NULL)
            Severe("Error from CreateThread");
    }
#endif // WIN32
#endif // PBRT_USE_GRAND_CENTRAL_DISPATCH
}
Example #11
0
void PhotonIntegrator::Preprocess(const Scene *scene,
        const Camera *camera, const Renderer *renderer) {
    if (scene->lights.size() == 0) return;
    // Declare shared variables for photon shooting
    Mutex *mutex = Mutex::Create();
    int nDirectPaths = 0;
    vector<Photon> causticPhotons, directPhotons, indirectPhotons;
    vector<RadiancePhoton> radiancePhotons;
    bool abortTasks = false;
    causticPhotons.reserve(nCausticPhotonsWanted);
    indirectPhotons.reserve(nIndirectPhotonsWanted);
    uint32_t nshot = 0;
    vector<Spectrum> rpReflectances, rpTransmittances;

    // Compute light power CDF for photon shooting
    Distribution1D *lightDistribution = ComputeLightSamplingCDF(scene);

    // Run parallel tasks for photon shooting
    ProgressReporter progress(nCausticPhotonsWanted+nIndirectPhotonsWanted, "Shooting photons");
    vector<Task *> photonShootingTasks;
    int nTasks = NumSystemCores();
    for (int i = 0; i < nTasks; ++i)
        photonShootingTasks.push_back(new PhotonShootingTask(
            i, camera ? camera->shutterOpen : 0.f, *mutex, this, progress, abortTasks, nDirectPaths,
            directPhotons, indirectPhotons, causticPhotons, radiancePhotons,
            rpReflectances, rpTransmittances,
            nshot, lightDistribution, scene, renderer));
    EnqueueTasks(photonShootingTasks);
    WaitForAllTasks();
    for (uint32_t i = 0; i < photonShootingTasks.size(); ++i)
        delete photonShootingTasks[i];
    Mutex::Destroy(mutex);
    progress.Done();

    // Build kd-trees for indirect and caustic photons
    KdTree<Photon> *directMap = NULL;
    if (directPhotons.size() > 0)
        directMap = new KdTree<Photon>(directPhotons);
    if (causticPhotons.size() > 0)
        causticMap = new KdTree<Photon>(causticPhotons);
    if (indirectPhotons.size() > 0)
        indirectMap = new KdTree<Photon>(indirectPhotons);

    // Precompute radiance at a subset of the photons
    if (finalGather && radiancePhotons.size()) {
        // Launch tasks to compute photon radiances
        vector<Task *> radianceTasks;
        uint32_t numTasks = 64;
        ProgressReporter progRadiance(numTasks, "Computing photon radiances");
        for (uint32_t i = 0; i < numTasks; ++i)
            radianceTasks.push_back(new ComputeRadianceTask(progRadiance,
                i, numTasks, radiancePhotons, rpReflectances, rpTransmittances,
                nLookup, maxDistSquared, nDirectPaths, directMap,
                nIndirectPaths, indirectMap,
                nCausticPaths, causticMap));
        EnqueueTasks(radianceTasks);
        WaitForAllTasks();
        for (uint32_t i = 0; i < radianceTasks.size(); ++i)
            delete radianceTasks[i];
        progRadiance.Done();
        radianceMap = new KdTree<RadiancePhoton>(radiancePhotons);
    }
    delete directMap;
}
Example #12
0
void MetropolisRenderer::Render(const Scene *scene) {
    PBRT_MLT_STARTED_RENDERING();
    if (scene->lights.size() > 0) {
        int x0, x1, y0, y1;
        camera->film->GetPixelExtent(&x0, &x1, &y0, &y1);
        float t0 = camera->shutterOpen, t1 = camera->shutterClose;
        Distribution1D *lightDistribution = ComputeLightSamplingCDF(scene);

        if (directLighting != NULL) {
            PBRT_MLT_STARTED_DIRECTLIGHTING();
            // Compute direct lighting before Metropolis light transport
            if (nDirectPixelSamples > 0) {
                LDSampler sampler(x0, x1, y0, y1, nDirectPixelSamples, t0, t1);
                Sample *sample = new Sample(&sampler, directLighting, NULL, scene);
                vector<Task *> directTasks;
                int nDirectTasks = max(32 * NumSystemCores(),
                                 (camera->film->xResolution * camera->film->yResolution) / (16*16));
                nDirectTasks = RoundUpPow2(nDirectTasks);
                ProgressReporter directProgress(nDirectTasks, "Direct Lighting");
                for (int i = 0; i < nDirectTasks; ++i)
                    directTasks.push_back(new SamplerRendererTask(scene, this, camera, directProgress,
                                                                  &sampler, sample, false, i, nDirectTasks));
                std::reverse(directTasks.begin(), directTasks.end());
                EnqueueTasks(directTasks);
                WaitForAllTasks();
                for (uint32_t i = 0; i < directTasks.size(); ++i)
                    delete directTasks[i];
                delete sample;
                directProgress.Done();
            }
            camera->film->WriteImage();
            PBRT_MLT_FINISHED_DIRECTLIGHTING();
        }
        // Take initial set of samples to compute $b$
        PBRT_MLT_STARTED_BOOTSTRAPPING(nBootstrap);
        RNG rng(0);
        MemoryArena arena;
        vector<float> bootstrapI;
        vector<PathVertex> cameraPath(maxDepth, PathVertex());
        vector<PathVertex> lightPath(maxDepth, PathVertex());
        float sumI = 0.f;
        bootstrapI.reserve(nBootstrap);
        MLTSample sample(maxDepth);
        for (uint32_t i = 0; i < nBootstrap; ++i) {
            // Generate random sample and path radiance for MLT bootstrapping
            float x = Lerp(rng.RandomFloat(), x0, x1);
            float y = Lerp(rng.RandomFloat(), y0, y1);
            LargeStep(rng, &sample, maxDepth, x, y, t0, t1, bidirectional);
            Spectrum L = PathL(sample, scene, arena, camera, lightDistribution,
                               &cameraPath[0], &lightPath[0], rng);

            // Compute contribution for random sample for MLT bootstrapping
            float I = ::I(L);
            sumI += I;
            bootstrapI.push_back(I);
            arena.FreeAll();
        }
        float b = sumI / nBootstrap;
        PBRT_MLT_FINISHED_BOOTSTRAPPING(b);
        Info("MLT computed b = %f", b);

        // Select initial sample from bootstrap samples
        float contribOffset = rng.RandomFloat() * sumI;
        rng.Seed(0);
        sumI = 0.f;
        MLTSample initialSample(maxDepth);
        for (uint32_t i = 0; i < nBootstrap; ++i) {
            float x = Lerp(rng.RandomFloat(), x0, x1);
            float y = Lerp(rng.RandomFloat(), y0, y1);
            LargeStep(rng, &initialSample, maxDepth, x, y, t0, t1,
                      bidirectional);
            sumI += bootstrapI[i];
            if (sumI > contribOffset)
                break;
        }

        // Launch tasks to generate Metropolis samples
        uint32_t nTasks = largeStepsPerPixel;
        uint32_t largeStepRate = nPixelSamples / largeStepsPerPixel;
        Info("MLT running %d tasks, large step rate %d", nTasks, largeStepRate);
        ProgressReporter progress(nTasks * largeStepRate, "Metropolis");
        vector<Task *> tasks;
        Mutex *filmMutex = Mutex::Create();
        Assert(IsPowerOf2(nTasks));
        uint32_t scramble[2] = { rng.RandomUInt(), rng.RandomUInt() };
        uint32_t pfreq = (x1-x0) * (y1-y0);
        for (uint32_t i = 0; i < nTasks; ++i) {
            float d[2];
            Sample02(i, scramble, d);
            tasks.push_back(new MLTTask(progress, pfreq, i,
                d[0], d[1], x0, x1, y0, y1, t0, t1, b, initialSample,
                scene, camera, this, filmMutex, lightDistribution));
        }
        EnqueueTasks(tasks);
        WaitForAllTasks();
        for (uint32_t i = 0; i < tasks.size(); ++i)
            delete tasks[i];
        progress.Done();
        Mutex::Destroy(filmMutex);
        delete lightDistribution;
    }
    camera->film->WriteImage();
    PBRT_MLT_FINISHED_RENDERING();
}
Example #13
0
int MaxThreadIndex() {
    return PbrtOptions.nThreads == 0 ? NumSystemCores() : PbrtOptions.nThreads;
}
Example #14
0
int main(int argc, char *argv[]) {
    if (argc != 2) {
        fprintf(stderr, "usage: mbrast [grid_file.out]\n");
        return 1;
    }

    // Read grids from grid dump file
    std::vector<ShadedGrid> grids;
    if (!ReadGrids(argv[1], &grids))
        return 1;

    InitSamples();

    // Extract the name of the scene in case a full pathname was provided
    // on the command line
    char *sceneName = rindex(argv[1], '/');
    if (sceneName != NULL)
        ++sceneName;
    else
        sceneName = argv[1];

    // Remove trailing ".grids" from scene name
    char *end = rindex(sceneName, '.');
    assert(end);
    *end = '\0';

    printf("Rendering scene \"%s\"\n", sceneName);

    // Change this call to switch to creating an instance of your 3D
    // rasterizer once you start implementing it.

#if MBRAST_MODE == NAIVE_RAST_2D || MBRAST_MODE == SMART_RAST_2D
    Rasterizer *rast = Create2DRasterizer();
#elif MBRAST_MODE == BASIC_RAST_3D || MBRAST_MODE == INTER_RAST_3D
    Rasterizer *rast = Create3DRasterizer();
#elif MBRAST_MODE == BASIC_RAST_5D
    Rasterizer *rast = Create5DRasterizer();
#endif

    // Initialize task system for multithreading if the rasterizer
    // indicates that it's thread safe.
    bool useTasks = rast->IsThreadSafe();
    int nThreads = NumSystemCores();
    assert(nThreads < MAX_CORES);
    if (useTasks) {
        printf("Using %d threads!\n", nThreads);
        TasksInit();
    }

    // Render the scene multiple times, with each of the pixelSamples
    // sample counts.  The sample counts must all be powers of two.
    // The bucketSize array, which must be the same size as
    // pixelSamples[], gives the length of the side of the bucket we'll
    // decompose the image into for the corresponding sample count.
    int pixelSamples[] = { 1, 4, 32 };
    int bucketSize[] = { 64, 32, 8 };
    assert(sizeof(pixelSamples) == sizeof(bucketSize));
    int samplesSize = sizeof(pixelSamples) / sizeof(pixelSamples[0]);

    int failures = 0;
    for (int samplesIndex = 0; samplesIndex < samplesSize; ++samplesIndex) {
        assert(pixelSamples[samplesIndex] <= MAX_SAMPLES_PER_PIXEL);
        int nPixelSamples = pixelSamples[samplesIndex];
        int bucketExtent = bucketSize[samplesIndex];

        printf("Rendering with %d samples per pixel\n", nPixelSamples);

        // 720p resolution.  (This can't be easily changed, as it's baked
        // into the xy coordinates of the micropolygons.  So changing this
        // here would require a corresponding adjustment to those
        // coordinate values when the grids are read in....)
        int xRes = 1280, yRes = 720;

        // Allow the rasterizer to preprocess the grids
        ResetAndStartTimer();
        rast->PreprocessGrids(grids, bucketExtent, xRes, yRes);
        double preprocessCycles = GetElapsedMCycles() / 1024.;
        printf("  Spent %.3f billion cycles on grid preprocessing.\n",
               preprocessCycles);

        // Allocate final output image as well as one Bucket structure for
        // each rasterization task thread we're running; this way the
        // rasterizer can update the framebuffer in its Bucket directly
        // without needing to coordinate with any other rasterizer threads.
        uint8_t *image = new uint8_t[xRes * yRes * 3];
        Bucket *buckets[MAX_CORES];
        int nBuckets = useTasks ? nThreads : 1;
        for (int i = 0; i < nBuckets; ++i)
            buckets[i] = new Bucket(bucketExtent, nPixelSamples);

        // Render with intervals set from 1 to the number of pixel samples
        // in multiples of two.
        for (int logIntervals = 0; (1 << logIntervals) <= nPixelSamples;
             ++logIntervals) {
            int nIntervals = (1 << logIntervals);

            printf("  Rendering with %d intervals: ", nIntervals);
            fflush(stdout);

            if (useTasks) {
                // Create a RastTask instance for each of the buckets of
                // the image; do this outside of the timer so as not to
                // penalize for the unnecessary dynamic allocation overhead
                // in the implementation here.
                std::vector<Task *> rastTasks;
                for (int y = 0; y < yRes; y += bucketExtent) {
                    for (int x = 0; x < xRes; x += bucketExtent) {
                        int x1 = std::min(x + bucketExtent, xRes);
                        int y1 = std::min(y + bucketExtent, yRes);
                        RastTask *rt = new RastTask(rast, &buckets[0], x, y,
                                                    x1, y1, nIntervals, grids,
                                                    image, xRes, yRes);
                        rastTasks.push_back(rt);
                    }
                }

                ResetAndStartTimer();
                EnqueueTasks(rastTasks);
                WaitForAllTasks();
            }
            else {
                // If not using tasks, just loop over all of the buckets
                // and rasterize.
                ResetAndStartTimer();
                for (int y = 0; y < yRes; y += bucketExtent) {
                    for (int x = 0; x < xRes; x += bucketExtent) {
                        buckets[0]->Start(x, y, std::min(x + bucketExtent, xRes),
                                          std::min(y + bucketExtent, yRes));
                        rast->Rasterize(grids, nIntervals, buckets[0]);
                        buckets[0]->Resolve(image, xRes, yRes);
                    }
                }
            }

            // Report total time for rasterization
            double rastGCycles = GetElapsedMCycles() / 1024.;
            printf("  %.3f billion cycles\n", rastGCycles);

            // Write the image
            char outName[256];
            sprintf(outName, "%s_int%d_samp%d.ppm", sceneName, nIntervals,
                    nPixelSamples);
            WritePPM(image, xRes, yRes, outName);
            printf("  Wrote output image \"%s\"\n", outName);

            // Compare to the "golden" image for correctness
            char goldenName[256];
            sprintf(goldenName, "golden/%s_%d.ppm", sceneName,
                    nPixelSamples);
            if (!CompareToGolden(image, xRes, yRes, goldenName, outName))
                ++failures;
        }
        printf("\n");

        for (int i = 0; i < nBuckets; ++i)
            delete buckets[i];

        delete[] image;
    }

    if (useTasks)
        TasksCleanup();

    delete rast;
    return failures;
}
Example #15
0
void MetropolisRenderer::Render(const Scene *scene) {
    int x0, x1, y0, y1;
    camera->film->GetPixelExtent(&x0, &x1, &y0, &y1);
    int nPixels = (x1-x0) * (y1-y0);
    float t0 = camera->shutterOpen;
    float t1 = camera->shutterClose;

    if (doDirectSeparately) {
        // Compute direct lighting before Metropolis light transport
        LDSampler sampler(x0, x1, y0, y1, directPixelSamples, t0, t1);
        Sample *sample = new Sample(&sampler, directLighting, NULL, scene);
        vector<Task *> directTasks;
        int nDirectTasks = max(32 * NumSystemCores(),
                         (camera->film->xResolution * camera->film->yResolution) / (16*16));
        nDirectTasks = RoundUpPow2(nDirectTasks);
        ProgressReporter directProgress(nDirectTasks, "Direct Lighting");
        for (int i = 0; i < nDirectTasks; ++i)
            directTasks.push_back(new SamplerRendererTask(scene, this, camera,
                &sampler, directProgress, sample, i, nDirectTasks));
        std::reverse(directTasks.begin(), directTasks.end());
        EnqueueTasks(directTasks);
        WaitForAllTasks();
        for (uint32_t i = 0; i < directTasks.size(); ++i)
            delete directTasks[i];
        delete sample;
        directProgress.Done();
    }
    // Take initial set of samples to compute $b$
    RNG rng(0);
    MemoryArena arena;
    vector<float> bootstrapSamples;
    float sumContrib = 0.f;
    bootstrapSamples.reserve(nBootstrap);
    MLTSample sample(maxDepth);
    for (int i = 0; i < nBootstrap; ++i) {
        // Compute contribution for random sample for MLT bootstrapping
        LargeStep(rng, &sample, maxDepth, x0, x1, y0, y1, t0, t1);
        float contrib = I(L(scene, this, camera, arena, rng, maxDepth,
                            doDirectSeparately, sample), sample);
        sumContrib += contrib;
        bootstrapSamples.push_back(contrib);
        arena.FreeAll();
    }
    float b = sumContrib / nBootstrap;

    // Select initial sample from bootstrap samples
    rng.Seed(0);
    float contribOffset = rng.RandomFloat() * sumContrib;
    sumContrib = 0.f;
    MLTSample initialSample(maxDepth);
    for (int i = 0; i < nBootstrap; ++i) {
        LargeStep(rng, &initialSample, maxDepth, x0, x1, y0, y1, t0, t1);
        sumContrib += bootstrapSamples[i];
        if (contribOffset < sumContrib)
            break;
    }

    // Launch tasks to generate Metropolis samples
    if (scene->lights.size() > 0) {
        int nTasks = int(nSamples / 50000);
        nTasks = max(nTasks, 32 * NumSystemCores());
        nTasks = min(nTasks, 32768);
        nSamples = (nSamples / nTasks) * nTasks;
        ProgressReporter progress(nTasks, "Metropolis");
        vector<Task *> tasks;
        Mutex *filmMutex = Mutex::Create();
        for (int i = 0; i < nTasks; ++i)
            tasks.push_back(new MLTTask(progress, i, int(nSamples/nTasks), nSamples,
                nPixels, x0, x1, y0, y1, t0, t1, b, largeStepProbability, initialSample,
                doDirectSeparately, maxConsecutiveRejects, maxDepth, scene, camera, this,
                &nSamplesFinished, filmMutex));
        EnqueueTasks(tasks);
        WaitForAllTasks();
        for (uint32_t i = 0; i < tasks.size(); ++i)
            delete tasks[i];
        progress.Done();
    }
    camera->film->WriteImage();
}