lets try speeding it up again.

This commit is contained in:
yggdrasil75
2026-02-02 06:34:36 -05:00
parent 58d90e9cd7
commit 3f88fdd14e
2 changed files with 120 additions and 62 deletions

View File

@@ -26,6 +26,12 @@ struct defaults {
int outWidth = 512; int outWidth = 512;
int outHeight = 512; int outHeight = 512;
int gridSizecube = 10000; int gridSizecube = 10000;
bool slowRender = false;
bool globalIllumination = true;
int rayCount = 3;
int reflectCount = 3;
int lodDist;
float lodDropoff;
PNoise2 noise = PNoise2(42); PNoise2 noise = PNoise2(42);
}; };
@@ -399,9 +405,15 @@ void livePreview(Octree<int>& grid, defaults& config, const Camera& cam) {
updatePreview = true; updatePreview = true;
auto renderStart = std::chrono::high_resolution_clock::now(); auto renderStart = std::chrono::high_resolution_clock::now();
frame currentPreviewFrame;
frame currentPreviewFrame = grid.fastRenderFrame(cam, config.outWidth, config.outHeight, frame::colormap::RGB); grid.setLODMinDistance(config.lodDist);
//frame currentPreviewFrame = grid.renderFrame(cam, config.outWidth, config.outHeight, frame::colormap::RGB, 3, 2, true); grid.setLODFalloff(config.lodDropoff);
if (config.slowRender) {
currentPreviewFrame = grid.renderFrame(cam, config.outWidth, config.outHeight, frame::colormap::RGB, config.rayCount, config.reflectCount, config.globalIllumination);
} else {
currentPreviewFrame = grid.fastRenderFrame(cam, config.outWidth, config.outHeight, frame::colormap::RGB);
}
auto renderEnd = std::chrono::high_resolution_clock::now(); auto renderEnd = std::chrono::high_resolution_clock::now();
renderFrameTime = std::chrono::duration<double>(renderEnd - renderStart).count(); renderFrameTime = std::chrono::duration<double>(renderEnd - renderStart).count();
@@ -649,7 +661,7 @@ int main() {
ImGui::NewFrame(); ImGui::NewFrame();
{ {
ImGui::Begin("Controls"); ImGui::Begin("Sim Controls");
ImGui::Text("Planet"); ImGui::Text("Planet");
float pos[3] = { sphereConf.centerX, sphereConf.centerY, sphereConf.centerZ }; float pos[3] = { sphereConf.centerX, sphereConf.centerY, sphereConf.centerZ };
@@ -711,7 +723,6 @@ int main() {
{ {
ImGui::Begin("Planet Preview"); ImGui::Begin("Planet Preview");
ImGui::Checkbox("update Preview", &worldPreview);
if (worldPreview) { if (worldPreview) {
if (gridInitialized) { if (gridInitialized) {
livePreview(grid, config, cam); livePreview(grid, config, cam);
@@ -913,6 +924,18 @@ int main() {
ImGui::SliderFloat("Pitch Speed", &pitchSpeed, 0.0f, 2.0f, "%.2f deg/sec"); ImGui::SliderFloat("Pitch Speed", &pitchSpeed, 0.0f, 2.0f, "%.2f deg/sec");
} }
ImGui::Separator();
ImGui::Checkbox("update Preview", &worldPreview);
ImGui::Checkbox("Use Slower renderer", &config.slowRender);
if (config.slowRender) {
ImGui::InputInt("Rays per pixel", &config.rayCount);
ImGui::InputInt("Max reflections", &config.reflectCount);
}
ImGui::InputFloat("Lod dropoff", &config.lodDropoff);
ImGui::InputInt("lod minimum Distance", &config.lodDist);
ImGui::Checkbox("use Global illumination", &config.globalIllumination);
ImGui::End(); ImGui::End();
} }

View File

@@ -75,6 +75,7 @@ public:
std::vector<std::shared_ptr<NodeData>> points; std::vector<std::shared_ptr<NodeData>> points;
std::array<std::unique_ptr<OctreeNode>, 8> children; std::array<std::unique_ptr<OctreeNode>, 8> children;
PointType center; PointType center;
float nodeSize;
bool isLeaf; bool isLeaf;
mutable std::shared_ptr<NodeData> lodData; mutable std::shared_ptr<NodeData> lodData;
@@ -85,6 +86,7 @@ public:
child = nullptr; child = nullptr;
} }
center = (bounds.first + bounds.second) * 0.5; center = (bounds.first + bounds.second) * 0.5;
nodeSize = (bounds.second - bounds.first).norm();
} }
bool contains(const PointType& point) const { bool contains(const PointType& point) const {
@@ -504,6 +506,24 @@ private:
return 0.2126f * color[0] + 0.7152f * color[1] + 0.0722f * color[2]; return 0.2126f * color[0] + 0.7152f * color[1] + 0.0722f * color[2];
} }
void collectNodesByObjectId(OctreeNode* node, int id, std::vector<std::shared_ptr<NodeData>>& results) const {
if (!node) return;
if (node->isLeaf) {
for (const auto& pt : node->points) {
if (pt->active && (id == -1 || pt->objectId == id)) {
results.push_back(pt);
}
}
} else {
for (const auto& child : node->children) {
if (child) {
collectNodesByObjectId(child.get(), id, results);
}
}
}
}
public: public:
Octree(const PointType& minBound, const PointType& maxBound, size_t maxPointsPerNode=16, size_t maxDepth = 16) : Octree(const PointType& minBound, const PointType& maxBound, size_t maxPointsPerNode=16, size_t maxDepth = 16) :
root_(std::make_unique<OctreeNode>(minBound, maxBound)), maxPointsPerNode(maxPointsPerNode), root_(std::make_unique<OctreeNode>(minBound, maxBound)), maxPointsPerNode(maxPointsPerNode),
@@ -847,55 +867,47 @@ public:
std::vector<std::shared_ptr<NodeData>> hits; std::vector<std::shared_ptr<NodeData>> hits;
if (empty()) return hits; if (empty()) return hits;
float invLodf = 1.0f / lodFalloffRate_;
uint8_t raySignMask = (direction.x() < 0 ? 1 : 0) | (direction.y() < 0 ? 2 : 0) | (direction.z() < 0 ? 4 : 0);
std::function<void(OctreeNode*, const PointType&, const PointType&, float, float)> traverseNode = std::function<void(OctreeNode*, const PointType&, const PointType&, float, float)> traverseNode =
[&](OctreeNode* node, const PointType& origin, const PointType& dir, float tMin, float tMax) { [&](OctreeNode* node, const PointType& origin, const PointType& dir, float tMin, float tMax) {
if (!node || tMin > tMax) return; if (!node) return;
if (enableLOD && !node->isLeaf) { // if (enableLOD && !node->isLeaf) {
float dist = (node->center - origin).norm(); // float dist = (node->center - origin).norm();
float nodeSize = (node->bounds.second - node->bounds.first).norm();
if (dist > lodMinDistance_) { // if (dist > lodMinDistance_) {
float ratio = dist / (nodeSize + 0.0001f); // float ratio = dist / (node->nodeSize + 0.0001f);
if (ratio > (1.0f / lodFalloffRate_)) { // if (ratio > (invLodf)) {
ensureLOD(node); // ensureLOD(node);
if (node->lodData) { // if (node->lodData) {
if (node->lodData->shape == Shape::SPHERE) { // float t;
float t; // PointType n;
if (raySphereIntersect(origin, dir, node->lodData->position, node->lodData->size, t)) { // PointType h;
if (t >= 0 && t <= maxDist) hits.emplace_back(node->lodData); // if (rayCubeIntersect(origin, dir, node->lodData.get(), t, n, h)) {
} // if (t >= 0 && t <= maxDist) hits.emplace_back(node->lodData);
} else { // }
float t; PointType n, h; // return;
if (rayCubeIntersect(origin, dir, node->lodData.get(), t, n, h)) { // }
if (t >= 0 && t <= maxDist) hits.emplace_back(node->lodData); // }
} // }
} // }
return;
}
}
}
}
if (node->isLeaf) { if (node->isLeaf) {
for (const auto& pointData : node->points) { for (const auto& pointData : node->points) {
if (!pointData->active) continue; if (!pointData->active) continue;
if (pointData->shape == Shape::SPHERE) { float t;
PointType center = pointData->position; // if (pointData->shape == Shape::SPHERE) {
float radius = pointData->size; // if (raySphereIntersect(origin, dir, pointData->position, pointData->size, t)) {
float t; // if (t >= 0 && t <= maxDist) {
// hits.emplace_back(pointData);
if (raySphereIntersect(origin, dir, center, radius, t)) { // if (stopAtFirstHit) return;
if (t >= 0 && t <= maxDist) { // }
hits.emplace_back(pointData); // }
if (stopAtFirstHit) return; // } else {
}
}
} else {
float t;
PointType normal, hitPoint; PointType normal, hitPoint;
if (rayCubeIntersect(origin, dir, pointData.get(), t, normal, hitPoint)) { if (rayCubeIntersect(origin, dir, pointData.get(), t, normal, hitPoint)) {
if (t >= 0 && t <= maxDist) { if (t >= 0 && t <= maxDist) {
@@ -903,25 +915,12 @@ public:
if (stopAtFirstHit) return; if (stopAtFirstHit) return;
} }
} }
} // }
} }
} else { } else {
std::array<std::pair<int, float>, 8> childOrder;
PointType center = node->center;
for (int i = 0; i < 8; ++i) { for (int i = 0; i < 8; ++i) {
if (node->children[i]) { int childIdx = i ^ raySignMask;
PointType childCenter = node->children[i]->center;
float dist = (childCenter - origin).dot(dir);
childOrder[i] = {i, dist};
} else {
childOrder[i] = {i, std::numeric_limits<float>::lowest()};
}
}
bitonic_sort_8(childOrder);
for (int i = 0; i < 8; ++i) {
int childIdx = childOrder[i].first;
if (node->children[childIdx]) { if (node->children[childIdx]) {
const auto& childBounds = node->children[childIdx]->bounds; const auto& childBounds = node->children[childIdx]->bounds;
@@ -938,9 +937,7 @@ public:
float tMin, tMax; float tMin, tMax;
if (rayBoxIntersect(origin, direction, root_->bounds, tMin, tMax)) { if (rayBoxIntersect(origin, direction, root_->bounds, tMin, tMax)) {
tMax = std::min(tMax, maxDist); tMax = std::min(tMax, maxDist);
if (tMin <= tMax) { traverseNode(root_.get(), origin, direction, tMin, tMax);
traverseNode(root_.get(), origin, direction, tMin, tMax);
}
} }
return hits; return hits;
} }
@@ -1299,6 +1296,44 @@ public:
return outFrame; return outFrame;
} }
std::vector<std::shared_ptr<NodeData>> getExternalNodes(int targetObjectId) {
std::vector<std::shared_ptr<NodeData>> candidates;
std::vector<std::shared_ptr<NodeData>> surfaceNodes;
collectNodesByObjectId(root_.get(), targetObjectId, candidates);
if (candidates.empty()) return surfaceNodes;
surfaceNodes.reserve(candidates.size());
const std::array<PointType, 6> directions = {
PointType(1, 0, 0), PointType(-1, 0, 0), PointType(0, 1, 0),
PointType(0, -1, 0), PointType(0, 0, 1), PointType(0, 0, -1)
};
for (const auto& node : candidates) {
bool isExposed = false;
float step = node->size;
for (const auto& dir : directions) {
PointType probePos = node->position + (dir * step);
auto neighbor = find(probePos, step * 0.25f);
if (neighbor == nullptr || !neighbor->active || neighbor->objectId != node->objectId) {
isExposed = true;
}
if (isExposed) break;
}
if (isExposed) {
surfaceNodes.push_back(node);
}
}
surfaceNodes.shrink_to_fit();
return surfaceNodes;
}
void printStats(std::ostream& os = std::cout) const { void printStats(std::ostream& os = std::cout) const {
if (!root_) { if (!root_) {
os << "[Octree Stats] Tree is null/empty." << std::endl; os << "[Octree Stats] Tree is null/empty." << std::endl;