Kudos on the animation system and physics. Nice to see your day/night cycle too. And the volumetric clouds and God Rays? Awesome! Very nice to see camera collision too. Regarding the animation, it would be cool to see they blending between each other, but I get that your main focus was the graphics part and there's only so many things you can do in that short amount of time, right? The Frustum culling is really nice and being able to see it working was a very nice touch to the project.
Great work! The chain of attacks for the character, that's a nice bit of game design detail there.
Love the fact you used Dear ImGui for your level editor. The code is well structured and fairly clean. Looking back, if you had to do it all again, what would you do differently?
The list of what I'd change are practically endless, but here are some of the first things that come to mind:
1. Make modifications to my Entity Component System: When profiling my application on the CPU side, I found that the time it takes to "submit" entities to be rendered takes up a significant portion of time. Instead of iterating over ALL entities and checking if they can be rendered I would add a callback function for when components are added to entities. That way, when a render component is added to an entity I can implement some sort of listener to add that specific "Render Component" to a vector. Now when I make render submissions, I would iterate over the vector of Render Components as opposed to iterating through all entities and checking if they are valid to render every frame.
Another great addition would be cache friendliness, the first technique that comes to mind is spatial locality for components. There is a high probability that if a specific component type is accessed, other neighbor components of that type will be accessed in the near future (for example, we iterate through all SkeletalAnimationComponents to process bone transforms). By grouping component types in contiguous memory, it will reduce the number of cache misses. In other words, copying a block of memory after a cache miss will improve access speed for subsequent components of that type.
2. Make the engine more flexible: Initially, the engine was designed to use OpenGL ONLY. At a certain point down the road I thought "wouldn't it be nice to maybe try out DirectX or Vulkan?" I obviously couldn't without subjecting my code to some serious changes. If I had to go back and change that, I would add and API that takes advantage of interfaces/pure virtual classes. This would allow each graphics library to have its own implementation of my custom-defined interfaces which would allow us to switch between graphics libraries easily. Take the class "VertexBuffer.h" for example. I'd imagine that the way DirectX and Vulkan make you define vertex layouts differ from OpenGL. To combat this I would add an IVertexBuffer class (interface) which could have any number of implementations. With that, I could now switch between graphics APIs very simply. Note that this is just ONE example of how I could use interfaces in my engine, there are plenty more opportunities to use this.
3. Error handling: This one is pretty obvious, but as it currently stands I have little to no error handling, or even warnings when an error takes place for that matter. Adding something like this would make debugging significantly easier.
4. Implementing sound into the game: Even though my demo is generally visually appealing, the atmosphere doesn't feel as immersive without sound. Adding some ambient noise, footsteps, sword swooshes, etc would be a massive help to making the game feel better.
5. Spatial partitioning: As it stands, my only form of "graphical performance enhancement" is frustum culling. This reduces the amount of draw calls that needs to be made by "getting rid" of the things the camera can't see, but what if the game world is massive? Doing frustum culling in a massive world can be very problematic due to the sheer amount of iterations you'd have to do over every renderable "thing" in the game world, thus causing a slow down on the CPU. To combat this, we could divide our game world into smaller regions. With the game world now divided into regions, we can find the region that the player currently resides in, and only do the culling in the regions we specify, thus reducing the amount of iterations. Now obviously this would make almost zero difference in my demo because the world is so small, but as someone who is developing an "engine" this is definitely something I have put some thought into.
Non technical stuff: 1. The tech stuff is great, but it's also important to consider the non-technical stuff. The thing that immediately jumps at me is how much time I spent and the procedural dungeon generation. I spent a great deal of time messing around trying to get my dungeon to generate in 3 dimensions. If I were to settle on a more simplistic rendition of that earlier I would have been able to implement some more interesting game mechanics like AI.
2. Another huge time sink was finding assets and making my level. Even though it's generally simple, the time it took to collect all of the necessary assets and actually make the level was around 3 days. I feel that I should have took some of that time to implement one of the technical features above.
Honorable mentions: One thing you'll notice in my code is that I use no smart pointers. I know that everyone has a different opinion on the relevance of smart pointers, but for me I feel that there is a time and place for both. Obviously if you are trying to squeeze the absolute most performance out of an application, using raw pointers will reduce overhead by a small amount. On the other hand, I can totally see how in a larger project, memory management becomes an extremely daunting task, thus making smart pointers a great option.
Anyways, I'll leave it at that for now, I don't want to write my entire autobiography here haha. On the other hand, if you'd like some more examples/improvements, I'd be happy to provide them.
Looks very visually impressive. The lighting/shadowing effects look great. The clouds look very realistic, and I love the ImGui layer for tweaking the values.
Your code is also reasonably easy to follow. Well done!
Thanks! Yep I totally agree with you there, AI would have helped immensely. I got a little too invested in the graphical portions, which gave me less time to deal with making an actual game. I couldn't help it, the graphics stuff is just too cool!
The camera collision was a smooth move! Everything looks amazing, you said you put focus on graphics and wow it really paid off. The clouds being affected by the day night cycle was a nice touch. If I had to pick on anything, some things, like walls would seem weirdly shiny at times. So I would want the specular light turned down on most things, but that could just be a preference. Well done!
Impressive visuals, camera was stuck in one position until I pressed escape to unlock it. Once it was unlocked I was impressed by the camera collision to avoid clipping through objects. Some of the collisions were missing on the mountains around the outside of the area and I ended up falling out of the world with no way to reset myself.
Thanks! I forgot to mention that you can press escape to toggle your cursor, so that technically is a feature. As for the rocks, I have to agree with you, I'm still experimenting with bullet physics and mesh colliders, so its very much a WIP.
Unfortunately ran super slow on my PC for whatever reason, but was super impressive visually! Not sure if also a bug, but third person camera wasn't working for me for a bit, then suddenly started working after mashing a bunch of random keys. Pretty awesome demo that you put together, would have loved to see more interactable stuff obviously, but as a quick demo, seemed pretty decent other than my performance issues!
That's unfortunate! I was honestly expecting something like this to happen though as I didn't really have the opportunity to test on anything other than my machine (I have a pretty powerful computer: RTX 3080 & Ryzen 9 5900X). That being said, there's plenty of room for performance enhancements in my engine that I just simply didn't have the time to implement, some of those include instanced rendering and a cache friendly ECS.
Great work on the graphics, I particularly liked the grass rendering and detail given to the sun, lights and shadows. Also, the passage of time was quite an interesting effect. Congratulations!
The real-time grass and clouds were very impressive! And I quite liked the detail of the lights turning on at night time. It would be cool to see some kind of AI in the dungeons to attack/interact with.
Yeah, AI was definitely next up on my list but I severely underestimated the time it would take to find some decent assets and put together a semi-decent looking level. That aside, you were actually the one who inspired me to look into volumetric clouds! I came across one of your videos from the previous year and thought it would be interesting to implement. As a side note, I also noticed your engine was called "Luna", I found that pretty funny since our names are so similar.
Comments
Kudos on the animation system and physics. Nice to see your day/night cycle too. And the volumetric clouds and God Rays? Awesome! Very nice to see camera collision too. Regarding the animation, it would be cool to see they blending between each other, but I get that your main focus was the graphics part and there's only so many things you can do in that short amount of time, right? The Frustum culling is really nice and being able to see it working was a very nice touch to the project.
Great work! The chain of attacks for the character, that's a nice bit of game design detail there.
Love the fact you used Dear ImGui for your level editor. The code is well structured and fairly clean. Looking back, if you had to do it all again, what would you do differently?
The list of what I'd change are practically endless, but here are some of the first things that come to mind:
1. Make modifications to my Entity Component System:
When profiling my application on the CPU side, I found that the time it takes to "submit" entities to be rendered takes up a significant portion of time. Instead of iterating over ALL entities and checking if they can be rendered I would add a callback function for when components are added to entities. That way, when a render component is added to an entity I can implement some sort of listener to add that specific "Render Component" to a vector. Now when I make render submissions, I would iterate over the vector of Render Components as opposed to iterating through all entities and checking if they are valid to render every frame.
Another great addition would be cache friendliness, the first technique that comes to mind is spatial locality for components. There is a high probability that if a specific component type is accessed, other neighbor components of that type will be accessed in the near future (for example, we iterate through all SkeletalAnimationComponents to process bone transforms). By grouping component types in contiguous memory, it will reduce the number of cache misses. In other words, copying a block of memory after a cache miss will improve access speed for subsequent components of that type.
2. Make the engine more flexible:
Initially, the engine was designed to use OpenGL ONLY. At a certain point down the road I thought "wouldn't it be nice to maybe try out DirectX or Vulkan?" I obviously couldn't without subjecting my code to some serious changes. If I had to go back and change that, I would add and API that takes advantage of interfaces/pure virtual classes. This would allow each graphics library to have its own implementation of my custom-defined interfaces which would allow us to switch between graphics libraries easily. Take the class "VertexBuffer.h" for example. I'd imagine that the way DirectX and Vulkan make you define vertex layouts differ from OpenGL. To combat this I would add an IVertexBuffer class (interface) which could have any number of implementations. With that, I could now switch between graphics APIs very simply. Note that this is just ONE example of how I could use interfaces in my engine, there are plenty more opportunities to use this.
3. Error handling:
This one is pretty obvious, but as it currently stands I have little to no error handling, or even warnings when an error takes place for that matter. Adding something like this would make debugging significantly easier.
4. Implementing sound into the game:
Even though my demo is generally visually appealing, the atmosphere doesn't feel as immersive without sound. Adding some ambient noise, footsteps, sword swooshes, etc would be a massive help to making the game feel better.
5. Spatial partitioning:
As it stands, my only form of "graphical performance enhancement" is frustum culling. This reduces the amount of draw calls that needs to be made by "getting rid" of the things the camera can't see, but what if the game world is massive? Doing frustum culling in a massive world can be very problematic due to the sheer amount of iterations you'd have to do over every renderable "thing" in the game world, thus causing a slow down on the CPU. To combat this, we could divide our game world into smaller regions. With the game world now divided into regions, we can find the region that the player currently resides in, and only do the culling in the regions we specify, thus reducing the amount of iterations. Now obviously this would make almost zero difference in my demo because the world is so small, but as someone who is developing an "engine" this is definitely something I have put some thought into.
Non technical stuff:
1. The tech stuff is great, but it's also important to consider the non-technical stuff. The thing that immediately jumps at me is how much time I spent and the procedural dungeon generation. I spent a great deal of time messing around trying to get my dungeon to generate in 3 dimensions. If I were to settle on a more simplistic rendition of that earlier I would have been able to implement some more interesting game mechanics like AI.
2. Another huge time sink was finding assets and making my level. Even though it's generally simple, the time it took to collect all of the necessary assets and actually make the level was around 3 days. I feel that I should have took some of that time to implement one of the technical features above.
Honorable mentions:
One thing you'll notice in my code is that I use no smart pointers. I know that everyone has a different opinion on the relevance of smart pointers, but for me I feel that there is a time and place for both. Obviously if you are trying to squeeze the absolute most performance out of an application, using raw pointers will reduce overhead by a small amount. On the other hand, I can totally see how in a larger project, memory management becomes an extremely daunting task, thus making smart pointers a great option.
Anyways, I'll leave it at that for now, I don't want to write my entire autobiography here haha. On the other hand, if you'd like some more examples/improvements, I'd be happy to provide them.
Looks very visually impressive. The lighting/shadowing effects look great. The clouds look very realistic, and I love the ImGui layer for tweaking the values.
Your code is also reasonably easy to follow. Well done!
Thanks!
Hey
Great demo you got there!
I liked how you implemented the grass and volumetric clouds. Daynight cycle was cool to see as well.
The state machine used for chaining animation was an interesting idea and of course points for the procedural generation.
What could have improved and made this demo a well rounded one, would be to add a bit of AI and some basic gameplay.
Keep it up and wish you all the best
Thanks! Yep I totally agree with you there, AI would have helped immensely. I got a little too invested in the graphical portions, which gave me less time to deal with making an actual game. I couldn't help it, the graphics stuff is just too cool!
The camera collision was a smooth move! Everything looks amazing, you said you put focus on graphics and wow it really paid off. The clouds being affected by the day night cycle was a nice touch. If I had to pick on anything, some things, like walls would seem weirdly shiny at times. So I would want the specular light turned down on most things, but that could just be a preference. Well done!
Impressive visuals, camera was stuck in one position until I pressed escape to unlock it. Once it was unlocked I was impressed by the camera collision to avoid clipping through objects. Some of the collisions were missing on the mountains around the outside of the area and I ended up falling out of the world with no way to reset myself.
Thanks! I forgot to mention that you can press escape to toggle your cursor, so that technically is a feature. As for the rocks, I have to agree with you, I'm still experimenting with bullet physics and mesh colliders, so its very much a WIP.
Unfortunately ran super slow on my PC for whatever reason, but was super impressive visually! Not sure if also a bug, but third person camera wasn't working for me for a bit, then suddenly started working after mashing a bunch of random keys. Pretty awesome demo that you put together, would have loved to see more interactable stuff obviously, but as a quick demo, seemed pretty decent other than my performance issues!
That's unfortunate! I was honestly expecting something like this to happen though as I didn't really have the opportunity to test on anything other than my machine (I have a pretty powerful computer: RTX 3080 & Ryzen 9 5900X). That being said, there's plenty of room for performance enhancements in my engine that I just simply didn't have the time to implement, some of those include instanced rendering and a cache friendly ECS.
Great work on the graphics, I particularly liked the grass rendering and detail given to the sun, lights and shadows. Also, the passage of time was quite an interesting effect. Congratulations!
Thanks!
The real-time grass and clouds were very impressive! And I quite liked the detail of the lights turning on at night time. It would be cool to see some kind of AI in the dungeons to attack/interact with.
Yeah, AI was definitely next up on my list but I severely underestimated the time it would take to find some decent assets and put together a semi-decent looking level. That aside, you were actually the one who inspired me to look into volumetric clouds! I came across one of your videos from the previous year and thought it would be interesting to implement. As a side note, I also noticed your engine was called "Luna", I found that pretty funny since our names are so similar.
Haha yeah, the moon and anything wintery sounding seems to be a common point of influence for game engine names.