3D Texturing cubes with Multiple Textures?

I'm working on a game right now that I want to be a simple 3D platformer, using cubes/prisms made from vertex buffers for the terrain.

My problem is the way I want to texture the terrain differs based on how the terrain is shaped. Something like this below:

3D Texture 1.png

I understand I might not be able to get it as nice as the example above, but is there any way at all to achieve this?

(If I had to guess, this would have be done through texture coordinates or a shader of some kind, but I'm still relatively new to learning Game maker so I could be missing something.)
 

Joe Ellis

Member
Is the terrain made out of cubes like minecraft?
If so you'd be able to do a quite simple thing where for each block\cube:

if no other blocks are above it, give the walls the top layer with the grass, and the top ground face grass texture.
else (if there is a block above it)

for each of the 4 walls of the block:
if the block next to it is empty, and below that empty block there is a solid block, give that wall the bottom texture.
if there isn't a block below that empty block, give that wall the middle texture.
if the block next to it is not empty, don't create a wall there
 
Right now I'm trying to make it where it takes only one vertex buffer to make a whole length of terrain, like the two examples above, instead of a bunch of tiny cubes like minecraft. So it's just one cube/prism with different textures along the faces of it.

The problem with doing one large vertex buffer and wanting to have multiple textures displayed on it is I'm not sure how I would put the multiple textures on the block. If I use UV coordinates, it will only take one texture and cover the entire face of the block with that, but I want to use a couple of different textures to display on the same face. So I basically am trying to get what you're saying, except I would need it to be in the texture of the block instead of using multiple blocks themselves.

I'll most likely fall back on the minecraft strategy if there isn't another solution to this, but I want to avoid making that many cubes if I can because I'm worried that it will slow the game down.
 

Joe Ellis

Member
Would you be able to post a picture of what you've got so far cus I can't really tell exactly what you mean?

I was gonna say, you can build the entire level in one vertex buffer, you'd just build the cubes\square faces where needed and use a tilemap with all the textures.

On minecraft, each cell in the grid has a flag\tag determining what material it is, and 0 is air.

Then the faces of the cubes are built by iterating through each cell and checking the neighbour cells to see if they are air or solid.

It can be done either by each air cell checking if any of it's neighbour cells are solid, or each solid cell checking if any of it's neighbour cells are air.
Though I think it'd be a bit simpler doing the latter cus then you don't have to get what the neighbour cell's material is when applying the textures.

So it would be like this:

for each cell
{
if the cell is solid (it's tag/flag is not zero)
{
for each of the 6 neighbour cells
{
if it's air
{
create a square with the orientation of that neighbour(up, down, north, south, east, west)
give the square uv coordinates on the tilemap depending what material flag it has
}
}
}
}

and you'd have to add an extra thing to determine what layer of the tilemap each square should use, but I'd start by getting this first part working first.

It won't slow the game down if you have as many cubes as on minecraft btw, not if you do it this way cus most of the cubes are invisible\have no geometry cus of them being hidden, and you can use chunking later down the line if the world is really big, so it'll be split into one vertex buffer per "view region", then only 4 need to be rendered at a time (the ones in the view region)
As you can see here, if the vertex buffers are the same size as the view region (or slightly larger), it's only possible for view region to be intersecting 4 at a time:



Then getting the cells to draw can be done by simply rounding the view's position divided by the grid res:

GML:
var
cx = clamp(round(global.view_x / global.chunk_grid_res), 1, global.chunks_x - 1),
cy = clamp(round(global.view_y / global.chunk_grid_res), 1, global.chunks_y - 1);

vertex_submit(world_chunk_vbuffers[cx, cy], pr_trianglelist, tilemap_texture)
vertex_submit(world_chunk_vbuffers[cx - 1, cy], pr_trianglelist, tilemap_texture)
vertex_submit(world_chunk_vbuffers[cx, cy - 1], pr_trianglelist, tilemap_texture)
vertex_submit(world_chunk_vbuffers[cx - 1, cy - 1], pr_trianglelist, tilemap_texture)
 
Last edited:
Sorry for taking so long to get back to you, summer school's kept me busy.

I don't think I'd ever get to Minecraft levels of cubes in a given room (or chunk), but if I wanted to have the game run on even really old computers, would creating this many cubes still be feasibly performant even with chunks and culling? The way I have the game set up, it looks like a top down, 2D game (like Mario and Luigi: Superstar Saga), so I worry that people might be disappointed if it can't run on their computer because a bunch of 3d geometry is being processed in the game despite its appearance.

Thank you for your help with this though, I really appreciate all the pictures and explanations you've given!
 
Last edited:
Top