int main(int argc, char* argv[]) { FreeImage_Initialise(); Camera camera; Sample sample; Ray ray; Color* color = new Color(0.f, 0.f, 0.f); initColor(); readfile(argv[1], &camera); const float pi = 3.14159265 ; float fovx = 2 * atan( tan(camera.fovy * pi/180/2.f) * ((float) w) / ((float) h) ) * 180/pi; Film film = Film::Film(w, h); while (Sample::getSample(&sample, w, h)) { if (sample.x % 700 == 0) printf("Sample: %d, %d\n", sample.x, sample.y); if (sample.y < 200) continue; camera.generateRay(sample, &ray, w, h, fovx, camera.fovy); RayTracer::trace(ray, 0, color, maxdepth, numprimitives, geometricPrimitives, numused, lights, attenuation); film.commit(sample, *color); if (sample.y > 250) break; } film.writeImage(outputFilename); FreeImage_DeInitialise(); return 0; }
void PathHybridState::Init(const PathHybridRenderThread *thread) { PathHybridRenderEngine *renderEngine = (PathHybridRenderEngine *)thread->renderEngine; Scene *scene = renderEngine->renderConfig->scene; depth = 1; lastPdfW = 1.f; throuput = Spectrum(1.f); directLightRadiance = Spectrum(); // Initialize eye ray PerspectiveCamera *camera = scene->camera; Film *film = thread->threadFilm; const u_int filmWidth = film->GetWidth(); const u_int filmHeight = film->GetHeight(); sampleResults[0].screenX = std::min(sampler->GetSample(0) * filmWidth, (float)(filmWidth - 1)); sampleResults[0].screenY = std::min(sampler->GetSample(1) * filmHeight, (float)(filmHeight - 1)); camera->GenerateRay(sampleResults[0].screenX, sampleResults[0].screenY, &nextPathVertexRay, sampler->GetSample(2), sampler->GetSample(3)); sampleResults[0].alpha = 1.f; sampleResults[0].radiance = Spectrum(0.f); lastSpecular = true; }
void BloomFilterPlugin::Apply(Film &film, const u_int index) { //const double t1 = WallClockTime(); Spectrum *pixels = (Spectrum *)film.channel_IMAGEPIPELINEs[index]->GetPixels(); const u_int width = film.GetWidth(); const u_int height = film.GetHeight(); // Allocate the temporary buffer if required if ((!bloomBuffer) || (width * height != bloomBufferSize)) { delete[] bloomBuffer; delete[] bloomBufferTmp; bloomBufferSize = width * height; bloomBuffer = new Spectrum[bloomBufferSize]; bloomBufferTmp = new Spectrum[bloomBufferSize]; InitFilterTable(film); } // Apply separable filter BloomFilter(film, pixels); for (u_int i = 0; i < bloomBufferSize; ++i) { if (*(film.channel_FRAMEBUFFER_MASK->GetPixel(i))) pixels[i] = Lerp(weight, pixels[i], bloomBuffer[i]); } //const double t2 = WallClockTime(); //SLG_LOG("Bloom time: " << int((t2 - t1) * 1000.0) << "ms"); }
void BloomFilterPlugin::InitFilterTable(const Film &film) { const u_int width = film.GetWidth(); const u_int height = film.GetHeight(); // Compute image-space extent of bloom effect const u_int bloomSupport = Float2UInt(radius * Max(width, height)); bloomWidth = bloomSupport / 2; // Initialize bloom filter table delete[] bloomFilter; bloomFilterSize = 2 * bloomWidth * bloomWidth + 1; bloomFilter = new float[bloomFilterSize]; for (u_int i = 0; i < bloomFilterSize; ++i) bloomFilter[i] = 0.f; for (u_int i = 0; i < bloomWidth * bloomWidth; ++i) { const float z0 = 3.8317f; const float dist = z0 * sqrtf(i) / bloomWidth; if (dist == 0.f) bloomFilter[i] = 1.f; else if (dist >= z0) bloomFilter[i] = 0.f; else { // Airy function //const float b = boost::math::cyl_bessel_j(1, dist); //bloomFilter[i] = powf(2*b/dist, 2.f); // Gaussian approximation // best-fit sigma^2 for above airy function, based on RMSE // depends on choice of zero const float sigma2 = 1.698022698724f; bloomFilter[i] = expf(-dist * dist / sigma2); } } }
int main() { Karyawan kasir; Film film; Studio studio; Transaksi transaksi; menu(); cout<<endl<<"Input Data"<<endl; cout<<"-------------------"<<endl; kasir.addKaryawan(); do{studio.addStudio();} while((studio.getStudio()!="1")&&(studio.getStudio()!="2")); do{film.addFilm();} while((film.getFilm()!="A")&&(film.getFilm()!="B")); transaksi.addTransaksi(); system("cls"); menu(); cout<<endl<<"----- Faktur Transaksi Anda -----"<<endl<<endl; transaksi.generateKode(); film.showFilm(); studio.showStudio(); transaksi.showTransaksi(); kasir.showKaryawan(); cout<<endl<<endl<<" ----- TERIMA KASIH -----"<<endl<<endl; system("pause"); return 0; }
void BackgroundImgPlugin::UpdateFilmImageMap(const Film &film) { const u_int width = film.GetWidth(); const u_int height = film.GetHeight(); // Check if I have to resample the image map if ((!filmImageMap) || (filmImageMap->GetWidth() != width) || (filmImageMap->GetHeight() != height)) { delete filmImageMap; filmImageMap = NULL; filmImageMap = imgMap->Copy(); filmImageMap->Resize(width, height); } }
void PSSMLTSplats::AccumulateContributionToFilm( Film& film, const Math::Float& weight ) const { for (auto& splat : splats) { film.AccumulateContribution(splat.rasterPos, splat.L * weight); } }
void SampleRenderer::render_tile(CtxG&, Recti tile_rect, Recti tile_film_rect, Film& tile_film, Sampler& sampler) const { StatTimer t(TIMER_RENDER_TILE); Vec2 film_res(float(this->film->x_res), float(this->film->y_res)); for(int32_t y = tile_rect.p_min.y; y < tile_rect.p_max.y; ++y) { for(int32_t x = tile_rect.p_min.x; x < tile_rect.p_max.x; ++x) { sampler.start_pixel(); for(uint32_t s = 0; s < sampler.samples_per_pixel; ++s) { sampler.start_pixel_sample(); Vec2 pixel_pos = sampler.get_sample_2d(this->pixel_pos_idx); Vec2 film_pos = Vec2(float(x), float(y)) + pixel_pos; Ray ray(this->scene->camera->cast_ray(film_res, film_pos)); Spectrum radiance = this->get_radiance(*this->scene, ray, 0, sampler); assert(is_finite(radiance)); assert(is_nonnegative(radiance)); if(is_finite(radiance) && is_nonnegative(radiance)) { Vec2 tile_film_pos = film_pos - Vec2(float(tile_film_rect.p_min.x), float(tile_film_rect.p_min.y)); tile_film.add_sample(tile_film_pos, radiance); } } } } }
int main(int argc, char ** argv) { Film * film = new Film(); Index * i1 = new FixedIndex(1.5); Index * i2 = new FixedIndex(2.2); double thick; if( argc == 2 ) { sscanf(argv[1], "%lf", &thick); } else { printf("Usage: model <thickness>\n"); return -1; } /* for( int i=0; i<10; i++ ) { double q = 1.0 + ((i-5.0)/10.0); q /= 4.0; fprintf(stderr, "%05.3lf %03.0lf\n", q, thick); film->addLayer(Layer(q*thick/1.5, i1)); film->addLayer(Layer(q*2*thick/2.2, i2)); film->addLayer(Layer(q*thick/1.5, i1)); } */ /* film->addLayer(Layer(thick/2/1.5, i1)); film->addLayer(Layer(thick/2/2.2, i2)); film->addLayer(Layer(thick/2/1.5, i1)); */ film = new FakeFilm(); //film->print(); //return 0; Spectrum * s; s = new FileSource("color/illuminants/CIE-C.txt"); s = film->reflect(s, 0); Spectrum::const_iterator itr; for( itr = s->begin(); itr != s->end(); ++itr ) { printf("%09lf %09lf\n", *itr, f(s->get(*itr))); } sRGB color = s->tosRGB(); //printf("RGB: %d %d %d\n", color.r, color.g, color.b); return 0; }
void BloomFilterPlugin::BloomFilterY(const Film &film) { const u_int width = film.GetWidth(); const u_int height = film.GetHeight(); // Apply bloom filter to image pixels #pragma omp parallel for for ( // Visual C++ 2013 supports only OpenMP 2.5 #if _OPENMP >= 200805 unsigned #endif int x = 0; x < width; ++x) { for (u_int y = 0; y < height; ++y) { if (*(film.channel_FRAMEBUFFER_MASK->GetPixel(x, y))) { // Compute bloom for pixel (x, y) // Compute extent of pixels contributing bloom const u_int y0 = Max<u_int>(y, bloomWidth) - bloomWidth; const u_int y1 = Min<u_int>(y + bloomWidth, height - 1); float sumWt = 0.f; const u_int bx = x; Spectrum &pixel(bloomBuffer[x + y * width]); pixel = Spectrum(); for (u_int by = y0; by <= y1; ++by) { if (*(film.channel_FRAMEBUFFER_MASK->GetPixel(bx, by))) { // Accumulate bloom from pixel (bx, by) const u_int dist2 = (x - bx) * (x - bx) + (y - by) * (y - by); const float wt = bloomFilter[dist2]; if (wt == 0.f) continue; const u_int bloomOffset = bx + by * width; sumWt += wt; pixel += wt * bloomBufferTmp[bloomOffset]; } } if (sumWt > 0.f) pixel /= sumWt; } } } }
void TileRepository::Tile::AddPass(const Film &tileFilm) { // Increase the pass count ++pass; // Update the done flag if (tileRepository->enableMultipassRendering) { // Check if convergence test is enable if (tileRepository->convergenceTestThreshold > 0.f) { // Add the tile to the all pass film allPassFilm->AddFilm(tileFilm, 0, 0, tileFilm.GetWidth(), tileFilm.GetHeight(), 0, 0); if (pass % 2 == 1) { // If it is an odd pass, add also to the even pass film evenPassFilm->AddFilm(tileFilm, 0, 0, tileFilm.GetWidth(), tileFilm.GetHeight(), 0, 0); } else { // Update tileRepository->tileMaxPixelValue before to check the // convergence UpdateMaxPixelValue(); // Update linear tone mapping plugin LinearToneMap *allLT = (LinearToneMap *)allPassFilm->GetImagePipeline()->GetPlugin(typeid(LinearToneMap)); allLT->scale = 1.f / tileRepository->tileMaxPixelValue; LinearToneMap *evenLT = (LinearToneMap *)evenPassFilm->GetImagePipeline()->GetPlugin(typeid(LinearToneMap)); evenLT->scale = allLT->scale; // If it is an even pass, check convergence status CheckConvergence(); } } if ((tileRepository->maxPassCount > 0) && (pass >= tileRepository->maxPassCount)) done = true; } else done = true; }
float ImagePipelinePlugin::GetGammaCorrectionValue(const Film &film, const u_int index) { float gamma = 1.f; const ImagePipeline *ip = film.GetImagePipeline(index); if (ip) { const GammaCorrectionPlugin *gc = (const GammaCorrectionPlugin *)ip->GetPlugin(typeid(GammaCorrectionPlugin)); if (gc) gamma = gc->gamma; } return gamma; }
std::string GetCinemaPeople(const Film& film, const std::string& prev) { if (!prev.size()) return ""; auto creators = film.getCreators(); for (auto i : creators) if (i > prev) return i; return ""; }
void Reinhard02ToneMap::Apply(Film &film, const u_int index) { Spectrum *pixels = (Spectrum *)film.channel_IMAGEPIPELINEs[index]->GetPixels(); RGBColor *rgbPixels = (RGBColor *)pixels; const float alpha = .1f; const u_int pixelCount = film.GetWidth() * film.GetHeight(); float Ywa = 0.f; for (u_int i = 0; i < pixelCount; ++i) { if (*(film.channel_FRAMEBUFFER_MASK->GetPixel(i)) && !rgbPixels[i].IsInf()) Ywa += logf(Max(rgbPixels[i].Y(), 1e-6f)); } if (pixelCount > 0) Ywa = expf(Ywa / pixelCount); // Avoid division by zero if (Ywa == 0.f) Ywa = 1.f; const float invB2 = (burn > 0.f) ? 1.f / (burn * burn) : 1e5f; const float scale = alpha / Ywa; const float preS = scale / preScale; const float postS = scale * postScale; #pragma omp parallel for for ( // Visual C++ 2013 supports only OpenMP 2.5 #if _OPENMP >= 200805 unsigned #endif int i = 0; i < pixelCount; ++i) { if (*(film.channel_FRAMEBUFFER_MASK->GetPixel(i))) { const float ys = rgbPixels[i].Y() * preS; // Note: I don't need to convert to XYZ and back because I'm only // scaling the value. rgbPixels[i] *= postS * (1.f + ys * invB2) / (1.f + ys); } } }
Film::Film(const Film & f):AbstractMedia(f) { m_realisateur = f.getRealisateur(); m_scenariste = f.getScenariste(); m_acteurPrincipaux = f.getActeursPrincipaux(); m_type = f.getType(); m_duree = f.getDuree(); m_support = f.getSupport(); }
void BackgroundImgPlugin::Apply(Film &film, const u_int index) { if (!film.HasChannel(Film::ALPHA)) { // I can not work without alpha channel return; } // Check if I have to resample the image map UpdateFilmImageMap(film); Spectrum *pixels = (Spectrum *)film.channel_IMAGEPIPELINEs[index]->GetPixels(); const u_int width = film.GetWidth(); const u_int height = film.GetHeight(); #pragma omp parallel for for ( // Visual C++ 2013 supports only OpenMP 2.5 #if _OPENMP >= 200805 unsigned #endif int y = 0; y < height; ++y) { for (u_int x = 0; x < width; ++x) { const u_int filmPixelIndex = x + y * width; if (*(film.channel_FRAMEBUFFER_MASK->GetPixel(filmPixelIndex))) { float alpha; film.channel_ALPHA->GetWeightedPixel(x, y, &alpha); // Need to flip the along the Y axis for the image const u_int imgPixelIndex = x + (height - y - 1) * width; pixels[filmPixelIndex] = Lerp(alpha, filmImageMap->GetStorage()->GetSpectrum(imgPixelIndex), pixels[filmPixelIndex]); } } } }
int main() { std::string separator = "\n----------------------------------------------\n"; std::string separatorStar = "\n**********************************************\n"; std::cout << separator << "RTIS - Ray Tracer for \"Imatge Sintetica\"" << separator << std::endl; // Create an empty film Film *film; film = new Film(720, 576); // Declare the shader Vector3D bgColor(0.0, 0.0, 0.0); // Background color (for rays which do not intersect anything) Vector3D intersectionColor(1,0,0); Shader *shader = new IntersectionShader (intersectionColor, bgColor); Shader *depthShader = new DepthShader(Vector3D(0.4, 1, 0.4), 8, bgColor); Shader *directShader = new DirectShader(Vector3D(0.4, 1, 0.4), 8, bgColor); // Declare pointers to all the variables which describe the scene Camera *cam; std::vector<Shape*> *objectsList; std::vector<PointLightSource> *lightSourceList = new std::vector<PointLightSource>; // Build the scene buildSceneSphere(cam, film, objectsList, lightSourceList); // Launch some rays! raytrace(cam, directShader, film, objectsList, lightSourceList); // Save the final result to file std::cout << "\n\nSaving the result to file output.bmp\n" << std::endl; film->save(); std::cout << "\n\n" << std::endl; return 0; }
bool Film::operator == (const Film& f) { return ((this->AbstractMedia::operator ==(f)) && (getRealisateur() == f.getRealisateur()) && (getScenariste() == f.getScenariste()) && (getActeursPrincipaux() == f.getActeursPrincipaux()) && (getType() == f.getType()) && (getDuree() == f.getDuree()) && (getSupport() == f.getSupport())); }
TileRepository::Tile::Tile(TileRepository *repo, const Film &film, const u_int tileX, const u_int tileY) : xStart(tileX), yStart(tileY), pass(0), error(numeric_limits<float>::infinity()), done(false), tileRepository(repo), allPassFilm(NULL), evenPassFilm(NULL), allPassFilmTotalYValue(0.f), hasEnoughWarmUpSample(false) { const u_int *filmSubRegion = film.GetSubRegion(); tileWidth = Min(xStart + tileRepository->tileWidth, filmSubRegion[1] + 1) - xStart; tileHeight = Min(yStart + tileRepository->tileHeight, filmSubRegion[3] + 1) - yStart; allPassFilm = NULL; evenPassFilm = NULL; const bool hasVarianceClamping = tileRepository->varianceClamping.hasClamping(); const bool hasConvergenceTest = (tileRepository->enableMultipassRendering && (tileRepository->convergenceTestThreshold > 0.f)); if (hasVarianceClamping || hasConvergenceTest) InitTileFilm(film, &allPassFilm); if (hasConvergenceTest) InitTileFilm(film, &evenPassFilm); }
Film::Film(const Film& film) : Video(film), chapter_count(film.getChapterCount()) { makeChapters(film.getChapters(), film.getChapterCount()); }
void BiDirVMCPURenderThread::RenderFuncVM() { //SLG_LOG("[BiDirVMCPURenderThread::" << threadIndex << "] Rendering thread started"); //-------------------------------------------------------------------------- // Initialization //-------------------------------------------------------------------------- BiDirVMCPURenderEngine *engine = (BiDirVMCPURenderEngine *)renderEngine; RandomGenerator *rndGen = new RandomGenerator(engine->seedBase + threadIndex); Scene *scene = engine->renderConfig->scene; Camera *camera = scene->camera; Film *film = threadFilm; const u_int filmWidth = film->GetWidth(); const u_int filmHeight = film->GetHeight(); pixelCount = filmWidth * filmHeight; // Setup the samplers vector<Sampler *> samplers(engine->lightPathsCount, NULL); const u_int sampleSize = sampleBootSizeVM + // To generate the initial light vertex and trace eye ray engine->maxLightPathDepth * sampleLightStepSize + // For each light vertex engine->maxEyePathDepth * sampleEyeStepSize; // For each eye vertex // metropolisSharedTotalLuminance and metropolisSharedSampleCount are // initialized inside MetropolisSampler::RequestSamples() double metropolisSharedTotalLuminance, metropolisSharedSampleCount; for (u_int i = 0; i < samplers.size(); ++i) { Sampler *sampler = engine->renderConfig->AllocSampler(rndGen, film, &metropolisSharedTotalLuminance, &metropolisSharedSampleCount); sampler->RequestSamples(sampleSize); samplers[i] = sampler; } u_int iteration = 0; vector<vector<SampleResult> > samplesResults(samplers.size()); vector<vector<PathVertexVM> > lightPathsVertices(samplers.size()); vector<Point> lensPoints(samplers.size()); HashGrid hashGrid; const u_int haltDebug = engine->renderConfig->GetProperty("batch.haltdebug").Get<u_int>(); for(u_int steps = 0; !boost::this_thread::interruption_requested(); ++steps) { // Clear the arrays for (u_int samplerIndex = 0; samplerIndex < samplers.size(); ++samplerIndex) { samplesResults[samplerIndex].clear(); lightPathsVertices[samplerIndex].clear(); } // Setup vertex merging float radius = engine->baseRadius; radius /= powf(float(iteration + 1), .5f * (1.f - engine->radiusAlpha)); radius = Max(radius, DEFAULT_EPSILON_STATIC); const float radius2 = radius * radius; const float vmFactor = M_PI * radius2 * engine->lightPathsCount; vmNormalization = 1.f / vmFactor; const float etaVCM = vmFactor; misVmWeightFactor = MIS(etaVCM); misVcWeightFactor = MIS(1.f / etaVCM); // Using the same time for all rays in the same pass is required by the // current implementation (i.e. I can not mix paths with different // times). However this is detrimental for the Metropolis sampler. const float time = rndGen->floatValue(); //---------------------------------------------------------------------- // Trace all light paths //---------------------------------------------------------------------- for (u_int samplerIndex = 0; samplerIndex < samplers.size(); ++samplerIndex) { Sampler *sampler = samplers[samplerIndex]; // Sample a point on the camera lens if (!camera->SampleLens(time, sampler->GetSample(3), sampler->GetSample(4), &lensPoints[samplerIndex])) continue; TraceLightPath(time, sampler, lensPoints[samplerIndex], lightPathsVertices[samplerIndex], samplesResults[samplerIndex]); } //---------------------------------------------------------------------- // Store all light path vertices in the k-NN accelerator //---------------------------------------------------------------------- hashGrid.Build(lightPathsVertices, radius); //cout << "==========================================\n"; //cout << "Iteration: " << iteration << " Paths: " << engine->lightPathsCount << " Light path vertices: "<< hashGrid.GetVertexCount() <<"\n"; //---------------------------------------------------------------------- // Trace all eye paths //---------------------------------------------------------------------- for (u_int samplerIndex = 0; samplerIndex < samplers.size(); ++samplerIndex) { Sampler *sampler = samplers[samplerIndex]; PathVertexVM eyeVertex; SampleResult eyeSampleResult(Film::RADIANCE_PER_PIXEL_NORMALIZED | Film::ALPHA, 1); eyeSampleResult.alpha = 1.f; Ray eyeRay; eyeSampleResult.filmX = min(sampler->GetSample(0) * filmWidth, (float)(filmWidth - 1)); eyeSampleResult.filmY = min(sampler->GetSample(1) * filmHeight, (float)(filmHeight - 1)); camera->GenerateRay(eyeSampleResult.filmX, eyeSampleResult.filmY, &eyeRay, sampler->GetSample(9), sampler->GetSample(10), time); eyeVertex.bsdf.hitPoint.fixedDir = -eyeRay.d; eyeVertex.throughput = Spectrum(1.f); const float cosAtCamera = Dot(scene->camera->GetDir(), eyeRay.d); const float cameraPdfW = 1.f / (cosAtCamera * cosAtCamera * cosAtCamera * scene->camera->GetPixelArea()); eyeVertex.dVCM = MIS(1.f / cameraPdfW); eyeVertex.dVC = 1.f; eyeVertex.dVM = 1.f; eyeVertex.depth = 1; while (eyeVertex.depth <= engine->maxEyePathDepth) { const u_int sampleOffset = sampleBootSizeVM + engine->maxLightPathDepth * sampleLightStepSize + (eyeVertex.depth - 1) * sampleEyeStepSize; RayHit eyeRayHit; Spectrum connectionThroughput, connectEmission; const bool hit = scene->Intersect(device, false, &eyeVertex.volInfo, sampler->GetSample(sampleOffset), &eyeRay, &eyeRayHit, &eyeVertex.bsdf, &connectionThroughput, NULL, NULL, &connectEmission); // I account for volume emission only with path tracing (i.e. here and // not in any other place) eyeSampleResult.radiancePerPixelNormalized[0] += connectEmission; if (!hit) { // Nothing was hit, look for infinitelight // This is a trick, you can not have a BSDF of something that has // not been hit. DirectHitInfiniteLight must be aware of this. eyeVertex.bsdf.hitPoint.fixedDir = -eyeRay.d; eyeVertex.throughput *= connectionThroughput; DirectHitLight(false, eyeVertex, &eyeSampleResult.radiancePerPixelNormalized[0]); if (eyeVertex.depth == 1) eyeSampleResult.alpha = 0.f; break; } eyeVertex.throughput *= connectionThroughput; // Something was hit // Update MIS constants const float factor = 1.f / MIS(AbsDot(eyeVertex.bsdf.hitPoint.shadeN, eyeVertex.bsdf.hitPoint.fixedDir)); eyeVertex.dVCM *= MIS(eyeRayHit.t * eyeRayHit.t) * factor; eyeVertex.dVC *= factor; eyeVertex.dVM *= factor; // Check if it is a light source if (eyeVertex.bsdf.IsLightSource()) DirectHitLight(true, eyeVertex, &eyeSampleResult.radiancePerPixelNormalized[0]); // Note: pass-through check is done inside Scene::Intersect() //-------------------------------------------------------------- // Direct light sampling //-------------------------------------------------------------- DirectLightSampling(time, sampler->GetSample(sampleOffset + 1), sampler->GetSample(sampleOffset + 2), sampler->GetSample(sampleOffset + 3), sampler->GetSample(sampleOffset + 4), sampler->GetSample(sampleOffset + 5), eyeVertex, &eyeSampleResult.radiancePerPixelNormalized[0]); if (!eyeVertex.bsdf.IsDelta()) { //---------------------------------------------------------- // Connect vertex path ray with all light path vertices //---------------------------------------------------------- const vector<PathVertexVM> &lightPathVertices = lightPathsVertices[samplerIndex]; for (vector<PathVertexVM>::const_iterator lightPathVertex = lightPathVertices.begin(); lightPathVertex < lightPathVertices.end(); ++lightPathVertex) ConnectVertices(time, eyeVertex, *lightPathVertex, &eyeSampleResult, sampler->GetSample(sampleOffset + 6)); //---------------------------------------------------------- // Vertex Merging step //---------------------------------------------------------- hashGrid.Process(this, eyeVertex, &eyeSampleResult.radiancePerPixelNormalized[0]); } //-------------------------------------------------------------- // Build the next vertex path ray //-------------------------------------------------------------- if (!Bounce(time, sampler, sampleOffset + 7, &eyeVertex, &eyeRay)) break; } samplesResults[samplerIndex].push_back(eyeSampleResult); } //---------------------------------------------------------------------- // Splat all samples //---------------------------------------------------------------------- for (u_int samplerIndex = 0; samplerIndex < samplers.size(); ++samplerIndex) samplers[samplerIndex]->NextSample(samplesResults[samplerIndex]); ++iteration; #ifdef WIN32 // Work around Windows bad scheduling renderThread->yield(); #endif //hashGrid.PrintStatistics(); if ((haltDebug > 0u) && (steps >= haltDebug)) break; } for (u_int samplerIndex = 0; samplerIndex < samplers.size(); ++samplerIndex) delete samplers[samplerIndex]; delete rndGen; //SLG_LOG("[BiDirVMCPURenderThread::" << renderThread->threadIndex << "] Rendering thread halted"); }
void BloomFilterPlugin::ApplyOCL(Film &film, const u_int index) { const u_int width = film.GetWidth(); const u_int height = film.GetHeight(); if ((!bloomFilter) || (width * height != bloomBufferSize)) { bloomBufferSize = width * height; InitFilterTable(film); } if (!bloomFilterXKernel) { oclIntersectionDevice = film.oclIntersectionDevice; // Allocate OpenCL buffers film.ctx->SetVerbose(true); oclIntersectionDevice->AllocBufferRW(&oclBloomBuffer, bloomBufferSize * sizeof(Spectrum), "Bloom buffer"); oclIntersectionDevice->AllocBufferRW(&oclBloomBufferTmp, bloomBufferSize * sizeof(Spectrum), "Bloom temporary buffer"); oclIntersectionDevice->AllocBufferRO(&oclBloomFilter, bloomFilter, bloomFilterSize * sizeof(float), "Bloom filter table"); film.ctx->SetVerbose(false); // Compile sources const double tStart = WallClockTime(); cl::Program *program = ImagePipelinePlugin::CompileProgram( film, "-D LUXRAYS_OPENCL_KERNEL -D SLG_OPENCL_KERNEL", slg::ocl::KernelSource_plugin_bloom_funcs, "BloomFilterPlugin"); //---------------------------------------------------------------------- // BloomFilterPlugin_FilterX kernel //---------------------------------------------------------------------- SLG_LOG("[BloomFilterPlugin] Compiling BloomFilterPlugin_FilterX Kernel"); bloomFilterXKernel = new cl::Kernel(*program, "BloomFilterPlugin_FilterX"); // Set kernel arguments u_int argIndex = 0; bloomFilterXKernel->setArg(argIndex++, film.GetWidth()); bloomFilterXKernel->setArg(argIndex++, film.GetHeight()); bloomFilterXKernel->setArg(argIndex++, *(film.ocl_IMAGEPIPELINE)); bloomFilterXKernel->setArg(argIndex++, *(film.ocl_FRAMEBUFFER_MASK)); bloomFilterXKernel->setArg(argIndex++, *oclBloomBuffer); bloomFilterXKernel->setArg(argIndex++, *oclBloomBufferTmp); bloomFilterXKernel->setArg(argIndex++, *oclBloomFilter); bloomFilterXKernel->setArg(argIndex++, bloomWidth); //---------------------------------------------------------------------- // BloomFilterPlugin_FilterY kernel //---------------------------------------------------------------------- SLG_LOG("[BloomFilterPlugin] Compiling BloomFilterPlugin_FilterY Kernel"); bloomFilterYKernel = new cl::Kernel(*program, "BloomFilterPlugin_FilterY"); // Set kernel arguments argIndex = 0; bloomFilterYKernel->setArg(argIndex++, film.GetWidth()); bloomFilterYKernel->setArg(argIndex++, film.GetHeight()); bloomFilterYKernel->setArg(argIndex++, *(film.ocl_IMAGEPIPELINE)); bloomFilterYKernel->setArg(argIndex++, *(film.ocl_FRAMEBUFFER_MASK)); bloomFilterYKernel->setArg(argIndex++, *oclBloomBuffer); bloomFilterYKernel->setArg(argIndex++, *oclBloomBufferTmp); bloomFilterYKernel->setArg(argIndex++, *oclBloomFilter); bloomFilterYKernel->setArg(argIndex++, bloomWidth); //---------------------------------------------------------------------- // BloomFilterPlugin_Merge kernel //---------------------------------------------------------------------- SLG_LOG("[BloomFilterPlugin] Compiling BloomFilterPlugin_Merge Kernel"); bloomFilterMergeKernel = new cl::Kernel(*program, "BloomFilterPlugin_Merge"); // Set kernel arguments argIndex = 0; bloomFilterMergeKernel->setArg(argIndex++, film.GetWidth()); bloomFilterMergeKernel->setArg(argIndex++, film.GetHeight()); bloomFilterMergeKernel->setArg(argIndex++, *(film.ocl_IMAGEPIPELINE)); bloomFilterMergeKernel->setArg(argIndex++, *(film.ocl_FRAMEBUFFER_MASK)); bloomFilterMergeKernel->setArg(argIndex++, *oclBloomBuffer); bloomFilterMergeKernel->setArg(argIndex++, weight); //---------------------------------------------------------------------- delete program; const double tEnd = WallClockTime(); SLG_LOG("[BloomFilterPlugin] Kernels compilation time: " << int((tEnd - tStart) * 1000.0) << "ms"); } oclIntersectionDevice->GetOpenCLQueue().enqueueNDRangeKernel(*bloomFilterXKernel, cl::NullRange, cl::NDRange(RoundUp(film.GetWidth() * film.GetHeight(), 256u)), cl::NDRange(256)); oclIntersectionDevice->GetOpenCLQueue().enqueueNDRangeKernel(*bloomFilterYKernel, cl::NullRange, cl::NDRange(RoundUp(film.GetWidth() * film.GetHeight(), 256u)), cl::NDRange(256)); oclIntersectionDevice->GetOpenCLQueue().enqueueNDRangeKernel(*bloomFilterMergeKernel, cl::NullRange, cl::NDRange(RoundUp(film.GetWidth() * film.GetHeight(), 256u)), cl::NDRange(256)); }
void BiDirVMCPURenderThread::RenderFuncVM() { //SLG_LOG("[BiDirVMCPURenderThread::" << threadIndex << "] Rendering thread started"); //-------------------------------------------------------------------------- // Initialization //-------------------------------------------------------------------------- BiDirVMCPURenderEngine *engine = (BiDirVMCPURenderEngine *)renderEngine; RandomGenerator *rndGen = new RandomGenerator(engine->seedBase + threadIndex); Scene *scene = engine->renderConfig->scene; PerspectiveCamera *camera = scene->camera; Film *film = threadFilm; const unsigned int filmWidth = film->GetWidth(); const unsigned int filmHeight = film->GetHeight(); pixelCount = filmWidth * filmHeight; // Setup the samplers vector<Sampler *> samplers(engine->lightPathsCount, NULL); const unsigned int sampleSize = sampleBootSize + // To generate the initial light vertex and trace eye ray engine->maxLightPathDepth * sampleLightStepSize + // For each light vertex engine->maxEyePathDepth * sampleEyeStepSize; // For each eye vertex double metropolisSharedTotalLuminance, metropolisSharedSampleCount; for (u_int i = 0; i < samplers.size(); ++i) { Sampler *sampler = engine->renderConfig->AllocSampler(rndGen, film, &metropolisSharedTotalLuminance, &metropolisSharedSampleCount); sampler->RequestSamples(sampleSize); samplers[i] = sampler; } u_int iteration = 0; vector<vector<SampleResult> > samplesResults(samplers.size()); vector<vector<PathVertexVM> > lightPathsVertices(samplers.size()); vector<Point> lensPoints(samplers.size()); HashGrid hashGrid; while (!boost::this_thread::interruption_requested()) { // Clear the arrays for (u_int samplerIndex = 0; samplerIndex < samplers.size(); ++samplerIndex) { samplesResults[samplerIndex].clear(); lightPathsVertices[samplerIndex].clear(); } // Setup vertex merging float radius = engine->baseRadius; radius /= powf(float(iteration + 1), .5f * (1.f - engine->radiusAlpha)); radius = Max(radius, DEFAULT_EPSILON_STATIC); const float radius2 = radius * radius; const float vmFactor = M_PI * radius2 * engine->lightPathsCount; vmNormalization = 1.f / vmFactor; const float etaVCM = vmFactor; misVmWeightFactor = MIS(etaVCM); misVcWeightFactor = MIS(1.f / etaVCM); //---------------------------------------------------------------------- // Trace all light paths //---------------------------------------------------------------------- for (u_int samplerIndex = 0; samplerIndex < samplers.size(); ++samplerIndex) { Sampler *sampler = samplers[samplerIndex]; // Sample a point on the camera lens if (!camera->SampleLens(sampler->GetSample(3), sampler->GetSample(4), &lensPoints[samplerIndex])) continue; TraceLightPath(sampler, lensPoints[samplerIndex], lightPathsVertices[samplerIndex], samplesResults[samplerIndex]); } //---------------------------------------------------------------------- // Store all light path vertices in the k-NN accelerator //---------------------------------------------------------------------- hashGrid.Build(lightPathsVertices, radius); //---------------------------------------------------------------------- // Trace all eye paths //---------------------------------------------------------------------- for (u_int samplerIndex = 0; samplerIndex < samplers.size(); ++samplerIndex) { Sampler *sampler = samplers[samplerIndex]; const vector<PathVertexVM> &lightPathVertices = lightPathsVertices[samplerIndex]; PathVertexVM eyeVertex; SampleResult eyeSampleResult; eyeSampleResult.type = PER_PIXEL_NORMALIZED; eyeSampleResult.alpha = 1.f; Ray eyeRay; eyeSampleResult.screenX = min(sampler->GetSample(0) * filmWidth, (float)(filmWidth - 1)); eyeSampleResult.screenY = min(sampler->GetSample(1) * filmHeight, (float)(filmHeight - 1)); camera->GenerateRay(eyeSampleResult.screenX, eyeSampleResult.screenY, &eyeRay, sampler->GetSample(9), sampler->GetSample(10)); eyeVertex.bsdf.hitPoint.fixedDir = -eyeRay.d; eyeVertex.throughput = Spectrum(1.f, 1.f, 1.f); const float cosAtCamera = Dot(scene->camera->GetDir(), eyeRay.d); const float cameraPdfW = 1.f / (cosAtCamera * cosAtCamera * cosAtCamera * scene->camera->GetPixelArea()); eyeVertex.dVCM = MIS(1.f / cameraPdfW); eyeVertex.dVC = 1.f; eyeVertex.dVM = 1.f; eyeVertex.depth = 1; while (eyeVertex.depth <= engine->maxEyePathDepth) { const unsigned int sampleOffset = sampleBootSize + engine->maxLightPathDepth * sampleLightStepSize + (eyeVertex.depth - 1) * sampleEyeStepSize; RayHit eyeRayHit; Spectrum connectionThroughput; if (!scene->Intersect(device, false, sampler->GetSample(sampleOffset), &eyeRay, &eyeRayHit, &eyeVertex.bsdf, &connectionThroughput)) { // Nothing was hit, look for infinitelight // This is a trick, you can not have a BSDF of something that has // not been hit. DirectHitInfiniteLight must be aware of this. eyeVertex.bsdf.hitPoint.fixedDir = -eyeRay.d; eyeVertex.throughput *= connectionThroughput; DirectHitLight(false, eyeVertex, &eyeSampleResult.radiance); if (eyeVertex.depth == 1) eyeSampleResult.alpha = 0.f; break; } eyeVertex.throughput *= connectionThroughput; // Something was hit // Update MIS constants const float factor = 1.f / MIS(AbsDot(eyeVertex.bsdf.hitPoint.shadeN, eyeVertex.bsdf.hitPoint.fixedDir)); eyeVertex.dVCM *= MIS(eyeRayHit.t * eyeRayHit.t) * factor; eyeVertex.dVC *= factor; eyeVertex.dVM *= factor; // Check if it is a light source if (eyeVertex.bsdf.IsLightSource()) DirectHitLight(true, eyeVertex, &eyeSampleResult.radiance); // Note: pass-through check is done inside SceneIntersect() //-------------------------------------------------------------- // Direct light sampling //-------------------------------------------------------------- DirectLightSampling(sampler->GetSample(sampleOffset + 1), sampler->GetSample(sampleOffset + 2), sampler->GetSample(sampleOffset + 3), sampler->GetSample(sampleOffset + 4), sampler->GetSample(sampleOffset + 5), eyeVertex, &eyeSampleResult.radiance); if (!eyeVertex.bsdf.IsDelta()) { //---------------------------------------------------------- // Connect vertex path ray with all light path vertices //---------------------------------------------------------- for (vector<PathVertexVM>::const_iterator lightPathVertex = lightPathVertices.begin(); lightPathVertex < lightPathVertices.end(); ++lightPathVertex) ConnectVertices(eyeVertex, *lightPathVertex, &eyeSampleResult, sampler->GetSample(sampleOffset + 6)); //---------------------------------------------------------- // Vertex Merging step //---------------------------------------------------------- hashGrid.Process(this, eyeVertex, &eyeSampleResult.radiance); } //-------------------------------------------------------------- // Build the next vertex path ray //-------------------------------------------------------------- if (!Bounce(sampler, sampleOffset + 7, &eyeVertex, &eyeRay)) break; ++(eyeVertex.depth); } samplesResults[samplerIndex].push_back(eyeSampleResult); } //---------------------------------------------------------------------- // Splat all samples //---------------------------------------------------------------------- for (u_int samplerIndex = 0; samplerIndex < samplers.size(); ++samplerIndex) samplers[samplerIndex]->NextSample(samplesResults[samplerIndex]); ++iteration; #ifdef WIN32 // Work around Windows bad scheduling renderThread->yield(); #endif } for (u_int samplerIndex = 0; samplerIndex < samplers.size(); ++samplerIndex) delete samplers[samplerIndex]; delete rndGen; //SLG_LOG("[BiDirVMCPURenderThread::" << renderThread->threadIndex << "] Rendering thread halted"); }
void Scene::Deserialization( const char* filename /* = nullptr */ ) { SAFE_DELETE(mRendererPtr); mFilename = filename; tinyxml2::XMLDocument doc; doc.LoadFile( filename ); tinyxml2::XMLElement* pRootElement = doc.FirstChildElement(); // ---------------------------------------Environment-------------------------------------------- tinyxml2::XMLElement* pEnvironmentElement = pRootElement->FirstChildElement( "Environment" ); if( pEnvironmentElement ) { const char* str = pEnvironmentElement->Attribute( "type" ); Environment* pEnvironment = Environment::Create( pEnvironmentElement->Attribute( "type" ) ); pEnvironment->Deserialization( pEnvironmentElement ); AddEnvironment( pEnvironment ); } else { Environment* pEnvironment = new ConstantEnvironment; AddEnvironment( pEnvironment ); } // -------------------------------------Primitive------------------------------------------------- tinyxml2::XMLElement* pPrimitiveElement = pRootElement->FirstChildElement( "primitive" ); while( pPrimitiveElement ) { Primitive* pPrimitive = new Primitive; pPrimitive->Deserialization( pPrimitiveElement ); AddEntity( pPrimitive ); AddLight( pPrimitive->GetAreaLight() ); pPrimitiveElement = pPrimitiveElement->NextSiblingElement( "primitive" ); } // ---------------------------------------Light-------------------------------------------------- tinyxml2::XMLElement* pLightElement = pRootElement->FirstChildElement( "light" ); while( pLightElement ) { const char* LightType = pLightElement->Attribute( "type" ); Light* light = Light::Create( LightType ); light->Deserialization( pLightElement ); AddLight( light ); pLightElement = pLightElement->NextSiblingElement( "light" ); } // --------------------------------------Film----------------------------------------------------- Film* film = new Film; tinyxml2::XMLElement* pFilmElement = pRootElement->FirstChildElement( "Film" ); film->Deserialization( pFilmElement ); // --------------------------------------Camera-------------------------------------------------- tinyxml2::XMLElement* pCameraElement = pRootElement->FirstChildElement( "Camera" ); const char* CameraType = pCameraElement->Attribute( "type" ); mCameraPtr = Camera::Create( CameraType ); mCameraPtr->SetFilm( film ); mCameraPtr->Deserialization( pCameraElement ); // --------------------------------------Integrator--------------------------------------------- tinyxml2::XMLElement* pIntegratorRootElement = pRootElement->FirstChildElement( "Integrator" ); const char* IntegratorType = pIntegratorRootElement->Attribute( "type" ); mSurfaceIntegratorPtr = SurfaceIntegrator::Create( IntegratorType ); mSurfaceIntegratorPtr->Deserialization( pIntegratorRootElement ); // --------------------------------------Sampler-------------------------------------------------- tinyxml2::XMLElement* pSamplerRootElement = pRootElement->FirstChildElement( "Sampler" ); const char* SamplerType = pSamplerRootElement->Attribute( "type" ); mSamplerPtr = Sampler::Create( SamplerType ); mSamplerPtr->Deserialization( pSamplerRootElement ); // --------------------------------------Renderer--------------------------------------------------- tinyxml2::XMLElement* pRendererRootElement = pRootElement->FirstChildElement( "Renderer" ); const char* RendererType = pRendererRootElement->Attribute( "type" ); mRendererPtr = Renderer::Create( RendererType ); mRendererPtr->Deserialization( pRendererRootElement ); // -------------------------------------Build Acceleration Structure--------------------------------- Grid* pGrid = new Grid; pGrid->Setup( this ); mRendererPtr->SetProperty( mSamplerPtr , mCameraPtr , mSurfaceIntegratorPtr , pGrid ); }
void BDPTIntegrator::Render(const Scene &scene) { std::unique_ptr<LightDistribution> lightDistribution = CreateLightSampleDistribution(lightSampleStrategy, scene); // Compute a reverse mapping from light pointers to offsets into the // scene lights vector (and, equivalently, offsets into // lightDistr). Added after book text was finalized; this is critical // to reasonable performance with 100s+ of light sources. std::unordered_map<const Light *, size_t> lightToIndex; for (size_t i = 0; i < scene.lights.size(); ++i) lightToIndex[scene.lights[i].get()] = i; // Partition the image into tiles Film *film = camera->film; const Bounds2i sampleBounds = film->GetSampleBounds(); const Vector2i sampleExtent = sampleBounds.Diagonal(); const int tileSize = 16; const int nXTiles = (sampleExtent.x + tileSize - 1) / tileSize; const int nYTiles = (sampleExtent.y + tileSize - 1) / tileSize; ProgressReporter reporter(nXTiles * nYTiles, "Rendering"); // Allocate buffers for debug visualization const int bufferCount = (1 + maxDepth) * (6 + maxDepth) / 2; std::vector<std::unique_ptr<Film>> weightFilms(bufferCount); if (visualizeStrategies || visualizeWeights) { for (int depth = 0; depth <= maxDepth; ++depth) { for (int s = 0; s <= depth + 2; ++s) { int t = depth + 2 - s; if (t == 0 || (s == 1 && t == 1)) continue; std::string filename = StringPrintf("bdpt_d%02i_s%02i_t%02i.exr", depth, s, t); weightFilms[BufferIndex(s, t)] = std::unique_ptr<Film>(new Film( film->fullResolution, Bounds2f(Point2f(0, 0), Point2f(1, 1)), std::unique_ptr<Filter>(CreateBoxFilter(ParamSet())), film->diagonal * 1000, filename, 1.f)); } } } // Render and write the output image to disk if (scene.lights.size() > 0) { ParallelFor2D([&](const Point2i tile) { // Render a single tile using BDPT MemoryArena arena; int seed = tile.y * nXTiles + tile.x; std::unique_ptr<Sampler> tileSampler = sampler->Clone(seed); int x0 = sampleBounds.pMin.x + tile.x * tileSize; int x1 = std::min(x0 + tileSize, sampleBounds.pMax.x); int y0 = sampleBounds.pMin.y + tile.y * tileSize; int y1 = std::min(y0 + tileSize, sampleBounds.pMax.y); Bounds2i tileBounds(Point2i(x0, y0), Point2i(x1, y1)); std::unique_ptr<FilmTile> filmTile = camera->film->GetFilmTile(tileBounds); for (Point2i pPixel : tileBounds) { tileSampler->StartPixel(pPixel); if (!InsideExclusive(pPixel, pixelBounds)) continue; do { // Generate a single sample using BDPT Point2f pFilm = (Point2f)pPixel + tileSampler->Get2D(); // Trace the camera subpath Vertex *cameraVertices = arena.Alloc<Vertex>(maxDepth + 2); Vertex *lightVertices = arena.Alloc<Vertex>(maxDepth + 1); int nCamera = GenerateCameraSubpath( scene, *tileSampler, arena, maxDepth + 2, *camera, pFilm, cameraVertices); // Get a distribution for sampling the light at the // start of the light subpath. Because the light path // follows multiple bounces, basing the sampling // distribution on any of the vertices of the camera // path is unlikely to be a good strategy. We use the // PowerLightDistribution by default here, which // doesn't use the point passed to it. const Distribution1D *lightDistr = lightDistribution->Lookup(cameraVertices[0].p()); // Now trace the light subpath int nLight = GenerateLightSubpath( scene, *tileSampler, arena, maxDepth + 1, cameraVertices[0].time(), *lightDistr, lightToIndex, lightVertices); // Execute all BDPT connection strategies Spectrum L(0.f); for (int t = 1; t <= nCamera; ++t) { for (int s = 0; s <= nLight; ++s) { int depth = t + s - 2; if ((s == 1 && t == 1) || depth < 0 || depth > maxDepth) continue; // Execute the $(s, t)$ connection strategy and // update _L_ Point2f pFilmNew = pFilm; Float misWeight = 0.f; Spectrum Lpath = ConnectBDPT( scene, lightVertices, cameraVertices, s, t, *lightDistr, lightToIndex, *camera, *tileSampler, &pFilmNew, &misWeight); VLOG(2) << "Connect bdpt s: " << s <<", t: " << t << ", Lpath: " << Lpath << ", misWeight: " << misWeight; if (visualizeStrategies || visualizeWeights) { Spectrum value; if (visualizeStrategies) value = misWeight == 0 ? 0 : Lpath / misWeight; if (visualizeWeights) value = Lpath; weightFilms[BufferIndex(s, t)]->AddSplat( pFilmNew, value); } if (t != 1) L += Lpath; else film->AddSplat(pFilmNew, Lpath); } } VLOG(2) << "Add film sample pFilm: " << pFilm << ", L: " << L << ", (y: " << L.y() << ")"; filmTile->AddSample(pFilm, L); arena.Reset(); } while (tileSampler->StartNextSample()); } film->MergeFilmTile(std::move(filmTile)); reporter.Update(); }, Point2i(nXTiles, nYTiles)); reporter.Done(); } film->WriteImage(1.0f / sampler->samplesPerPixel); // Write buffers for debug visualization if (visualizeStrategies || visualizeWeights) { const Float invSampleCount = 1.0f / sampler->samplesPerPixel; for (size_t i = 0; i < weightFilms.size(); ++i) if (weightFilms[i]) weightFilms[i]->WriteImage(invSampleCount); } }
#include "catch.hpp" #include "../src/film.hpp" TEST_CASE( "Can commit color to buffer in the Film Class", "[Film]" ) { Film film(200, 200); SECTION( "Do not throw exceptions when commit not out of bound" ) { REQUIRE_NOTHROW(film.commit(199, 199, ColorRGB(0, 0, 0))); } SECTION( "Exceptions when try to commit out of bound" ) { REQUIRE_THROWS_AS(film.commit(200, 200, ColorRGB(0, 0, 0)), std::out_of_range); } }
void HybridRenderThread::RenderFunc() { //SLG_LOG("[HybridRenderThread::" << threadIndex << "] Rendering thread started"); boost::this_thread::disable_interruption di; Film *film = threadFilm; const u_int filmWidth = film->GetWidth(); const u_int filmHeight = film->GetHeight(); pixelCount = filmWidth * filmHeight; RandomGenerator *rndGen = new RandomGenerator(threadIndex + renderEngine->seedBase); const u_int incrementStep = 4096; vector<HybridRenderState *> states(incrementStep); try { // Initialize the first states for (u_int i = 0; i < states.size(); ++i) states[i] = AllocRenderState(rndGen); u_int generateIndex = 0; u_int collectIndex = 0; while (!boost::this_thread::interruption_requested()) { // Generate new rays up to the point to have 3 pending buffers while (pendingRayBuffers < 3) { states[generateIndex]->GenerateRays(this); generateIndex = (generateIndex + 1) % states.size(); if (generateIndex == collectIndex) { //SLG_LOG("[HybridRenderThread::" << threadIndex << "] Increasing states size by " << incrementStep); //SLG_LOG("[HybridRenderThread::" << threadIndex << "] State size: " << states.size()); // Insert a set of new states and continue states.insert(states.begin() + generateIndex, incrementStep, NULL); for (u_int i = generateIndex; i < generateIndex + incrementStep; ++i) states[i] = AllocRenderState(rndGen); collectIndex += incrementStep; } } //SLG_LOG("[HybridRenderThread::" << threadIndex << "] State size: " << states.size()); //SLG_LOG("[HybridRenderThread::" << threadIndex << "] generateIndex: " << generateIndex); //SLG_LOG("[HybridRenderThread::" << threadIndex << "] collectIndex: " << collectIndex); //SLG_LOG("[HybridRenderThread::" << threadIndex << "] pendingRayBuffers: " << pendingRayBuffers); // Collect rays up to the point to have only 1 pending buffer while (pendingRayBuffers > 1) { samplesCount += states[collectIndex]->CollectResults(this); const u_int newCollectIndex = (collectIndex + 1) % states.size(); // A safety-check, it should never happen if (newCollectIndex == generateIndex) break; collectIndex = newCollectIndex; } } //SLG_LOG("[HybridRenderThread::" << threadIndex << "] Rendering thread halted"); } catch (boost::thread_interrupted) { SLG_LOG("[HybridRenderThread::" << threadIndex << "] Rendering thread halted"); } #ifndef LUXRAYS_DISABLE_OPENCL catch (cl::Error err) { SLG_LOG("[HybridRenderThread::" << threadIndex << "] Rendering thread ERROR: " << err.what() << "(" << luxrays::utils::oclErrorString(err.err()) << ")"); } #endif // Clean current ray buffers if (currentRayBufferToSend) { currentRayBufferToSend->Reset(); freeRayBuffers.push_back(currentRayBufferToSend); currentRayBufferToSend = NULL; } if (currentReiceivedRayBuffer) { currentReiceivedRayBuffer->Reset(); freeRayBuffers.push_back(currentReiceivedRayBuffer); currentReiceivedRayBuffer = NULL; } // Free all states for (u_int i = 0; i < states.size(); ++i) delete states[i]; delete rndGen; // Remove all pending ray buffers while (pendingRayBuffers > 0) { RayBuffer *rayBuffer = device->PopRayBuffer(); --(pendingRayBuffers); rayBuffer->Reset(); freeRayBuffers.push_back(rayBuffer); } }
bool operator<(Film &f) { return rejting() < f.rejting(); }
bool operator>(Film &f) { return rejting() > f.rejting(); }
void LightCPURenderThread::TraceEyePath(Sampler *sampler, vector<SampleResult> *sampleResults) { LightCPURenderEngine *engine = (LightCPURenderEngine *)renderEngine; Scene *scene = engine->renderConfig->scene; PerspectiveCamera *camera = scene->camera; Film *film = threadFilm; const u_int filmWidth = film->GetWidth(); const u_int filmHeight = film->GetHeight(); // Sample offsets const u_int sampleBootSize = 11; const u_int sampleEyeStepSize = 3; Ray eyeRay; const float screenX = min(sampler->GetSample(0) * filmWidth, (float)(filmWidth - 1)); const float screenY = min(sampler->GetSample(1) * filmHeight, (float)(filmHeight - 1)); camera->GenerateRay(screenX, screenY, &eyeRay, sampler->GetSample(9), sampler->GetSample(10)); Spectrum radiance, eyePathThroughput(1.f, 1.f, 1.f); int depth = 1; while (depth <= engine->maxPathDepth) { const u_int sampleOffset = sampleBootSize + (depth - 1) * sampleEyeStepSize; RayHit eyeRayHit; BSDF bsdf; Spectrum connectionThroughput; const bool somethingWasHit = scene->Intersect(device, false, sampler->GetSample(sampleOffset), &eyeRay, &eyeRayHit, &bsdf, &connectionThroughput); if (!somethingWasHit) { // Nothing was hit, check infinite lights (including sun) const Spectrum throughput = eyePathThroughput * connectionThroughput; if (scene->envLight) radiance += throughput * scene->envLight->GetRadiance(scene, -eyeRay.d); if (scene->sunLight) radiance += throughput * scene->sunLight->GetRadiance(scene, -eyeRay.d); break; } else { // Something was hit, check if it is a light source if (bsdf.IsLightSource()) radiance = eyePathThroughput * connectionThroughput * bsdf.GetEmittedRadiance(scene); else { // Check if it is a specular bounce float bsdfPdf; Vector sampledDir; BSDFEvent event; float cosSampleDir; const Spectrum bsdfSample = bsdf.Sample(&sampledDir, sampler->GetSample(sampleOffset + 1), sampler->GetSample(sampleOffset + 2), &bsdfPdf, &cosSampleDir, &event); if (bsdfSample.Black() || ((depth == 1) && !(event & SPECULAR))) break; // If depth = 1 and it is a specular bounce, I continue to trace the // eye path looking for a light source eyePathThroughput *= connectionThroughput * bsdfSample * (cosSampleDir / bsdfPdf); assert (!eyePathThroughput.IsNaN() && !eyePathThroughput.IsInf()); eyeRay = Ray(bsdf.hitPoint, sampledDir); } ++depth; } } // Add a sample even if it is black in order to avoid aliasing problems // between sampled pixel and not sampled one (in PER_PIXEL_NORMALIZED buffer) AddSampleResult(*sampleResults, PER_PIXEL_NORMALIZED, screenX, screenY, radiance, (depth == 1) ? 1.f : 0.f); }