Sparrow WebGL Devlog 12: Real-time Engine Options
Sky, lighting, fog, and water options with new UI features
22.10.2023 - 10:20Real-time feedback is extremely valuable when tweaking options. When you edit an image and change the brightness you expect to see the result immediately.
The same applies to graphics programming. You can set the options in the source code, but this requires refreshing your browser to see the effect in the best case (JavaScript), or a multi-minute-long recompile in the worst case (C++).
Therefore I worked on a new user interface for my WebGL engine that enables the user to change certain options in real-time and export the settings when they are happy with the look of the scene.
UI Improvements
User interfaces are one of the most important features of any graphics engine, which is why I added them very early on in the development process of my WebGL engine. Since then, I found a few issues and wanted to make some improvements.
The biggest flaw with my original design was that the default styles for the UI elements were static. This came from their C++ origin and meant there could only be one default style. However, I changed how UIs are handled in the WebGL engine and there can now be multiple interfaces per engine instance. Think about a game, for example: There is a user interface in the main menu and when you start a match, there is a different user interface. While this could be handled by just showing and hiding different elements, it makes sense to separate the UIs in the code to make it cleaner.
Therefore, the first thing I worked on was to make the default styles non-static and members of the main UI class instead. This proved to be a bit more tricky than I originally thought because the constructors of the elements don’t require a reference to the main UI class. It’s only set after the constructor returns in the add or addChild methods. This meant I had to move the style initialization to a later point too.
The next feature I added was style classes. Style classes are very similar to CSS classes and are just a collection of options that can easily be applied to an element by setting the class instead of all options individually.
A very convenient UI element when working with numbers is spin boxes. Spin boxes are just a number-only edit field with two buttons to increase or decrease the value. Because my engine already had edit fields and buttons this was quite easy to implement (although I had to add a number-only option to the edit fields).
The next UI element required more work: Color inputs and a color selection window. In my C++ implementation, the color selection window was terrible and only had three spin boxes for red, green, and blue. My goal for the WebGL version was something like the Photoshop color selection window instead.
After creating a new ColorHSV class to handle hue-saturation-value colors and convert between them, I started with the color selection window, which required two custom elements: The hue selector at the top and the color selector below. Linearly interpolating between colors is theoretically very easy with WebGL because the fragment shader does it automatically. However, because the UI shader doesn’t work with vertex colors, I had to create a new shader to render the two elements. Since shader switching is slow, the elements are rendered into a texture instead, so the normal UI shader can be used to draw the color selection window. The selected color is simply calculated from the mouse coordinates within the selection elements.
Global Options
With the new UI elements, I was finally able to work on the real-time options. Previously, the global options were hardcoded in the engine class and there was no way to set them externally. I moved all options into a new class and added an options parameter to the engine constructor. I also implemented a few new options like the lighting settings, which required some changes to the default shader. Creating the UI was quick and easy with the new UI elements. Since my WebGL engine has no concept of something like a project file at the moment, the options can simply be exported as a JSON object and pasted directly into the JavaScript code.
Water Options
Last week, I added animated water with reflections to my WebGL engine. The water has a lot of options to fine-tune the look of the scene too, so I added an options window for the water settings as well.
Live Demo
Playing around with the options is a lot of fun, so I uploaded the test project to my website. Feel free to experiment with it:
https://pingpoli.de/sparrow/engine-options/
The water textures are quite big at the moment so they might take a moment to load.
The ability to control the options in real-time is very useful when fine-tuning the look of a scene. The current implementation is a good starting point but many other features could benefit from option interfaces of their own. I’m going to keep improving the engine options and add more controls in the future.
by Christian - 22.10.2023 - 10:20
Comments
Comments are disabled