But, if I use twice as many bits, then it means I'm using twice as much memory - which, if I'm also using the fancy lighting methods described here: https://0fps.net/2018/02/21/voxel-lighting/, means using a whole long per cube I want to track lighting for. I can probably save space by not tracking lighting for the insides of solid blocks, but that might still be a lot of memory? :/
Right now I'm thinking about how much data I want to dedicate to lighting. I kinda want my lighting to range from total darkness to blindingly bright. If I do that with just 4 bits per lighting value, it means I need to stretch the 16 possible values over like, twice as much total distance.
Now, what next? Do I keep messing with terrain? Maybe try for continents, via voronoi, or erosion of some sort, or both? Or do I move on to lighting or collision or something for now? :/
I'm trying simplex noise now. I think I mostly understand it, at least so far, though this paper is mentioning hypercubes a lot more than I was expecting it to. XD
Alright, I think I have a much better understanding of perlin noise now, and I cleaned up my perlin and value noise functions a bunch. Still doesn;t quite work the way I want it too - the peaks aren's as high as they should be, specifically, and it's really messy. I'm gonna read up on simplex noise next, and try and implement that, I think.
Fixed it up some, but the resulting values from said perlin noise go negaitve sometimes, which isn't what I want. Brute force fix works okay though I guess? :/
Fixed an issue with the z-direction for the value noise I was using for world gen, allowed for unlimited heightmap generation, and added chunk border display to the debug screen. Now I have to decide what I want to do next for worldgen... :/
Okay, so I fixed the Z-fighting, and I didn't actually have to rewrite that much of the algorithm. I did make it messier though, and it was already pretty messy, so come cleanup is probably in order... :/
Yeah I found the source of the z-fighting - but, it means I gotta rewrite basically my whole mesh optimization algorithm. It was pretty lazy in the beginning, to be honest, but still. :/
Well, think I know where the X-fighting is coming from, now I just need to figure out how to fix it. In the meantime, I went ahead and allowed specifying coverage for a siide - and used that to implement some simple grass, and covered everything in that, instead of moss. looks a bit better, I think. XD
Well, fixed that thing, added a very basic world select and world gen screen, though they don;t actually do much yet, and poked at the shaders some. Now I'm starting to actually mess with world gen. Think I'm gonna start by figuring out how compute shaders work. Wish me well! XD
Well, could use some polishing, but it works! I'll leave it there for now I think. This thing took sooo much effort. But now I know more about FBO's and rendering, so, that's cool at least. XD
Alright, I think I figured it out. It's rendering the bottom left corner of the screen to the texture, and upside down. Kinda obvious in retrospect, but oh well. Now I just need to figure out how to fix it. XD
Okay, so it should be rendering - but, it's not. I've checked everything, too, I swear! The texture is passed to the shader, and it has the right size when it shows up, and should have all the data in it. The thing I want to render to framebuffer will render to the screen just fine. But, it stubbornly refuses to work... :/
Alright, I added unloading chunks as you move away from them, fixed raycasting for looking straight up or down, and now I'm back to working on the block preview. I have it on screen, at least, though it's in the wrong place and it looks like I screwed up drawing the block somehow. :/
It was still failing once you moved out of the origin region though. I fixed that. Of course, now I have an issue with generating and loading chunks, so I gotta fix that now. I think part of the issue here is that I'm curently using like, four different coordinate systems and translating between them. Not quite what I had meant to be doing, but! Live and learn. :X
And now I've added an outline around the block the player is looking at. My raycasting function seems buggy with negative values, I think, so I'll fix that next. XD
Alright, added an fps counter to the debug window, though it only counts off the last frame, and like the first half of a WAILA display, though it uses the raycasting function I mad earlier, which is inconsistent for some reason. :/
Working on the UI stuff. Turns out the friend who's library I'm using already put in a whole UI package, so I'm using that. Had an issue with it, but he helped me figure out how to fix it, and I put in a pull request for the fix, just for practice. XD
Alright, did a ton of code cleanup, and made blocks half as big so that stairs and slabs can be natively represented. Now I need to decide what to do next. I'm thinking either attempting multithreading, for chunk generation and loading, or some UI stuff, including a title screen. Not sure. :/
I created a discord server for the project. It's not nearly ready to be an actual game, but if you're interested, feel free to check it out. If you code with Java, I'd be willing to walk you through how to get it running, and show you how it works. XD
And the world coordinate hashmap exists so that I can afford to have much larger worlds, without running into weird behavior due to unreasonably large coordinate numbers, but maybe I shouldn't worry about that? I dunno, I think i still want to do things that way. :/
Not entirely sure what I want to do about this though. Maybe I should just ditch regions? They might not be necessary. They exist mainly so I don;t have to add every chunk to the world coordinate hashmap, but maybe that's fine and I should actually do it that way. :/
Also, I have like, three different coordinate systems - block position, chunk position, and region position, and I keep needing to translate between them. That's probably a problem. :/
Alright, I have dynamic Region generation working, now I need dynamic chunk generation, and dynamic chunk loading first actually. Hmm. Oh, and I should fix the bug where it generates dirt ceilings. XD
Alright, switched to using a VertexStream. Still lags though - probably need to load fewer chunks at once, and maybe use more than one VertexStream, lol. XD
Okay, now using a whole lot of small VertexStreams instead of one big one. Still lags a little on startup, but only a couple seconds. Gonna work on dynamic terrain generation next. Maybe even try and record a video of it. XD
Well okay, I can dynamically load stuff if I just redo the whole vertexbuffer. But the game lags when I make it do that, so, vertexstream time I think. XD
Yeah I can't dynamically load or unload anything yet, it only works once. Gotta fix that next. Then I think I'm gonna go back and finish working on raycasting for block picking, and implement the UI for that. Then UI in general, I guess? XD
Well, I have a basic raycasting algorithm implemented, and have started debugging it. I think I screwed up somewhere and aimed it sideways though, not sure. I also added another region, and fixed a bug that was making it draw in the wrong place:
Yeah, I'm gonna start with block picking, and a WAILA (What Am I Looking At) interface to go with it. Now, that's mostly just raycasting, so it shouldn't be too hard, but I haven't done raycasting in a while. Wish me luck! XD
Actually, maybe I should leave block data and entities until I actually know what I want to do with them. So, maybe I should focus on implementing stuff so I'd actually want to use metadata. I think for now, that would mean actually allowing interaction with the world - collision detection and block picking (Selecting the block the user is looking directly at), specifically.
Oh, so a friend suggested I use KD Trees to store chunk data, instead of octrees. What do you all think about that? I'm not sure how well I could make it work - it sounds complicated. I should at least be able to hide all that complexity inside the chunks, though, so that's not to bad. :/
I already started implementing this, but at some point I made it lag on startup. Shouldn't be too hard to fix, as I haven't actually added much new data, just changed it's structure, but I'm still trying to get the profiler to work.
Alright, so I changed my mind about block stacking. Rather, I'm just gonna create a new kind of block as necessary, or use block entities, or something. And I'm gonna also track sides - so, if you make a house, and then paint the outside red, the paint is tracked separately from the blocks.
Huh. Do I want to switch over my chunks to tracking blocks by id's first though? Right now it's all java's object references, so I should be able to save space by assigning ints as id's and then looking those up when referenced... But that'd also make the code a bit slower, and I have no idea if it's necessary. Hmm. :/
Anyway, now I just need to clean up the code some and then I'm going to work on block stacking - that is, having multiple different bits of block data in one voxel. So you can stack slabs, or have piles of stuff on a desk, or have a solid block with a crack in it and a layer of dirt on top of that, or the like.
Alright, I got it more or less working. Looks kinda crappy when you have large spreads of a single block, but it'll do for now. Now, I need to figure out what I'm doing next, I guess. Mesh Optimization, maybe? :/
Okay, working on changing up my shader so it blurs things the further away they get, to reduce that weird static you get when things are far away. Problem is, I have no idea how to write a good blur function. Can anyone advise me? This is the relevant file, with my current attempt at the end: https://gitlab.com/AngularAngel/omnicraft/-/blob/master/resources/dirt_shader.frag
Gonna just try making things blur at long distances, see where that gets me. Haven't finished implementing it yet though. And, it turns out my randomization function has a few weird artifacts:
Still working on polishing up my shaders. Gotta add the dynamic shader equivalent of mipmapping, I think - the textures dissolve into static at long distances, at the moment. :/
Alright, now we're drawing with the right substances! And via rendering all the different pallettes to a texture and sampling that texture, no less. Not Bad! XD
Alright, I have the colors I want! Now I need to actually pass the positions of the actual blocks, and to draw them all. Still not entirely sure how to do this - do I make each block type it's own data structure, or do I pack them all into one? The second will be more difficult, but will likely come with some real savings... I dunno, I'll have to see. :/
Alright, ripped out my old code for generating colors and textures. Lot of code, but it was all kinda meh anyway, and I need to make space for something new. Now to decide exactly what I want to do for generating textures. My old implementation for picking colors for the various bits of a texture was ennecessarily complicated, but I still want to do something similar... :/
Just ripped out all the old drawing code. Trying to decide whether or not to change my old method of generating textures - it's not super shader friendly, I think, nor very good overall. But of course, how would I redo things...? Hmmm. :/
Well, I've got a whole cube, but I don;t like my current implementation -it uses a separate vertexbuffer for every different texture, which is no good. Actually gonna look at ditching saved textures entirely and moving to wholly procedural textures, using fancy shader business? I dunno, not sure. I'ma try it and see how it goes. XD
Alright, think I'm done with coords and regions for now. Time to finally take a crack at that graphics pipeline I've been talking about. My friend put up some examples of how to do the kind of thing, so now I just need to look through them. Wish me luck! XD
Alright, so my friend suggested just using coordinates for the chunks, and then making a hashmap - which is much simpler. And I should be able to just extend the numbers for the chunk coordinates as much as I need? I dunno, I'll think about it. :/
Maybe extending the coordinate numbers as necessary, and only using them for tracking region coordinates? So, it shouldn't cause slowdown for players, only when it needs to check region coordinates to ensure proper map knitting, and that should be pretty minor. :/
No, octrees all the way up has the same issue with limitations on the size of the coordinate numbers. I guess maaaybe there's a clever solution with a good search algorithm or some method of data storing? Or some way of just extending the coordinate numbers as necessary, though that sounds like it would cause problems once people start actually playing way out in those extended far reaches. Or I just need to give up on a truly infinite world. :/
So, I need to think about this. Maybe said map searching algorithm wouldn't be too bad? There are some pretty efficient search algorithms, I think, though it could still get pretty gnarly. I was also considering just going octree all the way up - not entirely sure that will work properly, though. I mean, I guess I could just give up on having a truly infinite world, subject only to hardware limitations? Just doing a few million blocks like minecraft does is /probably/ sufficient. :/
Either they pass through each other intangibly (Bad!) or you need a monstrous algorithm that searches, like, the entire map (Bad? I think?), or you need a global positioning system. (Which will eventually run into limits on number size, which is what I was trying to avoid in the first place.) :/
So, say one person starts at spawn and goes way north, and then west? So far no problem - you have a trail of regions going way north, and then west, linking to each other. Then suppose that person dies and respawns at spawn - and this time, they go way west, and then north. So you end up with another trail of regions going west, and then north - and then what happens where these two trails intersect?
Lol no, I lied, I need to rethink my Region code entirely. See, I was gonna have regions refer to each other linked list style, and just create new ones at the edge as needed - but there's a problem.
Alright, think I'm mostly done sorting out regions and hunting down the last of their bugs, at least for now. Got interior culling working between chunks and everything. Maybe a bit of code hygiene, and then it's time to finally tackle that graphics pipeline. XD
Been working on a bunch of structural stuff, nothing that makes for a good screenshot though. Still need to rework the graphics pipeline. I'm looking forward to doing trees - I hope to do some kind of fancy cellular automata to make them grow really nice. Want to do more detail than minecraft does, too - Like, have logs, and then branches, and then maybe twigs, and then maybe leaves? I dunno - I'll figure it out. XD
Added proper Regions today, my method of working with multiple chunks at once. Now I need to work on that proper graphics pileline, as it lags HARD if I try and render so much as a region of empty space. XD
Alright, implemented some basic interior culling. Now I need to figure out the larger world structure beyond just chunks, and then sort out a better graphics pipeline, I think. :/
Alright, so the textures could still use some work, but they're better. I'll leave them for now and work on some other stuff. Gonna work on cleaning up the code and improving efficiency. Anybody who wants to help, it'd be appreciated! XD
Like, so that you can have tables and desks covered by all sorts of stuff, or fancy woodwork with support beams and platforms, or implement a variety of different kinds of walls, and then have a bunch of different modifers - moss, cracks, scratches, crumbling bricks, bloodstains, etc, etc, and implement each of those individually, and then stack them on top of the different kinds of walls.
Still haven't got procedural textures working to my satisfaction, I got distracted trying to figure out how to render shaders to textures. I might go back and take another crack at that, or maybe just move on. Right now I'm thinking about blocks, and whether I want to implement some kind of multipart functionality?
Alright, so now I'm messing around with procedurally generated dirt textures (And eventually other textures, hopefully.) Making some progress but it needs a bit more work, I think. Code needs to be cleaned up and rewritten too. Probably looking at generating most things more like the lower left corner, obv.
Not as neat as the Octrees, but more visually noticeable - now some of the blocks are slightly bluish. Internet points to anyone who checks the code to figure out why. XD
The code where it splits HomogenousChunks into OctreeChunks is particularly meh - I'ma need to do some optimization there, I think. It has a lot of unnecessary creating and then destroying of chunks. :/
Though, I guess at some point in my Octree I'm going to want to HomogenousChunks or whatever, even if they're 2^3 or 4^3 blocks. And I will need the capability to go and dynamically replace these with more octrees if a player goes and starts messing with them, right?
But, hmm. Okay. So, say I've got a solid 16^3 chunk of all one block. Should I just represent this as HomogenousChunk(block)? And, then if, say, 0,0,0 gets changed into another block, should I have a method go and replace that HomogenousChunk with an octree chunk and work it's way down the nodes? Or is this an attempt to over optimize, and I should just load it as an Octree from the start, and only worry about try to optimize to that level when I'm saving to disk?
Alright, so now I'm looking at implementing Octrees for tracking block chunks. I get the general idea, but I have a feeling the details are going to be trickier. I dunno, I'll write an implementation and then see iabout going back and changing it if necessary. :/
Not a lot to show off today, but I did some stuff behind the scenes, and now I have code for SteppedCube shapes and textures - basically, a 16x16x16 block, except missing some texels of height. See below a whole chunk of the 12 high ones.
Hmm... I think I want to have render data, behavior data, and collision data all be separate class heirarchies, and then have BlockTypes that have references to each of these three things. Then, for the actual world, I have ID's for each of these block types, and maybe also store metadata if necessary? I'll have to experiment a bit to get all that working well, I think.
Maybe I should store material and shape separately? Or even material, shape, and orientation? Or, maybe I should just look up how minecraft tracks the orientation of stairs? I think they use a different system. Aaargh, I'm not even sure how to gauge the effectiveness or costs of all these options. :/
The downside of all this is I'm probably going to end up with a tremendous variety of blocks, which could pose issues on the data storage front. Like, if I have, say, a couple hundred varieties of stone and soil, and then I have varients of this for each of the 15 levels of flat, plus the 6 possible half slabs, plus the 8 possible normal stairs, the 8 quarter stairs, the 8 corners, the 8 quarter blocks... We get a lot of block types. And that's not even getting into plants, furniture, etc, etc.
Or, no, actually before I do chunks I should decide how I want to deal with the data for blocks. I want to have most, or maybe even all, blocks be procedurally generated - something like Chisels & bits, except a bit more restrictive and easier to deal with. Like, there are different kinds of soil and rock, and these are procedurally generated, and then there's a process for digging up stone and turning it into bricks and the like.
Super tempted to make my own minecraft. Write in the functionality of all my favorite mods from the start, make everything super detailed, exactly the way I want it. I'd probably never finish, but it could be fun. XD