Putting all the pieces together, I was able to create a GUI with a sprite layer, attach it to a camera with a texture buffer render target, and render the GUI onto a texture applied to a 3D surface. Then I used the picked UV coords to convert to mouse coordinates and send user events to the GUI. Here is the result:
This can be used for GUIs rendered onto surfaces in your game, or for a user interface that can be interacted with in VR. This example will be included in the next beta upd
I have been working on 2D rendering off and on since October. Why am I putting so much effort into something that was fairly simple in Leadwerks 4? I have been designing a system in anticipation of some features I want to see in the GUI, namely VR support and in-game 3D user interfaces. These are both accomplished with 2D drawing performed on a texture. Our system of sprite layers, cameras, and sprites was necessary in order to provide enough control to accomplish this.
I now have 2D drawin
In Leadwerks 4, render-to-texture was accomplished with the SetRenderTarget command, which allowed a camera to draw directly to a specified texture, while hiding the underlying framebuffer object (FBO). In the new engine we have a bit more explicit handling of this behavior. This is largely in part due to the use of Vulkan's bindless design, which greatly improves the context-binding design of OpenGL. The Leadwerks "Buffer" class was never documented or officially supported because the underlyin
It's 2020, and we are officially now living in the future. I predict a 1980s neon / Cyberpunk will start to manifest in real life as the number of this decade starts to imprint on peoples' minds.
In fact, it has already begun. Tesla will be remembered as the start of this trend.
I am happy with this direction because pretty much all entertainment and style has sucked since the late 1990s. Installing some microchip neural enhancement implants is a small price to pay in order to g
The GUIBlock structure now has an iVec4 "clipregion" member. This allows you to set a clipping region around a block to prevent it from drawing outside the region. The region will automatically be shrunk to show only the visible area of the widget, within the visible area of its parent. The purpose of this is to prevent text from overflowing outside of the widget. I found this necessary because the multi-line text area widget involves the dynamic creation of different persistent 2D elements, and
An update is available for Leadwerks Game Engine 5 beta. The GUI system is now working with support for the following items:
Text field (editable, single line)
Text area (multiline, read-only, allows text selection)
The GUI scripts use a system of "blocks". You can add a solid rectangle, a wire rectangle, (both support rounded corners) or a text block.
The drawing hierarchy is not yet respected, so
I'm back from I/ITSEC. This conference is basically like the military's version of GDC. VR applications built with Leadwerks took up about half of Northrop Grumman's booth. There were many interesting discussions about new technology and I received a very warm reception. I feel very positive about our new technology going forward.
I am currently reworking the text field widget script to work with our persistent 2D objects. This is long and boring but needs to be done. Not much else to
Here are some screenshots showing more complex interface items scaled at different resolutions. First, here is the interface at 100% scaling:
And here is the same interface at the same screen resolution, with the DPI scaling turned up to 150%:
The code to control this is sort of complex, and I don't care. GUI resolution independence is a complicated thing, so the goal should be to create a system that does what it is supposed to do reliably, not to make complicated things s
A new beta is available with the following changes:
Script prefixes are now changed to lowercase entity:Update(), entity:Start(), etc., as well as widget:Draw(), etc. This is because Entity() and Widget() are going to be functions to cast an object to that type.
Sprites are now created on a sprite layer object. A sprite layer is created in a world and added to a camera. This allows control over what camera sees what set of sprites. See the examples for details.
GUI system i
I did a little experiment with FPS Creator Pack #75 by upsampling the images with Gigapixel, which uses deep learning to upsample images and infer details that don't appear in the original pixels. The AI neural network does a pretty impressive job, generating results that are look better than a simple sharpen filter: I doubled the size of the textures to 1024x1024. Then I generated normal maps from the high-res images using AMD's TGA to DOT3 tool, and saved the normal maps with BC5 DDS compressi
DPI scaling and the 2D drawing and GUI system were an issue I was a bit concerned about, but I think I have it worked out. This all goes back to the multi-monitor support that I designed back in September. Part of that system allows you to retrieve the DPI scale for each display. This gives you another piece of information in addition to the raw screen resolution. The display scale gives you a percentage value the user expects to see vector graphics at, with 100% being what you would expect with
For finer control over what 2D elements appear on what camera, I have implemented a system of "Sprite Layers". Here's how it works:
A sprite layer is created in a world.
Sprites are created in a layer.
Layers are attached to a camera (in the same world).
The reason the sprite layer is linked to the world is because the render tweening operates on a per-world basis, and it works with the sprite system just like the entity system. In fact, the rendering thread uses the
EAX audio effects for supported hardware.
Source class renamed to "Speaker".
Plane joint for 2D physics, so now you can make Angry Birds with Vulkan graphics.
Fixed DPI issues with fullscreen mode.
Added impact noise to barrels, fixed Lua collision function not being called.
Script functions now start with "Entity:" instead of "Script:", i.e. Entity:Update() instead of Script:Update().
Additionally, four examples can be run showing var
I've been doing some work on the sound system in Leadwerks 5 beta, and I added EAX effects in. If you have a dedicated sound card this can be used to add some nice reverb effects that make your sound environment sound a lot more real:
Here's the simplest usage:
auto fx = LoadSoundEffect("Sound/FX/sewerpipe.json");
auto listener = CreateListener(world);
This will apply the effect to all mono sources. Stereo sources are assumed to be music or GUI n
An update for Leadwerks 5 is now available.
The Vulkan data transfer system has been revised and is now simpler but uses more memory. Data is likely to be quadruple-buffered, but it's a fairly small amount of data and this isn't a big concern.
I fixed a bad bug where multiple threads were accessing a global variable in the Mat4::GetQuaternion function. This fixes the object flashing glitch that was visible in previous builds.
The engine is updated to the latest version of Newton
The best way to test the new engine is to use it to make something. I am messing around with the beginnings of a new first-person shooter template. I'm telling everyone involved "We are remaking Doom, but a little differently" and it actually works really well. Everyone understand what it should look like, and there is no need to establish a new visual style. We can tell when we have it right, and when we have it wrong. And the original game gives us a sort of benchmark for quality and performan
An update is available for the Leadwerks 5 beta.
Shadow updating is fixed so the lights no longer turn black during the update whenever a shadow changes.
We're now using multiview to draw all six faces of a cube shadow map in one single pass! Point light shadow updates are something that used to be a considerable bottleneck in Leadwerks 4, and their performance impact is now very insignificant. Thanks to Sascha Williams for his excellent Vulkan examples.
Joints are finished, a new
Leadwerks 3 / 4 was aimed at beginners who were completely new to game development. Since we were the first game engine on Steam, this made a lot of sense at the time, and the decision resulted in a successful outcome. However, in the next engine we are taking a different approach. (This is a direct result of Steam Direct.)
Enterprise is a new market I am pursuing, and we have a lot of interest from aerospace and defense VR developers. The fact that I am American also helps here. There are
I'm happy to say the physics joint class in the new engine is completed. I made all the members that are not meant to be accessed private. One interesting part is the parent and child public members, which are constant pointers to private members. This should result in a read-only member in C++. A sol property is used to expose this to Lua in a read-only manner.
The upvector joint will align an object's Y axis to any vector you set, but still allow rotation around the axis. This is perfect
The following changes have been made to the GLTF model loader:
Correctly loaded rotations and orientations.
Mesh collision caching for faster loading.
Supports transforms with negative scale and correct face orientation.
Support for adjustable alpha cutoff value.
Support for KHR_materials_unlit extension (full bright materials).
This model from SketchFab was useful for testing because it uses so many features of the GLTF format:
There are two aspects of GLTF files that have non-optimal loading speed. First, the vertex data is not stored in the same exact layout and format as our vertex structure. I found the difference in performance for this was pretty small, even for large models, so I was willing to let it go. Tangents can take a bit longer to build, but those are usually included in the model if they are needed.
The second issue is the triangle tree structure which is used for raycasting (the pick commands). I
A big update is now available for beta subscribers!
You can use several cameras to increase the depth range or mix 2D and 3D graphics.
As discussed earlier, 2D graphics are now supported using persistent 2D objects.
Multiple layers of transparency will now render in correct order, with lighting in each layer. Note that I used an empty script called "null.lua" to prevent the glass surfaces here from being collapsed at loa
Previously, we saw how the new renderer can combine multiple cameras and even multiple worlds in a single render to combine 3D and 2D graphics. During the process of implementing Z-sorting for multiple layers of transparency, I found that Vulkan does in fact respect rasterization order. That is, objects are in fact drawn in the same order you provide draw calls to a command buffer.
Furthermore, individual primitives (polygons) are also rendered in the order they are stored in the indice b
Previously I described how multiple cameras can be combined in the new renderer to create an unlimited depth buffer. That discussion lead into multi-world rendering and 2D drawing. Surprisingly, there is a lot of overlap in these features, and it makes sense to solve all of it at one time.
Old 2D rendering systems are designed around the idea of storing a hierarchy of state changes. The renderer would crawl through the hierarchy and perform commands as it went along, rendering all 2D elemen
Current generation graphics hardware only supports up to a 32-bit floating point depth buffer, and that isn't adequate for large-scale rendering because there isn't enough precision to make objects appear in the correct order and prevent z-fighting.
After trying out a few different approaches I found that the best way to support large-scale rendering is to allow the user to create several cameras. The first camera should have a range of 0.1-1000 meters, the second would use the same n