GML Functions: Drawing Polygons in 3D

The problem with drawing in the old way is that a sprite or polygon always lies in the xy-plane, that is, all corners have the same depth. For true 3D you want to be able to have vertices at different depths. From this moment on we will talk about z-coordinate rather than depth. So we want to specify coordinates as (x,y,z) tuples. For this there are special version of the advanced drawing functions:


 * d3d_primitive_begin(kind) Start a 3D primitive of the indicated kind: pr_pointlist, pr_linelist, pr_linestrip,pr_trianglelist,pr_trianglestrip or pr_trianglefan.
 * d3d_vertex(x,y,z) Add vertex (x,y,z) to the primitive, using the color and alpha value set before.
 * d3d_vertex_color(x,y,z,col,alpha) Add vertex (x,y,z) to the primitive, with its own color and alpha value. This allows you to create primitives with smoothly changing color and alpha values.
 * d3d_primitive_end End the description of the primitive. This function actually draws it.

For example, to draw a tetrahedron (three sided pyramid) standing on the z=0 plane with its top at z = 200, you can use the following code:

d3d_primitive_begin(pr_trianglelist); d3d_vertex(100,100,0); d3d_vertex(100,200,0); d3d_vertex(150,150,200); d3d_vertex(100,200,0); d3d_vertex(200,200,0); d3d_vertex(150,150,200); d3d_vertex(200,200,0); d3d_vertex(100,100,0); d3d_vertex(150,150,200); d3d_vertex(100,100,0); d3d_vertex(100,200,0); d3d_vertex(200,200,0); d3d_primitive_end;

Now if you would use this, most likely you would just see a triangle on the screen because the top of the tetrahedron will be behind it from the viewpoint. Also, using just one color, it would be difficult to see the different faces. Below we will see ways to change the viewpoint. Assigning colors can be done as before by added draw_set_color(col) function calls between the vertices.

You can also use textured poygons in 3D. It works exactly the same as described in the advanced drawing functions in the documentation. But this time you need 3D variants of the basic functions. One thing you must realize. In a texture the position (0,0) is the top-left corner. But often, when using projections (as indicated below), the bottom-left corner is (0,0). In such a case you might need to flip the texture vertically.


 * d3d_primitive_begin_texture(kind,texid) Start a 3D primitive of the indicated kind with the given texture.
 * d3d_vertex_texture(x,y,z,xtex,ytex) Add vertex (x,y,z) to the primitive with position (xtex,ytex) in the texture, blending with the color and alpha value set before.
 * d3d_vertex_texture_color(x,y,z,xtex,ytex,col,alpha) Add vertex (x,y,z) to the primitive with position (xtex,ytex) in the texture, blending with its own color and alpha value.
 * d3d_primitive_end End the description of the primitive. This function actually draws it.

So, for example you can use the following code to draw a background image that disappears into the distance

var ttt; ttt = background_get_texture(back); d3d_primitive_begin_texture(pr_trianglefan,ttt); d3d_vertex_texture(0,480,0,0,0); d3d_vertex_texture(640,480,0,1,0); d3d_vertex_texture(640,480,1000,1,1); d3d_vertex_texture(0,480,1000,0,1); d3d_primitive_end;

A triangle has a front and a back side. The front side is defined to be the side where the vertices are defined in counter-clockwise order. Normally both sides are drawn. But if you make a closed shape this is a waste because the back side of the triangle can never be seen. In this case you can switch on backface culling. This saves about half the amount of drawing time but it leaves you with the task of defining your polygons in the right way. The following function exists:


 * d3d_set_culling(cull) Indicates to start backface culling (true) or stop backface culling (false).