• C Coolcoder360

    I guess there's this Gruedorf thing, may as well participate and hopefully have motivation/accountability on this project.
    I'm not working on a game yet, just a game engine that I have code named "Nebula 3" which is my 3rd complete re-write that I've named Nebula, probably my 10th rewrite of a game engine in total, over the course of something like 7 years or so, but this one is the final rewrite I'm sure.

    Basically Nebula 3 is a 3D game engine that uses an ECS(Entity Component System) under the hood this time, which I got pre-canned in the form of Flecs. Flecs lets me focus less on how to store objects in the world and more on functionality, which is great because all my previous iterations had 3d functionality working, but not a very good method of storing entities in the world.

    Currently in addition to the ECS, I have Lua scripting working, and I've implemented a basic OpenGL renderer for now, and I even have input binding, and text input working. With a working console even.
    There is a separate rendering and update loops, with all Lua calls for the input being handled in the Update loop due to some quirks with the ECS system not liking things changing while it is running the systems.
    In addition, Unicode support is a thing that actually sort of works too, character input is given as UTF-32, converted to UTF-8, then back to UTF-32 to render the text, tested with Japanese, only issue is switching fonts to support the characters needed.

    I can't show any screenshots as I found out that for some reason my full screen OpenGL window doesn't show up in screenshots, so I guess I'll need to implement in engine screenshotting capabilities, which was already planned, just moves the timeline up a bit.

    Plus before the screenshots can be captured, I have another segfault to deal with, this time I believe caused by attempting to load things onto the GPU in the update thread, I need to queue items that need to be loaded to the GPU to be done on the render thread instead of the update thread. This was caused by re-arranging things to be done completely from Lua scripts instead of hardcoded C++.

    Next steps include: fixing above mentioned bugs, working further on UI elements, and porting over old 3d rendering and model loading code from older projects,

    The UI is planned to be "done" with an in-engine editor in a working state by the end of March 2021. With an in-engine console with console commands counting as an editor.

    posted in Blogs read more
  • C Coolcoder360

    So in-between when I wrote that post and now, I've fixed my crashing, split the textures and fonts to load the data in the update thread, but load the textures to the GPU in the render thread, and added screenshot functionality to my engine.

    So behold, I have an FPS counter which keeps track of how often the render thread runs per second, as well as a TPS (Ticks Per Second) counter which counts how often the update thread runs per second, locked at about 60TPS.
    Also I have a console that has working text input.
    Screemshoot_02-09-2021_2233.png

    I promise the texture rendering works too, I just was too excited from getting both my crashing issue and the new screenshot feature working that I decided I didn't feel like throwing a texture in there.
    I'd say today has been a productive day 😄
    Maybe next week I'll have buttons and graphics to show off more of.

    posted in Blogs read more
  • C Coolcoder360

    Missed a couple weeks, been busy with life things.

    So far I decided to kind of temporarily scrap the schedule I had for my game engine, and just go forth and add in the 3d stuff right away instead of waiting, since that seemed a little bit more interesting than just doing lua bindings. So I ported all the mesh/model loading stuff I had from a previous iteration, then realized I need to add lua bindings for that too now....

    I've added in the components to how I think I want to put meshes and models into my ECS, but I have not touched rendering stuff just yet, since well I want the lua scripts to be able to add the meshes/models to the scene, so the lua bindings must happen first.
    In a week or two when I get around to finishing the lua bindings then I'll have the fun task of testing all these lua bindings I've been adding, and fixing all the bugs that will inevitably spring forth.

    Hopefully at that point I'll be able to make a demo/test showing off the UI buttons which are yet to be tested, as well as the 3d model rendering.
    I know the loading works from my previous iteration, I basically copy pasted the code from there.

    For the model loading I use Assimp, which allows loading of pretty much any common format that I would want to use, along with loading in the animations. I haven't bothered tackling animations yet in this iteration or any previous iteration, the skinning is a bit complicated for a first go, and I'll need a way to keep track of animation frames/keyframes to play it back, so that's very much an in progress thing.

    posted in Blogs read more
  • C Coolcoder360

    Bout time for another update I think.
    So I got the 3d movement and spawn/exit location picking working ish just after the last post, so now you can see what it'll look like in game:
    screenshot000.png

    Yes movement works.

    Then I also made the map look much better too with map zoom and scrolling buttons:
    screenshot001.png

    The reason I say the entry/exit location picking works-ish is because I'm not really satisfied with the location selection, basically right now it just chooses the tile, then loops through the tile to select the nearest "open" square, it does this because I didn't bother to have it track which tiles have the spawn/exit values in them, so right now it'll end up putting the player and the exit into the middle of a hallway.

    You can see the player as the yellow circle on the above map, and the exit as the blue square.

    I've thought about potentially having the map track/only update if you've seen an area, but that seems like potentially scope creep I don't know that I care for, so I'll probably look into that after I get enemies and combat working, since that's like the next things required to make this actually be a game.

    I think next time I'll try to have more UI figured out, not sure I'll do inventory, but at least the scrolling text showing what happened, or what is going on would be nice to have so I can potentially have debug printing in there instead of to console.

    I may also see if I can set up a jenkins job to build this as well, since I already have a jenkins semi-working on my laptop, it has bad uptime, but if it works to build Linux, no problems there, then I might take a break from dev on this project to work on making a docker image to build windows builds from linux, which would be helpful so I can just press buttons to get both builds of this project. Since I plan on chunking this project out commercially prior to finishing up my game engine project.

    posted in Blogs read more
  • C Coolcoder360

    I did some more lua bindings and added some console commands to my game engine, however that's a bit less than exciting and I'm a bit less than excited about that.
    So Instead of doing a lot of work on that and making good progress, I decided to forget about the rigorous schedule I had for that, and pick up and old project I had started in Godot.

    I also don't have much to mention on this other godot project, I spent most of a day going through some asset packs I have trying to find assets to help with the game.
    It's planned to be a mobile idle type game, where you have units that attack a boss, and the boss gradually gets higher and higher level, so your units needs to also get higher and higher level.

    I do have a basic mockup of what it will look like for now:
    Capture.PNG

    I have yet to get any boss art made, and I'm planning to use some art from some asset packs I have for the units to make things simpler.
    I'm hoping to do pixel art for the bosses, but I'm not used to doing pixel art at the size that I want the boss to be, so I might need to get creative. I'm a bit more used to making 16x16 or 32x32 pixel art.

    My main goal for this game is to learn more about Godot in preparation for Godot 4.0, at which point I may just drop my own game engine entirely and switch to Godot. I specifically want to learn more about customizing the look and feel of the UI, as well as learn about saving and loading save games.

    I'm also expecting to end up missing Gruedorf next week, I'll probably post an update the week after, and hopefully have something significant.

    posted in Blogs read more
  • C Coolcoder360

    Admittedly I don't really have much new progress in terms of anything being completed, but I have started on a couple different items, one being build version numbers, including a version specified from Jenkins, the other being getting started on lighting.

    For build versions I'm not entirely sure how I want to do it yet, I'll probably have it be where a prefix is hardcoded in the repo (like 0.1.0.), that way each branch can have a different version number, and then append the jenkins job number and maybe a suffix depending on what kind of build it is (ie if its release/beta/debug/test/whatever, potentially with a different suffix if its a steam build or some special build like that.)

    This method of having a prefix hardcoded in the repo does mean that I'll need to remember to update it every time I bump the version number, either when I branch, update trunk, or when I tag a release, update trunk, but it is how we do it at my work currently and I don't want to have to pass it into Jenkins, because I want the local builds to retain that number so you can tell what branch a local build was on.

    The idea is that I'd get a version number from jenkins builds of prefix+job number+ suffix, like 1.1.0.799_beta or something like that, and then if I made a local build it'd be something like prefix+builduser+date+suffix like 1.1.0.coder2021621_debug so you can tell what branch/version tag you're at, as well as the build date and that its a debug build.
    I haven't yet decided on the suffixes but I'll probably do that after I get the jenkins/CMake all set up to put in the build numbers.

    For the lighting work I'm planning to do a full PBR renderer, which means I'm now at the point of figuring out IBL (Image Based Lighting). I already have/had point lights implemented for my PBR renderer but no IBL yet, and apparently you need to have your lights have area in order to make it realistic, so I'm currently doing a ton of research on how to do all of this and I'm not even sure how to store the info needed for an area light, or what info is needed.

    LearnOpenGL has a decent tutorial and sample code on getting started with IBL, however it only covers having a single global probe/HDRI environment map, which basically means you only get IBL from from the skybox. In order to make your environment look realistic with IBL, you need to set up local probes, which of course isn't taught in that tutorial.

    The basic process for local probes is to capture from all directions at an artist/level maker designated point, and then blend that with other probes and the environment map. Issues to this include: how often to update local probes, since dynamic objects will need them to be updated regularly, also how to actually pass the probes to the shader. I think I get in theory how to blend the probes together a little bit, basically by having an alpha in the local probes that cuts off at a certain distance, so where there's alpha 1 you use local probe, alpha 0 use other probes. And then there's some fancy business you can do with blending the probes, or just take the closest probe's input.

    Once I get IBL working with probes, it'll basically put me at early UE 4 levels of lighting, I have realtime global illumination planned for later on, I've been debating if it'd be better to just do that and skip out on this probe nonsense but I am worried about how to handle things for lower end hardware, and it is my belief that I could pre-bake the local probes with non-dynamic objects and it may be acceptable for lower end hardware to simply not reflect dynamic objects, or just supplement with SSR (Screen Space Reflections) somehow, but of course that would probably involve more blending madness.

    Also I'm nearing what I wanted for my 0.0.1 milestone, all that remains is engine build versioning, 3d lighting, some more editor console commands stuff, and scene saving/loading which I have yet to start. Once I get all the features implemented I'll probably try to make some sort of simple game to test it all out since I haven't tested half of it yet, I'm thinking breakout clone.

    I did have a schedule planned for when I wanted the 0.0.1 milestone complete, which was like 3 months ago, but I pulled things into it from 0.0.2 milestone, like a lot of the 3d stuff got moved because it was more fun than other things, so I'm basically planning to just skip/ignore the schedule for now and go with the flow.

    posted in Blogs read more
  • C Coolcoder360

    Gonna update here again since I fixed it:
    Screemshoot_08-07-2021_082536.png

    So the answer to the problem was in how I was transferring data between my update and render threads, I had used the shaders before without issue so I wasn't sure how it was not working.

    See I send data between threads via loading up a RenderState with all the data needed to render meshes, etc. Well I added lights to that rather sloppily and forgot to add a line to clear out any lights added to the data, so the number of lights in the RenderState increased every frame, and apparently when you get hundreds to thousands of lights added in the same spot, it did that weird thing I was seeing before.

    Part of what tipped me off is also that after maybe a minute or less the FPS would start dropping to nearly zero, and I figured it had to be something that was increasing or something every frame, and sure enough it was this leak causing the FPS drops as well as the rendering issue.

    Problem Solved!

    Now I'm thinking I'll put IBL off to a different release, so I split off that to a different story, as well as spotlights, I'm going to leave "3d lighting" at point lights and wrap this up, so only scene saving/loading and version numbering remain, version numbering is part finished and just needs some Jenkins love and it should be finished. So close to the first milestone I wanted!

    posted in Blogs read more
  • C Coolcoder360

    Some progress on versioning but I don't think its totally finished yet, still want to take the version number and put it into the filename of the zip file that Jenkins spits out.

    But on the saving/loading scenes front I've gotten a bit of progress, I chose a json library to use to save things out to json and started writing code.

    Not sure yet if I like how the code is shaping up, but right now it makes most sense to me to have separate code paths for each scene saving/loading format, however I'm not sure I like that I have the separate formats in the SceneLoader specific code itself, or if I should have split it off to a separate utility to handle the specifics and I just broke the pieces up into different parts, so I'm sort of split on that since I suspect I"ll need to do the same shit for serializing other things should I need to do that, so we'll see how that goes.

    I chose the Pico Json library for doing the json, it's a single header file json library, so easy to integrate and the API doesn't seem to be too much pain to use.

    Basically I just use a picojson::value() to refer to a value, and if I want that value to be a JSON object I just make it be a std::map<std::string, picojson::value> and if I want an array, its a std::vector<picojson::value>. This is nice because then I can just make maps and vectors as normal and it works, only issue is constantly wrapping everything with the picojson::value and I don't tend to do the using C++ thing to use namespaces, so I type every little std:: or picojson:: out, and that seems like it'll get to be a lot of duplicate typing, since I'm basically looking at having each entity be one JSON object, with keys for each component in my ECS, and then each component is also a JSON object, which keys for its values, which are sometimes also JSON objects.

    And there'll be arrays thrown in there in some places too 😛

    But yeah so that's my progress, started on Scene Saving and chose a json library. now the boredom of typing out code to save/load every single component. and then I get to do that shit twice when I add the binary save/load.

    Maybe I should get an intern. Or come up with a better way to serialize this stuff.

    posted in Blogs read more
  • C Coolcoder360

    well I guess it's about a week-ish since my last post, and for consistency I should probably post again.

    Not much to talk about on the game engine front, been writing boring json saving/loading code as per usual.

    But I started a new project! hopefully it won't turn out like the last time I mentioned starting a new project in Godot and then stopped working on it pretty much that same week.

    I've been playing a ton of Tales of the Neon Sea lately, got it free on Epic and boy is that a fun game. It's got some very beautiful pixel art, and it's a story based detective/mystery solving game, with all sorts of puzzles and such. it kind of reminds me of a point and click game, but it's also a side-scroller, and has some really slick pixel art and pixel animations.

    I don't consider myself good at pixel art, I consider myself passable at it. But combine that with being reminded that pixel art in 3d with modern effects looks super cool, and being also passable at 3d modeling, I'm now in the process of throwing pixel art into 3d scenes in Godot and hoping it sticks.

    This is one of those projects where I start diving into art first instead of any planning or story, which means its bound to die within a few eons, especially since I'm currently in the process of hand making normal maps for some of my tiles. Very tedious stuff, and I have no way of knowing if it'll look cool or not.

    On the front of making the pixel art go into 3d, I'm not entirely sure on the method I want to use, Godot does support just straight Sprite3D objects, which is basically a 2d sprite rendered in 3d space, and they can be animated like 2d sprites, and have the option to be billboarded. However there's also this pretty slick addon for Blender I found called Sprytile which is free. Sprytile isn't like, always the easiest to use or the fastest most intuitive, but it does let you make 3d models with pixel perfect textures, either applying the textures onto a pre-made model, or making models with the textures, and it supports tilesets. so you can basically make a regular old tileset, and then map that into 3d.

    i'm hoping to combine that with hand drawn normal and roughness maps in Godot, to make some PBR-ish pixel art so I can do some cool 3d lighting and GI effects to hide the fact that my pixel art is bad.

    So far I haven't done much, but here's a quick peek at what I've got with a mostly default Godot scene, and a couple Pixel art assets:
    Screenshot_2021-09-08_12-27-48.png
    Both the pixel art assets are Sprite3D for now, and the floor is just a CSGBox for now, with a very reflective surface on it to show off the SSR. I'd put some reflection probes in but I've found they are kind of shitty for a direct mirror finish like this and work better with more uneven surfaces.

    I think the plan for if I ever make a character for this is to make a 3d model and render it out as pixel art in Blender, but for now I'll probably just use a box as the character and try to get some type of gameplay down. I'm hoping that with more of a point and click type interaction it should be simpler to do, maybe some side scrolling segments too, but hopefully I can get some kind of gameplay that consists of interacting with items, and maybe popping up panels to interact with for like, minigame type puzzles.

    I think once I get a basic prototype with working gameplay, it'll be easier to continue from there and come up with art and story once that's there. That way hopefully instead of having scope creep from making a massive story and then burning myself out on having too many potential coding features, I'll be able to go the other way, do the coding and add the features/puzzles or the ability to have puzzles and do interactions, and then I can do the story writing and actual game design stuff once I have features that sort of work, I think/hope that workflow will let me not get super burnt out, or at least I can call it quits sooner based on being bored of the mechanics themselves, instead of being bored of making art.

    posted in Blogs read more
  • C Coolcoder360

    Yeah I decided not to do the mystery/detective/story based game for the crunchless challenge, because I'm not fast enough at writing to be able to write a story between now and november to implement.

    So instead I decided to go with a dungeon crawler roguelike idea, basically inspired by Nethack and Ultima Underworld.
    I figure if I can get world gen working then I can just make a crap ton of tiles and basic combat and boom there I go.

    Also decided to use Raylib for this project, which I'd never used before, and I accidentally slipped yesterday and basically got a whole main menu, character creation screens all done, and some basic character stat generation working, although I haven't figured out how to have the RPG combat work yet so I might need to rehash that at some point.

    Working on doing the map gen now, basically I plan for it to be done using Wang tiles, I would do herringbone wang tiles but having never done wang tiles before I think it's better to start off with basic square tiles and go from there.

    Here have some screenshots of what I got together after work yesterday:
    screenshot000.png
    screenshot001.png
    screenshot002.png
    screenshot003.png

    Maybe the only thing I need to update/change, is that the main menu uses keyboard input only to select the options, and everything else is mouse only, so I need to figure out how to allow both keyboard + mouse for everything, but tbh maybe going mouse for most things makes more sense.

    posted in Blogs read more
  • C Coolcoder360

    And consider the random walk method of improving connectivity and ensuring more of the map is connected to the rest working!
    screenshot000.png

    Much better connectivity and much better variety in terms of which direction the halls cross each other.
    One caveat to this is that if no tile is found, then the default tile with no connections is used, that might be a problem since that can block off paths that may be wanted. Not sure if I want to make the default wang tile be completely connected or not, but that would prevent any blockages for sure, so then at least if spawn and stairway down are both on the random walk, then they will be connected.

    I also have 3d rendering working for floors/walls, but not really any of the other tile types.
    Issue is that I haven't done the player spawning yet, so you just spawn in the wall at 0,0, and can't move out of there.

    posted in Blogs read more
  • C Coolcoder360

    Well here we are, the end of November. I 1000% got distracted by other things instead of working on the roguelike for the crunchless challenge thing I was trying to do. But hey I didn't crunch on anything so i succeeded on the crunchless part of it! I just didn't do much of anything programming or game dev related.

    My 3d printer came in and I got distracted and now have another new project: I'm making a redox split keyboard with Kailh box jade switches. Parts are all on order and arrive in January, printing the case and the keycaps myself, so far the two test keycaps I made feel okay to me, but I don't have any other box switches to test fit them with so I need to wait until january when they arrive to test fit them to make sure that they will work.

    Back to the Game engine project

    Yeah I went back to working on my game engine project again. Still trying to get scene saving/loading working, still using json for that, and currently bored of writing save/load logic so will likely keep saving json until either I run into it taking up too much memory/space, or it takes too long to load when needed. I think lazy route is best for getting anything actually finished/shipped.

    So basically I'm stuck on writing out how to convert a bunch of different components that an entity might have to JSON, and then I eventually need to write the code to load all that back in too, which I don't think is even started yet.

    But it has been a while since I provided screenshots, and I was super close to getting json output actually, so here have some screenshots of me showing me typing a console command to save an entity, and then let me show some json that was generated from the Entity that was saved.

    Screenshot first:
    Screemshoot_11-29-2021_223413.png

    And a screenshot showing the feedback you get from running the command, I know it's not much feedback but its something:
    Screemshoot_11-29-2021_223416.png

    And now check out the json generated for the cube you see in the screenshot, in a file called "MeshEntity.json"

     {"EcsName":{"value":"MeshEntity"},"TransformComponent":{"position":{"x":0,"y    ":0,"z":0},"rotation":{"w":0,"x":0,"y":0,"z":0},"scale":1},"VisibleComponent    ":{"opaque":true,"visible":true}}
    
    

    I haven't fully figured out how I want to save Mesh components yet, part of the issue is with this specific case, I don't have a RUID/path to just store to a model, that mesh is generated in Lua, which means that if I wanted to store it I would likely have to parse/store out the entire freaking mesh into the json, including vert data, face data, texcoord data, and maybe vert color data, and texture data somehow since the texture is handled by being a material set to the mesh.

    So I'm so close yet so far. I'm hoping that if I set up model loading from files, that I can make it easier to save that out to json, and then either just won't save programmically generated meshes, or something. idk yet.

    I also have a few other components not implemented yet, and loading hasn't been touched at all, neither is saving the children of the entity selected to save. But still this is good progress!

    posted in Blogs read more
  • C Coolcoder360

    Well Cereal has been a bit more of a pain than I expected, the examples make it all look easy, you just do something like the following:

    template<class Archive>
    void serialize(Archive & ar, NameComponent & ncomp){
        ar(ncomp.string);
    }
    

    And then now that component can be saved and loaded, with some extra setup crap of course, but that's how its supposed to work.

    Well, I do that, but there's little info on if you put it in the header or in your cpp file, or what, so I've tried a few combinations and keep getting some errors that look like this:

    Error: static assertion failed: cereal could not find any output serialization functions for the provided type and archive combination. 
    
     Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). 
     Serialize functions generally have the following signature: 
    
     template<class Archive> 
       void serialize(Archive & ar) 
       { 
         ar( member1, member2, member3 ); 
       } 
    

    And in fact it's longer than that, and this is repeated multiple times too. So now I've tried doing some combination of crap like this:

    269 template<class Archive>
    270 void serialize(Archive & ar, TransformComponent &tcomp){
    271     ar(tcomp.position.x, tcomp.position.y, tcomp.position.z);
    272     ar(tcomp.rotation.x, tcomp.rotation.y, tcomp.rotation.z, tcomp.rotation.w);
    273     ar(tcomp.scale);
    274 }
    275 template<>
    276 void serialize<cereal::JSONOutputArchive>(cereal::JSONOutputArchive & ar, TransformComponent &tcomp){
    277     ar(tcomp.position.x, tcomp.position.y, tcomp.position.z);
    278     ar(tcomp.rotation.x, tcomp.rotation.y, tcomp.rotation.z, tcomp.rotation.w);
    279     ar(tcomp.scale);
    280 }
    281 template<>
    282 void serialize<cereal::JSONInputArchive>(cereal::JSONInputArchive & ar, TransformComponent &tcomp){
    283     ar(tcomp.position.x, tcomp.position.y, tcomp.position.z);
    284     ar(tcomp.rotation.x, tcomp.rotation.y, tcomp.rotation.z, tcomp.rotation.w);
    285     ar(tcomp.scale);
    286 }
    

    And I think that kind of fixes some of it? but that's not what the docs say you can do, that's not how the EnTT serialization example does it, and it's specific to outputting to JSON, so if I want to switch what format I output to, since Cereal bakes in JSON, XML, and Binary outputting, then I'd have to rewrite the same function 2x for each additional format. Not an ideal situation.

    I suspect the answer is that either its a quirk of templates that I always forget about, to where you have to have the template stuff be either only in the cpp or only in the header, (And it doesn't help I'm doing this all in a single header, where I use defines to compile the "cpp" part of it, stb header style, so that means it's easy to confuse myself in which section I'm putting it into) or it's to do with the Cereal supporting C++ 11 but I'm compiling against C++ 17 and something changed.

    In other news, I'm doing Cereal a little bit non-mainstream. Basically the library writes to streams, so you would usually do an ifstream to input a file directly, or an ofstream to output to a file directly. That doesn't fit in with how I planned things, to where I want everything File/FS related to be handled by my FSManager so that I could possibly be loading stuff from a zipped archive or something else entirely instead of just files straight on the disk. So I needed to figure out how to get it to write to/read from memory so that the underlying file/whatever doesn't actually matter. stringstream is okay for that, if you need to write strings, but what if you want to write binary streams to memory instead of to a file?

    Well I found spanstream! A feature that is part of the C++ 23 standard... which isn't released/supported yet... So now I know how to implement binary save/load to memory later, for now I guess I'm just using stringstream but there are a few issues with that I think, specifically that I'm not sure how Cereal would deal with endianess, etc etc. Suppose that's a battle for another day...

    Plus I'm sure I won't really have much of anything actually implemented using this engine until like 2023 or 2024 anyways, so it's likely that the C++23 standard would be out by the time I'm ready to release anything 😛

    ECS switch progress

    The good news though on progress with converting to EnTT is that I sort of have the hierarchy stuff figured out, the only iffy part is really in deleting the children of children when you remove an entity, I haven't written it to traverse down the tree that far, and I'm not doing recursion on that part because of simplicity, and laziness.

    Maybe I'll do the traversal farther down the tree at a later time, but I'm not really expecting to have many cases of children of children, but I suppose I should allow it to delete them eventually. Most likely I'll want it all to be flat/in loops instead of recursive though, recursion just seems like a bad idea if you're trying to be portable to a bunch of different platforms because it's hard to say if there will be enough space for all the stack frames needed, and you can potentially loop infinitely but good luck recursing infinitely.

    Also another issue though is that this deletion all happens in the Update Thread, so it will basically hold up updating anything until it finishes, so I think not letting it get caught in a loop is likely a good idea, and for now I can just be careful about not having things nested more than one layer that will need to be deleted.

    Summary/Next Steps

    So I'm basically at the same place I was at with Flecs already, just struggling through saving/loading again/still. Just with a different type of struggle, but I think this struggle is worth it, because being able to save/load from 3 types at once is far better than the previous single type i had of just json.

    After I finish off the serialization crap I basically just need to test it, which I've been keeping the lua bindings updates for all this so it should be EZ PZ to just get in game, send some commands and such in the console to add some stuff, then save it out, then remove the entities I added, and load them back and make sure they're still there.

    Then after that I'll be pretty much done with my 0.0.1 milestone. Next would be my 0.0.2 milestone, I'll probably need to update the Quire a bit but it basically consists of implementing saving/loading assets/scene data from archives, creating those archives (Since I'm planning to implement all editing in engine, this also has the added benefit of basically being able to bundle world editing/map making/modding tools in game, it's not laziness of not wanting to make a separate editor, its a feature!)

    Then beyond that for the 0.0.2 milestone is basic audio features implemented with miniaudio which I think now has a high level API which does 3d spatial audio if I read the docs correctly, not sure if I'll do that or just use the low level API as planned previously.

    posted in Blogs read more
  • C Coolcoder360

    Well I've been trying to do Cereal, but here's kind of the issue, I follow the tutorials but it doesn't work for me, I can't get it to compile because it's for whatever reason not able to find the serialization functions I've written, unless I specialize each of the functions as I mentioned before, where I re-write the same thing for every combination of input and output that I want to do.

    To me that means I'd rather just write the serialization stuff myself to do Json, XMl, Binary, whatever I want to do rather than try to get Cereal to work the way its supposed to.

    Additionally, I found this issue which basically says that Cereal doesn't work right in a recent version of clang, but they were able to work around it by uncommenting some asserts. I use g++ with cmake, but I figured what the heck, I'll go uncomment the asserts that are causing failures too. That let's it compile! but then I just get this for the json output:

      1 {
      2     "value0": "NameComponent",
      3     "value1": {},
      4     "value2": "TransformComponent",
      5     "value3": {},
      6     "value4": "EntityEnd"
    ~                               
    

    And what I didn't even notice until now, I don't even have the closing } in there. So in my mind, Cereal is out of the competition now, if you can get it to work with your compiler, great, but for me, I don't think having XMl, Json, and Binary support if I want to write the same thing 6 times is enough for me to use it.

    So I'm planning to go back to the picojson, however this time i'm going to try to not do it the dumb dumb way, and I'll write serialization methods for types, that way I can have less struggle of writing everything out the long way. This does mean I'm still re-writing my serialization stuff I had before, even though I kept what I had before, but I think my hope is that this means that I can more easily use the serialization again elsewhere if needed, so I could serialize things like settings, configuration, input mappings, etc hopefully more easily in the future.

    So right now the plan is to basically make a SerDes abstract class, which I would then use as a base for having a JsonSerDes and other such serialization classes, so I could potentially serialize to multiple formats that way, and then each such class would have a .save(type) function implemented for each type that needs to be serialized. This does mean writing all the serialization for each type manually, but hopefully that should be minimal effort, and then hopefully I can find a way to have Json, Binary, etc saving/loading happen by just changing which class is used, and then calling the same set of methods on it.

    This does add some complications in that Json is key/value based, and binary and other formats are not, so there may be some confusion/confusing stuff going on there to where it might not be as clear to read the Json as it would be if I did it the way I did before, but I think this will be least effort in terms of being able to write the SceneLoader to be able to save/load to each format without any extra effort, and as long as saving it out happens in the same way as loading it in does, maybe that does not matter. I could also likely allow using std::map<std::string, value> type deals to allow saving things that already have key/value pairs, perhaps there is a way I can denote the key/string in a binary format as well without much issues. Something yet to be determined I suppose, or maybe I could use BSON or protobuf for binary save/load instead of a custom format.

    On top of that, I will probably also need to get bindings together to use it from Lua, either the serialization data directly, or just have a way for Lua to save chunks of memory somehow, that way scripts can save things if they need. Perhaps I could even find a pre-canned Json library for Lua that I could include, that would allow for generating lua saves from Lua, and then just use some API to save it to disk.

    Next steps

    I'm going to keep including these next steps sections even if I keep rehashing the same crap every time. it helps me keep my duckies in a row in terms of what is next, and it's nice to be able to see how close I am to having something usable when I'm slogging through saving/loading nonsense.

    Next steps are to finish up the save/load junk, and then I'll basically be done with the first 0.0.1 milestone. Next up is miniaudio audio playback, likely using low level API so I can implement my own stuff on top. not that I need to spend the time implementing my own stuff on top...

    other than that, multithreaded loading of things I think is high desire, currently my whole update thread stops to load things, which means large time spend lagging out. Render thread keeps going but no processing happens there, so it basically looks frozen and is frozen. Probably going to need to look into the future/promise types that are C++11/whatever for threading. Then basically just not render/use those assets until they are loaded in. Yes this means that assets that are not loaded at the time they are needed will be invisible and pop in, I might need to implement some kind of preloading system to allow loading crap on a loading screen or with a loading bar, or background pre-loading stuff for nearby areas to load them before they are visible or needed.

    Test games/testing the engine

    After the audio stuff is done, I think it'll be a good idea to implement a simple toy game to prove out that the lua bindings work, and everything works. I think my plan for that is likely to be a breakout clone, just because I've done those before, the logic is minimal, and the physics can be fairly simple.

    I also technically have bullet physics already "integrated" but I haven't actually tested that, or implemented the lua bindings to create rigidbody components for entities, so that as well as save/load for the rigidbody component will be needed. Then a different test game will be needed, likely i'll go for some sort of sandbox-y type thing or something where you walk a player character around and can throw things and bump into things. Just to make sure that the physics of things all works as expected.

    Once those basic tests are complete, I think it can be time to actually try to go implement a game. the engine would be mostly in a usable state hopefully by that point, maybe with some UI work to be done, I'm still not decided on if I want to finish implementing my own UI elements as originally planned, or to proceed with using the nuklear library, although I'm not sure nuklear is set up to be used with an entity/component system like I have.

    I've gotten a few ideas/plans together for what I would want my first game or games to be in engine, but of course I keep switching around what I would want to do, between a basic FPS type campaign game, to a horror game, to something else entirely. I think for starting out I would want minimal effort dialog and/or just no dialog options/responses, and no quest systems, that would let me prove out and thoroughly test the basic features before moving on to implementing further elements that would not be able to be thoroughly tested until later. Likely i would add an achievement system before a branching dialog and quest systems, so the achievement system could be tacked on to an existing campaign style FPS game I think.

    Or alternatively, I could just jump around between prototypes, slowly building up a library of 3d assets and scripts that could be re-used in other projects. hard to say.

    posted in Blogs read more
  • C Coolcoder360

    Time again for another update.

    First I wanted to show off the Unicode text rendering, since it took me ages to figure out how to store and render Unicode. I've yet to fully test unicode input. My Japanese keyboard input just defaults to Alpha-numeric. The chinese keyboard input sort of works, but I got a crash from trying to input a couple things with it, I guess I need to work on getting test automation set up for this thing since it likes to crash so often and so randomly.
    Screemshoot_02-15-2021_170704.png
    One of the reasons that Unicode rendering took so long, is that it's impossible to pre-load all of the characters that could be used, so I needed to figure out how to load them on the fly. I still need to work out how to dynamically load extra fonts if needed, currently rendering is limited to the characters supported by the current font. I also should probably figure out how to unload characters if they haven't been used for a while, since GPUs do tend to have a memory limit.

    On to what's new. I've started working on a profiler to help measure performance for the rendering and update threads, this was prompted by noticing how much of a stutter happened every time a screenshot was taken, and realizing that I may need to still be careful with how things are loaded, possibly even loading the images to the GPU in DXT format.
    The profiler I made basically tracks the timestamp of each frame, as well as the deltaTime with the last frame to a couple really long arrays. Then a simple console command can be run to output that data as CSV.
    Nebula3_profile.PNG
    I haven't quite figured out how to graph it to make the most sense yet, on the left you see both the frame timestamp and the deltaTime graphed on the same graph, with the x axis being just what cell it was in. This actually makes more sense to me, since a screenshot was taken in the middle of the capture, so big drop in frame performance was seen, which can be seen by the large disconnect in the recorded frame time.

    On the right we see just the deltaTime being measured, which doesn't seem to make as much sense as I thought it would, I would have expected to see a large spike in that as well, but I don't, I just see a large gap in the frame timestamp. I might need to research this more to see why that would be, or maybe there's an error with how the graph is done.

    Edit: found the spot with the discrepancy, I'm confused on what could cause this:
    Capture.PNG
    The deltaTime on the right doesn't match with the wide variance in the timestamp on the left. So that's fun.
    I have a theory it could be a bug related to threading, I'll probably have to add either locks or make it export that from the render thread, since in this case it was exported from the update thread, not the render thread.

    In the future I hope to be able to show a realtime graph of performance as part of the UI in engine, but I think this will do for now, even if it is a little bit janky. It works great for all the Power Point presentations I'm sure are in the future of this engine!

    posted in Blogs read more
  • C Coolcoder360

    This week I fixed the threading issue with the profiler, but haven't gotten around to testing it yet because I got distracted by putting tasks into Quire.
    I also found out that I have over 60 tasks planned as part of working on this engine, just the engine. Those tasks range from things like porting 3d code from my previous engines, setting up the UI, to adding VR support and global illumination support later down the line. And animation support at some point.

    Also started throwing some stuff together in sprytile, and discovered that sprytile doesn't really work in Blender 2.91 for some reason, got the LTS version of blender and did some light modeling stuff in there with a quick tileset I made in pyxel.

    Nothing to show there yet, maybe I'll have a screenshot once i get the 3d working on the engine.

    The other work I've been doing is adding some more Lua bindings, but that's been boring and slow work, I tend to get distracted by gaming and other things when I'm working on something boring for the engine.
    Theoretically, I have UI buttons working and all that, its just untested right now.
    My main focus is to finish up all the Lua bindings I'd need right now to be able to have complete control over the ECS, then I should be able to start getting some sort of editor going. Maybe with buttons, we'll see.
    Might update this thread or edit this post later today or in a couple days if I get more of the bindings working and have some screenshots or something.

    posted in Blogs read more
  • C Coolcoder360

    I had written a massive update about choosing an audio library and all that, but then Windows update ate it, so instead I'll write about the other half of what I was going to write, and save the audio stuff for some other time, like when I'm actually at that point of the project.

    I'm currently working on the rendering stuff, the way my engine works is there's a Rendering thread, and an Update thread, and they need some way to synchronize between them.
    I had read at some point a series of articles on making a multithreaded renderloop, which I've been referencing and can be found here. This is the second entry, but it has the most exciting diagrams of what is going on, as well as discussions on how to resolve some issues with it, related to jitter, or a lack of smoothness caused by one thread going significantly faster or slower than the other, and frames being skipped over.

    The reason I'm going with this method is because I need a way to basically take a snapshot of the state of everything, and then chunk it into the render thread, if I use a query like I sort of have been doing right now, there is the possibility for the update thread to remove nodes while the render thread is trying to render them, which could be the case on some of the unexpected crashes I've had some trouble resolving and reproducing.

    So to avoid issues with my update thread changing/removing entities while the render thread is rendering them, I'm creating a RenderState class, which will basically hold a set of vectors, one for shared pointers to all opaque 3d objects, and one for all transparent 3d objects, the opaque objects will be sorted front to back, and the transparent 3d objects that require blending will be sorted back to front.

    This sort is done to optimize for the corresponding shaders, while still allowing transparent objects to be drawn in the proper order.

    Then the rendering thread selects a render state that is updated from the update thread most recently, and renders that.

    I'm planning to use a partial deferred renderer, where the opaque objects get rendered through a deferred pipeline, allowing them to be lit with a ton of lights, while the objects requiring transparency are rendered using a forward renderer, I believe this would allow me to also use deferred decals on all of the opaque objects, I'm sure a simple quad mesh decal will be sufficient for objects requiring transparency for now.

    This whole rendering plan is subject to change of course, I've done a bit of research on Global Illumination and I suspect I'll have to basically completely redo the whole renderer in order to support global illumination, but I have a deferred renderer that sort of handles PBR already working, only issues are it doesn't do any IBL (Image Based Lighting) or reflections yet.
    Gonna work with what I already have for now and perhaps just scrap what I have now in favor of something I create later that can do Global Illumination, I'm eyeing some form of Voxel Cone Tracing, just haven't figured out if it works well for transparent objects or not, most examples don't seem to have much in the way of transparency, so I'm hopeful but unsure of how to handle transparency with Global illumination. Who knew rendering could be so painful.

    Hopefully will be able to have something spewing triangles to the screen within a week or few so I can provide some more interesting screenshots.

    posted in Blogs read more
  • C Coolcoder360

    Well I have now hit the brick wall, the point where I may end up restarting from scratch or burning out to take a significant break from my project.

    I managed to finish all my lua bindings for creating meshes and all that and now I'm at the part where I actually test things and see if they run.
    Testing things goes as it normally does, find segfault, fix segfault. I usually test compilation regularly, but not always execution regularly, sometimes I need all the parts made and the lua bindings in before I can make a lua script to test. Unit tests may have been useful here but it's far too late and far less fun to do those.

    So now I'm at a conniving little segfault. Right smack on an assignment operation. I checked, nothing is null as far as I can tell, let me give some context so maybe someone can help or laugh at how awful this code is and how its better to do it some other way.

    Yes I'm using std::shared_ptr and I'm thinking of changing that, since that's the thing that's segfaulting, so here's the line that's failing:

    (*texture) = TextureLoader::getResource(path);
    

    texture is a std::shared_ptr<Texture>*, or a pointer to a shared pointer. the reason for that is this is in the luabinding, and the idea is to have a lua userdata that is the shared pointer, so that means I do a lua_newuserdata(state, sizeof(std::shared_ptr<Texture>)) and that returns a pointer to the shared pointer.
    The reason to have lua hold the shared pointer is of course to have the reference count of lua's reference be included in the shared pointer, that way it won't get deleted when its only reference is in lua.

    Now here's the kicker, I know the textureloader code works, it's already been loading a logo for months and months now without issues.
    And I know this assignment operation works, it actually fails on a second call to it from lua, as can be seen from the log output here:

    04-20-2021 19:49:26 | D LUASCRIPT: path: assets/textures/Bricks054_2K-PNG/Bricks054_2K_Color.png
    04-20-2021 19:49:26 | I TextureLoader: TextureLoader loading: assets/textures/Bricks054_2K-PNG/Bricks054_2K_Color.png
    04-20-2021 19:49:26 | D FSManager: loaded file from assets/textures/Bricks054_2K-PNG/Bricks054_2K_Color.png with size 24775201, total loaded datasize: 41202785
    04-20-2021 19:49:27 | D Texture: loaded texture with nchannels: 4
    04-20-2021 19:49:27 | D Texture: Loaded all the things, scheduled work.
    04-20-2021 19:49:27 | D LUASCRIPT: path: assets/textures/Bricks054_2K-PNG/Bricks054_2K_Normal.png
    04-20-2021 19:49:27 | I TextureLoader: TextureLoader loading: assets/textures/Bricks054_2K-PNG/Bricks054_2K_Normal.png
    04-20-2021 19:49:27 | D FSManager: loaded file from assets/textures/Bricks054_2K-PNG/Bricks054_2K_Normal.png with size 24154252, total loaded datasize: 40581836
    04-20-2021 19:49:28 | D Texture: loaded texture with nchannels: 4
    04-20-2021 19:49:28 | D Texture: Loaded all the things, scheduled work.
    
    Segmentation fault (core dumped)
    

    It loads the Color texture just fine, no issues, then it goes to load the Normal texture, that finds the image file just fine, you can see that it finds and loads 24154252 bytes, and it has 4 channels.
    It exits out of the texture creation.
    Then exits from the textureloader, and proceeds to segfault on the assignment, as seen in the backtrace here:

    Thread 22 "Nebula3" received signal SIGSEGV, Segmentation fault.
    [Switching to Thread 0x7fff977fe640 (LWP 17747)]
    0x000055555568e9f8 in __gnu_cxx::__exchange_and_add (__val=-1, __mem=0xa32c049ccdffa6c6) at /usr/include/c++/10.2.0/ext/atomicity.h:50
    50	  { return __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL); }
    (gdb) bt 10
    #0  0x000055555568e9f8 in __gnu_cxx::__exchange_and_add (__val=-1, __mem=0xa32c049ccdffa6c6) at /usr/include/c++/10.2.0/ext/atomicity.h:50
    #1  __gnu_cxx::__exchange_and_add_dispatch (__val=-1, __mem=0xa32c049ccdffa6c6) at /usr/include/c++/10.2.0/ext/atomicity.h:84
    #2  std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release (this=0xa32c049ccdffa6be) at /usr/include/c++/10.2.0/bits/shared_ptr_base.h:155
    #3  0x000055555568de4b in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count (this=0x7fff977fd1e8, __in_chrg=<optimized out>)
        at /usr/include/c++/10.2.0/bits/shared_ptr_base.h:733
    #4  0x00005555556b7fb2 in std::__shared_ptr<Texture, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr (this=0x7fff977fd1e0, __in_chrg=<optimized out>)
        at /usr/include/c++/10.2.0/bits/shared_ptr_base.h:1183
    #5  0x00005555556b8af6 in std::__shared_ptr<Texture, (__gnu_cxx::_Lock_policy)2>::operator= (this=0x7fff88218af8, __r=...) at /usr/include/c++/10.2.0/bits/shared_ptr_base.h:1279
    #6  0x00005555556b8616 in std::shared_ptr<Texture>::operator= (this=0x7fff88218af8, __r=...) at /usr/include/c++/10.2.0/bits/shared_ptr.h:384
    #7  0x00005555557745c1 in loadtexture (state=0x5555570a7df8) at /home/alex/nebula3/luatexturelib.cpp:29
    #8  0x00005555558e03f0 in luaD_precall ()
    #9  0x00005555558ee4ab in luaV_execute ()
    

    The one other hint I have is that adding two log lines to my render loop (separate thread from this, this is in the update thread) will suddenly cause this whole issue to not exist. This would maybe indicate some locking issue, and I inserted it around calling on a work queue that is loaded from the function that creates the texture. That's all fine and good but when I rip out either loading the work into that queue, or the call to the queue entirely, the problem still persists. And it's segfaulting consistently here, whenever I've had a threading issue in the past, it would usually be sporadic, so far it's failing on the second lua loadtexture call 100% of the time. Never the first, never any others after that. Never segfaults from any other thread, just consistently on this assignment.

    So what are my next steps?
    Probably stop using std::shared_ptr and try rolling my own resource counter. it would give me more control at least, and possibly fewer possibilities for bugs, and it may already fit considering I already have loaders for resources, just need to revamp those to utilize my customer counter thingies, and then have it count somehow. problem is keeping track of the count, easier with shared pointers if possible. Also there's a chance that doesn't fix this issue.

    Knowing my luck by the time I roll my own resource counter, I'll figure out that this was some simple fix and fix it. and then it'll be too late to go back to the shared pointers, and there'll be tons of bugs in the resource counters to fix. Such is life I suppose.

    Oh and maybe I'll think about adding gmock/gtest unit tests. I haven't done that in like a year and a half, might be worth brushing up on it again, and I can't really argue that it wouldn't be beneficial for if I ever decide to make this engine actually a big thing.

    An after note while editing/writing:
    the "total loaded datasize" from the FSManager seems to be a bit telling, perhaps things are getting freed unexpectedly by the shared pointers?
    The total data size is supposed to be the grand total of all loaded memory, but here it actually decreases between the first and the second loadtexture calls

    04-20-2021 19:49:26 | D FSManager: loaded file from assets/textures/Bricks054_2K-PNG/Bricks054_2K_Color.png with size 24775201, total loaded datasize: 41202785
    04-20-2021 19:49:27 | D FSManager: loaded file from assets/textures/Bricks054_2K-PNG/Bricks054_2K_Normal.png with size 24154252, total loaded datasize: 40581836
    

    This could possibly be due to the logo being free of course, however neither total datasize is equal to both image sizes together, instead they're both whatever the image size is plus 16427584 so it seems that the lua textures are being freed when they shouldn't be, which could be an issue with something else, but would hopefully be 99% fixed by a custom resource counter implementation.

    Gruedorfing this possibly helped me fix this bug, tune in next time after much excruciating pain implementing my own resource counters to know if that fixed this!

    posted in Blogs read more
  • C Coolcoder360

    Trying to get myself back onto the weekend gruedorf schedule, also managed to basically fix the segfaulting issue I had last post.

    The answer was to do this:

             std::shared_ptr<Texture>* texture = (std::shared_ptr<Texture>*)lua_newuserdata(state,sizeof(std::shared_ptr<Texture>));
    +        new (texture) std::shared_ptr<Texture>(nullptr);
    

    I found this out from an error in valgrind about something being uninitialized in the assignment operation, so that pointed me in the right direction of needing to call the constructor like this.

    Basically the lua_newuserdata() acts as a malloc, which doesn't initialize anything. So we call the constructor and that sets up everything.

    I still need to handle calling the destructor, I haven't done too much research into that but apparently there is a __gc method I could add to the userdata which I could use to call the destructor on any of the shared pointers, so I think case mostly closed for now.

    Didn't have rendering fully set up yet so no screenshots, also booted back into windows to test on windows and now I'm getting an error of not finding a .dll when I'm trying to statically link with the library, so that's fun 🙂

    Can't wait until I get the docker set up to cross compile for windows, should hopefully be better than dealing with the windows weirdness. But that's not planned to start for a little while yet, and I should probably implement the __gc to fix the memory leak before I forget all about it and wonder later why it's leaking memory and none of the assets are ever being cleaned from memory.

    posted in Blogs read more
  • C Coolcoder360

    Not much to report in this week, mostly more work on getting the dependencies to build on the Jenkins/in the docker. I switched from using the declarative pipeline to the scripted pipeline in Jenkins because it let me do something I couldn't figure out how to do in the declarative pipeline, which was to load a dockerfile from a sub-directory of a code repo I just downloaded. Somehow the agent{ Dockerfile true} stuff from declarative doesn't access the same workspace that the code was downloaded into in a previous stage, so now I use scripted and basically just do a def dockerimage = docker.image("...") or whatever it is, then I can do like a dockerimage.inside(){ ...} thing to run commands inside of it, which gets me the functionality I want.

    A bit of rinse and repeating on trying to sort out all the dependencies for all the dependencies needed. There were a lot more than I expected to build some of the dependencies, Next steps is to finish up the Jenkins build to be able to build the final engine executable, then after that work on getting the docker to hopefully be able to cross compile to Windows. I'm a bit less hopeful after finding out how many dependencies my dependencies have, but if I can pull it off it'll make dev much easier on me by being able to verify that the windows build still works without having to reboot to Windows.

    Then after that I'll probably get back to the rendering stuff at some point, just right now I'm motivated for the Jenkins and docker set up, and I'm learning it which is useful, I've used Jenkins and Docker for work, but never really had to write the jenkins scripts or configure the jobs, or write the Dockerfile myself.

    Part of why I want to set up a kubernetes cluster on raspberry pis to be a build server is to learn more about containerization and that sort of thing, and learning React.js and maybe koa.js would help too. those are all pieces of things that we use at work, just I'm not fully up to speed on all of react, typescript, and all that webdev stuff we use. Got out of learning webdev when frameworks were becoming all the rage and changing like every time I turned around, just too much stuff to keep track of. Now that's its settled down and we actually have some of that at work, I may as well learn it and maybe do some hobby experimenting with it so I can pick it up more easily if needed. Maybe I'll make some sort of site for my engine at some point with it.

    posted in Blogs read more