It’s been a long time since the last update but rest assured, we’ve been working hard. This update aimed to make substantial improvements to the engine’s existing systems, namely landscapes. The entire terrain system and dynamic foliage have been completely re-written to allow for far greater flexibility and quality, with the introduction of tessellation!
A Huge Thank you to our Patrons! Your contributions make Bright Engine Possible!
Cody Pryor • Daniel Burkhart • Massum Zaidi • Mark Makarainen • Çağlayan Karagözler
The most prominent new feature of this update is the new terrain system. Previously, the engine couldn’t support open-world scale terrains very easily. While it was possible to add multiple terrain objects, scaling and aligning these objects was a nightmare. But we’ve now fixed all that.
The new terrain system is comprised out of chunks aligned to a grid. Whenever additional terrain is needed, a new chunk can be added and moved into the right position. This solves the problem where building a landscape from a single large square area results in a lot of space being wasted with rendering performance suffering.
Furthermore, because each chunk is treated as independent objects, it allows many textures to be supported. So, the number of texture layers has been increased from 8 to 18. Each chunk has its own independent texture set, allowing for quick and easy biome shifts.
But that’s not the only improvement for textures. Originally, terrain textures had to be pre-channel packed in a specific way. While not difficult to perform, it’s time that could be better-spent painting terrain. Now, all textures can be added to a painting layer independently. Bright Engine will automatically channel pack the textures at runtime. Ultimately this saves you time without any loss in performance.
Beyond improved texture support, terrain geometry just got a whole lot more detailed with the introduction of tessellation. This system adds and removes terrain geometry depending on the position of the camera. Subsequently, incredibly high-density polygons are supported, using heightmap data from texture layers to shift the landscape, allowing for a far greater detail level.
But this tessellation system doesn’t solely rely on distance to the camera. It also tests against the slope angle. If you look at a cliff in the distance, the increased geometric detail is still clearly visible.
In addition, a terrain LOD system has also been introduced that lowers the geometric detail of the terrain chunks as a whole, improving performance just a little bit more.
Changes & Improvements
Re-writing the terrain system also meant attention needed to be given to the sculpting and painting system. And after some deliberation, we decided to simply re-write the whole system and adding a whole bunch of new tools in the process.
In terms of visual features, all brush settings are now located in their own panel that will appear whenever you enter sculpting or painting mode. Initially, these settings required you to switch between tabs. Needless to say, it was a pretty annoying process. We also moved all vertex colour painting settings into their own tab, but more on that later.
In terms of code architecture, almost 2,500 lines were eliminated from the Bright Engine brush system. It now runs significantly faster, with no more annoying performance drops when working on large scale terrains. What’s more, we added a bit more functionality with the introduction of slope restriction settings.
You can now set constraints on where textures can be painted depending on slope angle. This allows you to paint all your cliffs or flat paints within seconds instead of hours!
The same works in reverse when erasing terrain textures
We adjusted the shortcut increments for changing brush settings. And also, the new painting tools were extended to be used in the vertex colour painting system.
But most importantly, the Undo/Redo system for terrain has finally been extended. Originally only sculpting actions could be reversed. But now, this is possible with all texture, vertex, and foliage painting.
With the new terrain system in place, something still looked off—specifically the dynamic foliage system. The fundamental code behind it was sound and didn’t require much tweaking, but for some reason, the end result just looked like cardboard.
So we did some research and made some much-needed improvements. Starting with the planting system. Originally the engine would simply place foliage clusters around terrain vertex points with random offsets. The new system works quite similarly. However, it is based on a texture mask system instead. This allows for far higher levels of foliage density that can be increased by the user (something that was severely lacking in the older system)
Another problem with using purely random placements was that with each load, everything looked slightly different. Clusters move around and create some unwanted results, so now the random engine allows you to specify a seed value. This number could be anything, but it will ensure that the same series of random numbers will be selected every time the scene is loaded.
The last problem we wanted to address with the placement was slope alignment. The foliage clusters had a hobbit of floating in the air on steep angles. Needless to say, that’s not very realistic. So we’ve now added some rotational matrices into the placement algorithm so that foliage is always aligned with the terrain slope underneath it.
With placements now fixed, it was time to address the visuals. The vertex normals now align themselves to slope angle underneath, eliminating the problem of incredibly harsh lighting. We also made several improvements to the geometry generation shader, wiping out almost 300 lines of unnecessary shader code. But most importantly, we added Alpha Blending as a transparency method.
Originally the engine used Mask alpha to cut out the transparent parts of foliage clusters (this option is still available). The reasoning was, alpha blending requires the clusters to be drawn in a specific order to achieve the correct results. And sorting 100,000’s of foliage objects is quite an expensive process when using a traditional insertion sort algorithm.
But we’re no longer using insertion sorting. After further research, we found an alternative approach based on Tim Peter’s hybrid sorting algorithm, which works almost ten times faster. With the sorting bottleneck out of the way, Alpha Blending is now supported. It has drastically improved the overall quality while simultaneously allowing for partial transparency of foliage.
With placements and visuals at a much superior level, the last thing that needed fixing was wind simulation. The older algorithm gave some semi-decent results and made everything look like it was in a fish tank. The movement was too uniform, even with added jittering. So once again, we went on a researching spree and came up with a solution - gust simulation.
Bright Engine now calculates a 3D simplex noise texture (where the 3rd dimension is time) to create variation in the wind waves speed, creating the illusion of gusts. The size and speed of these areas are entirely within your control. Here’s what the generated noise texture ends up looking like
Generating 3D Simplex noise was undoubtedly a challenge. But that was made even harder by the fact we needed it to run in realtime. Our original approach of calculating it in the geometry shader when rendering foliage was impractical. Why? Because it would have to be recalculated for every foliage cluster for each render pass (PBR, Shadows, etc.). So the next approach was to calculate it once per frame on the CPU, but this was also too slow.
But we did find a GPU solution. Enter the compute shader. Using this modern system allowed us to calculate the simplex noise once per frame by storing the results into a texture sampled by the geometry shader of foliage. Problem solved!
Adding compute shaders into the existing rendering pipeline wasn’t too much of a challenge. But it did reveal several opportunities for performance improvements unrelated to this new system.
Sphere and Cuboid primitives used to visualise distances and bounding boxes now use element buffers to draw (element buffers allow you to draw models the same way but using fewer vertex data to do it).
The shadow sampling algorithm for models, terrain and foliage got an update, fixing several visual bugs (including the one where adding lights reduced shadow strength of shadow miles away from the new light source). It also eliminated four shadow map samples per light source, giving a nice boost to performance. And we removed redundant code in the calculation of directional shadows, providing another small boost.
We also added additional settings that allow you to change which objects are included in the shadow rendering pass. For example, if you don’t want terrain to be drawn in the shadow map of small light sources, you can exclude it. It is still possible to individually exclude objects from shadow maps using the material settings.
The skybox is now included in the bloom render pass if the pixel luminance passes the minimum threshold, solving the problem where a bright scene could end up with a dim sky.
Beyond the rendering pipeline’s visual side, we’ve made some minor improvements to the underlying mechanics. Bright Engine now uses adaptive v-sync. This means that v-sync will only turn on if the frame rate is higher than 60 fps, reducing the graphical load on weaker machines.
We’ve also revamped the Occlusion Query system that was causing the CPU to sit idle each frame, giving a small but notable boost in performance.
The last of the improvements were made to the Render Panel. All the settings have now been organised into separate tabs, similar to the rest of the UI. This is also where the new settings for shadows rendering quality can be found. And as a last addition, we added a setting that controls the number of undo/redo steps to keep in the local cache. Running out of memory became a common problem after prolonged use of the engine due to the Undo system remembering everything. This has subsequently eliminated that problem.
- Fixed bug where DDS texture data was being loaded twice
- Fixed bug where HDR textures were not being removed from memory when switching zones
- Fixed bug where a missing texture caused a crash - textures will appear black if they failed to load
- Fixed bug where texture data was not being cleared from memory correctly (Memory Leak)
- Fixed bug where terrain painting data was not being cleared from memory correctly (Memory Leak)
- Fixed bug where sculpting terrain near its edge sometimes caused a crash
- Fixed bug where erasing painted textures on every fourth layer also erased the layers beneath it
- Fixed bug where terrain normal strength was being halved
- Fixed bug where changing a terrain object's setting would cause the data file to be saved twice
- Fixed bug where the flatten marker for the Flatten/Ramp sculpting Tool intersected with the terrain creating visual glitching
- Fixed bug where paint layers could be renamed - this ultimately led to strange behaviour
- Fixed bug where the terrain was being continuously resized each frame (performance)
- Fixed bug where the engine would crash when fetching GPU data from specific AMD Chips
- Fixed bug where the Sculpting and painting brush ruler was incorrectly scaled
- Fixed bug where occlusion queries were not given enough time to complete operation resulting in incorrect results
- Fixed bug where brush size could be set to zero creating strange behaviour due to a divide by zero math error
- Fixed bug where entering diagnostics mode would create a memory leak of 1MB per second
- Fixed bug where terrain vertex positions were being smoothed even when not being imported from the external heightmap
- Fixed bug where terrain vertex painting created some strange alpha artefacts and thus inaccurate results
- Fixed bug where the sculpting smooth tool created dips along the outer left edge of a terrain chunk
- Fixed bug where pressing redo after undoing an action that affected a room would trigger a second undo instead
- Fixed bug where foliage settings only affected the first layer
- Fixed bug where loading a zone would trigger the World data file to be rewritten, sometimes causing a crash or even wiping the world file altogether
- Fixed bug where sculpting terrain caused a small memory leak that gobbled up RAM
- Fixed bug where painting terrain caused a small memory leak that gobbled up RAM
- Fixed bug where painting foliage caused a small memory leak that gobbled up RAM
- Fixed bug where re-uploading image data to the GPU caused a small memory leak that gobbled up RAM
- Fixed bug where specific light settings were not updating correctly when selecting between two light sources
- Fixed bug where FPS counter gave inaccurate results
- Fixed bug where the wrong hierarchy icons were being used for specific objects
- Fixed bug where switching between zones would cause a crash
- Fixed bug where thumbnails for blank texture slots on terrain were not showing
- Fixed bug where cloud speed setting had the wrong label
- Fixed bug where cloud height strength setting had no effect
- Fixed bug where alpha artefacts appeared when looking through dynamic foliage at the sky without terrain behind it
- Fixed bug where bounding boxes for models were being incorrectly clipped, resulting in the user not being able to select objects in the scene
- Fixed bug where switching out of the sculpting panel and then back in would reset the sculpting tool back to Raise/Lower even if it is not selected
This update ended up becoming far more extensive than expected. Almost a third of the entire engine architecture was re-written to improve functionality, stability, and performance. But it’s nowhere near where we want it to be.
Bright Engine v0.1.8c is going to be all about extending what we’ve added in this update even further and continuing to improve and update older features as well.
Thanks to the incredible support from our Patreons, we have raised enough money to start bringing in outside help. The terrain system now can support open-world scale terrains. But the performance is still lacking. We’re bringing some expert software engineers to help implement a new Quad-Tree system that will take terrain rendering to a whole new level.
And while they are working away on that, we will be fixing a lot of bugs, as well as re-introducing the model brush tools for procedural object placement.
Looking forward to sharing the results soon!