Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1786
  • Last Modified:

C# Managed DirectX best practice in drawing large scenes?

Have a little experience working with C# Managed DirectX, I would like some general info I am not finding in the book.

I've setup some basic scenes with success, but I want to know about what is the best pratice as far as using buffers (video card memory right?) for rendering. I've been pushing the onpaint calls to include FOR loops which use the Mesh.DrawSubset() method. The application seems to slow down when i do it a couple of hundred times. This is regaurdless of whether the mesh is a cube or a sphere, so I'm pretty sure it's not the face/vertex count that is becoming a problem.

My questions are, what is the best practive for issueing the call to draw, when dealing with a high number of different meshes like you find in many modern 3D apps. Do I somehow load all my meshes into a buffer, and if so how? Is it possible to have a scene make a present() call using mulitple buffers? And what limitations do i face when trying to draw meshes which made be of vertext type (like if its just a color or if it has a bitmap texture). Do those meshes need to be loaded into different buffers?

Thanks much.
Matt
0
mattososky
Asked:
mattososky
  • 5
  • 3
1 Solution
 
Javin007Commented:
That's an AWEFUL lot of information you're asking for for 250 points.  Personally, I think your best bet would be to go with an already developed DirectX engine to handle the majority of the work for you.  This will save you somewhere in the neighborhood of 4 years of programming.

My personal favorite is TrueVision3D (www.TrueVision3D.com), which costs $150, and has a built-in physics engine (with vehicles) full shader support, etc.  It's fast, and does the mesh loading/culling for you.  

That being said, I assume by "large number of meshes" you're talking in the hundreds, such as a normal game like say, Doom 3 or such, where you'll see 100's of meshes throughout the game, but no more than 3-4 at a time.

If this is the case, your best bet is to run a separate thread that handles the loading/unloading of your textures/meshes.  As the game comes close to the appropriate "zone" where it will soon need to render the mesh, it informs the loading thread that it needs to fire up.  Also, as a mesh is no longer needed, it tells the loading thread to take care of its garbage.  Thus, in real-time, the meshes are loaded and unloaded based on whether or not their needed.  In Doom 3, this was done by determining "zones."  

A "zone" is an area of the map, grouped off.  Say you have 4 zones, A-D.  Zone A can see Zone B.  Zone B can see zone A and zone C.  Zone c can see B and D, and zone D can just see zone C.  If my character is in zone B, and the "enemy" moves to zone D, I know he's no longer going to be visible, so I tell the loading thread to dump him.  However, if my "enemy" is in zone D and moving towards zone C, I tell the loading app to load him up.  This is the simplistic version, and doesn't consider the fact that my character may be moving, the concept of "potential zones" etc.

Alternately, if your game will have "loading" screens (think "Oblivion" when entering/exiting houses) you can take the easier route by loading all of your data into RAM as you enter, since the house itself is your only "zone."  If your zones will be small enough to fit the entire zone into RAM, and you don't mind a loading screen, this will work and possibly be much easier for you.  Assuming you're writing native DirectX, you will have to design your own "culling" system to swap the data from RAM to the GPU as it's "visible," tracking how much Texture memory the GPU has, and swapping the "oldest" stuff with the "new" stuff as the character moves around.

I still say finding a pre-made engine is your best bet.

-Javin
0
 
mattososkyAuthor Commented:
Ok, point value up. I thought it wal kind of a general question, but lets get technical.

I will definately take a look at the DX Engine you have suggested, initially it does look interesting. But I still want to know the particulars of my question. While interesting I'm not sure the second half of your answer is on target. The answer may be more general than your thinking.

I don't think it is the loading and unloading of meshes that I am concerned with. Say I've got 500 spheres that are in a scene. The only way I am understanding I can draw them, is to use the Mesh.DrawSubset() method.

I think I am hitting a performance penalty for the large number of DrawSubset calls (one for each mesh, being 500). I'm pretty sure there is a better way to do this. With your last comment and and answer to that I will accept the solution.

Thanks,
Matt
0
 
Javin007Commented:
Ah.  I see what you're saying.  It's the actual rendering of the 500 meshes is the slowdown.  What else are you rendering in the scene if I may ask, and WITHOUT the meshes rendered, what's your FPS, and with the meshes, what's your FPS?  You might be looking at a fillrate issue.

-Javin
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
mattososkyAuthor Commented:
Right, we both say it's the rendering of the meshes, but I wonder if I am going about it in a bad way. As I said before if I change from using spheres to cubes (which should take dramitically less time to calculate) it does not improve performance.

basically, during the OnPaint() call I am calling this method:

private void DrawDebris()
        {
            device.Material = DMat;
            for (int i = 0; i < Debris.Length; i++ )
            {
                device.Transform.World = Matrix.Translation(Debris[i].Location);
                MeshDebris[i].DrawSubset(0);
            }
        }
______________________________________________________________

You can see that the Mesh array is already filled so I believe I'm doing the smallest amount of work I think I can. Each mesh's position must be updated each frame. So there are calculations going on in another loop for that. I need to get rid of this loop for the draw.subet, and tell the device to draw all the meshes. With the correct (Mesh specific) color that is.

FPS were variable. My first app had a moving camera and a collect of sphere randomly spaced and sized at about how lights on a christmas tree might look. With the camera moving around and about the spheres, frame rates were as i specificed with about 100 spheres in the scene. If the number went to around 200, noticable perform lag unsued. At 400 performance was very crappy.

I have another app now. The camera is stationary and I can get several hunedred spheres bouncing around the scene with fine performance. if the number of spehere goes to around 1000, starts to get a little choppy, a few thousand of them and it;s major lag.

Thanks again,
Matt
0
 
Javin007Commented:
"A few thousand of them" you're very, very, very likely far past capping out your CPU.  Keep in mind that you've got a ZBuffer here that's tracking the location of every vertex/face in the application, and having to place them in the correct order.  Z-Sorting costs grow exponentially as you add more meshes to the scene.  It sounds to me like you're just simply trying to push the card faster than it's capable of.

You'll be hard pressed to find a game of any sort that has 1000 unique meshes rendered on the screen simultaneously, much less more than 1000.  What most engines do is to take a "duplicate" of a single mesh, simply moving it around using their own Z-Ordering and drawing it to the screen without using the Z-Buffer at all.  Your more complex games with massive mesh counts (think Black & White 2) don't actually draw each individual mesh at all, but instead draw the mesh one time onto a SINGLE polygon (ie: rendersurface texture on a single polygon) then move that one polygon around the scene rendering it in the necessary places.

Your video cards will have a poly count on them (usually in the millions) that they can render.  As far as they're concerned, these "polies" are not "faces" but individual triangles.  Also, this is the number of polies the card is CAPABLE of rendering per second (at 1 FPS), not how many it can render in a normal scene.

Finally, you have the fillrate limitation.  This is how many pixels per second your card is capable of rendering.  This number is ALSO gotten under VERY specific tests on VERY specific pieces of hardware making them highly inaccurate when the card is put into a real-world PC, and the bottlenecks are in your BUS, internal cables, cards, etc.  You can expect your fillrate to give you a dramatic drop when even rendering a single object that fills the entire screen.

ALL that being said, you have the ADDITIONAL slowdown of the simple mesh rendering calls.  If you can get your scene to handle 1000 simultaneously, good on ya.  I've managed to get 2000 on a RADEON x800 at about 30 FPS on 1024x768, but those "meshes" were simple 2 poly planes (billboards) with tiny (32x32) textures on them.

I don't think the DrawSubset() call is your problem, but rather that you're trying to render thousands of entire meshes on screen simultaneously.  Unless you've got some high-end dual-core 64bit processor with dual high-end video cards, I don't see that happening.
0
 
Javin007Commented:
To give you an example, here's using that 3D engine:

www.Javin-Inc.com/TV65/Boxen.jpg

Keep in mind that I'm using an optimized, finished, polished engine here.  That's 1014 boxes rendered full screen 1024 x 768.

Absolutely no AI.  No calculations, ONLY the render.  On a 3.8 ghz dual-core, 4 megs of RAM, and a RADEON x600, I get only 56 FPS.  This is normal.

I think the answer to your question is that you're doing it "right" in that you're using the right command, but you're trying to make your card do things it just simply can't do.
0
 
Javin007Commented:
Here's another screenshot for ya:

www.Javin-Inc.com/TV65/Boxen2.jpg

Notice here, now, the FPS have gone up to 483 FPS.  (847% increase).  This is because, like I said, I'm no longer rendering 1015 seperate box meshes, but am instead, during the render phase, I've only got a SINGLE box, and I'm moving it, and rendering it 1015 times at different positions.  Thus, not choking the card/gpu out with mesh/zbuffer information.
0
 
mattososkyAuthor Commented:
Ok, you've given me alot to think about. I'll accept this as solution.

But I'm still not clear if I am using the best method to draw all these meshes. I guess I need to better understand the buffers and video card memory and how mesh objects play into that.
Thanks for your input.
Matt
0

Featured Post

Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

  • 5
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now