Jump to content


Coding for the new 3D system....


  • This topic is locked This topic is locked
82 replies to this topic

#1

  • Guests

Posted 04 May 2011 - 07:42 AM

General rules.

Draw as much as you can in a single draw call. This means put as much into a GM model as you can.

If you draw <1000 polys (more on larger systems), the CPU will get in the way, and the GPU will get bored and have an affair with your HardDisk and thereby slowing your game down even more. :P

The more you can draw, the more time your CPU will have to execute other game code. The CPU and GPU work in parallel with large models.

Skin your models - even buildings and terrain. This allows large sections of a world to be rendered in one go, rather than a brick at a time.

Never, ever, draw QUADS if you can possibly avoid it. Your graphics card WILL hate you.


Anything else.....?

#2 ~Dannyboy~

~Dannyboy~

    ~hoqhuue(|~

  • GMC Member
  • 2144 posts
  • Version:GM8

Posted 04 May 2011 - 08:19 AM

This is probably a silly question, but... Are you suggesting that if we have to draw 500 poly's it would be faster to batch them with another 500 invisible poly's to stop the GPU getting bored? Or is it more just about drawing 1 lot of 1000 poly's rather than 2 lots of 500?

EDIT: I understand that the second point is obviously true. My main question is the first one, that is, is it faster to draw 1000 poly's than 500?

Edited by ~Dannyboy~, 04 May 2011 - 08:32 AM.

  • 0

#3 Phantom107

Phantom107

    Graphics Enthusiast

  • GMC Member
  • 2661 posts
  • Version:GM:Studio

Posted 04 May 2011 - 08:28 AM

This is probably a silly question, but... Are you suggesting that if we have to draw 500 poly's it would be faster to batch them with another 500 invisible poly's to stop the GPU getting bored? Or is it more just about drawing 1 lot of 1000 poly's rather than 2 lots of 500?

Modern GPUs are optimized to draw thousands of polygons in as few draw calls possible.

It's faster to draw 10000 triangles in 1 draw call than 2 draw calls of 5000 triangles each.
  • 0

#4

  • Guests

Posted 04 May 2011 - 08:44 AM

This is probably a silly question, but... Are you suggesting that if we have to draw 500 poly's it would be faster to batch them with another 500 invisible poly's to stop the GPU getting bored? Or is it more just about drawing 1 lot of 1000 poly's rather than 2 lots of 500?

EDIT: I understand that the second point is obviously true. My main question is the first one, that is, is it faster to draw 1000 poly's than 500?



No, if you only need 500 polys, then don't draw "invisible" ones, your just wasting bandwidth doing that. If you CAN batch more into a call, then do so. There's no point drawing doing 20 calls where 1 would do. For "world" models (those that don't need a separate matrix), then try and batch them together so you minimize calls.

Main rule... don't CALL drawing more than you have to. By all means keep things in "chunks" so you can cull nicely, but keep those chunks reasonably large if you can.

#5 ~Dannyboy~

~Dannyboy~

    ~hoqhuue(|~

  • GMC Member
  • 2144 posts
  • Version:GM8

Posted 04 May 2011 - 09:58 AM

Thank you for that clarification. ^_^
  • 0

#6 Phantom107

Phantom107

    Graphics Enthusiast

  • GMC Member
  • 2661 posts
  • Version:GM:Studio

Posted 04 May 2011 - 10:15 AM

So Mike, are you going to provide GM8.1 with a system that can disable certain batches over distance? Making a ton of distance checks in GML can really hurt performance.
  • 0

#7

  • Guests

Posted 04 May 2011 - 11:08 AM

Nope... you'll have to do that in GML. That would require a proper model format, and we're not adding that here. sorry. There is a new distance in 3D GML command though, I'm sure that'll help :)

#8 Smarty

Smarty

    GMC Member

  • Retired Staff
  • 7465 posts
  • Version:GM:Studio

Posted 04 May 2011 - 11:51 AM

Anything else.....?

Not entirely related, but I was wondering if these same kinds of awesome performance improvements are also going to be reflected in the iPod, Android and PSP engines in the future, or is 3D still a no-go area there?

Nope... you'll have to do that in GML. That would require a proper model format, and we're not adding that here. sorry. There is a new distance in 3D GML command though, I'm sure that'll help :)

Would it make sense that as a next best thing, we'd have a command that can concatenate models into a single model? I can hardly imagine it, but could this still be faster than drawing separate models? Concatenated models would allow us to combine models on the fly without having to define vertices and basic shapes independently, nor draw models independently. Preferably this uses transformation commands in between adding models to have them scaled, moved and rotated according to our needs, for example,

model=d3d_model_create();d3d_model_add(model,othermodel1);d3d_model_add_translation(xt,yt,zt);d3d_model_add(model,othermodel2);d3d_model_add_rotation(xr,yr,zr);d3d_model_add(model,othermodel3);...d3d_model_draw(model,x,y,z,texid)

(Transformations with respect to the drawing position)

Edited by Smarty, 04 May 2011 - 11:52 AM.

  • 1

#9 Phantom107

Phantom107

    Graphics Enthusiast

  • GMC Member
  • 2661 posts
  • Version:GM:Studio

Posted 04 May 2011 - 12:37 PM

I can hardly imagine it, but could this still be faster than drawing separate models?

It should improve performance a lot.

Take a look at the modern graphics pipeline: (image copyright nVidia Corporation)

Posted Image

As you can see, primitive assembly is required and eats away precious performance. By merging models as you suggested you're effectively making the amount of primitives a lot lower. That will result in less work for the graphics pipeline and thus increasing performance.
  • 0

#10 Smarty

Smarty

    GMC Member

  • Retired Staff
  • 7465 posts
  • Version:GM:Studio

Posted 04 May 2011 - 01:24 PM

It should improve performance a lot.

Take a look at the modern graphics pipeline: (image copyright nVidia Corporation)

Posted Image

As you can see, primitive assembly is required and eats away precious performance. By merging models as you suggested you're effectively making the amount of primitives a lot lower. That will result in less work for the graphics pipeline and thus increasing performance.

But in turn, more time is spent at the CPU which needs to merge the models together first (including transformations, to make things more useful). Note that this is a process one would intend to perform regularly, likely just before every time I wish to actually draw the model.

I really don't know if the performance boost at the GPU end makes up for the performance penalty at the CPU end, in that case.

EDIT: In spite of the demonstrations, I am also unsure if the execution of model drawing in parallel to game code execution is useful. Typically, drawing happens at the end of a step rather than in the middle, which means most of the logic pertaining to the game has already been taken care of. That is, unless it's still drawing while the engine is busy milling through the next step. How is that synced to the screen?

Edited by Smarty, 04 May 2011 - 01:31 PM.

  • 0

#11 Phantom107

Phantom107

    Graphics Enthusiast

  • GMC Member
  • 2661 posts
  • Version:GM:Studio

Posted 04 May 2011 - 01:56 PM

I really don't know if the performance boost at the GPU end makes up for the performance penalty at the CPU end, in that case.

Merging should not be used on the fly, but only in the create event. There is no need to merge models that are supposed to move (such as the player and items), because you'd be doing the same work that the graphics pipeline is optimized for. It would just be a waste of resources.

However, where it should be used, and where it will provide a great boost, is with static objects. Think of houses, trees and rocks. By merging those up you invest a tiny bit of processing time in the create event, but you will benefit every single frame. Without any extra CPU processing. Think of it as merging objects into areas of 1000x1000x1000, where areas are hidden depending on their distance to the camera.
  • 0

#12 NakedPaulToast

NakedPaulToast

    GM Studio/Mac/Win

  • GMC Member
  • 8125 posts
  • Version:GM:Studio

Posted 04 May 2011 - 01:56 PM

Any chance the runner can provide some basic gpu information and features to the games?
  • 0

#13 Smarty

Smarty

    GMC Member

  • Retired Staff
  • 7465 posts
  • Version:GM:Studio

Posted 04 May 2011 - 02:27 PM

Merging should not be used on the fly, but only in the create event. There is no need to merge models that are supposed to move (such as the player and items), because you'd be doing the same work that the graphics pipeline is optimized for. It would just be a waste of resources.

Actually this was the whole point of my question. I honestly can't tell which of the two - the CPU or the GPU would be faster performing, essentially, different tasks with similar outcome. The entire question was there to focus on investigating which would or could be the faster implementation of the two.

However, where it should be used, and where it will provide a great boost, is with static objects. Think of houses, trees and rocks. By merging those up you invest a tiny bit of processing time in the create event, but you will benefit every single frame. Without any extra CPU processing. Think of it as merging objects into areas of 1000x1000x1000, where areas are hidden depending on their distance to the camera.

The reason to want it to happen on the fly is to be able to provide for a mechanism to animate models, without introducing a proper model format. Since there already are other ways of building complex models, having a merger command mostly for convenience isn't really that interesting...
  • 0

#14 kburkhart84

kburkhart84

    Firehammer Games

  • GMC Member
  • 1909 posts
  • Version:GM:Studio

Posted 04 May 2011 - 03:06 PM

General rules.

Draw as much as you can in a single draw call. This means put as much into a GM model as you can.

If you draw <1000 polys (more on larger systems), the CPU will get in the way, and the GPU will get bored and have an affair with your HardDisk and thereby slowing your game down even more. :P

The more you can draw, the more time your CPU will have to execute other game code. The CPU and GPU work in parallel with large models.

Skin your models - even buildings and terrain. This allows large sections of a world to be rendered in one go, rather than a brick at a time.

Never, ever, draw QUADS if you can possibly avoid it. Your graphics card WILL hate you.


Anything else.....?


So basically, the way GM is now drawing models is similar to the way we would learn to do it if creating our own 3d engine, and therefore the same way modern 3d engines do it(except for the fancy stuff of course). Therefore, the way to optimize is the same as with any other 3d engine. I'm not going to repeat your post, but rather clarify that if someone needs optimization here, they can now apply public knowledge as far as 3d engines go, instead of only GM specific knowledge.

I'm glad 3d in GM is getting these improvements. But, it won't really be useful to me until we get some sort of animation, either bone or keyframe, of course bone being the much better option. But this is a great first step.
  • 0

#15 FredFredrickson

FredFredrickson

    Artist

  • Global Moderators
  • 9210 posts
  • Version:GM:Studio

Posted 04 May 2011 - 03:09 PM

The reason to want it to happen on the fly is to be able to provide for a mechanism to animate models, without introducing a proper model format. Since there already are other ways of building complex models, having a merger command mostly for convenience isn't really that interesting...

I could see tremendous value in a slower-to-execute but quicker-to-draw function that merged many models into one chunk. You can do this currently to some extent, but you can't draw models with multiple textures in one larger model, so it's only useful for many objects that share the same texture, and often, those objects are not always going to be placed close enough together to take advantage of being grouped into a single model.
  • 0

#16 Smarty

Smarty

    GMC Member

  • Retired Staff
  • 7465 posts
  • Version:GM:Studio

Posted 04 May 2011 - 04:13 PM

I could see tremendous value in a slower-to-execute but quicker-to-draw function that merged many models into one chunk.

I'm not saying there is no value. I'm only saying it isn't as interesting.

You can do this currently to some extent, but you can't draw models with multiple textures in one larger model, so it's only useful for many objects that share the same texture, and often, those objects are not always going to be placed close enough together to take advantage of being grouped into a single model.

That's not true - the purpose of being able to combine multiple models into one and be able to add translations and transformations on the fly to the added models is to provide an alternate mechanism of an animated model - a vehicle or a character, for example. And having a single texture for those is mostly exactly what you'd want.

Edit: I already said that.

Edited by Smarty, 04 May 2011 - 04:15 PM.

  • 0

#17

  • Guests

Posted 04 May 2011 - 08:08 PM

This would be incredibly slow... you'd be back to worse than the original speed as it has to do all that work, and more! You also have the issue of multiple textures. Unless the model has been generated with a single skin that works for both models, then it wouldn't work anyway, and if it HAS been done like that, then why isn't it part of the same model anyhow?

The rule is... make the models once, and never touch them again. This gives you by far the best performance. It's probably something you have to play with to know what's best, but having to "skin" a model will likely restrict what you can bundle anyway.

#18 Desert Dog

Desert Dog

    GMC Member

  • Retired Staff
  • 6409 posts
  • Version:Unknown

Posted 04 May 2011 - 09:51 PM

I guess I'm going to play the role of the ignorant guy. :(

Never, ever, draw QUADS if you can possibly avoid it. Your graphics card WILL hate you.

What are QUADS?

If you draw <1000 polys (more on larger systems), the CPU will get in the way, and the GPU will get bored and have an affair with your HardDisk and thereby slowing your game down even more.

Also,

I read on your blog how we now (or will have) static models, and dynamic models, rather than just dynamic.

You say you want calls to be big as possible, is this just for static models?

If I was to draw simple block, would it be 'best' if I use d3d_draw_block for what I understand would be a dynamic model, rather than creating a relatively tiny block model, which would be static, and the constant small drawing calls may get the cpu/gpu tangled up?

What I have in mind is a 3d breakout game type set up, where you have 100+ odd simple blocks(or other relatively low-poly models). Because these things are being destroyed, you cannot make them one big model.

How would you program this? Would using d3d_draw_block stop the cpu&gpu getting in each others way, and make a faster game, or is it 'business as usual' like we did before.. just turn them into models, and draw that, and even though the cpu/gpu are messing up, and slowing things down, it's still a lot faster.
  • 1

#19 Manuel777

Manuel777

    InvaderGames

  • GMC Member
  • 3525 posts
  • Version:GM:Studio

Posted 04 May 2011 - 10:26 PM

Simple rules i used to follow anyway, GM's 3d was always quicker when drawing a single model rather than many. ;)
  • 0

#20

  • Guests

Posted 05 May 2011 - 08:50 AM

What are QUADS?

rectangles, squares, 2 triangles etc...

If I was to draw simple block, would it be 'best' if I use d3d_draw_block for what I understand would be a dynamic model, rather than creating a relatively tiny block model, which would be static, and the constant small drawing calls may get the cpu/gpu tangled up?


If the model never changes (except texture), then make a static cube. it's ALWAYS faster if it's static. Of course... being static, you could now "round" the edges of the block if you wanted, making it a little nicer to look at. :)

If you need a different size, then make a "unit" cube (1x1x1 in size), then use matrix scaling to make it the correct size. (same for spheres etc.)

If your building the same model over and over again, then this sounds like it should be a static one...

On iOS, it's a little different.. but I'm not getting into that just now.

#21 Desert Dog

Desert Dog

    GMC Member

  • Retired Staff
  • 6409 posts
  • Version:Unknown

Posted 05 May 2011 - 09:53 AM

Thanks for that!

Yeah, so it sounds like it's pretty much business as usual then.. that was always the smart way to do 3d in GM... use models, make as few draw calls as possible, etc.

The only real difference as it seems to me is that know it seems we have the power here to draw high poly models lightning fast... in fact, if I'm reading you correctly, it's faster than low poly models because of gpu/cpu mix-mash. (which sounds bizarre!!)

Edited by Desert Dog, 05 May 2011 - 09:53 AM.

  • 0

#22 Manuel777

Manuel777

    InvaderGames

  • GMC Member
  • 3525 posts
  • Version:GM:Studio

Posted 05 May 2011 - 10:09 AM

in fact, if I'm reading you correctly, it's faster than low poly models because of gpu/cpu mix-mash. (which sounds bizarre!!)

It might at first, but its understandable given nowadays graphic cards have a LOT of power.. youre literally wasting it.


So, how are we gonna handle compatibility issues now? are the surfaces alerts going to pop up?

Edited by manuel777, 05 May 2011 - 10:09 AM.

  • 0

#23 Maarten Baert

Maarten Baert

    GMC Member

  • GMC Member
  • 744 posts
  • Version:GM8.1

Posted 05 May 2011 - 12:11 PM

If you need a different size, then make a "unit" cube (1x1x1 in size), then use matrix scaling to make it the correct size. (same for spheres etc.)

That doesn't work if you use lighting, scaling messes up the normals.

Is there a render state like D3D9's D3DRS_NORMALIZENORMALS in DirectX 8? It would be really useful if we had a function to enable and disable it. I know it's slower (on low-end video cards at least), but it's still better than weird lighting.
  • 0

#24 amd42

amd42

    GMC Member

  • GMC Member
  • 269 posts
  • Version:GM8

Posted 05 May 2011 - 01:58 PM

That doesn't work if you use lighting, scaling messes up the normals.

Is there a render state like D3D9's D3DRS_NORMALIZENORMALS in DirectX 8? It would be really useful if we had a function to enable and disable it. I know it's slower (on low-end video cards at least), but it's still better than weird lighting.


Looks like Mike Dailly's already one step ahead of you: glog comment
  • 0

#25 Nocturne

Nocturne

    Nocturne Games

  • Administrators
  • 20907 posts
  • Version:GM:Studio

Posted 05 May 2011 - 02:15 PM

Okay I am a 3D noob... BUT if a quad is a square or two triangles, isnīt that how GM deals with sprites? Two triangles textured from the sprite? And if so, then does my graphics card hate me for using sprites and making 2D games? More to the point, does all this speed boost for 3D have any rollover to the 2D world that I live in? Will I get a speed boost too on my games?
  • 0

#26 Manuel777

Manuel777

    InvaderGames

  • GMC Member
  • 3525 posts
  • Version:GM:Studio

Posted 05 May 2011 - 03:01 PM

Okay I am a 3D noob... BUT if a quad is a square or two triangles, isn´t that how GM deals with sprites? Two triangles textured from the sprite? And if so, then does my graphics card hate me for using sprites and making 2D games? More to the point, does all this speed boost for 3D have any rollover to the 2D world that I live in? Will I get a speed boost too on my games?

Nope, 3D and 2D are two very dirrefent things, you dont draw your sprites as textured poligons (thats what you have to do in 3D engines like Unity), in GM all 2D is really 2D, images stacked with different depths and effects, positioned over two axis, X nad Y, nothing more. Now when you go to 3D the things are hell of different, since you need a new axis ( Z ) all screen-position calculations are based on objects position in the world, the camera position, angles, etc. Plus you have to make sure objects dont mess up with other objects depth, you have to add shadows for every vertex in the models, normals.. etc etc etc..

Edited by manuel777, 05 May 2011 - 03:01 PM.

  • 0

#27 Medusar

Medusar

    GMC Member

  • GMC Member
  • 1228 posts
  • Version:GM:Studio

Posted 05 May 2011 - 03:10 PM


Okay I am a 3D noob... BUT if a quad is a square or two triangles, isnīt that how GM deals with sprites? Two triangles textured from the sprite? And if so, then does my graphics card hate me for using sprites and making 2D games? More to the point, does all this speed boost for 3D have any rollover to the 2D world that I live in? Will I get a speed boost too on my games?

Nope, 3D and 2D are two very dirrefent things, you dont draw your sprites as textured poligons (thats what you have to do in 3D engines like Unity), in GM all 2D is really 2D, images stacked with different depths and effects, positioned over two axis, X nad Y, nothing more. Now when you go to 3D the things are hell of different, since you need a new axis ( Z ) all screen-position calculations are based on objects position in the world, the camera position, angles, etc. Plus you have to make sure objects dont mess up with other objects depth, you have to add shadows for every vertex in the models, normals.. etc etc etc..

No, actually GM creates a D3D device regardless of 3D mode being on or not. That's why you can use the d3d_transform functions in 2D games. Enabling 3D mode just sets a couple of settings differently.

As for your question, Nocturne, I asked Mike that (don't recall where, must've been the other topic) and he said that the Delphi runner still draws sprites as individual quads. The C++ runner however puts sprites on a single texture page, so all drawing commands can be buffered by the runner and sent to the GPU all in one go.
  • 0

#28 Nocturne

Nocturne

    Nocturne Games

  • Administrators
  • 20907 posts
  • Version:GM:Studio

Posted 05 May 2011 - 03:13 PM

As for your question, Nocturne, I asked Mike that (don't recall where, must've been the other topic) and he said that the Delphi runner still draws sprites as individual quads. The C++ runner however puts sprites on a single texture page, so all drawing commands can be buffered by the runner and sent to the GPU all in one go.


Thanks... so at the moment this advance will make no difference to me? At least not until the C++ runner is ready... Oh well. I am a patient man and can wait for GM9!
  • 0

#29 Manuel777

Manuel777

    InvaderGames

  • GMC Member
  • 3525 posts
  • Version:GM:Studio

Posted 05 May 2011 - 05:16 PM

@Medusar: Really?? :huh:
Never knew that, i alway thought GM used a standard 2D drawing method..
  • 0

#30 Dark Matter

Dark Matter

    RPG Expert

  • GMC Member
  • 3196 posts
  • Version:GM:Studio

Posted 05 May 2011 - 05:39 PM


What are QUADS?

rectangles, squares, 2 triangles etc...

And that's different from drawing two triangles? How? How do you even do it, because I'm pretty sure you don't mean drawing two triangles is bad practice :P ?
  • 0




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users