#Blockens, my little voxel game/learning project
1296 messages Β· Page 2 of 2 (latest)
is fast, is easy to port, only issue is that you'd need/want the current chunks data padded with neighbor chunk voxel data, so an array of (chunk_size + 2) ^ 3
cosmos (the maintainer) also added vertex pulling stuff, check the branches
i see what you mean here, it's a similar but different idea
you're merging voxels to make bigger voxels and hence make bigger quads
yes
but don't think about the voxels, think about just the surface
there a quad has two dimensions, width and height
yes I was experimenting with this
I hadn't made it work and I already had the existing mesher code and it performed really well
I see what you're saying though
you're currently doing unnecessary computations because: the merged big voxels only produce a mesh on its surface but you still had to sample basically the entire voxel data array
oh how do you avoid that
can recommend checking out binary-greedy-meshing (on phone, too lazy to send you the github link lol)
I will research it thank you
im kind of shushing a few things and brushing them under the table:
simplified, the idea is to use a bitmask of solid/empty voxel data
that way you can
- cull occluded faces very easily and efficiently and
- greedy meshing also becomes very easy and efficient: you can use the bitmask to detect rows of set bits
and only for the set bits do you need to read and compare the voxel data
and im brushing stuff under the table because: you need to construct the bitmask first or have it already
otherwise, yes you do read all the voxel data but it's still in a much nicer linear fashion rather than the 'random' reads you could get by trying to enlarge/merge voxels
but if you ignore constructing the bitmask - you only ever read the voxel data of surface voxels
all other voxels don't contribute a quad to the final mesh and won't have their data read
the bitmask is why my render blocks are 8x8x8
how do you store your chunk data on disk? I literally just have big arrays where the index increments x every index, y every dimension length and z every dimension ^ 2
atm, i dont
im very bad at explaining stuff, i recommend watching "tantan"s latest video on youtube
he explains most of the binary greedy meshing algorithm (tho i don't like his code, the original repo is much better)
fucking amazing
doesnt match ground so its a bit flying lmao
that looks impressive
I might make a bit of a foundation part of the castle
yeh
this is using the same system i use for the trees
it loads a magicavoxel model
and plops it into a location
basically a tree castle π
tho because the castle is a hekin chonker, it uses a fancier system to detect when a world tile overlaps with a "big" structure
this does mean i can do a evil tower
which ill do next because i want an evil tower
yeah I think I might modify the magicavoxel model to make it have a foundation, instead of changing the terrain maybe, or pick location where castle goes, adjust terrain, and then add castle
really neat
evil towers nice
magicavoxel is really mostly a stopgap
it obviously misses a lot of actual game items that need to be setup in the game, think stuff like chest or special block types
what are your ideas for editing the map?
are you going full procgen, some prebaked, math only, edited chunks?
funny looking deccer cubes π
well my game's entire strategy is full customization for everything in game, a large part of the game is a content creator, I'll ship with some default content, but basically anyone can create whatever world they want, can customize their own terrain gen, create their own block types with their own textures, and create their own trees, they're own structures and buildings, their own mobs etc
I'm basically building the tools to build the content to put in the game
so however I do it, the application code needs to follow some type of content creation set of instructions
I do want to have the default game to have cool stuff in it and a game
I think the terrain gen will be pocedurally generated, and then there will be scripts to dump stuff into the world
these are just grand ideas and I really don't know yet, I don't even have trees yet
it would be really cool if someone used my game to make a better game than what I came up with
it's all a pipe dream, I am focused on one problem at a time and working hard to keep hope alive
that I'll keep making progress
I want to build command blocks that allow you to write lua scripts for the command blocks and let you do cool stuff in game
why not zig? π
because I'd have to ship a zig compiler
im going to be hooking lua into this soon
I'm not sure how that would work
need a way to script blocks in a modular way
for custom types and biomes generators and all that stuff
i think ill directly pilfer what factorio does
like this guy https://www.youtube.com/watch?v=U04fG3DHrws
In this video we put together a car engine sound using the Timbre game audio system and then implement it in the game using the Zig programming language. Read more in the development blog at https://www.madrigalgames.com/
godlike
im actually pretty happy with my iteration loop
i have a f5 "reload world" button, and combined with livepp... thats basically it
so my noises and worldgen are hardcoded af and i just reload code and refresh map
i mean worst case you have a button somewhere or press a hotkey and have it reload stuff
I know them, they're active on the zig #game-dev channel :) they're making a really cool game actually
there's no hot reload with zig right now
madrigal tech is amazing
his blender hotreload stuff is incredible
i wonder if i can implemnt something similar with my engine
have an "editor" executable that has no world, only template editing
and then you can modify something and it refreshes in-world
have you seen the jonathan blow engine streams?
of his sokoban game with jai
apart from the jai stuff, there is something i found super cool for the workflow side
first of them is that he has 1 key to load previus/next map, and another key to trigger a replay playthorugh of it. He also has a button that sends him into the "prototype world" where there is 1 of each item in the game, and he can click and edit them there, then come back to the map (where he left off, state is not restarted) and see how it goes
the entire workflow is fast
he's very active on the zig discord #634812978994085888 message :D
that's amazing
he doesnt have a direct hot-reload, but instead has some other trick. Remember Jai compiles his entire game in 2 seconds, so he has a button where the game closes, it compiles the code, and it re-launches where he was before at the exact same point. whole iteration loop takes something like 3 seconds total
I would love hot reload
Hot-reload/live code C and C++ applications.
i use this
its paid but it Just Works and well
absolute must have
looks like you can build a shared library with zig
ah yeah, zig is a clike, so the dll bounds/etc stuff is less dodgy
you can probably do what the machinery dudes did
it's C-ABI compatible yes
can you link the discord? π
i love his stuff too
nope links only work when you are on the server
I think thereβs a few servers that have some preview feature that lets you follow links without being in the server
time to get block editing to work with my new small chunks, then I can remove the old big chunks
so one thing im thinking now (that might be useful to all of you other block people), is to unload the data from cpu while keeping cpu structures around
so, only keep the tiles in memory on an "active radius" around the player, where they also do entity ticking and stuff
but past that, once they generate their gpu structures, drop their cpu side memory and leave them in an unloaded state
Yup makes sense to not hang on to memory not being used
I finally figured out how to do cross context OpenGL so I can have a dedicated graphics thread π
that took a bit of time to figure out
it was a bunch of glfw stuff I didn't know, opengl stuff I didn't know, but this brought it all home https://github.com/glfw/glfw/blob/master/examples/sharing.c
I started with driver panics, seg faults, moved to error mapping buffers, built a dedicated thread system with send and receive channels and now it works and I can make progress again, two day journey of ignorance
still sucks that you have to make the context you want top operate on current
yes
and that is usually a costly operation
I'm not sure how my performance is impacted yet, I just now got it finally working
I don't really have any alternative to this other than move sorting to the GPU I guess
it's just too slow to do on the same thread that I render on
how?
it's pretty naive
how many objects you cull per ms
all my subchunks
a decent system should easily do 100k in 1 core in sub 1 ms
1k*
1k is nothing
ok maybe my culling sucks
yeah
for culling it's just a [8]@Vector(4, f32)
I think it's just a really slow and dumb first attempt at culling
for each subchunk
its strange because vkguide doesnt even try and its like 20k a ms easy
what is vkguide
so 1k being anywhere near slow means something is odd
are you culling on the gpu
cpu
on cpu throught tryharding i once did 300k culls per ms on ps4 shite cpu
a frustum cull should run at whatever your memory bandwidth is
and on pc thats 50 gbs a sec
have you benched it properly?
I just see what it is in tracy
i fail to understand how culling 1000 objects can be slow when even the old godot, which was the absolute worsr impl you can imagine, did 1000 elements in 0.2 ms
try a sampling profiler (or tracy sampling mode) to get per_line info
absolute worst impl is something naive as in aabb vs frustum neh?
ah
3 cache misses per object minimum
I'm sure this is jus a skill issue, and I've embarrased myself
ofc, rather than linked list bs, gotcha
I made it a bit faster by making my culling and sorting logic less dumb and am now attempting to build an aabb structure and that should all help.
it's still pretty naive but it should help
As an aside, early on in my project I was initially calling things up, down, front, back, left right in my data structures. And it always led to mistakes and inconsistencies and hard to understand code and I've since just call things dimension_sign (like x_pos x_neg, y_pos etc) and it's lead to much cleaner and understandable code.
like the surfaces of my voxels, or in chunk traversal code
why an aabb structure? you dont need that @rigid arch
i was still doing bruteforce culling on my super high distance system just fine
you will run out of vram and drawcalls way before you need anything but a for loop over array for culling
I'm switching to the frustum culling algorithm from the rendering book I have https://foundationsofgameenginedev.com/
it's just checking the effective radius of each chunk is less or equal to the dot product of the planes of the frustum and the center point of the chunk
I already did all the aabb tree code yesterday so I'm just going to use it, it's pretty cool, I wrote tests and everything
I have a bunch of books on rendering, and that one is the best one by far
I have another one by the same author but this one is better
I think I'm going to spend some time going through this book and improve my basic understanding
thats a pretty good one
update.. my block renderer with the fancy pixel shader thingy runs like garbage on a steam deck :/
https://github.com/btipling/foundations/blob/main/src/main.zig tis looks funny
you import glfw and glad into "c" namespace so to speak
but you use glfw.xyz and c.glThisAndThat
which is a little weird
from a naming perspective
yeah I was just experimenting with glad, most zig people don't use glad
you have a namespace alias for gl.glThisAndThat at the bottom π
oh
it's importing my gl.zig
right this is kind of inbetween
alot of rs and go and zig people would call that gfx for some reason π
(ive seen that in other people's shit too)
thats the bare minimum
what I'm doing
and if you only use raw glfw/gl thats what i would do too then
is bare minimum
and wrap them into my rhi
yeah
thats actually what i am doing right now π
I just want the straight up C because zig is unstable
and it's such a pain to depend on other people's zig libraries
auto InitializeRhi() -> bool;
auto UnloadRhi() -> void;
auto CreateSampler(const SSamplerDescriptor& samplerDescriptor) -> SSampler;
auto CreateTexture(const SCreateTextureDescriptor& createTextureDescriptor) -> STexture;
auto CreateFramebuffer(const SFramebufferDescriptor& framebufferDescriptor) -> SFramebuffer;
auto ClearFramebuffer(SFramebuffer framebuffer) -> void;
auto DeleteFramebuffer(SFramebuffer framebuffer) -> void;
auto CreateGraphicsPipeline(const SGraphicsPipelineDescriptor& graphicsPipelineDescriptor) -> std::expected<SGraphicsPipeline, std::string>;
auto CreateComputePipeline(const SComputePipelineDescriptor& computePipelineDescriptor) -> std::expected<SComputePipeline, std::string>;
because nobody is really in step with all the constant breaking changes in zig
yeah as long as its unstable its probably best like so
so by using just C deps I avoid all of that
but the danger is that all the other 100 "gamedev" zig people do the same
and you end up having 300 shit libs
I still have to update all my own code with any zig breaking changes, but that's usually easy and if you use the stable 0.12.0 you don't have to worry about it
same in c# ecosystem and npm and anywhere else π unfortunately
yeah
zig-gamedev has a concept of pinned releases
so if it is the only dependency you have you can just always pin your zig to that version but that only works if you only have that as your only dep
the danger is also that a lot of kids and noobs come up with shit which makes no sense
and then people build on top of that : )
zig-gamedev was created by Michal Ziulek who is an experienced person I would say https://github.com/michal-z
yes, that's his new project
ah i also dont mean to make it bad or anything
ah neat
he handed off zig-gamedev to the community
thats what i mean
now everyone adds stuff
quality control is probably 0
dont get me wrong, its like that everywhere and its cool and good that people can contribute like that
do I reuse this thread if I wanted to share anything I make with my new project while this one is on hold?
it's going to take me a bit to get back to my voxel engine
I'll probably rewrite it
it was a learning project and I have learned a lot from it
I don't know, what I'm doing now isn't really interesting to others
I'm going to call that module rhi then instead of gl or gfx, I like that way better as a name, having just looked it up
ah ok thank you
you can rename the thread too if you like, and adjust the first post
really up to you
ah ok thank you, makes sense and appreciate it
I think I'll maybe make a game-dev with zig thread at some point
or something
or new thread and you put a link here
ah
btw I'm not sure I'm a fan of glad in zig because I tried a multi-context build of glad and the zig c-interpret made all the gl functions nullable, so they would require a .? unwrap in zig to call: gl.clear.?(... in addition to the zig-gamedev approach there are also gl generators with loaders written in zig as an alternative to using glad https://github.com/ziglibs/zgl for example
i dont think you really need multi context
and the zig gamedev approach of using the getProcAddress to load directly with zig can be borrowed if you wanted to manually load π
https://github.com/zig-gamedev/zig-gamedev/blob/main/libs/zopengl/src/zopengl.zig#L1001-L1020
requires some comptime fancy stuff and pointer tricks though
does everything HAVE to be comptime
i do the same though, in my c# EngineKit bs, i load glfw dynamically, get its GlfwGetProcAddress to load GL functions π
comptime is pretty cool, it's basically zig's replacement for macros, and allows for some polymorphism
I haven't used it much personally
well when you create an std.ArrayList, which is like zig's version of a cpp vector you define what types are in the arraylist via comptime declaration
it's not macros, zig doesn't have macros
it's like you can use zig at compile time
and during that time you can create types
I'm really new at all of this and the zig discord has a lot of brilliant people
Compile-time parameters is how Zig implements generics. It is compile-time duck typing.
perhaps i should also just try to reimplement what i have right now in ziggorino
yes so like C++ templates
maxes out at 300-400 fps benchmarks, that's what I saw in blockens too
I'm going to create a new community project thread tbh
have you done this? didn't wanna use vma with @cImport and decided to build zig bindings for vma
yeah, I meant to ask about if you used vma rather than specific zig allocator impl*, my bad
what is vma?
vulkan memory allocator
I don't like writing zig bindings for C lib stuff
I just have a single C import file and I import what it imports all over my project
gl is a bit different because I want to build a vulkan backend also
that's currently how I use sdl2, but for vulkan I'm using vulkan-zig, which generates implementations from a xml if I'm not mistaken. so thought having a similar api for vma would be fun
I see, I kind of would like to try and to Vulkan just like I do with GL, but I haven't tried it yet. I just don't like zig bindings. I just want to go read the C/C++ docs/header files and use it just like it's documented