fixed some rendering

This commit is contained in:
Yggdrasil75
2026-02-27 08:45:26 -05:00
parent b4a7f536bc
commit 926ffe18cd
3 changed files with 145 additions and 88 deletions

View File

@@ -24,8 +24,9 @@ private:
int rayCount = 3; int rayCount = 3;
int reflectCount = 4; int reflectCount = 4;
bool slowRender = false; bool slowRender = false;
float lodDist = 4096.0f; float lodDist = 1024.0f;
float lodDropoff = 0.001f; float lodDropoff = 0.001f;
float maxViewDistance = 4096;
bool globalIllumination = false; bool globalIllumination = false;
bool useLod = true; bool useLod = true;
std::map<int, bool> keyStates; std::map<int, bool> keyStates;
@@ -37,6 +38,9 @@ private:
bool tectonicGenned = false; bool tectonicGenned = false;
bool doFixPlates = true; bool doFixPlates = true;
bool platesUseCellular = false; bool platesUseCellular = false;
std::chrono::steady_clock::time_point lastStatsUpdate;
std::string cachedStats;
bool statsNeedUpdate = true;
enum class DebugColorMode { enum class DebugColorMode {
BASE, BASE,
@@ -271,6 +275,10 @@ public:
if (ImGui::Button(orbitEquator ? "Stop Equator" : "Orbit Equator")) orbitEquator = !orbitEquator; if (ImGui::Button(orbitEquator ? "Stop Equator" : "Orbit Equator")) orbitEquator = !orbitEquator;
} }
updateStatsCache();
ImGui::TextUnformatted(cachedStats.c_str());
ImGui::EndChild(); ImGui::EndChild();
} }
@@ -487,6 +495,7 @@ public:
sim.grid.setLODMinDistance(lodDist); sim.grid.setLODMinDistance(lodDist);
sim.grid.setLODFalloff(lodDropoff); sim.grid.setLODFalloff(lodDropoff);
sim.grid.setMaxDistance(maxViewDistance);
if (slowRender) { if (slowRender) {
currentPreviewFrame = sim.grid.renderFrame(cam, outWidth, outHeight, frame::colormap::RGB, rayCount, reflectCount, globalIllumination, useLod); currentPreviewFrame = sim.grid.renderFrame(cam, outWidth, outHeight, frame::colormap::RGB, rayCount, reflectCount, globalIllumination, useLod);
@@ -541,6 +550,14 @@ public:
void fillPlanet() { void fillPlanet() {
sim.fillPlanet(); sim.fillPlanet();
} }
void updateStatsCache() {
std::stringstream gridstats;
sim.grid.printStats(gridstats);
cachedStats = gridstats.str();
lastStatsUpdate = std::chrono::steady_clock::now();
statsNeedUpdate = false;
}
}; };
#endif #endif

View File

@@ -18,6 +18,7 @@
#include <fstream> #include <fstream>
#include <mutex> #include <mutex>
#include <map> #include <map>
#include <unordered_set>
#ifdef SSE #ifdef SSE
#include <immintrin.h> #include <immintrin.h>
@@ -134,6 +135,7 @@ private:
float lodFalloffRate_ = 0.1f; // Lower = better, higher = worse. 0-1 float lodFalloffRate_ = 0.1f; // Lower = better, higher = worse. 0-1
float lodMinDistance_ = 100.0f; float lodMinDistance_ = 100.0f;
float maxDistance_ = 4096;
struct Ray { struct Ray {
PointType origin; PointType origin;
@@ -175,6 +177,12 @@ private:
return {childMin, childMax}; return {childMin, childMax};
} }
bool boxIntersectsBox(const BoundingBox& a, const BoundingBox& b) const {
return (a.first[0] <= b.second[0] && a.second[0] >= b.first[0] &&
a.first[1] <= b.second[1] && a.second[1] >= b.first[1] &&
a.first[2] <= b.second[2] && a.second[2] >= b.first[2]);
}
void splitNode(OctreeNode* node, int depth) { void splitNode(OctreeNode* node, int depth) {
if (depth >= maxDepth) return; if (depth >= maxDepth) return;
for (int i = 0; i < 8; ++i) { for (int i = 0; i < 8; ++i) {
@@ -182,12 +190,23 @@ private:
node->children[i] = std::make_unique<OctreeNode>(childBounds.first, childBounds.second); node->children[i] = std::make_unique<OctreeNode>(childBounds.first, childBounds.second);
} }
std::vector<std::shared_ptr<NodeData>> keep;
for (const auto& pointData : node->points) { for (const auto& pointData : node->points) {
int octant = getOctant(pointData->position, node->center); // Keep massive objects in the parent
node->children[octant]->points.emplace_back(pointData); if (pointData->size >= node->nodeSize) {
keep.emplace_back(pointData);
continue;
}
BoundingBox cubeBounds = pointData->getCubeBounds();
for (int i = 0; i < 8; ++i) {
if (boxIntersectsBox(node->children[i]->bounds, cubeBounds)) {
node->children[i]->points.emplace_back(pointData);
}
}
} }
node->points.clear(); node->points = std::move(keep);
node->isLeaf = false; node->isLeaf = false;
for (int i = 0; i < 8; ++i) { for (int i = 0; i < 8; ++i) {
@@ -203,7 +222,8 @@ private:
node->lodData = nullptr; node->lodData = nullptr;
} }
if (!node->contains(pointData->position)) return false; BoundingBox cubeBounds = pointData->getCubeBounds();
if (!boxIntersectsBox(node->bounds, cubeBounds)) return false;
if (node->isLeaf) { if (node->isLeaf) {
node->points.emplace_back(pointData); node->points.emplace_back(pointData);
@@ -212,12 +232,20 @@ private:
} }
return true; return true;
} else { } else {
int octant = getOctant(pointData->position, node->center); // Keep in parent if size is larger than or equal to the node size
if (node->children[octant]) { if (pointData->size >= node->nodeSize) {
return insertRecursive(node->children[octant].get(), pointData, depth + 1); node->points.emplace_back(pointData);
return true;
} }
bool inserted = false;
for (int i = 0; i < 8; ++i) {
if (node->children[i] && boxIntersectsBox(node->children[i]->bounds, cubeBounds)) {
inserted |= insertRecursive(node->children[i].get(), pointData, depth + 1);
}
}
return inserted;
} }
return false;
} }
void ensureLOD(const OctreeNode* node) const { void ensureLOD(const OctreeNode* node) const {
@@ -232,10 +260,10 @@ private:
bool anyLight = false; bool anyLight = false;
int count = 0; int count = 0;
if (node->points.size() == 1) { if (node->isLeaf && node->points.size() == 1) {
node->lodData = node->points[0]; node->lodData = node->points[0];
return; return;
} else if (node->isLeaf && node->points.size() == 0) { } else if (node->isLeaf && node->points.empty()) {
return; return;
} }
@@ -249,13 +277,13 @@ private:
count++; count++;
}; };
for(const auto& pt : node->points) accumulate(pt);
for (const auto& child : node->children) { for (const auto& child : node->children) {
if (child) { if (child) {
ensureLOD(child.get()); ensureLOD(child.get());
if (child->lodData) { if (child->lodData) {
accumulate(child->lodData); accumulate(child->lodData);
} else if (child->isLeaf && !child->points.empty()) {
for(const auto& pt : child->points) accumulate(pt);
} }
} }
} }
@@ -305,45 +333,44 @@ private:
return nullptr; return nullptr;
} }
bool removeRecursive(OctreeNode* node, const PointType& pos, float tolerance) { bool removeRecursive(OctreeNode* node, const BoundingBox& bounds, const PointType& pos, float tolerance, bool& sizeDecremented) {
{ {
std::lock_guard<std::mutex> lock(node->lodMutex); std::lock_guard<std::mutex> lock(node->lodMutex);
node->lodData = nullptr; node->lodData = nullptr;
} }
if (!node->contains(pos)) return false; if (!boxIntersectsBox(node->bounds, bounds)) return false;
if (node->isLeaf) { bool foundAny = false;
bool found = false;
auto it = std::remove_if(node->points.begin(), node->points.end(), auto it = std::remove_if(node->points.begin(), node->points.end(),
[&](const std::shared_ptr<NodeData>& pointData) { [&](const std::shared_ptr<NodeData>& pointData) {
if (!pointData->active) return false; if (!pointData->active) return false;
float distSq = (pointData->position - pos).squaredNorm();
float distSq = (pointData->position - pos).squaredNorm(); return (distSq <= tolerance * tolerance);
if (distSq <= tolerance * tolerance) { });
found = true;
return true; if (it != node->points.end()) {
} node->points.erase(it, node->points.end());
return false; if (!sizeDecremented) {
});
if (found) {
node->points.erase(it, node->points.end());
size--; size--;
return true; sizeDecremented = true;
} }
return false; foundAny = true;
} else { }
int octant = getOctant(pos, node->center);
if (node->children[octant]) { if (!node->isLeaf) {
return removeRecursive(node->children[octant].get(), pos, tolerance); for (int i = 0; i < 8; ++i) {
if (node->children[i]) {
foundAny |= removeRecursive(node->children[i].get(), bounds, pos, tolerance, sizeDecremented);
}
} }
} }
return false; return foundAny;
} }
void searchNode(OctreeNode* node, const PointType& center, float radiusSq, int objectid, void searchNodeRecursive(OctreeNode* node, const PointType& center, float radiusSq, int objectid,
std::vector<std::shared_ptr<NodeData>>& results) const { std::vector<std::shared_ptr<NodeData>>& results, std::unordered_set<std::shared_ptr<NodeData>>& seen) const {
PointType closestPoint; PointType closestPoint;
for (int i = 0; i < Dim; ++i) { for (int i = 0; i < Dim; ++i) {
closestPoint[i] = std::max(node->bounds.first[i], std::min(center[i], node->bounds.second[i])); closestPoint[i] = std::max(node->bounds.first[i], std::min(center[i], node->bounds.second[i]));
@@ -354,25 +381,29 @@ private:
return; return;
} }
if (node->isLeaf) { for (const auto& pointData : node->points) {
for (const auto& pointData : node->points) { if (!pointData->active) continue;
if (!pointData->active) continue;
float pointDistSq = (pointData->position - center).squaredNorm();
float pointDistSq = (pointData->position - center).squaredNorm(); if (pointDistSq <= radiusSq && (pointData->objectId == objectid || objectid == -1)) {
if (pointDistSq <= radiusSq && (pointData->objectId == objectid || objectid == -1)) { if (seen.insert(pointData).second) results.emplace_back(pointData);
results.emplace_back(pointData);
}
} }
} else { }
if (!node->isLeaf) {
for (const auto& child : node->children) { for (const auto& child : node->children) {
if (child) { if (child) searchNodeRecursive(child.get(), center, radiusSq, objectid, results, seen);
searchNode(child.get(), center, radiusSq, objectid, results);
}
} }
} }
} }
void voxelTraverseRecursive(OctreeNode* node, float tMin, float tMax, float maxDist, void searchNode(OctreeNode* node, const PointType& center, float radiusSq, int objectid,
std::vector<std::shared_ptr<NodeData>>& results) const {
std::unordered_set<std::shared_ptr<NodeData>> seen;
searchNodeRecursive(node, center, radiusSq, objectid, results, seen);
}
void voxelTraverseRecursive(OctreeNode* node, float tMin, float tMax, float& maxDist,
bool enableLOD, const Ray& ray, std::shared_ptr<NodeData>& hit, float invLodf) const { bool enableLOD, const Ray& ray, std::shared_ptr<NodeData>& hit, float invLodf) const {
if (enableLOD && !node->isLeaf) { if (enableLOD && !node->isLeaf) {
float dist = (node->center - ray.origin).norm(); float dist = (node->center - ray.origin).norm();
@@ -383,7 +414,10 @@ private:
PointType n; PointType n;
PointType h; PointType h;
if (rayCubeIntersect(ray, node->lodData.get(), t, n, h)) { if (rayCubeIntersect(ray, node->lodData.get(), t, n, h)) {
if (t >= 0 && t <= maxDist) hit = node->lodData; if (t >= 0 && t <= maxDist) {
hit = node->lodData;
maxDist = t;
}
} }
return; return;
} }
@@ -395,9 +429,9 @@ private:
float t; float t;
PointType normal, hitPoint; PointType normal, hitPoint;
if (rayCubeIntersect(ray, pointData.get(), t, normal, hitPoint)) { if (rayCubeIntersect(ray, pointData.get(), t, normal, hitPoint)) {
if (t <= maxDist) { if (t >= 0 && t <= maxDist && t <= tMax + 0.001f) {
maxDist = t;
hit = pointData; hit = pointData;
return;
} }
} }
} }
@@ -412,7 +446,7 @@ private:
float tNext; float tNext;
while(tMin < tMax && !hit) { while(tMin < tMax && tMin <= maxDist) {
Eigen::Vector3f next_t; Eigen::Vector3f next_t;
next_t[0] = (currIdx & 1) ? tMax : ttt[0]; next_t[0] = (currIdx & 1) ? tMax : ttt[0];
next_t[1] = (currIdx & 2) ? tMax : ttt[1]; next_t[1] = (currIdx & 2) ? tMax : ttt[1];
@@ -609,27 +643,27 @@ private:
node->isLeaf = isLeaf; node->isLeaf = isLeaf;
node->lodData = nullptr; node->lodData = nullptr;
if (isLeaf) { size_t pointCount;
size_t pointCount; readVal(in, pointCount);
readVal(in, pointCount); node->points.reserve(pointCount);
node->points.reserve(pointCount);
for (size_t i = 0; i < pointCount; ++i) {
for (size_t i = 0; i < pointCount; ++i) { auto pt = std::make_shared<NodeData>();
auto pt = std::make_shared<NodeData>(); readVal(in, pt->data);
readVal(in, pt->data); readVec3(in, pt->position);
readVec3(in, pt->position); readVal(in, pt->objectId);
readVal(in, pt->objectId); readVal(in, pt->active);
readVal(in, pt->active); readVal(in, pt->visible);
readVal(in, pt->visible); readVal(in, pt->size);
readVal(in, pt->size); readVec3(in, pt->color);
readVec3(in, pt->color); readVal(in, pt->light);
readVal(in, pt->light); readVal(in, pt->emittance);
readVal(in, pt->emittance); readVal(in, pt->refraction);
readVal(in, pt->refraction); readVal(in, pt->reflection);
readVal(in, pt->reflection); node->points.push_back(pt);
node->points.push_back(pt); }
}
} else { if (!isLeaf) {
uint8_t childMask; uint8_t childMask;
readVal(in, childMask); readVal(in, childMask);
@@ -945,6 +979,7 @@ public:
void setLODFalloff(float rate) { lodFalloffRate_ = rate; } void setLODFalloff(float rate) { lodFalloffRate_ = rate; }
void setLODMinDistance(float dist) { lodMinDistance_ = dist; } void setLODMinDistance(float dist) { lodMinDistance_ = dist; }
void setMaxDistance(float dist) { maxDistance_ = dist; }
void generateLODs() { void generateLODs() {
if (!root_) return; if (!root_) return;
@@ -1028,7 +1063,10 @@ public:
} }
bool remove(const PointType& pos, float tolerance = EPSILON) { bool remove(const PointType& pos, float tolerance = EPSILON) {
return removeRecursive(root_.get(), pos, tolerance); auto pt = find(pos, tolerance);
if (!pt) return false;
bool sizeDecremented = false;
return removeRecursive(root_.get(), pt->getCubeBounds(), pos, tolerance, sizeDecremented);
} }
std::vector<std::shared_ptr<NodeData>> findInRadius(const PointType& center, float radius, int objectid = -1) const { std::vector<std::shared_ptr<NodeData>> findInRadius(const PointType& center, float radius, int objectid = -1) const {
@@ -1170,7 +1208,8 @@ public:
float tMin, tMax; float tMin, tMax;
if (rayBoxIntersect(oray, root_->bounds, tMin, tMax)) { if (rayBoxIntersect(oray, root_->bounds, tMin, tMax)) {
tMax = std::min(tMax, maxDist); tMax = std::min(tMax, maxDist);
voxelTraverseRecursive(root_.get(), tMin, tMax, maxDist, enableLOD, oray, hit, invLodf); float currentMaxDist = maxDist;
voxelTraverseRecursive(root_.get(), tMin, tMax, currentMaxDist, enableLOD, oray, hit, invLodf);
} }
return hit; return hit;
} }
@@ -1234,7 +1273,8 @@ public:
float tMin, tMax; float tMin, tMax;
if (rayBoxIntersect(ray, root_->bounds, tMin, tMax)) { if (rayBoxIntersect(ray, root_->bounds, tMin, tMax)) {
tMax = std::min(tMax, maxDist); tMax = std::min(tMax, maxDist);
voxelTraverseRecursive(root_.get(), tMin, tMax, maxDist, enableLOD, ray, hit, lodRatio); float currentMaxDist = maxDist;
voxelTraverseRecursive(root_.get(), tMin, tMax, currentMaxDist, enableLOD, ray, hit, lodRatio);
} }
return hit; return hit;
} }
@@ -1259,7 +1299,6 @@ public:
const PointType globalLightDir = (-cam.direction * 0.2f).normalized(); const PointType globalLightDir = (-cam.direction * 0.2f).normalized();
const float fogStart = 1000.0f; const float fogStart = 1000.0f;
const float fogEnd = 4000.0f;
const float minVisibility = 0.2f; const float minVisibility = 0.2f;
#pragma omp parallel for schedule(dynamic, 128) collapse(2) #pragma omp parallel for schedule(dynamic, 128) collapse(2)
@@ -1276,7 +1315,7 @@ public:
Eigen::Vector3f color = backgroundColor_; Eigen::Vector3f color = backgroundColor_;
Ray ray(origin, rayDir); Ray ray(origin, rayDir);
auto hit = fastVoxelTraverse(ray, std::numeric_limits<float>::max(), true); auto hit = fastVoxelTraverse(ray, maxDistance_, true);
if (hit != nullptr) { if (hit != nullptr) {
auto obj = hit; auto obj = hit;
@@ -1295,7 +1334,7 @@ public:
color = color * intensity; color = color * intensity;
} }
float fogFactor = std::clamp((fogEnd - t) / (fogEnd - fogStart), minVisibility, 1.0f); float fogFactor = std::clamp((maxDistance_ - t) / (maxDistance_ - fogStart), minVisibility, 1.0f);
color = color * fogFactor + backgroundColor_ * (1.0f - fogFactor); color = color * fogFactor + backgroundColor_ * (1.0f - fogFactor);
} }
@@ -1608,6 +1647,7 @@ public:
os << " Point Data : " << (dataMem / 1024.0) << " KB\n"; os << " Point Data : " << (dataMem / 1024.0) << " KB\n";
os << "========================================\n" << std::defaultfloat; os << "========================================\n" << std::defaultfloat;
} }
bool empty() const { return size == 0; } bool empty() const { return size == 0; }
void clear() { void clear() {

View File

@@ -128,7 +128,7 @@ public:
planetsim() { planetsim() {
config = planetConfig(); config = planetConfig();
grid = Octree<Particle>({-config.gridSizeCube,-config.gridSizeCube,-config.gridSizeCube,},{config.gridSizeCube,config.gridSizeCube,config.gridSizeCube}); grid = Octree<Particle>(v3(-config.gridSizeCube,-config.gridSizeCube,-config.gridSizeCube),v3(config.gridSizeCube,config.gridSizeCube,config.gridSizeCube), 16, 32);
} }
float evaluate2DStack(const Eigen::Vector2f& point, const NoisePreviewState& state, PNoise2& gen) { float evaluate2DStack(const Eigen::Vector2f& point, const NoisePreviewState& state, PNoise2& gen) {
@@ -352,9 +352,9 @@ public:
std::cout << "have " << unassignedCount << " remaining nodes" << std::endl; std::cout << "have " << unassignedCount << " remaining nodes" << std::endl;
while (unassignedCount > 0) { while (unassignedCount > 0) {
if (unassignedCount % 100 == 0) { // if (unassignedCount % 100 == 0) {
std::cout << "have " << unassignedCount << " remaining nodes" << std::endl; // std::cout << "have " << unassignedCount << " remaining nodes" << std::endl;
} // }
int totalWeight = 0; int totalWeight = 0;
for (int i = 0; i < config.numPlates; i++) { for (int i = 0; i < config.numPlates; i++) {