Zengine - A Java game engine in LWJGL using Assimp, IMGUI, and more.

posted in Zengine for project Zengine
Published April 08, 2023
Advertisement

So a couple of months ago, my friend and I both wanted to work on some sort of programming project together. We both work in software engineering but come from different backgrounds, I studied a BSc in Games Programming and he studied a BSc in Computer Science. Our idea was that we wanted to essentially try our hand at creating something and after a bit of brainstorming I decided to potentially create a game engine in Java. This is solely because my friends background is in Java and personally I think transfering from C++ to Java is MUCH easier than transferring from Java to C++. Since C++ has a lot more you can do which also means a lot you can do wrong. For example not handling resources correctly, trying to teach RAII, template usage, and in general aspects of modern C++ including library related programming techniques. So after doing some research, I came across LWJGL (Lightweight Java Game Library) This library essentially contains bindings for OpenGL to be used in Java, it also provides additional libraries ported for use in Java such as ASSIMP, and IMGUI (which is essential for model loading and animations and some form of editor). It's also the same library that Mojang use for Minecraft. Of course, this is not the case with Bedrock edition.

You might be wondering, “so doesn't Java pretty much bottleneck the performance you can get out of an engine?” and personally I would respond yes, but not to a high degree. There are various resources online showcasing what some people have created in LWJGL, including deferred rendering, terrain generation, light scattering, AA - deferred water - all courtesy of the OREON engine. Now provided with this in mind this doesn't mean that LWJGL will essentially run as quick as say an engine running using the Vulkan API in C++ as LWJGL is treated at a much higher level. Memory management features are essential for game engines such as inclusion for creation of memory pools and resource handling, this is a potential drawback which hasn't been addressed yet however considering this I'm actually excited as I see this as a potential challenge which will require some coding magic to overcome. There will be some areas which will either require “smoke and mirror” solutions or require just a simple implementation of less resources in use to free up and improve performance, but it'll be interesting to see what's capable if these hinderances show.

The design ethos of the engine is to essentially provide iterability for implementaiton, I want to be able to implement graphical features while my friend can implement other technical features of the engine, and this design essentially follows a render entity component system. Each render entity can hold multiple components which all have specifics about them. Think for example a game object holding a geometry component, a texture component and even potentially a lighting component if it needs to emit light, and an animation component if there is to be animation information attributed with it. With this in mind it will be very easy to abstract the rest of the engine from rendering. I've seen many tutorials online which showcase imlementation of a game object only to have all the additional rendering components coupled in the game object class definition, which prevents iterable implementation of new rendering techniques. Without abstraction, implementing new techniques means a redundant process of updating the definitions for every game object associated, my method hopefully provides a means for just “add component” and thus will advance the rendering of the engine.

Currently the engine has the following features implemented: Render entity/component system, Shader management, VAO creation (quite strange in LWJGL), Error handling and output, UBO creation and management. VAO creation is quite strange in LWJGL because opposed to OpenGL's C++ VAO creation whereby a struct of said type can be created and then bound to an openGL buffer, LWJGL does NOT have this ability. Instead the bindings expect a “Float Buffer" (exactly what it says on the tin) for the data used inside a VAO. What this means is that where you have a VAO created in C++ OpenGL which is accomplished by first creating a struct then determining the size of the struct which can hold different data types of different sizes, the equivalent in LWJGL is to create a single continuous list of floats of each of the components, this means that if you have a VAO in LWJGL, with the components Vec3 for pos, Vec3 for normal and Vec2 for texture coord, that you would then determine an array of these types to be the total size of the individual components - in this case 8 (vec3 + vec3 + vec2). So in OpenGL C++ you might have a single array of this VAO layout which could be say 20 entries long, however in LWJGL, you'd need to create an array 160 entries long and put the floats in, in order of vec3,vec3,vec2. It's definitely a nuisance but that's what the binding has provided, there's no sizeof function in Java nor are there structs. Anyways, it just makes creation of the VAO objects a bit more of a difficulty. It's not necessarily a huge issue, as there's no actual additional memory required, it's still the same size as a C++ OpenGL created VAO of the same structure.

I've found though that there is a different direction I want to take with this engine which is implementation of an editor into the engine right from the get go. For an engine created in Vulkan, DirectX or OpenGL, a lot of the time, developers integrate IMGUI What you obtain from the integration is not only a lot of support for editing the current “chunk” or “level” that you're working on, but from a developers point of view you get a much greater sense of accomplishment since the engine actually functions in such a way to help development of any title you throw at it. Of course a question might be “well why not just use Unity or Unreal?” That's not the purpose of this project, the purpose is to create an engine, if it's like Unity or Unreal, then honestly that's better. The difference is where you've got that feeling that you've actually CREATED it rather than used it. In a cringeworthy way, you feel zen. This does bring a concern though, the main idea is to have the game window render in the centre of the editor and then essentially pause, play and even rewind if applicable but these approaches are quite difficult in Java. It would be good if there was some way to have a different executable type thing which if ran, would run the game version which runs off a file which is saved, there's probably some method around that: The editor needs to both save state for the current editing configuration and to save and store state for gameplay so when the game version of the program is run, the editor is pretty much not even there and runs off the recently saved game state.

Anyways, that's where I'm up to and where I want to continue forwards, firstly to get some sort of editor running and secondary build setting to run a game only.

There's still a lot to implement: UBO management working correctly and to a precise high performance, Implementing shader factory and UBO factory so that each scene can load the correct UBO's and shaders and set binding points with potential modification based on video settings, Implementing a true game management class with information about FPS, tick settings, e.t.c, implementing textures of course, having a system to render components and entities in the correct order (some entities rely on others and some components rely on others - I know that isn't a great design ethos HOWEVER, in some situations we'll need to do a render pass and render something to texure and then use this as a texture on a render entity - some queue system could work?)

0 likes 0 comments

Comments

Nobody has left a comment. You can be the first!
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Advertisement
Advertisement