- 14
- 20 564
FuniGameDev
Czechia
Приєднався 8 жов 2022
I make games
How Does My C++ Game Engine Load And Render 3D Objects
How does a game engine load in and render complex 3D objects on screen?
In today's devlog we'll take a look at how my C++ game engine FuniTinker engine loads in objects and how we can use simple shaders in opengl to render these objects with cool effects!
There's definitely a lot that could be simplified by using libraries, but I'll tell you why I don't want to and what kind of libraries I do use for the FuniTinker engine.
00:00 Intro
00:11 Why GLTF 2.0?
00:36 What is GLTF 2.0 made of
00:51 What libraries I use
01:23 GLTF format in action
02:46 What are shaders?
03:21 Shader showcase
03:47 Outro
In today's devlog we'll take a look at how my C++ game engine FuniTinker engine loads in objects and how we can use simple shaders in opengl to render these objects with cool effects!
There's definitely a lot that could be simplified by using libraries, but I'll tell you why I don't want to and what kind of libraries I do use for the FuniTinker engine.
00:00 Intro
00:11 Why GLTF 2.0?
00:36 What is GLTF 2.0 made of
00:51 What libraries I use
01:23 GLTF format in action
02:46 What are shaders?
03:21 Shader showcase
03:47 Outro
Переглядів: 643
Відео
3D Debugging In My Own C++ Game Engine
Переглядів 1,3 тис.7 місяців тому
Debugging games can be a complex task. That's why many of us game developers like to debug in 3D directly in the game. Hopefully this video will shine a little light into how 3D debugging renderers work. I'll show you how I implemented a 3D debugging system in my C game engine. It's mainly an explaration of singleton structures and how we can use globally accessible functions in C . I also made...
Game Engine in C++ Parkour Demo
Переглядів 8548 місяців тому
A little update video showing what the game engine I'm building in C looks like. It's called FuniTinker engine and I'm very proud of it. 00:00 Intro 00:21 Name announcement! 00:43 Why my own game engine 00:57 Struggles 01:30 Game engine showcase! 03:05 Roadmap 03:23 Outro
How I Structure Entities In My Own C++ Game Engine
Переглядів 15 тис.8 місяців тому
How do you structure a game engine? That's one of the first questions we as game developers have. Hopefully you'll find this video informative and maybe a bit helpful too. ENTT C ECS: github.com/skypjack/entt 00:00 Intro 00:06 Entity inheritance 01:25 Entity Component System
Why I Decided To Make My Own Game Engine From Scratch In C++
Переглядів 1 тис.9 місяців тому
Alternative title: Man cannot understand simple tools so he has to make one himself. After years of trying to create a cool game I found out that using engines isn't for me, so I decided to make one! A really small one, that'll have only the features needed to create my small game PetCat. Why would anyone do this? That's a great question, it's fun i guess, we'll see how the engine turns out and...
The issue is that you have three vectors each pointing to a different section on the heap making it much more likely to not be cached. This is the primary reason why std::vector<std::vector> is slow.
I see your point, it would be much better to not rely on the standard library and make a custom allocator, but currently I don't have the skill or knowledge to dive deep into that, since the engine is still highly experimental, and I don't know what I'm doing :D
😮 perfect
😮
😯 maybe it will take a longggggg timee 😅
This video has been such a breath of fresh air. I am building my engine on top of the Raylib Framework and am integrating Bullet3 for my physics and collision detection, but NOT using an ECS is just asking for a bad time. I'd love to get in touch with you, I want to connect with other devs doing this kind of stuff
Good stuff! Keep up the content
Thank you so much!
I've been beating struggling with this issue for 2 days now trying to rewrite my messy code into more organized and workable code. There's really only 3 options, from my limited experience, that I see. First: dump all possible components into one generic entity. Easy to use. Very wasteful, messy and what if someone else touches your code and tries to access a component which shouldn't exist? Conclusion, not great. Second: Polymorphism. Ultimately what this video suggested is also polymorphism except it was moved from the entity to component and at the end of the day you're dealing with the same issues. I'd say this is the cleanest approach, probably the easiest to maintain but since I'm a novice myself, I am not sure if this is all too good. I see a lot of criticism for polymorphism. Maybe I just need someone to hold my shoulders and say it's alright. Third: Make every entity into its own base class. This would lead to massive code repetition and you'd have to go through old code every single time you choose to create a new entity type. Probably the most powerful to run, the most annoying and thus buggy to write. I've been thinking and I just can't crack the code, I feel like there is no good solution. One way could also be writing a separate manager class for each type of entity. Entity would be generic ID holder, the manager would hold all the components and all of the entities associated with the ID (which in my case is both an enum and an int).
Thank you for reaching out. I'd say if you're a novice starting out with ECS might not be the greatest idea. It's not necessary to use ECS in everything, if you're starting out I'd probably recommend to just use polymorphism, keeping the data inside the entities, even though I criticize it in this video it is really simple, and my main critique is that if handled incorrectly it creates a lot of messy code. Just like in the example I have given, if you know what the entities are going to be like for a small game, there's nothing bad with using polymorphism to handle the entities and not worrying about ECS. Let's say that you're making a simple tower defense game, and the only entities you need are Tower and Enemy, having them both inherit some sort of BaseEntity class, which gives them both position x and y, is fine. I also hear a lot of criticisms for this approach, and yet Unreal Engine also has Characters which implement Actors and so on. I have set certain restrictions on this project, mostly out of boredom and because I want this project to "feel" different than what I'm working with on a daily basis at work, that's why I don't use any inheritance in the code. The components are each its own struct, the entities are just indexes and their connection is kept using the mappings. This way there's no need for polymorphism, each entity isn't defined by what it's inheriting, but by its components. If I were to do it the most simple way possible, I'd have two base classes, Components and Systems, where ComponentBase class would define for example the type of component and SystemBase would have a virtual Update() function. Then I'd have a manager holding all of the components in some sort of a map maybe where the entity is the key and the component is the value. If entity wants to know its own components it can look into the maps of components to find itself, if a system wants to get components of a certain type to edit their data, they can look into the maps looking for a component type. Then a manager for systems where each system executes all of their Update() functions. This way you have only one level deep inheritance which isn't that messy and you can still have ECS architecture. Maybe it's even better than what I have currently. If you want to learn more about the challenges of ECS based systems I'd recommend looking into EnTT's creator blog skypjack.github.io/ where there are blogposts with his insight into how EnTT was built.
@@funigamedev Thanks for the comment! It's very reassuring to hear how it's actually done in real work environments. I am following a course on youtube comp 4300. Making these design decisions is hard, so I'm grateful for this. I decided to go the with a static approach. I just have one entity with most vital components (ID, enum tag, collision, transform, bool active). And I have two manager classes both of which are static since realistically an instance of a manager class would be active all the time anyway and it should probably always be the same manager. The other manager class holds the extra potential components. Upside is I am dealing with simple objects, downside is the support manager does have to be updated if a new component is created. But the simple entity manager will always stay the same now. Deletion of components and entities is such: void EntityManager::removeDisabledEnts(std::vector<std::shared_ptr<Entity>>& origin) { origin.erase(std::remove_if(origin.begin(), origin.end(), [](const std::shared_ptr<Entity>& ent){ if (!ent->isActive()) { EntityManagerSupport::removeComponent(ent->ID()); return true; } return false; }), origin.end()); } void EntityManagerSupport::removeComponent(const int entityID) { auto soundIt = soundComponents.find(entityID); auto textureIt = textureComponents.find(entityID); auto lifeIt = lifeComponents.find(entityID); if (soundIt != soundComponents.end()) { soundComponents.erase(soundIt); } if (textureIt != textureComponents.end()) { textureComponents.erase(textureIt); } if (lifeIt != lifeComponents.end()) { lifeComponents.erase(lifeIt); } } How addition of extra components I have not yet decided upon, probably will be handled in the systems. Note, I am not asking for code review 😃. Just sharing the stuff I came up with. i have no idea if it's going to be nice or not. for example my bullet spawning: void spawnBullet(const std::shared_ptr<Entity>& origin, const Vec2D& target) { //add entity into static manager auto bullet = EntityManager::addEntity(Bullet); bullet->transform = std::make_shared<CTransform>(/*ignore this*/); bullet->shape = std::make_shared<CShape>(/*ignore this*/); bullet->collision = std::make_shared<CCollision>(/*ignore this*/); //add extra components into the other static manager, overloaded addComponent EntityManagerSupport::addComponent(bullet->ID(), LifeTag, BConfig.L); EntityManagerSupport::addComponent(bullet->ID(), SoundTag, "needToFigureOutHowToNotGiveTheEntirePath.wav"); //sound play should probably done elsewhere auto sound = EntityManagerSupport::getComponent<CSound>(bullet->ID(), SoundTag); sound->SoundPlay.play(); }
Thank you for sharing your thought process! I like these ideas, it's really interesting to see a different approach and these managers sound flexible and quite usable from the code examples you've provided! Keep up the good work!
Are the stills in the video rendered with your engine? Your devlogs are so charming, I look forward to the next one!
Thank you for your kind words! Sadly the engine isn't flexible enough yet, so they're made in blender :)
yooooooooooooooooooo
3:21 Instead of using "std::unordered_set<ComponentType> m_componentMask;" I would suggest to try and use a bitmask of 32 (or 64bit) unsigned int (or "std::bitset"), where every bit would represent a component index. Store it like "std::vector<uint64_t> m_componentMask;", every entity will have it's own bitmask. This would save you some memory since in your case with 'unordered_set' you already use 80bytes per entity, where using uint64_t bitmask would just use 8bytes.
Thank you for your suggestion! I'll definitely look into it, you've explained it really well.
2:57 There is one tiny little aspect that makes me die inside a little - you have 3 dynamic arrays that have an invariant, that they are ALWAYS the same size, but you're left to ensure that manually. If they were to ever grow out of sync, you'd have a massive problem on your hands. Realisticaly all allocation and deallocation of entities is going to happen in a very confined section of code the correctness of which is trivially ensured, so it's not a real problem, and one might sprinkle a handful asserts in a handful of places and sleep secure that the software is correct without some crazy mechanism. But you know how it is. Also whether you want array of structures or structure of arrays... it depends! I think a Component like this is simple enough that you wil always touch at least position and rotation at the same time, so having them in the same structure (array of structures) is going to act as prefetch and be hypothetically more efficient; but likely not by any measurable amount. However size isn't like these two, there are many operations that do not involve size. So perhaps size is worth a separate Component? But yeah structure of arrays is guaranteed good enough, then size doesn't need to be a separate component, and you don't need to closely consider the operations and their relative frequencies.
You're absolutely correct, is there a way to fix the size of the arrays? Having some way to ensure that all of the arrays have the same size without manually checking? It's also something I'm always afraid of "What if I don't delete one part of the component and then all of the indexes are wrong", so I understand the problem but I'm not sure if there's a nice solution. I've been doing a lot of refactoring lately so I can add this to my checklist of what to fix :) Also you're correct that size isn't always returned, the main way why I'm doing the whole transform is that for the purposes of rendering, for each object every frame we'll have to read all three. I'll think about it since size is different than position and rotation, for movement, physics and all that we don't really need the size. Thank you for sharing your thoughts!
@@funigamedev Well unfortunately C++ doesn't directly support "Design by Contract", a technique where you tag objects and methods with an explicit sanity checking code that is always executed in a validation run. But you can use it as inspiration. Linking three arrays together via a manager that just adjusts their sizes is for one cumbersome looking and potentially inefficient for other doesn't guard against logic bugs related to managing these Components. Various people have done their own approaches to implement Structure of Arrays, you could check them out, they all have something unwieldy and potentially offensive about them.
I'll look into it thank you!
hi bro
Hi!
@@funigamedev hmm i like engine its good❤ is it free to download
Thank you so much! Unfortunately currently it's still in development and I don't know when it'll be ready for public :)
@@funigamedev i subs to you 😀😀 byee see you in you next video
Great video, why do you have that less subs? Please continue you're going to blow up!
Thank you so much! I started releasing videos recently but I'm trying to get better at it with each one. I'm glad you like them!
awesome video.. i love it.. but, even if ECS is super efficient and optimal.. wouldn't it be super confusing in the future?? when you have a loot of stuff your videogames?
Thank you so much! You're correct that this approach will need further work to make it easier to work with, for now this is sufficient enough, but I'm already working on something better and easier to use. I don't want to introduce unnecessary complexity in the whole system since ECS is still new to me and C++ as a whole is really new, but I believe in the future there will definitely be a video on how I made it easier to work with.
That’s when you make a behaviour component that holds a ptr to a scriptable object which can be used as a base class for custom behaviour. That way you can create as many scripts as you like without there being too many components.
Really nice video, straight to the point. I like how you pointed out that today's debuggers don't help in game debugging much and this also has been my pain point. I kind of wanted to take a shot at improving the situation and made an extension for Visual Studio that eliminates the need for logging and shows all variables inline in realtime. It wouldn't help you draw lines/geometry in the renderer obviously, but I think it could help you a lot with removing the need for many breakpoints/log points. Here's a demo on what it does: ua-cam.com/video/5bfUWJYEQCw/v-deo.html. Let me know if it would be useful to you and if you'd be interested in trying it out!
Thank you for the recommendation I'll look into it, it looks nice!, Sorry for the wait the comment was held for review because there's a link in it, I didn't know youtube does that lol.
@@funigamedev Ah, that's fine! If you have any questions/issues while trying it, I'm always available to help.
very good video, love it
Thank you!
Its all fun and games, until you have to debug your debugger
True lol
This is very cool! Can you share the source code for your engine?
Thank you so much! Eventually I want people to get their hands on the source code of FuniTinker engine, but sadly I'm not currently at the stage where I'd be comfortable with sharing the code, but thank you for your interest!
Do you already know opengl/computer graphics? Or are you learning as you go?
I'm learning as I go, I just know the general stuff from trying to make games like 3d models have vertices, that there are things like shaders, stuff I encountered in unity, unreal or trying to make scenes in blender, but I have no prior knowledge of buffers, or opengl specifically. I've started with www.learnopengl.com and from there I'm trying to expand and fit the renderer into my ECS. I'll be making videos about graphics in the future but currently it's just a pbr shader and simple one directional light shadow :D
Always nice to see some custom engines devlogs! How are you structuring the renderer? I'm struggling a lot with my engine
Thank you! I currently have a really simple setup. For loop over all entities with a mesh, single texture set loaded from a folder for all of them, and then applied on a really simple PBR shader with model, view, projection matrix, the shadows are really simple too for now it's just a depth check render onto a texture, there will be a lot more content about renderers when I get to actually understand them :D but for now it's mostly just few things from www.learnopengl.com
Great video! I think the component mask could be a little faster if you used a bitset instead of an unordered map but I may be wrong
Thank you for the tip! I'll definitely look into that, you might be right that it's faster, I'm still kind of searching for some better way to map and keep track of the entity component relationship, since maybe I want one entity to have more than one mesh and for that the current system isn't enough.
Looks cool! Looking forward to future developments, and if possible a public release.
Thank you so much! I very much expected the question of public release to come up and it's still very early to know for sure. I definitely want other people to get their hands on the project someday, but right now I'm still inexperienced in the business side of things. Thank you for your support, it means a lot to me that people are even interested in this project.
you can do it
Thank you so much!
Krásná práce! Composition over inheritance can be applied in all sorts of fields in programming, but explaining it through game dev makes it really easy and intuitive to follow and understand, you did an awesome job!
Díky moc! I'm so happy you enjoyed it, composition over inheritance is exactly what I was aiming for so I'm glad it made sense. Thank you for your feedback!
I'm a beginner, and the video went really really fast. Can you storyboard more and make your future videos longer, taking time explaining stuff one at a time?
I'll try to look into that, thank you for your feedback!
Great video and solution! I'm also writing a game engine in C++ and have been tackling a similar problem. In my one, each entity has an array of component indexes where each index in the array represents a component ID. If an entity doesn't have a certain component, the component index is just set to -1. The systems iterate through the entity IDs they are interested in and they access the component data through that.
Thank you so much! Your solution sounds great too! It's great to hear different solutions to these problems and to see that I'm not the only one dealing with this :D
Interesting, I have stumbled upon the problem before where I have tried to make things abstract and follow proper inheritance. But sometimes it just falls flat when my entities suddenly need to have many different variables and functions from one another. It ends up with my base entity only having like 1 or two variables...
Thank you! I'm glad I'm not alone, thankfully many much smarter people than me have figured out the way already :D
I wish you luck in your journey!
Thank you!
i was using opengl ,openal and sfml
I've tried only opengl so far :D
Always wanted to do the same. Going to subscribe to see if I can learn something from you. :)
Thank you so much for the sub! I hope you will!
Wish you good luck and we'll see how this turns out!
Thank you very much!
Now let's create a game in BASIC !
Now that would be a challenge!
I love this
Thank you so much!
@@funigamedevNo, thank you! This has inspired me to try and make my own engin e!
zníš jak čech ale maximálně
to musí být čech
Cool concept!
Thank you! It looks so cute :D