inline void splat(Vec2u pixel, Vec3f w) { uint32 idx = pixel.x() + pixel.y()*_w; atomicAdd(_buffer[idx].x(), w.x()); atomicAdd(_buffer[idx].y(), w.y()); atomicAdd(_buffer[idx].z(), w.z()); }
bool PinholeCamera::sampleDirection(PathSampleGenerator &sampler, const PositionSample &/*point*/, Vec2u pixel, DirectionSample &sample) const { float pdf; Vec2f uv = _filter.sample(sampler.next2D(CameraSample), pdf); Vec3f localD = Vec3f( -1.0f + (float(pixel.x()) + 0.5f + uv.x())*2.0f*_pixelSize.x(), _ratio - (float(pixel.y()) + 0.5f + uv.y())*2.0f*_pixelSize.x(), _planeDist ).normalized(); sample.d = _transform.transformVector(localD); sample.weight = Vec3f(1.0f); sample.pdf = _invPlaneArea/cube(localD.z()); return true; }
void iterateTiles(std::array<QuadSetup, N> quads, Intersector intersector) const { Box2i bounds; for (const auto &q : quads) bounds.grow(q.bounds); if (bounds.empty()) return; uint32 minX = uint32(bounds.min().x()) & ~TileMask, maxX = bounds.max().x(); uint32 minY = uint32(bounds.min().y()) & ~TileMask, maxY = bounds.max().y(); for (auto &q : quads) { q.start(minX + TileSize*0.5f, minY + TileSize*0.5f); for (int k = 0; k < 3; ++k) { q.stepX[k] *= float(TileSize); q.stepY[k] *= float(TileSize); } } for (uint32 y = minY; y < maxY; y += TileSize) { for (auto &q : quads) q.beginRow(); for (uint32 x = minX; x < maxX; x += TileSize) { float wMin = -1.0f; for (auto &q : quads) wMin = max(wMin, q.reduce()); if (wMin >= 0.0f) { uint32 xjMax = min(x + TileSize, _res.x()); uint32 yjMax = min(y + TileSize, _res.y()); for (uint32 yj = y; yj < yjMax; ++yj) for (uint32 xj = x; xj < xjMax; ++xj) intersector(xj, yj, xj + yj*_res.x()); } for (auto &q : quads) q.stepCol(); } for (auto &q : quads) q.endRow(); } }
void Integrator::writeBuffers(const std::string &suffix, bool overwrite) { Vec2u res = _scene->cam().resolution(); std::unique_ptr<Vec3f[]> hdr(new Vec3f[res.product()]); std::unique_ptr<Vec3c[]> ldr(new Vec3c[res.product()]); for (uint32 y = 0; y < res.y(); ++y) for (uint32 x = 0; x < res.x(); ++x) hdr[x + y*res.x()] = _scene->cam().getLinear(x, y); for (uint32 i = 0; i < res.product(); ++i) ldr[i] = Vec3c(clamp(Vec3i(_scene->cam().tonemap(hdr[i])*255.0f), Vec3i(0), Vec3i(255))); const RendererSettings &settings = _scene->rendererSettings(); if (!settings.outputFile().empty()) ImageIO::saveLdr(incrementalFilename(settings.outputFile(), suffix, overwrite), &ldr[0].x(), res.x(), res.y(), 3); if (!settings.hdrOutputFile().empty()) ImageIO::saveHdr(incrementalFilename(settings.hdrOutputFile(), suffix, overwrite), &hdr[0].x(), res.x(), res.y(), 3); }
void ProgressivePhotonMapIntegrator::prepareForRender(TraceableScene &scene, uint32 seed) { _sampler = UniformSampler(MathUtil::hash32(seed)); _currentSpp = 0; _iteration = 0; _scene = &scene; advanceSpp(); scene.cam().requestColorBuffer(); _surfacePhotons.resize(_settings.photonCount); if (!_scene->media().empty()) _volumePhotons.resize(_settings.volumePhotonCount); int numThreads = ThreadUtils::pool->threadCount(); for (int i = 0; i < numThreads; ++i) { uint32 surfaceRangeStart = intLerp(0, uint32(_surfacePhotons.size()), i + 0, numThreads); uint32 surfaceRangeEnd = intLerp(0, uint32(_surfacePhotons.size()), i + 1, numThreads); uint32 volumeRangeStart = intLerp(0, uint32( _volumePhotons.size()), i + 0, numThreads); uint32 volumeRangeEnd = intLerp(0, uint32( _volumePhotons.size()), i + 1, numThreads); _taskData.emplace_back(SubTaskData{ SurfacePhotonRange(&_surfacePhotons[0], surfaceRangeStart, surfaceRangeEnd), VolumePhotonRange(_volumePhotons.empty() ? nullptr : &_volumePhotons[0], volumeRangeStart, volumeRangeEnd) }); _samplers.emplace_back(_scene->rendererSettings().useSobol() ? std::unique_ptr<PathSampleGenerator>(new SobolPathSampler(MathUtil::hash32(_sampler.nextI()))) : std::unique_ptr<PathSampleGenerator>(new UniformPathSampler(MathUtil::hash32(_sampler.nextI()))) ); _tracers.emplace_back(new PhotonTracer(&scene, _settings, i)); } Vec2u res = _scene->cam().resolution(); _w = res.x(); _h = res.y(); diceTiles(); }