horde3d / Horde3D

Horde3D is a small 3D rendering and animation engine. It is written in an effort to create an engine being as lightweight and conceptually clean as possible.
http://horde3d.org/
1.55k stars 308 forks source link

camera movement vs culling #199

Closed creutzerb closed 3 years ago

creutzerb commented 3 years ago

Hello,

I just noticed big black patches.

https://user-images.githubusercontent.com/10078731/138321582-f3ecb306-108d-4c86-be67-7e7e2e96aae3.mp4

The walls of the room are made separate tiles. When the camera turns fast enough, and with enough contrast tile/background, you can notice there are holes. I suppose they were culled one frame too many ?

algts commented 3 years ago

Hello. It is difficult to say at a glance. I don't know the algorithm you use to enable/disable tiles. One thing I noticed earlier with horde is that procedurally generated meshes can have issues with culling because of the incorrect bounding box. If you are using procedural geometry, check that bounding box around models/meshes is large enough. Also, if you are using occlusion culling, horde generates occlusion queues in one frame and checks them in the next frame. So probably some meshes may not be rendered if occlusion culling is on and camera is moving very fast.

What is the GPU and driver used? If it is Nvidia, then its likely not a problem (on both Windows and Linux with proprietary driver). If it is Intel, you should probably check if newer driver has this behavior (Windows OpenGL support is bad, Linux with Mesa Intel driver also has its quirks). Amd should probably work fine.

I suggest that you insert debug output in the SpatialGraph::updateQueues( uint32 filterIgnore, bool forceUpdateAllViews ) method and generate several log files with meshes currently used/culled, camera position/rotation. Maybe it can help to see some patterns of this behavior.

creutzerb commented 3 years ago

in egRenderer.cpp : (line 544)

// WARNING! Currently lighting will not be present in the first frame, because scene update will happen
// after lights addition to render views. If that behavior is not desirable uncomment the following statement (may reduce performance a bit)
scm.updateNodes();

~~So the models were culled properly - but they were not rendered in ambient/light pass. It makes sense I didn't see the objects then - a bit unexpected as I assumed ambient light wouldn't be affected by that kind of situation.~~ Do you know where I should look for performance change ?

algts commented 3 years ago

Sorry, I don't fully understand your question. I hadn't seen the commented scm.updateNodes() affect anything outside the first frame rendered, because first frame is a bit special. Ambient light, at least in samples, is just an additional material that gets processed with lights. If you uncomment scm.updateNodes() you will have another culling routine done. If your performance is not bound by cpu then you probably have nothing to worry about.

creutzerb commented 3 years ago

I kind of jumped to conclusions, sorry. I think I got it now. Because scm.updateNodes(); is commented, the camera node update happens later. But because we copy the camera frustum before it gets updated (551: scm.addRenderView( RenderViewType::Camera, _curCamera, _curCamera->getFrustum() );), the renderView frustum doesn't get updated until the next frame. That would explain the frustum lag, and why it disappears when the update is un-commented.

note that we achieve the same results by replacing scm.updateNodes(); by _curCamera->updateTree();

algts commented 3 years ago

Okay, I'll look into it. Probably scm.updateNodes should be returned back, because lights will not be updated, unless they are children of the camera. Chicago sample is a rather good example of how your performance will degrade with another scm.updateNodes() call, when there are multiple objects in the scene.

algts commented 3 years ago

Please check the latest commit in the develop branch. I've returned scm.updateNodes() call before adding camera render views and also introduced optimization that allows skipping updateNodes() inside SpatialGraph::updateQueues() during preparation of render views. This optimization did not bring any side effects for samples, but they are rather simple. Please check on your project. Thanks.

creutzerb commented 3 years ago

I haven't noticed anything out of place, but I'll keep an eye out ;) Thanks.