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
Improved lighting #4655
Improved lighting #4655
Conversation
This commit rewrites the procedure that is responsible for light updating. this commit -provides iterative solutions for unlighting and light spreading -introduces a new priority queue-like container for the iteration -creates per-node MapBlock caching to reduce retrieving MapBlocks from the map -calculates with map block positions and in-block relative node coordinates -skips light updating if it is not necessary since the node's new light will be the same as its old light was
I have made some speed tests, too (in debug build, so Minetest ran slower than its maximal speed). Single cobblestone placed in sunlight: 0,217 ms -> 0,122 ms |
Tried ingame, nothing suspicious yet. |
Are bulk node updates affected? Such as lua voxelmanip used after mapgen, placement of schematics, and placement of L-system structures? Currently we have problems with lighting bugs caused by these 3 operations. |
@paramat Someone needs to try Vanessas trees (maybe me, but tommorrow). |
@SmallJoker, sorry if I disappointed you, in fact I was also a bit disappointed. When I have been writing this commit, I only measured the speed of light updating with a TimeTaker. I did not take two things into account:
Also, since lights do not change in every server step, the improvement is hardly noticeable. But you can see the performance increase in extreme situations: if you create a big hole in the ground (see the image) with a piston, SEnv::step will be noticeably faster (the server does not compute meshes, so the light updating is more significant). Sorry if I have misinformed you. @paramat, @Fixer-007 my code only alters single node changes. This is why it does not correct the TNT lighting bug. I would like to rewrite all other lighting to this new style, but this will be in another PR. |
Any work on the lighting update for bulk node changes will be very welcome, our lighting bugs are a big problem, possibly MT's most serious bug. |
@SmallJoker, the lighting of bottom faces is in the mesh generation code, and is not related to light spreading, it is pure graphical. I think they are darker because their normal vector points downwards. This helps to visually separate the directions of the nodes' faces. |
This commit modifies the liquid transforming procedure to light and unlight nodes instead of whole map blocks.
Now liquid transform uses bulk per-node updating instead of map block updating. |
nice code quality (haven't review the feature itself, just the code quality), thanks |
* The parameters are the same as in ChangingLight's constructor. | ||
* \param light light level of the ChangingLight | ||
*/ | ||
inline void push(u8 light, relative_v3 &rel_pos, mapblock_v3 &block_pos, |
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.
Please make these references const
for (u8 i = 0; i <= LIGHT_SUN; i++) { | ||
const std::vector<ChangingLight> &lights = light_sources.lights[i]; | ||
for (std::vector<ChangingLight>::const_iterator it = lights.begin(); | ||
it < lights.end(); it++) { |
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.
Always use ++it for iterators because it++ creates a wasted copy.
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.
I doubt compilers are actually that stupid, do you have a source?
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.
I've asked that in C++ once, and they only said "maybe its optimized, maybe not".
Either way, we have commit 34b7a14 and I'd prefer if it++ wouldn't start entering the codebase again.
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.
I agree that it makes sense to follow the general code style, the optimization explanation just seemed weird to me.
|
||
void update_lighting_nodes(Map *map, INodeDefManager *ndef, | ||
std::vector<std::pair<v3s16, MapNode> > &oldnodes, | ||
std::map<v3s16, MapBlock*> & modified_blocks) |
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.
spaces
* \param modified_blocks output, all modified map blocks are added to this | ||
*/ | ||
void spreadLight(Map *map, INodeDefManager *nodemgr, LightBank bank, | ||
LightQueue & light_sources, std::map<v3s16, MapBlock*> & modified_blocks) |
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.
spaces
*/ | ||
void unspreadLight(Map *map, INodeDefManager *nodemgr, LightBank bank, | ||
UnlightQueue &from_nodes, ReLightQueue &light_sources, | ||
std::map<v3s16, MapBlock*> & modified_blocks) |
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.
spaces
* 4=Y- | ||
* 5=X- | ||
* 6=no direction | ||
* Two directions ate opposite only if their sum is 5. |
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.
are*
@@ -19,6 +19,9 @@ with this program; if not, write to the Free Software Foundation, Inc., | |||
|
|||
#include "voxelalgorithms.h" | |||
#include "nodedef.h" | |||
#include "mapblock.h" | |||
#include "map.h" | |||
#include "util/timetaker.h" |
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.
Is this still needed?
liquid (=water node was added) to transform queue. | ||
*/ | ||
Add neighboring liquid nodes and this node to transform queue. | ||
(it's vital for the node itself to get updated last, if it was removed.) |
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.
Can you explain in the comment why it is important for the node to get updated last?
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.
To tell the truth, I don't know. Since it was written in Map::removeNodeAndUpdate
, I didn't want to alter it, because I only wanted to modify code related to lighting and not to introduce liquid flow bugs.
I don't know who wrote this comment originally, but I would be very thankful if he/she explained there why is this important.
If you want me, I will try to find it out myself, but I think it is related to liquids, not lights.
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.
Ah I see, it appeared from the diff that you added it but if it was there before its okay.
relative_v3 rel_position; | ||
//! Position of the node's block. | ||
mapblock_v3 block_position; | ||
//! Reference to the node's block. |
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.
Its a pointer not a reference
struct ChangingLight { | ||
//! Relative position of the node in its map block. | ||
relative_v3 rel_position; | ||
//! Position of the node's block. |
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.
Add to the comment whether its in node coordinates or in block coordinates
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.
Added to mapblock_v3
's description.
I played with it in game and did not find nothing critical yet. |
I've looked over the code and for the most part I think it's great. I don't have any huge issues with it and find it easy to read (meaning it should be easy to maintain I guess). Spent an hour doing profiling with callgrind with and without this PR and there is certainly a performance difference (improvement with the PR). valgrind reports no memory related issues related to the PR. Played a singleplayer game for about 30 minutes. Didn't notice anything unusual with the lighting. So, in summary I think it's nice work 👍 |
👍 |
Okay for me too. |
#3004 is fixed by this it seems (good job 👍) |
I have noticed that this PR causes a compatibility break - before this PR, shadow next to sunlight had light level 13, after this PR it is changed to 14. This causes that players playing with new clients on old servers might see nodes one light level brighter than they are. |
@juhdanad, I've got a question about the order in which the ChangingLights are traversed. minetest/src/voxelalgorithms.cpp Lines 82 to 84 in 431d8a9
|
This PR rewrites the procedure that is responsible for light
updating when a single node changes.
The PR