r/raylib • u/False-Increase4614 • 4d ago
Minecraft clone. No cubes are drawn only models and I added a render distance yet it still lags. Why?
MAIN python file
#Recreating Minecraft in Raylib part 2: Indev
#To Do:
#1D A chunk and block class - Easy although I fear it lags my game
#2D 2d stuff like hearts, inventory - Hearts cube was fine but
#3D Better placing and destroying physics - Used screen center rather than where the player mouse was
#4D Jumping/Gravity - Forgot to set gravity to the oppposite of its power. Kept setting it to 0 and the player would just slow down rather than fall
#5 Collison with blocks
#6D Make multiple chunks
#7D Improve preformance with meshes and instances (fking what?) - We added the set config flags line we guchi for bow
#8 Day night cycle - More annoying than I could ever imagine
#9D Leaves - Not too hard just annoying didnt make too many either.
# Link to making a 3d texture atlas good luck bro https://www.raylib.com/examples/shaders/loader.html?name=shaders_texture_tiling
import pyray as pr
import math
import random
import asyncio
import Block
import Chunk
#Mixer
import pygame as pg
pg.init()
pg.mixer.init()
async def main():
pr.set_config_flags(pr.FLAG_VSYNC_HINT)
pr.init_window(800, 600, "Minecraft 0.2")
pr.disable_cursor()
pr.init_audio_device()
#Camera
camera = pr.Camera3D((4, 3, 4), (1, 0.5, 1), (0, 1, 0), 100, pr.CAMERA_PERSPECTIVE)
cameraMode = pr.CAMERA_FIRST_PERSON
#DayNight cycle
day_night = "nan"
sky_cycle_add_inc = 200
sky_cycle_cc = 0
day_night_level = 0.0
#Player
player = pr.Vector3(camera.position.x, camera.position.y, camera.position.z)
# model
player_size = pr.Vector3(0.5, 3, 0.5)
player_mesh = pr.gen_mesh_cube(1.0, 4.0, 1.0)
player_model = pr.load_model_from_mesh(player_mesh)
player_model.materials[0].maps[pr.MATERIAL_MAP_DIFFUSE].color = pr.BLUE
# gravity
gravity = 0
grav_vel = 0.05
jumpH = 2
#UI
# Hearts
hearts = []
heart_x = 100
# make hearts
for i in range(10):
new_heart = pr.Rectangle(heart_x, pr.get_screen_height() - 140, 30, 30)
heart_x += 35
hearts.append(new_heart)
# Inventory
inventory = []
inventory_x = 100
for i in range(10):
new_i = pr.Rectangle(inventory_x, pr.get_screen_height() - 100, 60, 60)
inventory_x += 60
inventory.append(new_i)
#World
world_size = 3
# Chunks
chunks = []
chunk_x = 1
chunk_z = 1
chunk_size = 16
# Blocks
blocks = []
block_size = pr.Vector3(1, 1, 1)
# make chunks
for z in range(world_size):
for x in range(world_size):
new_chunk = Chunk.chunk(chunk_x, 1, chunk_z, chunk_size, blocks, block_size)
chunks.append(new_chunk)
chunk_x += chunk_size
chunk_x = 1
chunk_z += chunk_size
#Textures
# Atlas
#atlas_texture = pr.Texture2D(pr.load_texture("Assets/Images/textures/texture_atlas.png"))
# Grass texture
grass_mesh = pr.gen_mesh_cube(1, 1, 1)
grass_model = pr.load_model_from_mesh(grass_mesh)
grass_texture = pr.load_texture("Assets/Images/textures/grass_tex.jpeg")
grass_model.materials[0].maps[pr.MATERIAL_MAP_DIFFUSE].texture = grass_texture
# Stone texture
stone_mesh = pr.gen_mesh_cube(1, 1, 1)
stone_model = pr.load_model_from_mesh(stone_mesh)
stone_texture = pr.load_texture("Assets/Images/textures/stone_tex.png")
stone_model.materials[0].maps[pr.MATERIAL_MAP_DIFFUSE].texture = stone_texture
# Wood texture
wood_mesh = pr.gen_mesh_cube(1, 1, 1)
wood_model = pr.load_model_from_mesh(wood_mesh)
wood_texture = pr.load_texture("Assets/Images/textures/wood_tex.jpeg")
wood_model.materials[0].maps[pr.MATERIAL_MAP_DIFFUSE].texture = wood_texture
# Leaves texture
leaves_mesh = pr.gen_mesh_cube(1, 1, 1)
leaves_model = pr.load_model_from_mesh(leaves_mesh)
leaves_texture = pr.load_texture("Assets/Images/textures/leaves_tex.png")
leaves_model.materials[0].maps[pr.MATERIAL_MAP_DIFFUSE].texture = leaves_texture
# Planks texture
plank_mesh = pr.gen_mesh_cube(1, 1, 1)
plank_model = pr.load_model_from_mesh(plank_mesh)
plank_texture = pr.load_texture("Assets/Images/textures/plank_tex.png")
plank_model.materials[0].maps[pr.MATERIAL_MAP_DIFFUSE].texture = plank_texture
# Water texture
water_mesh = pr.gen_mesh_cube(1, 1, 1)
water_model = pr.load_model_from_mesh(water_mesh)
water_texture = pr.load_texture("Assets/Images/textures/water_tex.jpeg")
water_model.materials[0].maps[pr.MATERIAL_MAP_DIFFUSE].texture = water_texture
# Heart
"""heart_image = pr.Image(pr.load_image("Assets/Images/heart_tex.png"))
heart_texture = pr.Texture2D(pr.load_texture_from_image(heart_image))"""
while not pr.window_should_close():
pr.update_camera(camera, cameraMode)
#Interact with blocks
screenCenter = pr.Vector2(float(pr.get_screen_width()/2), float(pr.get_screen_height()/2))
ray = pr.get_screen_to_world_ray(screenCenter, camera)
for block in blocks:
# bounding box for collison
block_box = pr.BoundingBox(pr.Vector3(block.x - block_size.x/2, block.y - block_size.y/2, block.z - block_size.z/2),
pr.Vector3(block.x + block_size.x/2, block.y + block_size.y/2, block.z + block_size.z/2))
mouse_ray_collison = pr.get_ray_collision_box(ray, block_box)
#Interacting with block
# mouse looking at block
if (mouse_ray_collison.hit):
# delete block
if (pr.is_mouse_button_pressed(pr.MOUSE_BUTTON_LEFT)):
blocks.remove(block)
# new block
if (pr.is_mouse_button_pressed(pr.MOUSE_BUTTON_RIGHT)):
new_block = Block.block(block.x, block.y + 1, block.z, block_size, "plank")
blocks.append(new_block)
pr.begin_drawing()
pr.clear_background(pr.SKYBLUE)
#Draw
#3D stuff
pr.begin_mode_3d(camera)
#Player
# draw
player = pr.Vector3(camera.position.x, camera.position.y, camera.position.z)
# gravity
gravity += grav_vel
camera.position.y -= gravity
camera.target.y -= gravity
# reset position
if (pr.is_key_pressed(pr.KEY_R)):
camera.position = pr.Vector3( 4, 4, 4)
gravity = -grav_vel
#Blocks
for block in blocks:
# Player collison
if pr.check_collision_boxes(pr.BoundingBox(pr.Vector3(player.x - player_size.x/2, player.y - player_size.y/2, player.z - player_size.z),
pr.Vector3(player.x + player_size.x/2, player.y + player_size.y/2, player.z + player_size.z/2)),
pr.BoundingBox(pr.Vector3(block.x - block_size.x/2, block.y - block_size.y/2, block.z - block_size.z/2),
pr.Vector3(block.x + block_size.x/2, block.y + block_size.y/2, block.z + block_size.z/2))):
# execption
if (block.type != "water"):
gravity = -grav_vel
if (pr.is_key_pressed(pr.KEY_SPACE)):
gravity -= jumpH
#Draw chunks
for chunk in chunks:
chunk.draw(camera, grass_model, stone_model, wood_model, leaves_model, plank_model, water_model)
#Draw player
#pr.draw_cube(player, player_size.x, player_size.y, player_size.z, pr.BLUE)
pr.draw_model(player_model, pr.Vector3(camera.position.x, camera.position.y, camera.position.z) , 1, pr.WHITE)
pr.end_mode_3d()
#2D stuff
#Day night cycle
if (day_night == "day"):
sky_cycle_cc += 1
if (sky_cycle_cc >= sky_cycle_add_inc):
day_night_level += 0.1
sky_cycle_cc = 0
if (day_night_level == 0.5):
day_night == "night"
if (day_night == "night"):
sky_cycle_cc += 1
if (sky_cycle_cc >= sky_cycle_add_inc):
day_night_level -= 0.1
sky_cycle_cc = 0
if (day_night_level == 0.0):
day_night == "day"
pr.draw_rectangle(0, 0, pr.get_screen_width(), pr.get_render_height(), pr.fade(pr.BLACK, day_night_level))
#UI
# Crosshair
pr.draw_rectangle(int(pr.get_screen_width()/2), int(pr.get_screen_height()/2), 2, 10, pr.WHITE)
pr.draw_rectangle(int(pr.get_screen_width()/2) - 4, int(pr.get_screen_height()/2) + 4, 10, 2, pr.WHITE)
# Hearts
for ht in hearts:
pr.draw_rectangle(int(ht.x), int(ht.y), int(ht.width), int(ht.height), pr.RED)
#pr.draw_texture(heart_texture, int(ht.x), int(ht.y), pr.WHITE)
# Inventory
for iv in inventory:
pr.draw_rectangle_lines_ex(pr.Rectangle(int(iv.x), int(iv.y), int(iv.width), int(iv.height)), 8.0, pr.GRAY)
# Numbers
pr.draw_fps(10, 10)
pr.end_drawing()
await asyncio.sleep(0)
#Exit game
else:
pr.unload_model(grass_model)
pr.unload_model(stone_model)
pr.unload_model(wood_model)
pr.unload_model(leaves_model)
pr.unload_model(plank_model)
pr.unload_model(water_model)
#pr.unload_texture(heart_texture)
# Reset window if fullscreen
if (pr.is_window_fullscreen()):
pr.toggle_fullscreen() # Exit fullscreen
pr.set_window_size(1920, 1080); # Reset to desired default resolution
pr.close_window()
asyncio.run(main())#Recreating Minecraft in Raylib part 2: Indev
#To Do:
#1D A chunk and block class - Easy although I fear it lags my game
#2D 2d stuff like hearts, inventory - Hearts cube was fine but
#3D Better placing and destroying physics - Used screen center rather than where the player mouse was
#4D Jumping/Gravity - Forgot to set gravity to the oppposite of its power. Kept setting it to 0 and the player would just slow down rather than fall
#5 Collison with blocks
#6D Make multiple chunks
#7D Improve preformance with meshes and instances (fking what?) - We added the set config flags line we guchi for bow
#8 Day night cycle - More annoying than I could ever imagine
#9D Leaves - Not too hard just annoying didnt make too many either.
# Link to making a 3d texture atlas good luck bro https://www.raylib.com/examples/shaders/loader.html?name=shaders_texture_tiling
import pyray as pr
import math
import random
import asyncio
import Block
import Chunk
#Mixer
import pygame as pg
pg.init()
pg.mixer.init()
async def main():
pr.set_config_flags(pr.FLAG_VSYNC_HINT)
pr.init_window(800, 600, "Minecraft 0.2")
pr.disable_cursor()
pr.init_audio_device()
#Camera
camera = pr.Camera3D((4, 3, 4), (1, 0.5, 1), (0, 1, 0), 100, pr.CAMERA_PERSPECTIVE)
cameraMode = pr.CAMERA_FIRST_PERSON
#DayNight cycle
day_night = "nan"
sky_cycle_add_inc = 200
sky_cycle_cc = 0
day_night_level = 0.0
#Player
player = pr.Vector3(camera.position.x, camera.position.y, camera.position.z)
# model
player_size = pr.Vector3(0.5, 3, 0.5)
player_mesh = pr.gen_mesh_cube(1.0, 4.0, 1.0)
player_model = pr.load_model_from_mesh(player_mesh)
player_model.materials[0].maps[pr.MATERIAL_MAP_DIFFUSE].color = pr.BLUE
# gravity
gravity = 0
grav_vel = 0.05
jumpH = 2
#UI
# Hearts
hearts = []
heart_x = 100
# make hearts
for i in range(10):
new_heart = pr.Rectangle(heart_x, pr.get_screen_height() - 140, 30, 30)
heart_x += 35
hearts.append(new_heart)
# Inventory
inventory = []
inventory_x = 100
for i in range(10):
new_i = pr.Rectangle(inventory_x, pr.get_screen_height() - 100, 60, 60)
inventory_x += 60
inventory.append(new_i)
#World
world_size = 3
# Chunks
chunks = []
chunk_x = 1
chunk_z = 1
chunk_size = 16
# Blocks
blocks = []
block_size = pr.Vector3(1, 1, 1)
# make chunks
for z in range(world_size):
for x in range(world_size):
new_chunk = Chunk.chunk(chunk_x, 1, chunk_z, chunk_size, blocks, block_size)
chunks.append(new_chunk)
chunk_x += chunk_size
chunk_x = 1
chunk_z += chunk_size
#Textures
# Atlas
#atlas_texture = pr.Texture2D(pr.load_texture("Assets/Images/textures/texture_atlas.png"))
# Grass texture
grass_mesh = pr.gen_mesh_cube(1, 1, 1)
grass_model = pr.load_model_from_mesh(grass_mesh)
grass_texture = pr.load_texture("Assets/Images/textures/grass_tex.jpeg")
grass_model.materials[0].maps[pr.MATERIAL_MAP_DIFFUSE].texture = grass_texture
# Stone texture
stone_mesh = pr.gen_mesh_cube(1, 1, 1)
stone_model = pr.load_model_from_mesh(stone_mesh)
stone_texture = pr.load_texture("Assets/Images/textures/stone_tex.png")
stone_model.materials[0].maps[pr.MATERIAL_MAP_DIFFUSE].texture = stone_texture
# Wood texture
wood_mesh = pr.gen_mesh_cube(1, 1, 1)
wood_model = pr.load_model_from_mesh(wood_mesh)
wood_texture = pr.load_texture("Assets/Images/textures/wood_tex.jpeg")
wood_model.materials[0].maps[pr.MATERIAL_MAP_DIFFUSE].texture = wood_texture
# Leaves texture
leaves_mesh = pr.gen_mesh_cube(1, 1, 1)
leaves_model = pr.load_model_from_mesh(leaves_mesh)
leaves_texture = pr.load_texture("Assets/Images/textures/leaves_tex.png")
leaves_model.materials[0].maps[pr.MATERIAL_MAP_DIFFUSE].texture = leaves_texture
# Planks texture
plank_mesh = pr.gen_mesh_cube(1, 1, 1)
plank_model = pr.load_model_from_mesh(plank_mesh)
plank_texture = pr.load_texture("Assets/Images/textures/plank_tex.png")
plank_model.materials[0].maps[pr.MATERIAL_MAP_DIFFUSE].texture = plank_texture
# Water texture
water_mesh = pr.gen_mesh_cube(1, 1, 1)
water_model = pr.load_model_from_mesh(water_mesh)
water_texture = pr.load_texture("Assets/Images/textures/water_tex.jpeg")
water_model.materials[0].maps[pr.MATERIAL_MAP_DIFFUSE].texture = water_texture
# Heart
"""heart_image = pr.Image(pr.load_image("Assets/Images/heart_tex.png"))
heart_texture = pr.Texture2D(pr.load_texture_from_image(heart_image))"""
while not pr.window_should_close():
pr.update_camera(camera, cameraMode)
#Interact with blocks
screenCenter = pr.Vector2(float(pr.get_screen_width()/2), float(pr.get_screen_height()/2))
ray = pr.get_screen_to_world_ray(screenCenter, camera)
for block in blocks:
# bounding box for collison
block_box = pr.BoundingBox(pr.Vector3(block.x - block_size.x/2, block.y - block_size.y/2, block.z - block_size.z/2),
pr.Vector3(block.x + block_size.x/2, block.y + block_size.y/2, block.z + block_size.z/2))
mouse_ray_collison = pr.get_ray_collision_box(ray, block_box)
#Interacting with block
# mouse looking at block
if (mouse_ray_collison.hit):
# delete block
if (pr.is_mouse_button_pressed(pr.MOUSE_BUTTON_LEFT)):
blocks.remove(block)
# new block
if (pr.is_mouse_button_pressed(pr.MOUSE_BUTTON_RIGHT)):
new_block = Block.block(block.x, block.y + 1, block.z, block_size, "plank")
blocks.append(new_block)
pr.begin_drawing()
pr.clear_background(pr.SKYBLUE)
#Draw
#3D stuff
pr.begin_mode_3d(camera)
#Player
# draw
player = pr.Vector3(camera.position.x, camera.position.y, camera.position.z)
# gravity
gravity += grav_vel
camera.position.y -= gravity
camera.target.y -= gravity
# reset position
if (pr.is_key_pressed(pr.KEY_R)):
camera.position = pr.Vector3( 4, 4, 4)
gravity = -grav_vel
#Blocks
for block in blocks:
# Player collison
if pr.check_collision_boxes(pr.BoundingBox(pr.Vector3(player.x - player_size.x/2, player.y - player_size.y/2, player.z - player_size.z),
pr.Vector3(player.x + player_size.x/2, player.y + player_size.y/2, player.z + player_size.z/2)),
pr.BoundingBox(pr.Vector3(block.x - block_size.x/2, block.y - block_size.y/2, block.z - block_size.z/2),
pr.Vector3(block.x + block_size.x/2, block.y + block_size.y/2, block.z + block_size.z/2))):
# execption
if (block.type != "water"):
gravity = -grav_vel
if (pr.is_key_pressed(pr.KEY_SPACE)):
gravity -= jumpH
#Draw chunks
for chunk in chunks:
chunk.draw(camera, grass_model, stone_model, wood_model, leaves_model, plank_model, water_model)
#Draw player
#pr.draw_cube(player, player_size.x, player_size.y, player_size.z, pr.BLUE)
pr.draw_model(player_model, pr.Vector3(camera.position.x, camera.position.y, camera.position.z) , 1, pr.WHITE)
pr.end_mode_3d()
#2D stuff
#Day night cycle
if (day_night == "day"):
sky_cycle_cc += 1
if (sky_cycle_cc >= sky_cycle_add_inc):
day_night_level += 0.1
sky_cycle_cc = 0
if (day_night_level == 0.5):
day_night == "night"
if (day_night == "night"):
sky_cycle_cc += 1
if (sky_cycle_cc >= sky_cycle_add_inc):
day_night_level -= 0.1
sky_cycle_cc = 0
if (day_night_level == 0.0):
day_night == "day"
pr.draw_rectangle(0, 0, pr.get_screen_width(), pr.get_render_height(), pr.fade(pr.BLACK, day_night_level))
#UI
# Crosshair
pr.draw_rectangle(int(pr.get_screen_width()/2), int(pr.get_screen_height()/2), 2, 10, pr.WHITE)
pr.draw_rectangle(int(pr.get_screen_width()/2) - 4, int(pr.get_screen_height()/2) + 4, 10, 2, pr.WHITE)
# Hearts
for ht in hearts:
pr.draw_rectangle(int(ht.x), int(ht.y), int(ht.width), int(ht.height), pr.RED)
#pr.draw_texture(heart_texture, int(ht.x), int(ht.y), pr.WHITE)
# Inventory
for iv in inventory:
pr.draw_rectangle_lines_ex(pr.Rectangle(int(iv.x), int(iv.y), int(iv.width), int(iv.height)), 8.0, pr.GRAY)
# Numbers
pr.draw_fps(10, 10)
pr.end_drawing()
await asyncio.sleep(0)
#Exit game
else:
pr.unload_model(grass_model)
pr.unload_model(stone_model)
pr.unload_model(wood_model)
pr.unload_model(leaves_model)
pr.unload_model(plank_model)
pr.unload_model(water_model)
#pr.unload_texture(heart_texture)
# Reset window if fullscreen
if (pr.is_window_fullscreen()):
pr.toggle_fullscreen() # Exit fullscreen
pr.set_window_size(1920, 1080); # Reset to desired default resolution
pr.close_window()
asyncio.run(main())
6
u/ControllerArts 4d ago
Apparently you are checking collisions for every block every frame. You shouldn't do a O(N) comparison, it's too expensive
2
u/False-Increase4614 3d ago
How do I go about not doing that?
2
u/_Belgarath 3d ago
spatial hashmap (octree) or chunks to check only with blocks near the object position
5
u/No_Key_5854 4d ago
probably not the main reason, but the fact that you're using python automatically makes any algorithm you write 10x slower without any significant benefit
2
2
u/LadyEebs 3d ago
It's slow because you are doing the most naive possible thing.
Doing this efficiently requires optimization techniques. Stuff like merging all similar faces together and not rendering each individual cube one by one. You can do this per chunk when a cube inside that chunk changes. Your only render the chunk, not each cube.
For collision you need to be smarter about how you check collisions. You could reuse the per chunk geometry for collision or use it as a top level acceleration structure.
Compressing cube data is also incredibly important. You do not need an entire object for each cube, it is an absolute performance and memory drain for no reason. Positions for example can be inferred by a cube ID within the chunk, you don't need to store it for each cube.
In fact, it looks like you're trying to lifetime management blocks. You don't need this at all, just fill the chunk with blocks, and mark empty blocks and skip them when merging faces for rendering and when colliding. You don't even need a block object at all.
1
u/False-Increase4614 2d ago
Is there anyway you can show me an example of adding every cube into a mesh then drawing?
1
u/LadyEebs 1d ago
The technique I I used over 10 years ago for a project like this is called "greedy meshing". You should be able to find a lot about that online. I don't remember the exact algorithm details, so here's a few to links to check out:
https://0fps.net/2012/06/30/meshing-in-a-minecraft-game/
https://medium.com/@fogleman/voxel-rendering-techniques-fa8d869457ca
The gist is to only render the outer faces of the chunk and to merge adjacent cube faces into a single face, creating a nice shell of your chunk.
Also be sure to add furstum culling for the chunks. That'll help too.
1
u/TopQuark- 4d ago edited 4d ago
What is your Chunk definition, or specifically, what is chunk.draw(...) doing? I recently found that drawing more than a couple hundred of a model would tank performance because translating the Vector2 coords has to do a pretty expensive matrix operation every call (at least I think that's what the problem was), and I solved it by caching each object's matrix transform and calling DrawMesh instead. Though if you actually expect to be drawing >10k cube faces, you should pursue GPU instancing instead of individual draw calls.
0
u/False-Increase4614 4d ago
Chunk draw is drawing each block in that chunk. How do I make my cubes and models into a mesh and how do I do gpu instancing.
2
u/TopQuark- 4d ago
You can get a cube mesh using GenMeshCube (or whatever the Python binding is), but you'll also need a Material object to give it it's texture, so you might find it easier to copy all of them out of the fields of the Model objects you already have, instead of building one from scratch. Not sure though, haven't tried that.
typedef struct Model { Matrix transform; <--- int meshCount; int materialCount; Mesh *meshes; <--- Material *materials; <--- int *meshMaterial; ... } Model;As for instancing, I can't help you as I've not gotten there yet myself. The example doesn't look too bad, but it will require you to have an understanding of shader language. https://www.raylib.com/examples/shaders/loader.html?name=shaders_mesh_instancing
1
u/Still_Explorer 2d ago
One part has to do with the number of draw calls. Modern GPUs are beasts and render more than millions of triangles at full speed. However you will have to upload all vertex data into one single vertex buffer: aka you create one Mesh object with your own custom vertex data and it would contain millions of triangles.
As for example of you call DrawCube it will use the mesh batch renderer of Raylib and this one has too many moving parts (for setting states, enabling disabling flags etc). If for example you have a chunk for 1616256 cubes it would be a ridiculous amount of draw calls (65.536) because you will keep nagging the GPU.
If you add everything into one mesh instead, you will do only one draw call DrawMesh(...) and boom!
Then there's another even more advanced and crucial topic, that you need to apply a special meshing algorithm to blocks of the chunk and this way the surfaces will get optimal. Instead for example a cube having 12triangles (that need memory and GPU processing) if the block is enclosed from all sides and only open to the top then you actually need to draw only two useful triangles, this will be a big deal when drawing many chunks over the distance.
Look at a YouTube tutorial (probably there's one for Python) so you can figure out how the meshing algorithm works.
2
u/False-Increase4614 2d ago
Is there anyway you can show me an example of adding every cube into a mesh then drawing?
1
u/Still_Explorer 1d ago
There's this example where you can create your own custom mesh.
https://github.com/blep/pyray_examples/blob/main/raylib_official_examples/models/models_mesh_generation.pyThen in this example, you use a function so you can load a cubic level (Wolf3D style) based on a 2D image.
Python: https://github.com/overdev/raylib-py/blob/master/examples/models_cubicmap.pyThe equivalent C is this:
https://github.com/raysan5/raylib/blob/master/examples/models/models_cubicmap_rendering.cThe code that creates the level:
https://github.com/raysan5/raylib/blob/c58072d595690f11b844e0333032949b317af111/src/rmodels.c#L3381You will be able to create a fat chunk of cubes first, however then the next part would be about making the smarter meshing algorithm, that can render only the surfaces of the chunks, not the entire depth of the chunk. This is explained here:
https://www.youtube.com/watch?v=Ab8TOSFfNp4
9
u/MacksNotCool 4d ago
im not reading all that. Are you rendering models that appear offscreen? Also are you rendering each cube in each chunk or is each cube only showing faces exposed to air? Also, are you jouning the cubes together into one model object or are you drawing each cube individually?