• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

3D Rendering a Simple Black Box (3D)

xenoargh

Member
Hi. I'm trying to do something that should be... super-simple, but apparently isn't, lol. I'm trying to learn how to get GMS to draw a simple, all-black cuboid.

At the beginning of time, I specify a vertex format:

GML:
global.hasBuiltFormat = false;
function scr_3D_Wall_Mesh_Format(){
    vertex_format_begin();
    vertex_format_add_colour();
    vertex_format_add_position_3d();
    vertex_format_add_colour();
    vertex_format_add_position_3d();
    vertex_format_add_colour();
    vertex_format_add_position_3d();
    vertex_format_add_colour();
    vertex_format_add_position_3d();
    vertex_format_add_colour();
    vertex_format_add_position_3d();
    vertex_format_add_colour();
    vertex_format_add_position_3d();
    vertex_format_add_colour();
    vertex_format_add_position_3d();
    vertex_format_add_colour();
    vertex_format_add_position_3d();
    global.vFormat = vertex_format_end();
    global.hasBuiltFormat = true;
    show_debug_message("built format!");
}
Then I have an Object that's responsible for building a Vertex Buffer, using this code in its Step Event:

GML:
if(!hasBuiltBuffer){
    if(global.hasBuiltFormat = false){
        scr_3D_Wall_Mesh_Format(); 
    } else {
        vertex_begin(vBuffer,global.vFormat);
        vertex_color(vBuffer,c_black,1);
        vertex_position_3d(vBuffer,bbox_bottom,-100,bbox_left);
        vertex_color(vBuffer,c_black,1);
        vertex_position_3d(vBuffer,bbox_top,-100,bbox_left);
        vertex_color(vBuffer,c_black,1);
        vertex_position_3d(vBuffer,bbox_top,-100,bbox_right);
        vertex_color(vBuffer,c_black,1);
        vertex_position_3d(vBuffer,bbox_bottom,-100,bbox_right);
        vertex_color(vBuffer,c_black,1);
        vertex_position_3d(vBuffer,bbox_bottom,0,bbox_left);
        vertex_color(vBuffer,c_black,1);
        vertex_position_3d(vBuffer,bbox_top,0,bbox_left);
        vertex_color(vBuffer,c_black,1);
        vertex_position_3d(vBuffer,bbox_top,0,bbox_right);
        vertex_color(vBuffer,c_black,1);
        vertex_position_3d(vBuffer,bbox_bottom,0,bbox_right);
        vertex_end(vBuffer);
        vertex_freeze(vBuffer);
      
        hasBuiltBuffer = true;
    }
}
Once the Vertex Buffer is built, it's trying to draw it via a shader in the Draw Event:

GML:
if(hasBuiltBuffer){
    show_debug_message("drawing box");
    shader_set(sh_BlackBox);
    vertex_submit(vBuffer, pr_trianglestrip, -1);
    shader_reset();
}
Using this shader:

C:
//VERTEX
attribute vec3 in_Position;                  // (x,y,z)
void main()
{
    vec4 object_space_pos = vec4( in_Position.x, in_Position.y, in_Position.z, 1.0);
    gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * object_space_pos;
}


//FRAGMENT
const vec4 black = vec4(0.0,0.0,0.0,1.0);
void main()
{
    gl_FragColor = black;
}
When I run my little test project, "drawing box" is printed to the console, but the 3D box does not draw in the Room. If I un-comment draw_self() in the Draw Event, the object is in the Room, sure enough.

Where did I go wrong here? Please help; it was fairly confusing just getting to this point and it seems like it should work... but it doesn't.
 

Bart

WiseBart
Hi.

There are a few things in your current code that prevent it from actually displaying the cube.

In the vertex format you specify a 3D position and color vertex attribute for each corner point of the cube (8 in total).
But the vertex format is supposed to describe the format of a single vertex.
Right now you only defined a single vertex.
The vertex format really needs to be little more than this (the position may need to go before the color, not sure about that):
GML:
vertex_format_begin();
vertex_format_add_colour();
vertex_format_add_position_3d();
global.vFormat = vertex_format_end();
It basically tells you "for each vertex of a triangle we'll be using a color and a 3D position".
That color attribute that you defined in the format should also be defined in the vertex shader.
The format and the shader attributes need to match.

You define the cube between those calls to vertex_begin and vertex_end as 8 vertices, using pr_trianglestrip.
It may be possible to define a cube using pr_trianglestrip but it makes things needlessly complex in my opinion.
It's not the most straightforward way to define a model's triangles.
It looks to me that, in your current code, the vertices aren't defined in the right order to make this work with pr_trianglestrip.
I personally always use pr_trianglelist since it allows you to specify triangles as triplets of vertices.
In the case of a cube you then define 12 triangles in total, 2 for each face of the cube (a face's diagonal splits it into two triangles).
Each corner point is defined more than once. Once for each triangle the vertex is part of, to be precise.

Right now you have:
GML:
/// The first two triangles defined using pr_trianglestrip
vertex_color(vBuffer,c_black,1);                              // first vertex of first triangle
vertex_position_3d(vBuffer,bbox_bottom,-100,bbox_left);
vertex_color(vBuffer,c_black,1);                              // second vertex of first triangle, also first vertex of second triangle (!)
vertex_position_3d(vBuffer,bbox_top,-100,bbox_left);
vertex_color(vBuffer,c_black,1);                              // third vertex of first triangle, also second vertex of second triangle
vertex_position_3d(vBuffer,bbox_top,-100,bbox_right);
vertex_color(vBuffer,c_black,1);                              // third vertex of second triangle
vertex_position_3d(vBuffer,bbox_bottom,-100,bbox_right);
With pr_trianglelist this becomes:
GML:
/// The first two triangles defined using pr_trianglelist
vertex_color(vBuffer,c_black,1);                              // first vertex of first triangle
vertex_position_3d(vBuffer,bbox_bottom,-100,bbox_left);
vertex_color(vBuffer,c_black,1);                              // second vertex of first triangle
vertex_position_3d(vBuffer,bbox_top,-100,bbox_left);
vertex_color(vBuffer,c_black,1);                              // third vertex of first triangle
vertex_position_3d(vBuffer,bbox_top,-100,bbox_right);

vertex_color(vBuffer,c_black,1);                              // first vertex of second triangle
vertex_position_3d(vBuffer,bbox_top,-100,bbox_left);
vertex_color(vBuffer,c_black,1);                              // second vertex of second triangle
vertex_position_3d(vBuffer,bbox_top,-100,bbox_right);
vertex_color(vBuffer,c_black,1);                              // third vertex of second triangle
vertex_position_3d(vBuffer,bbox_bottom,-100,bbox_right);

A thing that can be helpful for testing: you may want to use a couple of different colors for the different faces of the cube.
It'll be quite hard to debug otherwise.

Hope these things can help a bit!
 
Last edited:

xenoargh

Member
Oh man, I would've never figured out the problems with the vertex format! Thanks so much, that's probably where I went wrong.
 
Top