I'm moving on in my project and I am now hitting a huge performance issue with the way I implemented particles (using DPSF) in my SunBurn based project.
It seems that ParticleSystems in DPSF do not check their visibility against the View Frustrum and therefore update and render themselves whatever the camera position.
Since I'm developing a space shooting game, I'm attaching all my particle systems to my ships which are stored as SceneObjects in SunBurn.
What I tried to do without success thus far is to get the SceneObject visibility during update calls and enable or disable the attached ParticleSystems depending on the result.
I know some of you implemented DPSF in their projects and I wondered how you managed to achieve good performance using the SunBurn scenegraphs?
John, in your current SceneObject improvements for future releases, maybe you could change the Visible property or add a "WillBeDrawn" property once it passes the RenderManager or DeferredRenderManager BeginFrameRendering calls where you seem to sort SceneObjects depending on the ViewFrustrum?
There is an overload for ObjectManager.Find() that queries the scenegraph for all objects in a specific bounding volume.
To search for all visible objects pass in the SceneState.ViewFrustum as the bounding volume - this will return the same objects SunBurn renders on-screen (though depending on rendering and performance options some objects may be further culled).
Let me know if this helps!
Follow me on Twitter – development and personal tweetsAwesome XNA Videos – Lighting, Rendering, and game videos
I've seen this one but my question was more on trying to avoid creating queries that are already done inside SunBurn's rendering loop. By exposing a property, I would avoid doing again the same query as you do internally ;)
The Find methods are fairly lightweight, so you should be ok. We've been using them in prototypes for finding potential colliders (in collision systems) and similar applications.
It sounds like your game only needs to call the Find method once per frame, which should be very fast.
Time to wake this one up?
Is this still the only way to do this?
I have a situation where my scene has up to a hundred skinned characters. Turns out one of the expensive operations is calling the Update on the skinned mesh. So I want to not bother with that animation unless the model is visible.
Getting the list of models using this query means I then have to loop through my collection matching them with the collection you returned. Thats not very efficient on a per frame basis. Each of my objects has a reference to its corresponding SceneObject so reading a property would be very useful.
Also now I look at the API for Find I need to pass it a list to fill. To prevent garbage I need to make a List<ISceneEntity> in advance and guess how many items will need to be in it. Then I need to clear it out every time I use it. Not the most straightforward API but I suppose thats the price of a rubbish GC on the 360 - make the caller worry about memory.
Of course I have a split screen so a single object can be visible in one but not in the other which adds some complexity eh?
If you are looking for deep/custom space partitioning, I think you should try to move slightly in the core of the ObjectManager class and you'll get most benefits implementing your own by creating your space partitioning system.
Otherwise, you may simply set the SceneObject's Visibility property to None when not visible on your viewports (because you know they aren't there) and if I remember correctly they won't be returned by the Find method.
But I would need John's confirmation on this last one ;)
I dont need any of those things. I have 100 objects in the game. Sunburn already knows which are in the frustum and which are not. I can repeat the frustum check, its trivial and a fast enough loop but I'd rather just use what SB already knows if possible. Returning a list of the things in the frustum doesn't help me becuase then I have to compare every item in the list with my list. I may as well do the frustum check myself at that point.
Oh! I misread your post and didn't understand your issue clearly :)
In my current prototype, to achieve your result and for some other personal needs, I created an inherited SceneObject class with a Rendered property and an inherited ObjectManager class which overrides the Find methods so that foreach ISceneObject returned by these methods, I set this property to true (obviously clearing that property to false each frame before :p).
That seems to work like a charm and having low performance impact even if you have to cast these SceneObjects when checking for this property.
Still, would be great to have this piece of information directly from the initial frustrum check.
Setting a visibility flag is not possible at this time, there are two scenarios where the flag will not work correctly:
There are a number of ways to very efficiently use the Find() methods:
One would be to derive a custom class from SceneObject and look for objects based on that class in the find results (using "if(obj is YourClass)").
Another is to keep a dictionary (note: not a list) of objects you're specifically looking for, and perform a quick check for each object in the find results (using "if(dictionary.ContainsKey(obj))").
If the list of objects you're looking for is small (<100), it's probably best to simply test each for visibility (using "SceneState.ViewFrustum.Intersects(obj.WorldBoundingBox)").
Please note regarding the find results: you do not need to guess the number of potential objects each time (or at all), the .Net List class never reduces it's internal array, even if the list is cleared. This means after expanding the list to contain say 100 objects, you can continually clear and add 100 other objects without ever allocation more memory.
So simply creating a list that you can reuse is sufficient, then call Find() as many times as you want without worrying.
Actually I used a list with a big TODO comment that a dictionary might be quicker ;-) Right now I have code that relies on the otehr one being a list and I was too lazy to refactor it. It runs jsut fine - i.e. all my bottlenecks are elsewhere.
However doing the frustum check might be quicker still so I will time them later this week.
Thanks for the response.