void TileLayerComponentManager::_fillBuffer(VertexBuffer& buffer, const TileMapSP tileMap, unsigned layer, float tileWidth, float tileHeight, const Matrix4& wt) const { buffer.clear(); unsigned width = tileMap->width (layer); unsigned height = tileMap->height(layer); Vector2i nTiles(tileMap->tileSetHTiles(), tileMap->tileSetVTiles()); for(unsigned y = 0; y < height; ++y) { for(unsigned x = 0; x < width; ++x) { TileMap::TileIndex tile = tileMap->tile(x, y, layer); if(tile == 0) continue; unsigned index = buffer.vertexCount(); Box2 tc = boxView(tileBox(nTiles, tile - 1), Box2(Vector2(0.001, 0.001), Vector2(0.999, 0.999))); for(unsigned vi = 0; vi < 4; ++vi) { unsigned x2 = (vi & 0x01)? 1: 0; unsigned y2 = (vi & 0x02)? 1: 0; Vector4 pos = wt * Vector4(( x + x2) * tileWidth, (height - y - y2) * tileHeight, 0, 1); buffer.addVertex(SpriteVertex{ pos, Vector4::Constant(1), tc.corner(Box2::CornerType(x2 + y2*2)) }); } buffer.addIndex(index + 0); buffer.addIndex(index + 1); buffer.addIndex(index + 2); buffer.addIndex(index + 2); buffer.addIndex(index + 1); buffer.addIndex(index + 3); } } }
// SamplerIntegrator Method Definitions void SamplerIntegrator::Render(const Scene &scene) { ProfilePhase p(Prof::IntegratorRender); Preprocess(scene, *sampler); // Render image tiles in parallel // Compute number of tiles, _nTiles_, to use for parallel rendering Bounds2i sampleBounds = camera->film->GetSampleBounds(); Vector2i sampleExtent = sampleBounds.Diagonal(); const int tileSize = 16; Point2i nTiles((sampleExtent.x + tileSize - 1) / tileSize, (sampleExtent.y + tileSize - 1) / tileSize); ProgressReporter reporter(nTiles.x * nTiles.y, "Rendering"); { StatTimer timer(&renderingTime); ParallelFor2D([&](Point2i tile) { // Render section of image corresponding to _tile_ // Allocate _MemoryArena_ for tile MemoryArena arena; // Get sampler instance for tile int seed = tile.y * nTiles.x + tile.x; std::unique_ptr<Sampler> tileSampler = sampler->Clone(seed); // Compute sample bounds for tile 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)); // Get _FilmTile_ for tile std::unique_ptr<FilmTile> filmTile = camera->film->GetFilmTile(tileBounds); // Loop over pixels in tile to render them for (Point2i pixel : tileBounds) { { ProfilePhase pp(Prof::StartPixel); tileSampler->StartPixel(pixel); } do { // Initialize _CameraSample_ for current sample CameraSample cameraSample = tileSampler->GetCameraSample(pixel); // Generate camera ray for current sample RayDifferential ray; Float rayWeight = camera->GenerateRayDifferential(cameraSample, &ray); ray.ScaleDifferentials( 1 / std::sqrt((Float)tileSampler->samplesPerPixel)); ++nCameraRays; // Evaluate radiance along camera ray Spectrum L(0.f); if (rayWeight > 0) L = Li(ray, scene, *tileSampler, arena); // Issue warning if unexpected radiance value returned if (L.HasNaNs()) { Error( "Not-a-number radiance value returned " "for image sample. Setting to black."); L = Spectrum(0.f); } else if (L.y() < -1e-5) { Error( "Negative luminance value, %f, returned " "for image sample. Setting to black.", L.y()); L = Spectrum(0.f); } else if (std::isinf(L.y())) { Error( "Infinite luminance value returned " "for image sample. Setting to black."); L = Spectrum(0.f); } // Add camera ray's contribution to image filmTile->AddSample(cameraSample.pFilm, L, rayWeight); // Free _MemoryArena_ memory from computing image sample // value arena.Reset(); } while (tileSampler->StartNextSample()); } // Merge image tile into _Film_ camera->film->MergeFilmTile(std::move(filmTile)); reporter.Update(); }, nTiles); reporter.Done(); } // Save final image after rendering camera->film->WriteImage(); }