Skip to content

Drago3D

Michael edited this page Oct 10, 2024 · 5 revisions

If you've used 3D in GameMaker in the past before migrating to GMS2, you've probably been warned against using the compatibility scripts that GameMaker provides for you when you import an older project. There are many reasons for this:

  • They're slow
  • They're very barebones
  • They were created to use the DirectX 8 API, which at this point in time, is older than a significant number of GameMaker's actual users
  • They're actually even slower than you think, since the compatibility functions don't even make an API call but instead emulate them within GML

Vertex buffers are the preferred substitute in whatever the current year is, which are orders of magnitude faster and more capable. However, there remains something to be said for having a set of immediate-mode functions for drawing 3D geometry, so here you go.

To get started, download the YYMP from the Itch page and import it into GameMaker (Tools > Import Local Package).

Performance

In all cases performance with Drago3D will be noticeably better than with using the compatibility functions.

Some shapes, particularly spheres, will get a much, much larger boost. This is due to the potentially large number of vertices that can be involved, as the compatibility functions build the geometry from scratch (and then delete it) every single time they're called.

(steps = 32)

Links

  • Drago3D can be found on Itch here

This requires a relatively modern version of GameMaker to work, probably around 2022.11 or so.

API

If you know what the old D3D primitive functions were like, these are exactly the same.

There's a minor difference in that you're now allowed to specify the vertex color and alpha, where in the original functions this was not possible. The color and alpha arguments are optional and will default to the current draw color.

Some functions will take a "start" and an "end" color and alpha. Those arguments are also optional. If a "start" color or alpha is given but "end" is not, the whole shape will use the same color.

d3d_draw_block(x1, y1, z1, x2, y2, z2, tex, hrepeat, vrepeat, color*, alpha*)
d3d_draw_capsule(x1, y1, z1, x2, y2, z2, tex, closed, steps, hrepeat, vrepeat, color1*, alpha1*, color2*, alpha2*)
d3d_draw_cone(x1, y1, z1, x2, y2, z2, tex, closed, steps, hrepeat, vrepeat, color*, alpha*)
d3d_draw_cylinder(x1, y1, z1, x2, y2, z2, tex, closed, steps, hrepeat, vrepeat, color1*, alpha1*, color2*, alpha2*)
d3d_draw_ellipsoid(x1, y1, z1, x2, y2, z2, tex, steps, hrepeat, vrepeat, color*, alpha*)
d3d_draw_floor(x1, y1, z1, x2, y2, z2, tex, hrepeat, vrepeat, color*, alpha*)
d3d_draw_wall(x1, y1, z1, x2, y2, z2, tex, hrepeat, vrepeat, color*, alpha*)

In addition, there's a convenience function for drawing a sphere with a radius rather than an ellipsoid. Here the hrepeat and vrepeat arguments default to 1, and the steps argument defaults to 32.

d3d_draw_sphere(x, y, z, r, tex, hrepeat*, vrepeat*, steps*, color*, alpha*)

There's also a 3D "line" shape, or at least a capsule rotated on its side that generally looks like a line if you don't make it too wide. The idea of a line with a radius is rather silly but I figured if you didn't want that you'd just use a line primitive so anyway the radius defaults to 4.

d3d_draw_line(x1, y1, z1, x2, y2, z2, radius*, color1*, alpha1*, color2*, alpha2*)

And a polyline function, if you feel like getting fancy. Pass it an array of { x, y, z } structs and have it connect them with lines. color and alpha properties are optional.

d3d_draw_polyline(points, radius*, default_color*, default_alpha*)

Lastly, each of these shapes has a "simple" version, which omits the arguments that are used less often in favor of even more performance:

  • hrepeat and vrepeat arguments default to 1
  • steps arguments default to 32
  • color arguments default to c_white
  • alpha arguments default to 1
  • In d3d_draw_floor_simple, all four corners of the tile use the same z value

This skips out the cache lookup step and can improve performance by 10% or more.

d3d_draw_block_simple(x1, y1, z1, x2, y2, z2, tex)
d3d_draw_capsule_simple(x1, y1, z1, x2, y2, z2, tex)
d3d_draw_cone_simple(x1, y1, z1, x2, y2, z2, tex, closed)
d3d_draw_cylinder_simple(x1, y1, z1, x2, y2, z2, tex, closed)
d3d_draw_ellipsoid_simple(x1, y1, z1, x2, y2, z2, tex)
d3d_draw_floor_simple(x1, y1, x2, y2, z, tex)
d3d_draw_sphere_simple(x, y, z, r, tex)
d3d_draw_wall_simple(x1, y1, z1, x2, y2, z2, tex)

Other Stuff

I "fixed" the texture mapping on the tops and bottoms of cylinders and cones.

Should You Use This In A Finished Game?

Ideally you only use this thing for blocking out levels and replace everything with proper 3D meshes when you're finished, but if you really want to use this in production I can't stop you. It's better than the original d3d, at least.

Using this with shaders

These should work with the default GameMaker shader. If you want to use your own, the vertex format is position, normal, color, texture, which is what 95% of you are probably using anyway.

Clone this wiki locally