Progress Update: August 2019


#1


Left - Bokeh depth-of-field, Right - No depth-of-field

Hi everyone, time for another progress update!

Last month I said I won’t have a lot of time this month, but I did manage to get a lot more done than planned! I’ve been mostly focusing on new framework features while the editor has taken a back seat this month. I’ve wrapped up a couple of big features and started work on a new rendering effect, a major GUI system improvement, re-started work on networking and am working on a major RTTI system overhaul. A lot of stuff in the pipeline!

Highlights

Bokeh depth-of-field


Bokeh DOF - Focus on the background to see the Bokeh shapes

The engine now fully supports the Bokeh depth-of-field effect. The effect yields a prettier, more realistic depth-of-field effect, compared to the already existing Gaussian depth-of-field. It simulates the camera aperture shape, yielding nice highlights in bright areas of the scene, and a more cinematic and realistic look.

You can enable the effect through DepthOfFieldSettings available from RenderSettings::depthOfField available from the camera component.

HCamera camera = ...;
auto rs = camera->getRenderSettings();
rs->depthOfField.enabled = true;
rs->depthOfField.type = DepthOfFieldType::Bokeh;
camera->setRenderSettings(rs);

You can set custom shapes to use for camera’s aperture, simulating different Bokeh shapes (e.g. circular, hexagonal or otherwise) through DepthOfFieldSettings::bokehShape.

I’ve also ensured the algorithm relies on physical camera properties, including focal length, aperture size and sensor size, in order to more easily set up realistic shots.

HDR color support in editor

ColorPicker
New exposure control in the Color picker window

So far when setting color in the editor you could only select a normalized RGB color (i.e. channels in range [0, 1]). This was problematic for colors representing light values, such as emissive color property in a shader, which require greater ranges.

I’ve restructured the color picker so it includes an additional ‘Exposure’ slider that allows colors to be set outside of [0, 1] range.

BSL has been extended with an [hdr] attribute which can be used for marking a color that accepts a higher range of values. For such colors the exposure slider will be displayed in the color picker.

cbuffer MaterialParams
{
	[color][hdr]
	float3 gEmissiveColor = { 1.0f, 1.0f, 1.0f };
};

Similarily an hdr export flag was added to BS_SCRIPT_EXPORT in C++, and a [HDR] attribute in C#, which will yield similar behaviour.

Additionally all low-level classes such as color gradient and color distribution were also refactored so they support HDR colors. We’re having separate versions of these classes for normal LDR colors and HDR colors as the LDR versions can usually be more optimized. New HDR classes for the gradient and distribution are ColorGradientHDR and ColorHDRDistribution respectively.

Plain type serialization refactor

I’ve completely refactored how RTTIPlainType<T> is implemented. The refactor was guided mostly by the need of the new networking system, which will sometimes require fields to be serialized in a compressed manner. For example a normal integer would usually take 4 bytes, but an integer could be compressed as a var-int through the recently added Bitstream class. In which case it can take anywhere from 1-5 bytes. Additionally booleans can be compressed as 1 bit, requiring support for sub-byte values. This is useful for networking as keeping the data sizes small is very important in that case.

All this culminated in the refactor of RTTIPlainType<T>::toMemory() and RTTIPlainType<T>::fromMemory() which no longer write to raw memory buffer, but instead accept a Bitstream class. They also accept an additonal RTTIFieldInfo parameter that can be used for providing clues on how should a field be compressed (e.g. compress a Vector3 assuming it’s normalized) and a compress boolean, enabling or disabling compression.

// Old signature
static void toMemory(const T& data, char* memory);
static UINT32 fromMemory(T& data, char* memory);

// New signature
static uint32_t toMemory(const T& data, Bitstream& stream, const RTTIFieldInfo& fieldInfo, bool compress);
static uint32_t fromMemory(T& data, Bitstream& stream, const RTTIFieldInfo& fieldInfo, bool compress);

Aside from giving us compression options, this refactor also streamlined and cleaned up a lot of that code, as interfacting with Bitstream is more concise than writing to raw memory. rttiReadElem, rttiWriteElem and rttiGetElemSize were renamed to rtti_read, rtt_write and rtti_size to be more consistent with remaining global function naming.

Initial work on the networking replication system

After a long planning phase I’ve started work on the replication system! Initial skeleton for the system has been added and now it’s a matter of filling in the gaps. In particular I’m now working on refactoring the RTTI system so much of its functionality can be re-used for replication purposes as well.

The goal is to create a system that will allow networked games to created with a minimal amount of code, while also making the system extensible enough so users can tweak it to their liking (without having to re-implement parts of it).

Expect more work on this in the following months.

Initial work on GUI texture caching

I’ve started work on a GUI texture caching system. The system will cache the results of GUI rendering and only re-render them if a change is detected. This will significantly reduce GUI rendering times and improve overall performance. Most importantly it will reduce power usage on laptops and prevent your fans from spinning up on weaker hardware.

The ultimate plan is to avoid any drawing while the image is still, and this will eventually include 3D viewports as well. This is mainly useful for building tools and editors, but you should see a performance benefit in games as well.

Work on this is early but you might see it finished in September if lucky!

Initial work on motion blur

I’ve started work on the motion blur effect. I’ve did a lot of research and developed a plan that should yield us a nice high quality motion blur for both camera and object movement. Blur can be used simply as an artistic effect, for creating a sense of speed or for visual effects. Or it can be used for smoothing out the framerate in cinematics and on devices that cannot achieve high FPS.

I’ve already added a basic implementation for the camera blur, while I started work on the per-object blur. This work will also serve as a precursor for Temporal AA effect, as it requires some shared data (i.e. the velocity buffer).

You should be seeing more work on this soon.

Bug fixes

Framework

  • Fixed MSVC crash and error about structured exceptions with exceptions enabled with visual studio by @hhyyrylainen
  • Fixed cross-compiler generating code that doesn’t compile in Vulkan, due to invalid float literal generation
  • Fixed C# code broken due to multiple RenderSettings ctors being exported
  • Fixed broken SerializedObject creation, always assuming ‘shallow’ serialization mode
  • Fixed an issue with character input stopping to work after ctrl or alt keys get stuck on Windows
  • Fixed a crash during Material deserialization
  • Degree and Radian headers are no longer unnecessarily included in main prerequisites header
  • Fixed animation looping if not all curves are the same length
  • Fixed Animation::getState() returning invalid layer index
  • Fixed camera view sometimes getting stuck after render settings change
  • Fixed GPU parameters being parsed/set incorrectly if a color parameter used less than 4 channels
  • Fixed a crash if a skybox attempts to be initialized without the referenced cubemap texture being fully loaded
  • Fixed a crash caused by FBX importer when the imported mesh has no material indices defined
  • Fixed a crash when setting screen space lens flare’s ‘downsampleCount’ setting to zero

Editor

  • Fixed animation sample rate not being loaded when an existing clip is loaded in the animation window
  • Focus is now properly restored on library window after invalid rename modal dialog box closes
  • Fixed texture inspector not showing/hiding cubemap source field as cubemap option is enabled/disabled
  • Fixed issues caused by project library meta file having no referenced resource metas
  • Fixed a crash when hierarchy window was closed with an item selected

Minor features

Framework

  • Visual Studio 2019 compilation support for framework and editor
  • MemoryDataStream can now grow its internal buffer automatically
  • A lot of cleanup regarding RTTI code and RTTI includes, for better organization and faster compile times
  • When a window loses focus, focused GUI elements are remebered and restored when the window regains focus
  • Support for external main loop by @hhyyrylainen
  • Support for custom crash handler and debugging logging callbacks by @hhyyrylainen

Editor

  • Restore focus to last focused editor widget after the window its docked on regains focus

What’s next?

I’ll be focusing primarily on the networking system, which also includes the RTTI system overhaul, as well as the GUI caching feature. I’ll continue work on motion blur next after I finish GUI caching.

Pretty much all major issues with the Windows version of the editor have been resolved, and we’ve had a few people build fairly complex scenes with it. Things are looking a lot more stable than they’ve used to be, but there’s still plenty of minor things I wish to resolve before the next release. I’ll be solving those slowly along with other feature work on the framework.

That’s it for now, until next time!