inline void splatFiltered(Vec2f pixel, Vec3f w) { if (_filter.isDirac()) { return; } else if (_filter.isBox()) { splat(Vec2u(pixel), w); } else { float px = pixel.x() - 0.5f; float py = pixel.y() - 0.5f; uint32 minX = max(int(px + 1.0f - _filter.width()), 0); uint32 maxX = min(int(px + _filter.width()), int(_w) - 1); uint32 minY = max(int(py + 1.0f - _filter.width()), 0); uint32 maxY = min(int(py + _filter.width()), int(_h) - 1); // Maximum filter width is 2 pixels float weightX[4], weightY[4]; for (uint32 x = minX; x <= maxX; ++x) weightX[x - minX] = _filter.evalApproximate(x - px); for (uint32 y = minY; y <= maxY; ++y) weightY[y - minY] = _filter.evalApproximate(y - py); for (uint32 y = minY; y <= maxY; ++y) for (uint32 x = minX; x <= maxX; ++x) splat(Vec2u(x, y), w*weightX[x - minX]*weightY[y - minY]); } }
void processTiles(const TileProcessingFunc& fun) { auto task = [&](uint32_t threadID) { auto loopID = 0u; while(true) { auto tileID = loopID * getSystemThreadCount() + threadID; ++loopID; if(tileID >= m_Params.m_nTileCount) { return; } uint32_t tileX = tileID % m_Params.m_TileCount.x; uint32_t tileY = tileID / m_Params.m_TileCount.x; Vec2u tileOrg = Vec2u(tileX, tileY) * m_Params.m_TileSize; auto viewport = Vec4u(tileOrg, m_Params.m_TileSize); if(viewport.x + viewport.z > m_Params.m_FramebufferSize.x) { viewport.z = m_Params.m_FramebufferSize.x - viewport.x; } if(viewport.y + viewport.w > m_Params.m_FramebufferSize.y) { viewport.w = m_Params.m_FramebufferSize.y - viewport.y; } fun(threadID, tileID, viewport); } }; launchThreads(task, getSystemThreadCount()); }
void Camera::blitSplatBuffer() { for (uint32 y = 0; y < _res.y(); ++y) for (uint32 x = 0; x < _res.x(); ++x) _colorBuffer->addSample(Vec2u(x, y), _splatBuffer->get(x, y)); _splatBuffer->unsafeReset(); }
WindowScope addWindow(const char* title, bool isOpen = true, const Vec2i& size = Vec2u(0)) { auto it = m_bWindowOpenFlags.find(title); auto ptr = [&] { if(it == end(m_bWindowOpenFlags)) { m_bWindowOpenFlags[title] = isOpen; return &m_bWindowOpenFlags[title]; } else { return &(*it).second; } }(); return WindowScope(title, ptr, size); }
PG15RendererParams(const Scene& scene, const Sensor& sensor, Vec2u framebufferSize, std::size_t maxDepth, std::size_t resamplingPathCount): m_Scene(scene), m_Sensor(sensor), m_FramebufferSize(framebufferSize), m_nMaxDepth(maxDepth), m_nResamplingPathCount(resamplingPathCount) { m_TileCount = m_FramebufferSize / m_TileSize + Vec2u(m_FramebufferSize % m_TileSize != zero<Vec2u>()); m_nTileCount = m_TileCount.x * m_TileCount.y; }
void Grid::SetDimension(uint32_t width, uint32_t height) { int cellCountDiff = width * height - dimension.x * dimension.y; // Add cells if (cellCountDiff >= 0) { for (int i = 0; i < cellCountDiff; ++i) { Gui* cell = AddGui(); cell->DisableHover(); cells.push_back(cell); } } else // Remove cells { for (int i = 0; i < -cellCountDiff; ++i) { Gui* cell = cells[cells.size() - 1 - i]; cell->RemoveFromParent(); } cells.resize(cells.size() + cellCountDiff); } Vec2i dimensionDiff = Vec2i(width - dimension.x, height - dimension.y); // Add columns if (dimensionDiff.x >= 0) { for (int i = 0; i < dimensionDiff.x; ++i) columns.push_back(GridColumn(columns.size() + i, this)); } else // Remove columns { columns.resize(columns.size() + dimensionDiff.x); } // Add rows if (dimensionDiff.y >= 0) { for (int i = 0; i < dimensionDiff.y; ++i) rows.push_back(GridRow(rows.size() + i, this)); } else // Remove rows { rows.resize(rows.size() + dimensionDiff.y); } dimension = Vec2u(width, height); }
inline void recreateWindow() { if(renderWindow.isOpen()) renderWindow.close(); renderWindow.create({width, height}, title, fullscreen ? sf::Style::Fullscreen : sf::Style::Default, sf::ContextSettings{0, 0, antialiasingLevel, 0, 0}); renderWindow.setSize(Vec2u(width * pixelMult, height * pixelMult)); renderWindow.setVerticalSyncEnabled(vsync); renderWindow.setFramerateLimit(fpsLimited ? maxFPS : 0); inputState.reset(); mustRecreate = false; onRecreation(); }
EnvironmentLight loadEnvironmentLight( const Scene& scene, const tinyxml2::XMLElement& elt) { auto pBuildFromDirection = elt.FirstChildElement("BuildFromDirection"); if(pBuildFromDirection) { Vec3f wi(0, 1, 0); getChildAttribute(*pBuildFromDirection, "IncidentDirection", wi); Vec3f exitantPower = zero<Vec3f>(); getChildAttribute(*pBuildFromDirection, "ExitantPower", exitantPower); Vec2u resolution = Vec2u(1, 1); getChildAttribute(*pBuildFromDirection, "Resolution", resolution); return EnvironmentLight(resolution, wi, exitantPower, scene); } throw std::runtime_error("Unable to load EnvironmentLight"); }
void processSample(uint32_t threadID, uint32_t pixelID, uint32_t sampleID, uint32_t x, uint32_t y) const { PixelSensor sensor(getSensor(), Vec2u(x, y), getFramebufferSize()); auto pixelSample = getPixelSample(threadID, sampleID); auto lensSample = getFloat2(threadID); RaySample raySample; Intersection I; sampleExitantRay( sensor, getScene(), lensSample, pixelSample, raySample, I); auto ray = raySample.value; accumulate(0, pixelID, Vec4f(ray.dir, 1.f)); }
Vec2u getSize() const { return Vec2u(getWidth(), getHeight()); }
Vec2u Camera::tileGetFullSize(void) const { return Vec2u(0u, 0u); }
//map<color, Color> colors = { // { Black, Color::Black }, // { White, Color::White }, // { Red, Color::Red }, // { Green, Color::Green }, // { Blue, Color::Blue }, // { Yellow, Color::Yellow }, // { Magenta, Color::Magenta }, // { Cyan, Color::Cyan }, // { Transparent, Color::Transparent }, // { Orange, Color(255, 128, 0) } //}; ////////////////////////// this returns a lambda ////////////////////////// function<void()> ////////////////////////// TYPE APP NAME ON LINE BELOW ////////////////////////// mine_solver (RenderWindow&window, ui &UI) { return [&window, &UI]() { #ifndef COMMON_INITS //void smoothmouse(RenderWindow&window, ui &UI){ // tidy code organization, here we predeclare methods just like a header would, it's redundant but necessary function<void()> draw, loop, init, update; function<void(Vec2 pos)> mousemoved; function<void(sf::Mouse::Button button)> mouseclick, mouserelease; function<void(Event&e)> treatotherevent; function<void(Keyboard::Key k)> treatkeyevent; // we don't have a class/interface/struct with data, everything is local to this function, like a classic stack that all programs are anyway. Texture cursor_tx; Sprite cursor; configfile cfg; cfg.init("bedlab.cfg"); Color background = cfg.getvar<Color>("background"); if (!cursor_tx.loadFromFile(cfg.getstr("cursor"))) cout << "did not load cursor" << endl; cursor.setTexture(cursor_tx); cursor.setOrigin(3, 3); window.setMouseCursorVisible(false); Vec2 mpos; bool leftclicked = false, rightclicked = false; // view and zoom View view, ui_view; ui_view = view = window.getDefaultView(); float zoomlevel = 1; Vec2 mpos_abs; #endif // COMMON_INITS // ************************ CODE BEGIN ************************ barstack bst(FONT, FONTSIZE); slider_finder sl; randgenfloat cell_rnd(0, 16); //grd. vector<string> mines_str = { " ", " 21114X411 ", " 3X22XX212 ", " X3--4433X ", " 23--4XX3X ", " 1X4---433 ", " 12X4--4X2 ", " 123X3XX3X ", " 2X2122221 ", " " }; int w = mines_str[0].length(); int h = mines_str.size(); vector<int> mine_states(h*w); grid grd; grd.screen_init(Vec2u(window.getSize()), Vec2u( w,h ), true); /* 1-8: surrounding mines 0 no mine, "clear" -1: unknown -2 mine */ map<char, int> lookup = { { '-',-1 }, { 'X',-2 }, { ' ',0 } }; int i = 0; logfile lg("minelog.txt"); lg.logw(to_str("i", "j", "index", "value")); for (auto&a : mines_str) { int j = 0; for (auto&b : a) { int value = -10; //value = // lookup.count(b) ? // lookup[b] // : (b > '0' || b <= '9') ? // int(b - '0') // : value; //msg(value); if (lookup.count(b)) value = lookup[b]; else if (b > '0' || b <= '9')value = int(b - '0'); int index = getat(j, i, w); mine_states[index] = value; //msgm(i,j,index, value); lg.logw(to_str(i,j,index, value)); ++j; } ++i; } map<int, Color> mine_colors = { { -2,Color::Red }, { -1,Color::Cyan }, { 0,Color::Black } }; msg(mine_states); i = 0; for (auto&a : mine_states) { if(a > 0) grd.texts[i].setString(to_str(a)); else grd.cells[i].setFillColor(mine_colors[a]); //grd.texts2[i].setString(to_str(i)); //grd.texts3[i].setString(to_str(getat(i,w))); ++i; } auto analyse = [&mine_states, w, h, &grd]() { vector<Vec2i> offsets = { { -1,-1 }, { 1,-1 }, { -1,1 }, { 1,1 }, { 0,-1 }, { -1,0 }, { 0,1 }, { 1,0 } }; int i = 0; for (auto&a : mine_states) { auto pos = getat(i, w); int unknown = 0, is_mine = 0; for (auto&off : offsets) { auto cell = pos + off; int cell_index = getat(cell,w); if (cell_index < 0 || cell_index >= mine_states.size() || cell.x < 0 || cell.x > w) continue; switch (mine_states[cell_index]) { case -1: ++is_mine; break; //unknown case -2: ++unknown; break; //mine } } int mine_left = a - is_mine; float prob = mine_left / unknown; ++i; } }; auto nearest_pt = mkcircle({ 0, 0 }, Color::Transparent, 10); nearest_pt.setOutlineThickness(2); // ************************ INITS END ********************** //then we actually define the functions, note how all function captures the local context by reference #ifndef LOOP_LAMBDAS draw = [&]() { window.setView(view); // object draw, AFTER normal view //////////////// obj draw START //////////////// for (auto&a : glob_pts)window.draw(a); for (auto&a : glob_rects)window.draw(a); for (auto&a : glob_vert)window.draw(a); for (auto&a : glob_texts)window.draw(a); window.draw(nearest_pt); grd.draw(window); //////////////// obj draw END //////////////// // UI draw, AFTER ui view and BEFORE other draw window.setView(ui_view); bst.draw(window); // nothing after here please UI.draw(window); window.draw(cursor); }; update = [&]() { }; treatkeyevent = [&](Keyboard::Key k) { switch (k) { case Keyboard::BackSpace: glob_pts.clear(); glob_texts.clear(); glob_rects.clear(); glob_vert.clear(); break; case Keyboard::Space: break; case Keyboard::Q: break; } }; mousemoved = [&](Vec2 pos) { cursor.setPosition(pos); if (leftclicked) sl.mouse_callback(pos); }; mouseclick = [&](sf::Mouse::Button button) { if (button == Mouse::Button::Left) leftclicked = true; if (button == Mouse::Button::Right) rightclicked = true; }; mouserelease = [&](sf::Mouse::Button button) { if (button == Mouse::Button::Left) leftclicked = false; if (button == Mouse::Button::Right) rightclicked = false; sl.release(); }; loop = [&]() { while (window.isOpen()) { sf::Event event; while (window.pollEvent(event)) { switch (event.type) { case sf::Event::KeyPressed: if (event.key.code == sf::Keyboard::Escape) window.close(); treatkeyevent(event.key.code); break; case sf::Event::Closed: window.close(); break; case sf::Event::MouseButtonPressed: mouseclick(event.mouseButton.button); break; case sf::Event::MouseButtonReleased: mouserelease(event.mouseButton.button); break; case sf::Event::MouseMoved: mpos = Vec2(event.mouseMove.x, event.mouseMove.y); mousemoved(mpos); break; default: treatotherevent(event); break; } } window.clear(background); update(); draw(); window.display(); } }; treatotherevent = [&](Event&e) { if (e.type == Event::MouseWheelMoved && e.mouseWheel.delta) { mpos_abs = window.mapPixelToCoords(Vec2i(mpos), view); //view = window.getView(); if (e.mouseWheel.delta < 0) { zoomlevel *= 2.f; view.setSize(view.getSize()*2.f); view.setCenter(interp(mpos_abs, view.getCenter(), 2.f)); //view.setCenter(interp(mpos_abs, view.getCenter(), 2.f)); } if (e.mouseWheel.delta > 0) { zoomlevel *= 0.5; view.setSize(view.getSize()*.5f); view.setCenter(.5f*(view.getCenter() + mpos_abs)); //view.setCenter(.5f*(view.getCenter() + mpos_abs)); } window.setView(view); } }; loop(); #endif // LOOP_LAMBDAS }; }
void Texture::clear() { m_handle = 0; m_size = Vec2u(); }
void UniformResamplingRecursiveMISBPTRenderer::processSample(uint32_t threadID, uint32_t tileID, uint32_t pixelID, uint32_t sampleID, uint32_t x, uint32_t y) const { auto mis = [&](float v) { return Mis(v); }; ThreadRNG rng(*this, threadID); PixelSensor pixelSensor(getSensor(), Vec2u(x, y), getFramebufferSize()); auto pixelSample = getPixelSample(threadID, sampleID); auto sensorSample = getFloat2(threadID); auto fImportanceScale = 1.f / getSppCount(); BDPTPathVertex eyeVertex(getScene(), pixelSensor, sensorSample, pixelSample, m_nLightPathCount, mis); if(eyeVertex.m_Power == zero<Vec3f>() || !eyeVertex.m_fPathPdf) { return; } // Sample the light path to connect with the eye path auto lightPathIdx = clamp(std::size_t(getFloat(threadID) * m_nLightPathCount), std::size_t(0), m_nLightPathCount - 1); auto pLightPath = m_LightPathBuffer.getSlicePtr(lightPathIdx); auto maxEyePathDepth = getMaxEyePathDepth(); auto maxLightPathDepth = getMaxLightPathDepth(); auto extendEyePath = [&]() -> bool { return eyeVertex.m_nDepth < maxEyePathDepth && eyeVertex.extend(eyeVertex, getScene(), getSppCount(), false, rng, mis); }; // Iterate over an eye path do { // Intersection with light source auto totalLength = eyeVertex.m_nDepth; if(acceptPathDepth(totalLength) && totalLength <= m_nMaxDepth) { auto contrib = fImportanceScale * computeEmittedRadiance(eyeVertex, getScene(), m_LightSampler, getSppCount(), mis); if(isInvalidMeasurementEstimate(contrib)) { reportInvalidContrib(threadID, tileID, pixelID, [&]() { debugLog() << "s = " << 0 << ", t = " << (eyeVertex.m_nDepth + 1) << std::endl; }); } accumulate(FINAL_RENDER, pixelID, Vec4f(contrib, 0)); accumulate(FINAL_RENDER_DEPTH1 + totalLength - 1u, pixelID, Vec4f(contrib, 0)); auto strategyOffset = computeBPTStrategyOffset(totalLength + 1, 0u); accumulate(BPT_STRATEGY_s0_t2 + strategyOffset, pixelID, Vec4f(contrib, 0)); } // Connections if(eyeVertex.m_Intersection) { // Direct illumination auto totalLength = eyeVertex.m_nDepth + 1; if(acceptPathDepth(totalLength) && totalLength <= m_nMaxDepth) { float lightPdf; auto pLight = m_LightSampler.sample(getScene(), getFloat(threadID), lightPdf); auto s2D = getFloat2(threadID); auto contrib = fImportanceScale * connectVertices(eyeVertex, EmissionVertex(pLight, lightPdf, s2D), getScene(), getSppCount(), mis); if(isInvalidMeasurementEstimate(contrib)) { reportInvalidContrib(threadID, tileID, pixelID, [&]() { debugLog() << "s = " << 1 << ", t = " << (eyeVertex.m_nDepth + 1) << std::endl; }); } accumulate(FINAL_RENDER, pixelID, Vec4f(contrib, 0)); accumulate(FINAL_RENDER_DEPTH1 + totalLength - 1u, pixelID, Vec4f(contrib, 0)); auto strategyOffset = computeBPTStrategyOffset(totalLength + 1, 1); accumulate(BPT_STRATEGY_s0_t2 + strategyOffset, pixelID, Vec4f(contrib, 0)); } // Connection with each light vertex for(auto j = 0u; j < maxLightPathDepth; ++j) { auto pLightVertex = pLightPath + j; auto totalLength = eyeVertex.m_nDepth + pLightVertex->m_nDepth + 1; if(pLightVertex->m_fPathPdf > 0.f && acceptPathDepth(totalLength) && totalLength <= m_nMaxDepth) { auto contrib = fImportanceScale * connectVertices(eyeVertex, *pLightVertex, getScene(), getSppCount(), mis); if(isInvalidMeasurementEstimate(contrib)) { reportInvalidContrib(threadID, tileID, pixelID, [&]() { debugLog() << "s = " << (pLightVertex->m_nDepth + 1) << ", t = " << (eyeVertex.m_nDepth + 1) << std::endl; }); } accumulate(FINAL_RENDER, pixelID, Vec4f(contrib, 0)); accumulate(FINAL_RENDER_DEPTH1 + totalLength - 1u, pixelID, Vec4f(contrib, 0)); auto strategyOffset = computeBPTStrategyOffset(totalLength + 1, pLightVertex->m_nDepth + 1); accumulate(BPT_STRATEGY_s0_t2 + strategyOffset, pixelID, Vec4f(contrib, 0)); } } } } while(extendEyePath()); }
// Default to low-res 16:9 Camera::Camera() : Camera(Mat4f(), Vec2u(1000u, 563u)) { }
void InstantRadiosityRenderer::processTile(uint32_t threadID, uint32_t tileID, const Vec4u& viewport) const { TileProcessingRenderer::processTilePixels(viewport, [&](auto x, auto y) { this->processPixel(threadID, tileID, Vec2u(x, y)); }); }