-
-
Notifications
You must be signed in to change notification settings - Fork 21.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use distance to AABB surface to calculate Mesh LOD instead of using supports #92290
Conversation
Linking the MRP I created for testing LOD since it's quite useful: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested locally (rebased on top of master
568589c), it doesn't seem to work as expected with @huwpascoe's MRP. I still get sudden unexpected LOD level changes when the camera moves at certain positions (e.g. going from a low LOD level to full resolution LOD instantly).
Also, in general, the LOD level regularly decreases even though my camera is getting closer to the MultiMeshInstance3D's center, which doesn't make sense to me.
master
lod_selection_before.mp4
This PR
lod_selection_after.mp4
This makes me wonder if the full resolution LOD should always be used if the camera's AABB is inside the MultiMeshInstance's AABB. This will be slower, but it ensures one instance from the MultiMeshInstance3D will never look bad if it's right in front of you, no matter how isolated it is from the rest (or whether it's near the edges or at the center of the MultiMeshInstance3D).
A less extreme approach could be to clamp the LOD selection for MultiMeshInstance3Ds when the camera is inside its bounds (e.g. use only the two most detailed LOD levels to avoid too much discrepancy).
That's how the PR currently works. If the camera is inside the AABB then the most detailed LOD is always used. Do you know if the AABB in this MRP actually covers all the instances? Depending on how it was created it might not fit the instances very well
This could be from crossing the AABB threshold. I think we may need to do distance to the closest point on the surface of the AABB. The old logic computes distance to the nearest corner. But I think to fully resolve all issues unfortunately we may need to do the distance to the nearest point on the surface. That will be a more complex calculation. |
Found an algorithm: float aabb_dist(vec3 p_point, vec3 p_min, vec3 p_max) {
float dist_sq = 0.0;
for (int i = 0; i < 3; ++i) {
if (p_point[i] < p_min[i]) {
float d = p_point[i] - p_min[i];
dist_sq += d * d;
}
else if (p_point[i] > p_max[i]) {
float d = p_point[i] - p_max[i];
dist_sq += d * d;
}
}
return sqrt(dist_sq);
} Can probably replace that entire section, certainly reduces the number of conditionals. Could go one further and store LOD keys as distance squared and avoid the sqrt. |
Regarding comments in the meeting:
Yes the algorithm seems to work as advertised. |
Pushed an update with calculation to surface of the AABB instead of using the support. I didn't use the formula from huwpascoe, but instead used one that does the same thing mathematically but is branchless. Overall, the number of calculations are significantly reduced from the previous state and the results are much more accurate. I think this is ready for merging now. I have tested it with a few MRPs from previous issues and it appears to work the same or better in all cases. |
servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
Show resolved
Hide resolved
Thanks! |
Fixes: #81995
Fixes: #76436
Supersedes #82000
Builds on #92287 but introduces riskier changes.
This PR simplifies and improves the LOD selection logic by calculating the depth as the distance to the closest point on the surface of the AABB.
The old logic used the camera z direction to calculate the min and max supports. This was flawed as it meant that rotating the camera could drastically change which supports were chosen and (as pointed out in #81995) if the camera looked slightly past an AABB, it could cause the supports to change and then jump LOD levels.
The new code automatically handles being inside the AABB (distance will always be 0 inside the AABB) and gradually increases from 0 at the surface of the AABB so there is no snapping like with the first draft of this PR.
I also moved the entire calculation outside the loop since everything depends on the instance. It doesn't need to be recalculated for each surface.